Committed by
Gerrit Code Review
ONOS-4326: Working on topology topo2start processing.
- Added getPeers() to UiTopoLayoutService. - Fixed wipe-out command to leave the default layout alone. - Fixed handling of null-region (associated with default layout). - Added refresh() method to model cache. - Fixed regions-topo-2 device IDs Change-Id: Iee49b47ff6702bed9751be7b63392577422d4763
Showing
15 changed files
with
250 additions
and
134 deletions
... | @@ -115,7 +115,12 @@ public class WipeOutCommand extends ClustersListCommand { | ... | @@ -115,7 +115,12 @@ public class WipeOutCommand extends ClustersListCommand { |
115 | private void wipeOutLayouts() { | 115 | private void wipeOutLayouts() { |
116 | print("Wiping UI layouts"); | 116 | print("Wiping UI layouts"); |
117 | UiTopoLayoutService service = get(UiTopoLayoutService.class); | 117 | UiTopoLayoutService service = get(UiTopoLayoutService.class); |
118 | - service.getLayouts().forEach(service::removeLayout); | 118 | + // wipe out all layouts except the default, which should always be there |
119 | + service.getLayouts().forEach(l -> { | ||
120 | + if (!l.id().isDefault()) { | ||
121 | + service.removeLayout(l); | ||
122 | + } | ||
123 | + }); | ||
119 | } | 124 | } |
120 | 125 | ||
121 | private void wipeOutRegions() { | 126 | private void wipeOutRegions() { | ... | ... |
... | @@ -57,6 +57,15 @@ public interface UiTopoLayoutService { | ... | @@ -57,6 +57,15 @@ public interface UiTopoLayoutService { |
57 | UiTopoLayout getLayout(UiTopoLayoutId layoutId); | 57 | UiTopoLayout getLayout(UiTopoLayoutId layoutId); |
58 | 58 | ||
59 | /** | 59 | /** |
60 | + * Returns the set of peer layouts of the specified layout. That is, | ||
61 | + * those layouts that share the same parent. | ||
62 | + * | ||
63 | + * @param layoutId layout identifier | ||
64 | + * @return set of peer layouts; empty set if layout has no peers | ||
65 | + */ | ||
66 | + Set<UiTopoLayout> getPeers(UiTopoLayoutId layoutId); | ||
67 | + | ||
68 | + /** | ||
60 | * Returns the set of the child layouts of the specified layout. | 69 | * Returns the set of the child layouts of the specified layout. |
61 | * | 70 | * |
62 | * @param layoutId layout identifier | 71 | * @param layoutId layout identifier | ... | ... |
... | @@ -29,12 +29,27 @@ import java.util.List; | ... | @@ -29,12 +29,27 @@ import java.util.List; |
29 | import java.util.Set; | 29 | import java.util.Set; |
30 | 30 | ||
31 | import static com.google.common.base.MoreObjects.toStringHelper; | 31 | import static com.google.common.base.MoreObjects.toStringHelper; |
32 | +import static org.onosproject.net.region.RegionId.regionId; | ||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * Represents a region. | 35 | * Represents a region. |
35 | */ | 36 | */ |
36 | public class UiRegion extends UiNode { | 37 | public class UiRegion extends UiNode { |
37 | 38 | ||
39 | + private static final String NULL_NAME = "<null-region>"; | ||
40 | + | ||
41 | + /** | ||
42 | + * The identifier for the null-region. That is, a container for devices, | ||
43 | + * hosts, and links for those that belong to no region. | ||
44 | + */ | ||
45 | + public static final RegionId NULL_ID = regionId(NULL_NAME); | ||
46 | + | ||
47 | + private static final String[] DEFAULT_LAYER_TAGS = { | ||
48 | + UiNode.LAYER_OPTICAL, | ||
49 | + UiNode.LAYER_PACKET, | ||
50 | + UiNode.LAYER_DEFAULT | ||
51 | + }; | ||
52 | + | ||
38 | // loose bindings to things in this region | 53 | // loose bindings to things in this region |
39 | private final Set<DeviceId> deviceIds = new HashSet<>(); | 54 | private final Set<DeviceId> deviceIds = new HashSet<>(); |
40 | private final Set<HostId> hostIds = new HashSet<>(); | 55 | private final Set<HostId> hostIds = new HashSet<>(); |
... | @@ -53,10 +68,12 @@ public class UiRegion extends UiNode { | ... | @@ -53,10 +68,12 @@ public class UiRegion extends UiNode { |
53 | * @param region backing region | 68 | * @param region backing region |
54 | */ | 69 | */ |
55 | public UiRegion(UiTopology topology, Region region) { | 70 | public UiRegion(UiTopology topology, Region region) { |
71 | + // Implementation Note: if region is null, this UiRegion is being used | ||
72 | + // as a container for devices, hosts, links that belong to no region. | ||
56 | this.topology = topology; | 73 | this.topology = topology; |
57 | this.region = region; | 74 | this.region = region; |
58 | - // unless told otherwise, we'll use a single, default layer | 75 | + |
59 | - layerOrder.add(UiNode.LAYER_DEFAULT); | 76 | + setLayerOrder(DEFAULT_LAYER_TAGS); |
60 | } | 77 | } |
61 | 78 | ||
62 | @Override | 79 | @Override |
... | @@ -83,7 +100,7 @@ public class UiRegion extends UiNode { | ... | @@ -83,7 +100,7 @@ public class UiRegion extends UiNode { |
83 | * @return region ID | 100 | * @return region ID |
84 | */ | 101 | */ |
85 | public RegionId id() { | 102 | public RegionId id() { |
86 | - return region.id(); | 103 | + return region == null ? NULL_ID : region.id(); |
87 | } | 104 | } |
88 | 105 | ||
89 | @Override | 106 | @Override |
... | @@ -93,11 +110,12 @@ public class UiRegion extends UiNode { | ... | @@ -93,11 +110,12 @@ public class UiRegion extends UiNode { |
93 | 110 | ||
94 | @Override | 111 | @Override |
95 | public String name() { | 112 | public String name() { |
96 | - return region.name(); | 113 | + return region == null ? NULL_NAME : region.name(); |
97 | } | 114 | } |
98 | 115 | ||
99 | /** | 116 | /** |
100 | - * Returns the region instance backing this UI region. | 117 | + * Returns the region instance backing this UI region. If this instance |
118 | + * represents the "null-region", the value returned will be null. | ||
101 | * | 119 | * |
102 | * @return the backing region instance | 120 | * @return the backing region instance |
103 | */ | 121 | */ |
... | @@ -132,7 +150,17 @@ public class UiRegion extends UiNode { | ... | @@ -132,7 +150,17 @@ public class UiRegion extends UiNode { |
132 | * @return region type | 150 | * @return region type |
133 | */ | 151 | */ |
134 | public Region.Type type() { | 152 | public Region.Type type() { |
135 | - return region.type(); | 153 | + return region == null ? null : region.type(); |
154 | + } | ||
155 | + | ||
156 | + | ||
157 | + /** | ||
158 | + * Returns the count of devices in this region. | ||
159 | + * | ||
160 | + * @return the device count | ||
161 | + */ | ||
162 | + public int deviceCount() { | ||
163 | + return deviceIds.size(); | ||
136 | } | 164 | } |
137 | 165 | ||
138 | /** | 166 | /** |
... | @@ -195,7 +223,7 @@ public class UiRegion extends UiNode { | ... | @@ -195,7 +223,7 @@ public class UiRegion extends UiNode { |
195 | * optical layer should be rendered "below" nodes in the packet layer, | 223 | * optical layer should be rendered "below" nodes in the packet layer, |
196 | * this method should return: | 224 | * this method should return: |
197 | * <pre> | 225 | * <pre> |
198 | - * [UiNode.LAYER_OPTICAL, UiNode.LAYER_PACKET] | 226 | + * [UiNode.LAYER_OPTICAL, UiNode.LAYER_PACKET, UiNode.LAYER_DEFAULT] |
199 | * </pre> | 227 | * </pre> |
200 | * | 228 | * |
201 | * @return layer ordering | 229 | * @return layer ordering | ... | ... |
... | @@ -23,10 +23,13 @@ import org.onlab.util.Identifier; | ... | @@ -23,10 +23,13 @@ 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 | + private static final String DEFAULT_STR = "_default_"; | ||
27 | + | ||
26 | /** | 28 | /** |
27 | * Default topology layout identifier. | 29 | * Default topology layout identifier. |
28 | */ | 30 | */ |
29 | - public static final UiTopoLayoutId DEFAULT_ID = UiTopoLayoutId.layoutId("_default_"); | 31 | + public static final UiTopoLayoutId DEFAULT_ID = |
32 | + UiTopoLayoutId.layoutId(DEFAULT_STR); | ||
30 | 33 | ||
31 | // For serialization | 34 | // For serialization |
32 | private UiTopoLayoutId() { | 35 | private UiTopoLayoutId() { |
... | @@ -45,4 +48,13 @@ public final class UiTopoLayoutId extends Identifier<String> { | ... | @@ -45,4 +48,13 @@ public final class UiTopoLayoutId extends Identifier<String> { |
45 | public static UiTopoLayoutId layoutId(String value) { | 48 | public static UiTopoLayoutId layoutId(String value) { |
46 | return new UiTopoLayoutId(value); | 49 | return new UiTopoLayoutId(value); |
47 | } | 50 | } |
51 | + | ||
52 | + /** | ||
53 | + * Returns true if this is the identifier for the default layout. | ||
54 | + * | ||
55 | + * @return true if this is the default layout identifier | ||
56 | + */ | ||
57 | + public boolean isDefault() { | ||
58 | + return DEFAULT_STR.equals(identifier); | ||
59 | + } | ||
48 | } | 60 | } | ... | ... |
... | @@ -61,6 +61,9 @@ public class UiTopology extends UiElement { | ... | @@ -61,6 +61,9 @@ public class UiTopology extends UiElement { |
61 | private final Map<HostId, UiHost> hostLookup = new HashMap<>(); | 61 | private final Map<HostId, UiHost> hostLookup = new HashMap<>(); |
62 | private final Map<UiLinkId, UiLink> linkLookup = new HashMap<>(); | 62 | private final Map<UiLinkId, UiLink> linkLookup = new HashMap<>(); |
63 | 63 | ||
64 | + // a container for devices, hosts, etc. belonging to no region | ||
65 | + private final UiRegion nullRegion = new UiRegion(this, null); | ||
66 | + | ||
64 | 67 | ||
65 | @Override | 68 | @Override |
66 | public String toString() { | 69 | public String toString() { |
... | @@ -89,6 +92,8 @@ public class UiTopology extends UiElement { | ... | @@ -89,6 +92,8 @@ public class UiTopology extends UiElement { |
89 | deviceLookup.clear(); | 92 | deviceLookup.clear(); |
90 | hostLookup.clear(); | 93 | hostLookup.clear(); |
91 | linkLookup.clear(); | 94 | linkLookup.clear(); |
95 | + | ||
96 | + nullRegion.destroy(); | ||
92 | } | 97 | } |
93 | 98 | ||
94 | 99 | ||
... | @@ -145,6 +150,16 @@ public class UiTopology extends UiElement { | ... | @@ -145,6 +150,16 @@ public class UiTopology extends UiElement { |
145 | } | 150 | } |
146 | 151 | ||
147 | /** | 152 | /** |
153 | + * Returns a reference to the null-region. That is, the container for | ||
154 | + * devices, hosts, and links that belong to no region. | ||
155 | + * | ||
156 | + * @return the null-region | ||
157 | + */ | ||
158 | + public UiRegion nullRegion() { | ||
159 | + return nullRegion; | ||
160 | + } | ||
161 | + | ||
162 | + /** | ||
148 | * Returns the region with the specified identifier, or null if | 163 | * Returns the region with the specified identifier, or null if |
149 | * no such region exists. | 164 | * no such region exists. |
150 | * | 165 | * |
... | @@ -186,6 +201,15 @@ public class UiTopology extends UiElement { | ... | @@ -186,6 +201,15 @@ public class UiTopology extends UiElement { |
186 | } | 201 | } |
187 | 202 | ||
188 | /** | 203 | /** |
204 | + * Returns all devices in the model. | ||
205 | + * | ||
206 | + * @return all devices | ||
207 | + */ | ||
208 | + public Set<UiDevice> allDevices() { | ||
209 | + return new HashSet<>(deviceLookup.values()); | ||
210 | + } | ||
211 | + | ||
212 | + /** | ||
189 | * Returns the device with the specified identifier, or null if | 213 | * Returns the device with the specified identifier, or null if |
190 | * no such device exists. | 214 | * no such device exists. |
191 | * | 215 | * | ... | ... |
... | @@ -41,18 +41,18 @@ region-add r2 Region2 METRO ${host} | ... | @@ -41,18 +41,18 @@ region-add r2 Region2 METRO ${host} |
41 | region-add r3 Region3 CAMPUS ${host} | 41 | region-add r3 Region3 CAMPUS ${host} |
42 | 42 | ||
43 | region-add-devices r1 \ | 43 | region-add-devices r1 \ |
44 | - of:0000000000000002 \ | 44 | + null:0000000000000002 \ |
45 | - of:0000000000000003 \ | 45 | + null:0000000000000003 \ |
46 | - of:0000000000000004 | 46 | + null:0000000000000004 |
47 | 47 | ||
48 | region-add-devices r2 \ | 48 | region-add-devices r2 \ |
49 | - of:0000000000000005 \ | 49 | + null:0000000000000005 \ |
50 | - of:0000000000000006 | 50 | + null:0000000000000006 |
51 | 51 | ||
52 | region-add-devices r3 \ | 52 | region-add-devices r3 \ |
53 | - of:0000000000000007 \ | 53 | + null:0000000000000007 \ |
54 | - of:0000000000000008 \ | 54 | + null:0000000000000008 \ |
55 | - of:0000000000000009 | 55 | + null:0000000000000009 |
56 | 56 | ||
57 | regions | 57 | regions |
58 | 58 | ... | ... |
... | @@ -181,7 +181,9 @@ class Topo2Jsonifier { | ... | @@ -181,7 +181,9 @@ class Topo2Jsonifier { |
181 | return payload; | 181 | return payload; |
182 | } | 182 | } |
183 | payload.put("id", region.idAsString()); | 183 | payload.put("id", region.idAsString()); |
184 | + if (subRegions != null) { | ||
184 | payload.set("subregions", jsonSubRegions(subRegions)); | 185 | payload.set("subregions", jsonSubRegions(subRegions)); |
186 | + } | ||
185 | 187 | ||
186 | List<String> layerTags = region.layerOrder(); | 188 | List<String> layerTags = region.layerOrder(); |
187 | List<Set<UiNode>> splitDevices = splitByLayer(layerTags, region.devices()); | 189 | List<Set<UiNode>> splitDevices = splitByLayer(layerTags, region.devices()); |
... | @@ -226,31 +228,6 @@ class Topo2Jsonifier { | ... | @@ -226,31 +228,6 @@ class Topo2Jsonifier { |
226 | return result; | 228 | return result; |
227 | } | 229 | } |
228 | 230 | ||
229 | - /** | ||
230 | - * Returns a JSON payload that encapsulates the devices, hosts, links that | ||
231 | - * do not belong to any region. | ||
232 | - * | ||
233 | - * @param oDevices orphan devices | ||
234 | - * @param oHosts orphan hosts | ||
235 | - * @param oLinks orphan links | ||
236 | - * @param layerTags layer tags | ||
237 | - * @return a JSON representation of the data | ||
238 | - */ | ||
239 | - ObjectNode orphans(Set<UiDevice> oDevices, Set<UiHost> oHosts, | ||
240 | - Set<UiLink> oLinks, List<String> layerTags) { | ||
241 | - | ||
242 | - ObjectNode payload = objectNode(); | ||
243 | - | ||
244 | - List<Set<UiNode>> splitDevices = splitByLayer(layerTags, oDevices); | ||
245 | - List<Set<UiNode>> splitHosts = splitByLayer(layerTags, oHosts); | ||
246 | - | ||
247 | - payload.set("devices", jsonGrouped(splitDevices)); | ||
248 | - payload.set("hosts", jsonGrouped(splitHosts)); | ||
249 | - payload.set("links", jsonLinks(oLinks)); | ||
250 | - payload.set("layerOrder", jsonStrings(layerTags)); | ||
251 | - | ||
252 | - return payload; | ||
253 | - } | ||
254 | 231 | ||
255 | private ObjectNode json(UiNode node) { | 232 | private ObjectNode json(UiNode node) { |
256 | if (node instanceof UiRegion) { | 233 | if (node instanceof UiRegion) { |
... | @@ -270,7 +247,7 @@ class Topo2Jsonifier { | ... | @@ -270,7 +247,7 @@ class Topo2Jsonifier { |
270 | .put("id", device.idAsString()) | 247 | .put("id", device.idAsString()) |
271 | .put("type", device.type()) | 248 | .put("type", device.type()) |
272 | .put("online", device.isOnline()) | 249 | .put("online", device.isOnline()) |
273 | - .put("master", device.master().toString()) | 250 | + .put("master", nullIsEmpty(device.master())) |
274 | .put("layer", device.layer()); | 251 | .put("layer", device.layer()); |
275 | 252 | ||
276 | // TODO: complete device details | 253 | // TODO: complete device details |
... | @@ -303,7 +280,8 @@ class Topo2Jsonifier { | ... | @@ -303,7 +280,8 @@ class Topo2Jsonifier { |
303 | 280 | ||
304 | private ObjectNode jsonClosedRegion(UiRegion region) { | 281 | private ObjectNode jsonClosedRegion(UiRegion region) { |
305 | return objectNode() | 282 | return objectNode() |
306 | - .put("id", region.idAsString()); | 283 | + .put("id", region.idAsString()) |
284 | + .put("nDevs", region.deviceCount()); | ||
307 | // TODO: complete closed-region details | 285 | // TODO: complete closed-region details |
308 | } | 286 | } |
309 | 287 | ... | ... |
... | @@ -17,7 +17,6 @@ | ... | @@ -17,7 +17,6 @@ |
17 | package org.onosproject.ui.impl.topo; | 17 | package org.onosproject.ui.impl.topo; |
18 | 18 | ||
19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
20 | -import com.google.common.collect.ImmutableList; | ||
21 | import com.google.common.collect.ImmutableSet; | 20 | import com.google.common.collect.ImmutableSet; |
22 | import org.onlab.osgi.ServiceDirectory; | 21 | import org.onlab.osgi.ServiceDirectory; |
23 | import org.onosproject.ui.RequestHandler; | 22 | import org.onosproject.ui.RequestHandler; |
... | @@ -25,9 +24,6 @@ import org.onosproject.ui.UiConnection; | ... | @@ -25,9 +24,6 @@ import org.onosproject.ui.UiConnection; |
25 | import org.onosproject.ui.UiMessageHandler; | 24 | import org.onosproject.ui.UiMessageHandler; |
26 | import org.onosproject.ui.impl.UiWebSocket; | 25 | import org.onosproject.ui.impl.UiWebSocket; |
27 | import org.onosproject.ui.model.topo.UiClusterMember; | 26 | import org.onosproject.ui.model.topo.UiClusterMember; |
28 | -import org.onosproject.ui.model.topo.UiDevice; | ||
29 | -import org.onosproject.ui.model.topo.UiHost; | ||
30 | -import org.onosproject.ui.model.topo.UiLink; | ||
31 | import org.onosproject.ui.model.topo.UiRegion; | 27 | import org.onosproject.ui.model.topo.UiRegion; |
32 | import org.onosproject.ui.model.topo.UiTopoLayout; | 28 | import org.onosproject.ui.model.topo.UiTopoLayout; |
33 | import org.slf4j.Logger; | 29 | import org.slf4j.Logger; |
... | @@ -37,8 +33,6 @@ import java.util.Collection; | ... | @@ -37,8 +33,6 @@ import java.util.Collection; |
37 | import java.util.List; | 33 | import java.util.List; |
38 | import java.util.Set; | 34 | import java.util.Set; |
39 | 35 | ||
40 | -import static org.onosproject.ui.model.topo.UiNode.LAYER_DEFAULT; | ||
41 | - | ||
42 | /* | 36 | /* |
43 | NOTES: | 37 | NOTES: |
44 | 38 | ||
... | @@ -69,7 +63,6 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -69,7 +63,6 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
69 | private static final String CURRENT_LAYOUT = "topo2CurrentLayout"; | 63 | private static final String CURRENT_LAYOUT = "topo2CurrentLayout"; |
70 | private static final String CURRENT_REGION = "topo2CurrentRegion"; | 64 | private static final String CURRENT_REGION = "topo2CurrentRegion"; |
71 | private static final String PEER_REGIONS = "topo2PeerRegions"; | 65 | private static final String PEER_REGIONS = "topo2PeerRegions"; |
72 | - private static final String ORPHANS = "topo2Orphans"; | ||
73 | private static final String TOPO_START_DONE = "topo2StartDone"; | 66 | private static final String TOPO_START_DONE = "topo2StartDone"; |
74 | 67 | ||
75 | 68 | ||
... | @@ -109,6 +102,12 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -109,6 +102,12 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
109 | 102 | ||
110 | log.debug("topo2Start: {}", payload); | 103 | log.debug("topo2Start: {}", payload); |
111 | 104 | ||
105 | + // this may be a little heavyweight, but it might be safer to do | ||
106 | + // this than make assumptions about the order in which devices | ||
107 | + // and regions are added... and thus internal linkages set up | ||
108 | + // correctly | ||
109 | + topoSession.refreshModel(); | ||
110 | + | ||
112 | // this is the list of ONOS cluster members | 111 | // this is the list of ONOS cluster members |
113 | List<UiClusterMember> instances = topoSession.getAllInstances(); | 112 | List<UiClusterMember> instances = topoSession.getAllInstances(); |
114 | sendMessage(ALL_INSTANCES, t2json.instances(instances)); | 113 | sendMessage(ALL_INSTANCES, t2json.instances(instances)); |
... | @@ -131,14 +130,7 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -131,14 +130,7 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
131 | peersPayload.set("peers", t2json.closedRegions(peers)); | 130 | peersPayload.set("peers", t2json.closedRegions(peers)); |
132 | sendMessage(PEER_REGIONS, peersPayload); | 131 | sendMessage(PEER_REGIONS, peersPayload); |
133 | 132 | ||
134 | - // return devices, hosts, links belonging to no region | 133 | + // finally, tell the UI that we are done : TODO review / delete?? |
135 | - Set<UiDevice> oDevices = topoSession.getOrphanDevices(); | ||
136 | - Set<UiHost> oHosts = topoSession.getOrphanHosts(); | ||
137 | - Set<UiLink> oLinks = topoSession.getOrphanLinks(); | ||
138 | - List<String> oLayers = getOrphanLayerOrder(); | ||
139 | - sendMessage(ORPHANS, t2json.orphans(oDevices, oHosts, oLinks, oLayers)); | ||
140 | - | ||
141 | - // finally, tell the UI that we are done | ||
142 | sendMessage(TOPO_START_DONE, null); | 134 | sendMessage(TOPO_START_DONE, null); |
143 | 135 | ||
144 | 136 | ||
... | @@ -154,14 +146,6 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -154,14 +146,6 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
154 | 146 | ||
155 | } | 147 | } |
156 | 148 | ||
157 | - // TODO: we need to decide on how this should really get populated. | ||
158 | - // For example, to be "backward compatible", this should really be | ||
159 | - // [ LAYER_OPTICAL, LAYER_PACKET, LAYER_DEFAULT ] | ||
160 | - private List<String> getOrphanLayerOrder() { | ||
161 | - // NOTE that LAYER_DEFAULT must always be last in the array | ||
162 | - return ImmutableList.of(LAYER_DEFAULT); | ||
163 | - } | ||
164 | - | ||
165 | private final class Topo2Stop extends RequestHandler { | 149 | private final class Topo2Stop extends RequestHandler { |
166 | private Topo2Stop() { | 150 | private Topo2Stop() { |
167 | super(TOPO2_STOP); | 151 | super(TOPO2_STOP); | ... | ... |
... | @@ -34,6 +34,7 @@ import org.onosproject.ui.model.topo.UiTopoLayoutId; | ... | @@ -34,6 +34,7 @@ import org.onosproject.ui.model.topo.UiTopoLayoutId; |
34 | import org.slf4j.Logger; | 34 | import org.slf4j.Logger; |
35 | import org.slf4j.LoggerFactory; | 35 | import org.slf4j.LoggerFactory; |
36 | 36 | ||
37 | +import java.util.Collections; | ||
37 | import java.util.Map; | 38 | import java.util.Map; |
38 | import java.util.Objects; | 39 | import java.util.Objects; |
39 | import java.util.Set; | 40 | import java.util.Set; |
... | @@ -110,6 +111,21 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { | ... | @@ -110,6 +111,21 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { |
110 | } | 111 | } |
111 | 112 | ||
112 | @Override | 113 | @Override |
114 | + public Set<UiTopoLayout> getPeers(UiTopoLayoutId layoutId) { | ||
115 | + checkNotNull(layoutId, ID_NULL); | ||
116 | + UiTopoLayout layout = layoutMap.get(layoutId); | ||
117 | + if (layout == null) { | ||
118 | + return Collections.emptySet(); | ||
119 | + } | ||
120 | + | ||
121 | + UiTopoLayoutId parentId = layout.parent(); | ||
122 | + return layoutMap.values().stream() | ||
123 | + .filter(l -> !Objects.equals(l.id(), layoutId) && | ||
124 | + Objects.equals(l.parent(), parentId)) | ||
125 | + .collect(Collectors.toSet()); | ||
126 | + } | ||
127 | + | ||
128 | + @Override | ||
113 | public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) { | 129 | public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) { |
114 | checkNotNull(layoutId, ID_NULL); | 130 | checkNotNull(layoutId, ID_NULL); |
115 | return layoutMap.values().stream() | 131 | return layoutMap.values().stream() | ... | ... |
... | @@ -16,21 +16,19 @@ | ... | @@ -16,21 +16,19 @@ |
16 | 16 | ||
17 | package org.onosproject.ui.impl.topo; | 17 | package org.onosproject.ui.impl.topo; |
18 | 18 | ||
19 | +import org.onosproject.net.region.RegionId; | ||
19 | import org.onosproject.ui.UiTopoLayoutService; | 20 | import org.onosproject.ui.UiTopoLayoutService; |
20 | import org.onosproject.ui.impl.UiWebSocket; | 21 | import org.onosproject.ui.impl.UiWebSocket; |
21 | import org.onosproject.ui.impl.topo.model.UiModelEvent; | 22 | import org.onosproject.ui.impl.topo.model.UiModelEvent; |
22 | import org.onosproject.ui.impl.topo.model.UiModelListener; | 23 | import org.onosproject.ui.impl.topo.model.UiModelListener; |
23 | import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel; | 24 | import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel; |
24 | import org.onosproject.ui.model.topo.UiClusterMember; | 25 | import org.onosproject.ui.model.topo.UiClusterMember; |
25 | -import org.onosproject.ui.model.topo.UiDevice; | ||
26 | -import org.onosproject.ui.model.topo.UiHost; | ||
27 | -import org.onosproject.ui.model.topo.UiLink; | ||
28 | import org.onosproject.ui.model.topo.UiRegion; | 26 | import org.onosproject.ui.model.topo.UiRegion; |
29 | import org.onosproject.ui.model.topo.UiTopoLayout; | 27 | import org.onosproject.ui.model.topo.UiTopoLayout; |
30 | import org.slf4j.Logger; | 28 | import org.slf4j.Logger; |
31 | import org.slf4j.LoggerFactory; | 29 | import org.slf4j.LoggerFactory; |
32 | 30 | ||
33 | -import java.util.Collections; | 31 | +import java.util.HashSet; |
34 | import java.util.List; | 32 | import java.util.List; |
35 | import java.util.Set; | 33 | import java.util.Set; |
36 | 34 | ||
... | @@ -167,23 +165,23 @@ public class UiTopoSession implements UiModelListener { | ... | @@ -167,23 +165,23 @@ public class UiTopoSession implements UiModelListener { |
167 | * @return region that the layout is based upon | 165 | * @return region that the layout is based upon |
168 | */ | 166 | */ |
169 | public UiRegion getRegion(UiTopoLayout layout) { | 167 | public UiRegion getRegion(UiTopoLayout layout) { |
170 | - return sharedModel.getRegion(layout.regionId()); | 168 | + RegionId rid = layout.regionId(); |
169 | + return rid == null ? sharedModel.getNullRegion() : sharedModel.getRegion(rid); | ||
171 | } | 170 | } |
172 | 171 | ||
173 | /** | 172 | /** |
174 | * Returns the regions that are "peers" to this region. That is, based on | 173 | * Returns the regions that are "peers" to this region. That is, based on |
175 | * the layout the user is viewing, all the regions that are associated with | 174 | * the layout the user is viewing, all the regions that are associated with |
176 | - * layouts that are children of the parent layout to this layout. | 175 | + * layouts that share the same parent layout as this layout. |
177 | * | 176 | * |
178 | * @param layout the layout being viewed | 177 | * @param layout the layout being viewed |
179 | * @return all regions that are "siblings" to this layout's region | 178 | * @return all regions that are "siblings" to this layout's region |
180 | */ | 179 | */ |
181 | public Set<UiRegion> getPeerRegions(UiTopoLayout layout) { | 180 | public Set<UiRegion> getPeerRegions(UiTopoLayout layout) { |
182 | - UiRegion currentRegion = getRegion(layout); | 181 | + Set<UiTopoLayout> peerLayouts = layoutService.getPeers(layout.id()); |
183 | - | 182 | + Set<UiRegion> peers = new HashSet<>(); |
184 | - // TODO: consult topo layout service to get hierarchy info... | 183 | + peerLayouts.forEach(l -> peers.add(sharedModel.getRegion(l.regionId()))); |
185 | - // TODO: then consult shared model to get regions | 184 | + return peers; |
186 | - return Collections.emptySet(); | ||
187 | } | 185 | } |
188 | 186 | ||
189 | /** | 187 | /** |
... | @@ -193,42 +191,16 @@ public class UiTopoSession implements UiModelListener { | ... | @@ -193,42 +191,16 @@ public class UiTopoSession implements UiModelListener { |
193 | * @return all regions that are "contained within" this layout's region | 191 | * @return all regions that are "contained within" this layout's region |
194 | */ | 192 | */ |
195 | public Set<UiRegion> getSubRegions(UiTopoLayout layout) { | 193 | public Set<UiRegion> getSubRegions(UiTopoLayout layout) { |
196 | - UiRegion currentRegion = getRegion(layout); | 194 | + Set<UiTopoLayout> kidLayouts = layoutService.getChildren(layout.id()); |
197 | - | 195 | + Set<UiRegion> kids = new HashSet<>(); |
198 | - // TODO: consult topo layout service to get child layouts... | 196 | + kidLayouts.forEach(l -> kids.add(sharedModel.getRegion(l.regionId()))); |
199 | - // TODO: then consult shared model to get regions | 197 | + return kids; |
200 | - return Collections.emptySet(); | ||
201 | } | 198 | } |
202 | 199 | ||
203 | - | ||
204 | /** | 200 | /** |
205 | - * Returns all devices that are not in a region. | 201 | + * Refreshes the model's internal state. |
206 | - * | ||
207 | - * @return all devices not in a region | ||
208 | */ | 202 | */ |
209 | - public Set<UiDevice> getOrphanDevices() { | 203 | + public void refreshModel() { |
210 | - // TODO: get devices with no region | 204 | + sharedModel.refresh(); |
211 | - return Collections.emptySet(); | ||
212 | } | 205 | } |
213 | - | ||
214 | - /** | ||
215 | - * Returns all hosts that are not in a region. | ||
216 | - * | ||
217 | - * @return all hosts not in a region | ||
218 | - */ | ||
219 | - public Set<UiHost> getOrphanHosts() { | ||
220 | - // TODO: get hosts with no region | ||
221 | - return Collections.emptySet(); | ||
222 | - } | ||
223 | - | ||
224 | - /** | ||
225 | - * Returns all links that are not in a region. | ||
226 | - * | ||
227 | - * @return all links not in a region | ||
228 | - */ | ||
229 | - public Set<UiLink> getOrphanLinks() { | ||
230 | - // TODO: get links with no region | ||
231 | - return Collections.emptySet(); | ||
232 | - } | ||
233 | - | ||
234 | } | 206 | } | ... | ... |
... | @@ -41,6 +41,7 @@ import org.onosproject.ui.model.topo.UiTopology; | ... | @@ -41,6 +41,7 @@ import org.onosproject.ui.model.topo.UiTopology; |
41 | import org.slf4j.Logger; | 41 | import org.slf4j.Logger; |
42 | import org.slf4j.LoggerFactory; | 42 | import org.slf4j.LoggerFactory; |
43 | 43 | ||
44 | +import java.util.HashSet; | ||
44 | import java.util.List; | 45 | import java.util.List; |
45 | import java.util.Set; | 46 | import java.util.Set; |
46 | 47 | ||
... | @@ -169,18 +170,38 @@ class ModelCache { | ... | @@ -169,18 +170,38 @@ class ModelCache { |
169 | // TODO: post event | 170 | // TODO: post event |
170 | } | 171 | } |
171 | 172 | ||
173 | + // === THE NULL REGION | ||
174 | + | ||
175 | + UiRegion nullRegion() { | ||
176 | + return uiTopology.nullRegion(); | ||
177 | + } | ||
172 | 178 | ||
173 | // === REGIONS | 179 | // === REGIONS |
174 | 180 | ||
175 | private UiRegion addNewRegion(Region r) { | 181 | private UiRegion addNewRegion(Region r) { |
176 | UiRegion region = new UiRegion(uiTopology, r); | 182 | UiRegion region = new UiRegion(uiTopology, r); |
177 | uiTopology.add(region); | 183 | uiTopology.add(region); |
184 | + log.debug("Region {} added to topology", region); | ||
178 | return region; | 185 | return region; |
179 | } | 186 | } |
180 | 187 | ||
181 | private void updateRegion(UiRegion region) { | 188 | private void updateRegion(UiRegion region) { |
182 | - Set<DeviceId> devs = services.region().getRegionDevices(region.id()); | 189 | + RegionId rid = region.id(); |
183 | - region.reconcileDevices(devs); | 190 | + Set<DeviceId> deviceIds = services.region().getRegionDevices(rid); |
191 | + | ||
192 | + // Make sure device objects refer to their region | ||
193 | + deviceIds.forEach(d -> { | ||
194 | + UiDevice dev = uiTopology.findDevice(d); | ||
195 | + if (dev != null) { | ||
196 | + dev.setRegionId(rid); | ||
197 | + } else { | ||
198 | + // if we don't have the UiDevice in the topology, what can we do? | ||
199 | + log.warn("Region device {}, but we don't have UiDevice in topology", d); | ||
200 | + } | ||
201 | + }); | ||
202 | + | ||
203 | + // Make sure the region object refers to the devices | ||
204 | + region.reconcileDevices(deviceIds); | ||
184 | } | 205 | } |
185 | 206 | ||
186 | private void loadRegions() { | 207 | private void loadRegions() { |
... | @@ -224,21 +245,22 @@ class ModelCache { | ... | @@ -224,21 +245,22 @@ class ModelCache { |
224 | 245 | ||
225 | private UiDevice addNewDevice(Device d) { | 246 | private UiDevice addNewDevice(Device d) { |
226 | UiDevice device = new UiDevice(uiTopology, d); | 247 | UiDevice device = new UiDevice(uiTopology, d); |
248 | + updateDevice(device); | ||
227 | uiTopology.add(device); | 249 | uiTopology.add(device); |
250 | + log.debug("Device {} added to topology", device); | ||
228 | return device; | 251 | return device; |
229 | } | 252 | } |
230 | 253 | ||
254 | + // make sure the UiDevice is tagged with the region it belongs to | ||
231 | private void updateDevice(UiDevice device) { | 255 | private void updateDevice(UiDevice device) { |
232 | - Region regionForDevice = services.region().getRegionForDevice(device.id()); | 256 | + Region r = services.region().getRegionForDevice(device.id()); |
233 | - if (regionForDevice != null) { | 257 | + RegionId rid = r == null ? UiRegion.NULL_ID : r.id(); |
234 | - device.setRegionId(regionForDevice.id()); | 258 | + device.setRegionId(rid); |
235 | - } | ||
236 | } | 259 | } |
237 | 260 | ||
238 | private void loadDevices() { | 261 | private void loadDevices() { |
239 | for (Device d : services.device().getDevices()) { | 262 | for (Device d : services.device().getDevices()) { |
240 | - UiDevice device = addNewDevice(d); | 263 | + addNewDevice(d); |
241 | - updateDevice(device); | ||
242 | } | 264 | } |
243 | } | 265 | } |
244 | 266 | ||
... | @@ -248,8 +270,9 @@ class ModelCache { | ... | @@ -248,8 +270,9 @@ class ModelCache { |
248 | UiDevice uiDevice = uiTopology.findDevice(id); | 270 | UiDevice uiDevice = uiTopology.findDevice(id); |
249 | if (uiDevice == null) { | 271 | if (uiDevice == null) { |
250 | uiDevice = addNewDevice(device); | 272 | uiDevice = addNewDevice(device); |
251 | - } | 273 | + } else { |
252 | updateDevice(uiDevice); | 274 | updateDevice(uiDevice); |
275 | + } | ||
253 | 276 | ||
254 | postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice); | 277 | postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice); |
255 | } | 278 | } |
... | @@ -434,6 +457,43 @@ class ModelCache { | ... | @@ -434,6 +457,43 @@ class ModelCache { |
434 | } | 457 | } |
435 | 458 | ||
436 | 459 | ||
460 | + /** | ||
461 | + * Refreshes the internal state. | ||
462 | + */ | ||
463 | + public void refresh() { | ||
464 | + // fix up internal linkages if they aren't correct | ||
465 | + | ||
466 | + // at the moment, this is making sure devices are in the correct region | ||
467 | + Set<UiDevice> allDevices = uiTopology.allDevices(); | ||
468 | + | ||
469 | + services.region().getRegions().forEach(r -> { | ||
470 | + RegionId rid = r.id(); | ||
471 | + UiRegion region = uiTopology.findRegion(rid); | ||
472 | + if (region != null) { | ||
473 | + Set<DeviceId> deviceIds = services.region().getRegionDevices(rid); | ||
474 | + region.reconcileDevices(deviceIds); | ||
475 | + | ||
476 | + deviceIds.forEach(devId -> { | ||
477 | + UiDevice dev = uiTopology.findDevice(devId); | ||
478 | + if (dev != null) { | ||
479 | + dev.setRegionId(r.id()); | ||
480 | + allDevices.remove(dev); | ||
481 | + } else { | ||
482 | + log.warn("Region device ID {} but no UiDevice in topology", | ||
483 | + devId); | ||
484 | + } | ||
485 | + }); | ||
486 | + } else { | ||
487 | + log.warn("No UiRegion in topology for ID {}", rid); | ||
488 | + } | ||
489 | + }); | ||
490 | + | ||
491 | + // what is left over, must belong to the null-region | ||
492 | + Set<DeviceId> leftOver = new HashSet<>(allDevices.size()); | ||
493 | + allDevices.forEach(d -> leftOver.add(d.id())); | ||
494 | + uiTopology.nullRegion().reconcileDevices(leftOver); | ||
495 | + } | ||
496 | + | ||
437 | // === CACHE STATISTICS | 497 | // === CACHE STATISTICS |
438 | 498 | ||
439 | /** | 499 | /** | ... | ... |
... | @@ -217,6 +217,22 @@ public final class UiSharedTopologyModel | ... | @@ -217,6 +217,22 @@ public final class UiSharedTopologyModel |
217 | return cache.accessRegion(id); | 217 | return cache.accessRegion(id); |
218 | } | 218 | } |
219 | 219 | ||
220 | + /** | ||
221 | + * Returns the null region. | ||
222 | + * | ||
223 | + * @return the null region | ||
224 | + */ | ||
225 | + public UiRegion getNullRegion() { | ||
226 | + return cache.nullRegion(); | ||
227 | + } | ||
228 | + | ||
229 | + /** | ||
230 | + * Refreshes the cache's internal state. | ||
231 | + */ | ||
232 | + public void refresh() { | ||
233 | + cache.refresh(); | ||
234 | + } | ||
235 | + | ||
220 | // ===================================================================== | 236 | // ===================================================================== |
221 | 237 | ||
222 | 238 | ... | ... |
1 | { | 1 | { |
2 | "event": "topo2CurrentRegion", | 2 | "event": "topo2CurrentRegion", |
3 | "payload": { | 3 | "payload": { |
4 | - "note": "no-region" | 4 | + "id": "<null-region>", |
5 | + "subregions": [{ | ||
6 | + "id": "r2", | ||
7 | + "nDevs": 2 | ||
8 | + }, { | ||
9 | + "id": "r1", | ||
10 | + "nDevs": 3 | ||
11 | + }], | ||
12 | + "devices": [ | ||
13 | + [], | ||
14 | + [], | ||
15 | + [{ | ||
16 | + "id": "null:0000000000000001", | ||
17 | + "type": "switch", | ||
18 | + "online": false, | ||
19 | + "master": "", | ||
20 | + "layer": "def" | ||
21 | + }] | ||
22 | + ], | ||
23 | + "hosts": [ | ||
24 | + [], | ||
25 | + [], | ||
26 | + [] | ||
27 | + ], | ||
28 | + "links": [], | ||
29 | + "layerOrder": ["opt", "pkt", "def"] | ||
5 | } | 30 | } |
6 | } | 31 | } | ... | ... |
-
Please register or login to post a comment