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
251 additions
and
135 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 | - payload.set("subregions", jsonSubRegions(subRegions)); | 184 | + if (subRegions != null) { |
| 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); |
| 273 | + } else { | ||
| 274 | + updateDevice(uiDevice); | ||
| 251 | } | 275 | } |
| 252 | - updateDevice(uiDevice); | ||
| 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