Thomas Vachuska

Adding commands for managing layouts.

Adding support for wiping out regions and layouts.
Refactored UI layout manager to allow public knowledge of default layout id.
Enhanced test topo for layout hierarchy.

Change-Id: I254fd494175e753f542f12a664618c1a83f72127
1 +/*
2 + * Copyright 2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.cli.net;
17 +
18 +import org.apache.karaf.shell.commands.Argument;
19 +import org.apache.karaf.shell.commands.Command;
20 +import org.onosproject.cli.AbstractShellCommand;
21 +import org.onosproject.net.region.Region;
22 +import org.onosproject.net.region.RegionService;
23 +import org.onosproject.ui.UiTopoLayoutService;
24 +import org.onosproject.ui.model.topo.UiTopoLayout;
25 +import org.onosproject.ui.model.topo.UiTopoLayoutId;
26 +
27 +import static org.onosproject.net.region.RegionId.regionId;
28 +import static org.onosproject.ui.model.topo.UiTopoLayoutId.layoutId;
29 +
30 +/**
31 + * Creates a new UI layout.
32 + */
33 +@Command(scope = "onos", name = "layout-add",
34 + description = "Creates a new UI layout")
35 +public class LayoutAddCommand extends AbstractShellCommand {
36 +
37 + private static final String FMT = "id=%s, name=%s, type=%s";
38 + private static final String FMT_MASTER = " master=%s";
39 +
40 + @Argument(index = 0, name = "id", description = "Layout ID",
41 + required = true, multiValued = false)
42 + String id = null;
43 +
44 + @Argument(index = 1, name = "id", description = "Region ID (optional)",
45 + required = false, multiValued = false)
46 + String regionId = null;
47 +
48 + @Argument(index = 2, name = "id", description = "Parent layout ID (optional)",
49 + required = false, multiValued = false)
50 + String parentId = null;
51 +
52 + private RegionService regionService;
53 +
54 + @Override
55 + protected void execute() {
56 + UiTopoLayoutService service = get(UiTopoLayoutService.class);
57 + RegionService regionService = get(RegionService.class);
58 +
59 + Region region = regionId == null ? null : regionService.getRegion(regionId(regionId));
60 + UiTopoLayoutId pid = parentId == null ? UiTopoLayoutId.DEFAULT_ID : layoutId(parentId);
61 +
62 + UiTopoLayout layout = new UiTopoLayout(layoutId(id), region, pid);
63 + service.addLayout(layout);
64 + }
65 +}
1 +/*
2 + * Copyright 2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.cli.net;
18 +
19 +import org.apache.karaf.shell.commands.Argument;
20 +import org.apache.karaf.shell.commands.Command;
21 +import org.onosproject.cli.AbstractShellCommand;
22 +import org.onosproject.ui.UiTopoLayoutService;
23 +import org.onosproject.ui.model.topo.UiTopoLayout;
24 +import org.onosproject.ui.model.topo.UiTopoLayoutId;
25 +import org.onosproject.utils.Comparators;
26 +
27 +import java.util.Collections;
28 +import java.util.List;
29 +
30 +import static com.google.common.collect.Lists.newArrayList;
31 +
32 +/**
33 + * List layout details.
34 + */
35 +@Command(scope = "onos", name = "layouts",
36 + description = "List layout details")
37 +public class LayoutListCommand extends AbstractShellCommand {
38 +
39 + private static final String FMT = "id=%s, region=%s, parent=%s";
40 +
41 + @Argument(index = 0, name = "id", description = "Layout ID",
42 + required = false, multiValued = false)
43 + String id = null;
44 +
45 + private UiTopoLayoutService layoutService;
46 +
47 + @Override
48 + protected void execute() {
49 + layoutService = get(UiTopoLayoutService.class);
50 + if (id == null) {
51 + for (UiTopoLayout layout : getSortedLayouts(layoutService)) {
52 + printLayout(layout);
53 + }
54 + } else {
55 + UiTopoLayout layout = layoutService.getLayout(UiTopoLayoutId.layoutId(id));
56 + if (layout == null) {
57 + error("No such region %s", id);
58 + } else {
59 + printLayout(layout);
60 + }
61 + }
62 + }
63 +
64 + private List<UiTopoLayout> getSortedLayouts(UiTopoLayoutService service) {
65 + List<UiTopoLayout> layouts = newArrayList(service.getLayouts());
66 + Collections.sort(layouts, Comparators.LAYOUT_COMPARATOR);
67 + return layouts;
68 + }
69 +
70 + private void printLayout(UiTopoLayout layout) {
71 + print(FMT, layout.id(), layout.regionId(),
72 + layout.parent() != null ? layout.parent().id() : "none");
73 + }
74 +}
...@@ -26,6 +26,8 @@ import org.onosproject.net.intent.Intent; ...@@ -26,6 +26,8 @@ import org.onosproject.net.intent.Intent;
26 import org.onosproject.net.intent.IntentService; 26 import org.onosproject.net.intent.IntentService;
27 import org.onosproject.net.intent.IntentState; 27 import org.onosproject.net.intent.IntentState;
28 import org.onosproject.net.link.LinkAdminService; 28 import org.onosproject.net.link.LinkAdminService;
29 +import org.onosproject.net.region.RegionAdminService;
30 +import org.onosproject.ui.UiTopoLayoutService;
29 31
30 /** 32 /**
31 * Wipes-out the entire network information base, i.e. devices, links, hosts, intents. 33 * Wipes-out the entire network information base, i.e. devices, links, hosts, intents.
...@@ -51,6 +53,9 @@ public class WipeOutCommand extends ClustersListCommand { ...@@ -51,6 +53,9 @@ public class WipeOutCommand extends ClustersListCommand {
51 wipeOutHosts(); 53 wipeOutHosts();
52 wipeOutDevices(); 54 wipeOutDevices();
53 wipeOutLinks(); 55 wipeOutLinks();
56 +
57 + wipeOutLayouts();
58 + wipeOutRegions();
54 } 59 }
55 60
56 private void wipeOutIntents() { 61 private void wipeOutIntents() {
...@@ -106,4 +111,16 @@ public class WipeOutCommand extends ClustersListCommand { ...@@ -106,4 +111,16 @@ public class WipeOutCommand extends ClustersListCommand {
106 } 111 }
107 } 112 }
108 } 113 }
114 +
115 + private void wipeOutLayouts() {
116 + print("Wiping UI layouts");
117 + UiTopoLayoutService service = get(UiTopoLayoutService.class);
118 + service.getLayouts().forEach(service::removeLayout);
119 + }
120 +
121 + private void wipeOutRegions() {
122 + print("Wiping regions");
123 + RegionAdminService service = get(RegionAdminService.class);
124 + service.getRegions().forEach(r -> service.removeRegion(r.id()));
125 + }
109 } 126 }
......
...@@ -631,6 +631,19 @@ ...@@ -631,6 +631,19 @@
631 </completers> 631 </completers>
632 </command> 632 </command>
633 633
634 + <!-- UI Layout commands -->
635 + <command>
636 + <action class="org.onosproject.cli.net.LayoutListCommand"/>
637 + </command>
638 + <command>
639 + <action class="org.onosproject.cli.net.LayoutAddCommand"/>
640 + </command>
641 + <!--TODO: add this + completers
642 + <command>
643 + <action class="org.onosproject.cli.net.LayoutRemoveCommand"/>
644 + </command>
645 + -->
646 +
634 <!--virtual network commands --> 647 <!--virtual network commands -->
635 <command> 648 <command>
636 <action class="org.onosproject.cli.net.vnet.TenantListCommand"/> 649 <action class="org.onosproject.cli.net.vnet.TenantListCommand"/>
......
...@@ -23,6 +23,11 @@ import org.onlab.util.Identifier; ...@@ -23,6 +23,11 @@ import org.onlab.util.Identifier;
23 */ 23 */
24 public final class UiTopoLayoutId extends Identifier<String> { 24 public final class UiTopoLayoutId extends Identifier<String> {
25 25
26 + /**
27 + * Default topology layout identifier.
28 + */
29 + public static final UiTopoLayoutId DEFAULT_ID = UiTopoLayoutId.layoutId("_default_");
30 +
26 // For serialization 31 // For serialization
27 private UiTopoLayoutId() { 32 private UiTopoLayoutId() {
28 } 33 }
......
...@@ -33,6 +33,7 @@ import org.onosproject.net.group.Group; ...@@ -33,6 +33,7 @@ import org.onosproject.net.group.Group;
33 import org.onosproject.net.region.Region; 33 import org.onosproject.net.region.Region;
34 import org.onosproject.net.statistic.TypedFlowEntryWithLoad; 34 import org.onosproject.net.statistic.TypedFlowEntryWithLoad;
35 import org.onosproject.net.topology.TopologyCluster; 35 import org.onosproject.net.topology.TopologyCluster;
36 +import org.onosproject.ui.model.topo.UiTopoLayout;
36 37
37 import java.util.Comparator; 38 import java.util.Comparator;
38 39
...@@ -154,6 +155,12 @@ public final class Comparators { ...@@ -154,6 +155,12 @@ public final class Comparators {
154 } 155 }
155 }; 156 };
156 157
158 + public static final Comparator<UiTopoLayout> LAYOUT_COMPARATOR = new Comparator<UiTopoLayout>() {
159 + @Override
160 + public int compare(UiTopoLayout l1, UiTopoLayout l2) {
161 + return l1.id().toString().compareTo(l2.id().toString());
162 + }
163 + };
157 public static final Comparator<TenantId> TENANT_ID_COMPARATOR = new Comparator<TenantId>() { 164 public static final Comparator<TenantId> TENANT_ID_COMPARATOR = new Comparator<TenantId>() {
158 @Override 165 @Override
159 public int compare(TenantId tenant1, TenantId tenant2) { 166 public int compare(TenantId tenant1, TenantId tenant2) {
......
...@@ -195,6 +195,9 @@ import org.onosproject.net.packet.DefaultOutboundPacket; ...@@ -195,6 +195,9 @@ import org.onosproject.net.packet.DefaultOutboundPacket;
195 import org.onosproject.net.packet.DefaultPacketRequest; 195 import org.onosproject.net.packet.DefaultPacketRequest;
196 import org.onosproject.net.packet.PacketPriority; 196 import org.onosproject.net.packet.PacketPriority;
197 import org.onosproject.net.provider.ProviderId; 197 import org.onosproject.net.provider.ProviderId;
198 +import org.onosproject.net.region.DefaultRegion;
199 +import org.onosproject.net.region.Region;
200 +import org.onosproject.net.region.RegionId;
198 import org.onosproject.net.resource.ContinuousResource; 201 import org.onosproject.net.resource.ContinuousResource;
199 import org.onosproject.net.resource.ContinuousResourceId; 202 import org.onosproject.net.resource.ContinuousResourceId;
200 import org.onosproject.net.resource.DiscreteResource; 203 import org.onosproject.net.resource.DiscreteResource;
...@@ -504,6 +507,10 @@ public final class KryoNamespaces { ...@@ -504,6 +507,10 @@ public final class KryoNamespaces {
504 .register(new AnnotationsSerializer(), DefaultAnnotations.class) 507 .register(new AnnotationsSerializer(), DefaultAnnotations.class)
505 .register(new ExtensionInstructionSerializer(), Instructions.ExtensionInstructionWrapper.class) 508 .register(new ExtensionInstructionSerializer(), Instructions.ExtensionInstructionWrapper.class)
506 .register(new ExtensionCriterionSerializer(), ExtensionCriterion.class) 509 .register(new ExtensionCriterionSerializer(), ExtensionCriterion.class)
510 + .register(Region.class)
511 + .register(Region.Type.class)
512 + .register(RegionId.class)
513 + .register(DefaultRegion.class)
507 .register(ExtensionSelectorType.class) 514 .register(ExtensionSelectorType.class)
508 .register(ExtensionTreatmentType.class) 515 .register(ExtensionTreatmentType.class)
509 .register(TransactionId.class) 516 .register(TransactionId.class)
......
1 #!/bin/bash 1 #!/bin/bash
2 +# Test topology
2 3
3 host=${1:-127.0.0.1} 4 host=${1:-127.0.0.1}
4 5
...@@ -6,8 +7,6 @@ onos ${host} null-simulation stop custom ...@@ -6,8 +7,6 @@ onos ${host} null-simulation stop custom
6 onos ${host} wipe-out please 7 onos ${host} wipe-out please
7 onos ${host} null-simulation start custom 8 onos ${host} null-simulation start custom
8 9
9 -sleep 1
10 -
11 onos ${host} <<-EOF 10 onos ${host} <<-EOF
12 11
13 null-create-device switch s1 10 0 0 12 null-create-device switch s1 10 0 0
...@@ -35,8 +34,6 @@ null-create-link direct s8 s7 ...@@ -35,8 +34,6 @@ null-create-link direct s8 s7
35 34
36 EOF 35 EOF
37 36
38 -
39 -
40 onos ${host} <<-EOF 37 onos ${host} <<-EOF
41 38
42 region-add r1 Region1 METRO ${host} 39 region-add r1 Region1 METRO ${host}
...@@ -58,4 +55,10 @@ region-add-devices r3 \ ...@@ -58,4 +55,10 @@ region-add-devices r3 \
58 of:0000000000000009 55 of:0000000000000009
59 56
60 regions 57 regions
58 +
59 +layout-add l1 r1
60 +layout-add l2 r2
61 +layout-add l3 r3 l2
62 +
63 +layouts
61 EOF 64 EOF
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -40,6 +40,7 @@ import java.util.Set; ...@@ -40,6 +40,7 @@ import java.util.Set;
40 import java.util.stream.Collectors; 40 import java.util.stream.Collectors;
41 41
42 import static com.google.common.base.Preconditions.checkNotNull; 42 import static com.google.common.base.Preconditions.checkNotNull;
43 +import static org.onosproject.ui.model.topo.UiTopoLayoutId.DEFAULT_ID;
43 44
44 /** 45 /**
45 * Manages the user interface topology layouts. 46 * Manages the user interface topology layouts.
...@@ -54,8 +55,6 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { ...@@ -54,8 +55,6 @@ public class UiTopoLayoutManager implements UiTopoLayoutService {
54 private static final String ID_NULL = "Layout ID cannot be null"; 55 private static final String ID_NULL = "Layout ID cannot be null";
55 private static final String LAYOUT_NULL = "Layout cannot be null"; 56 private static final String LAYOUT_NULL = "Layout cannot be null";
56 57
57 - private static final UiTopoLayoutId DEFAULT_ID = UiTopoLayoutId.layoutId("_default_");
58 -
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected StorageService storageService; 59 protected StorageService storageService;
61 60
......