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
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
index df6dba9..02df84c 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
@@ -181,7 +181,9 @@
return payload;
}
payload.put("id", region.idAsString());
- payload.set("subregions", jsonSubRegions(subRegions));
+ if (subRegions != null) {
+ payload.set("subregions", jsonSubRegions(subRegions));
+ }
List<String> layerTags = region.layerOrder();
List<Set<UiNode>> splitDevices = splitByLayer(layerTags, region.devices());
@@ -226,31 +228,6 @@
return result;
}
- /**
- * Returns a JSON payload that encapsulates the devices, hosts, links that
- * do not belong to any region.
- *
- * @param oDevices orphan devices
- * @param oHosts orphan hosts
- * @param oLinks orphan links
- * @param layerTags layer tags
- * @return a JSON representation of the data
- */
- ObjectNode orphans(Set<UiDevice> oDevices, Set<UiHost> oHosts,
- Set<UiLink> oLinks, List<String> layerTags) {
-
- ObjectNode payload = objectNode();
-
- List<Set<UiNode>> splitDevices = splitByLayer(layerTags, oDevices);
- List<Set<UiNode>> splitHosts = splitByLayer(layerTags, oHosts);
-
- payload.set("devices", jsonGrouped(splitDevices));
- payload.set("hosts", jsonGrouped(splitHosts));
- payload.set("links", jsonLinks(oLinks));
- payload.set("layerOrder", jsonStrings(layerTags));
-
- return payload;
- }
private ObjectNode json(UiNode node) {
if (node instanceof UiRegion) {
@@ -270,7 +247,7 @@
.put("id", device.idAsString())
.put("type", device.type())
.put("online", device.isOnline())
- .put("master", device.master().toString())
+ .put("master", nullIsEmpty(device.master()))
.put("layer", device.layer());
// TODO: complete device details
@@ -303,7 +280,8 @@
private ObjectNode jsonClosedRegion(UiRegion region) {
return objectNode()
- .put("id", region.idAsString());
+ .put("id", region.idAsString())
+ .put("nDevs", region.deviceCount());
// TODO: complete closed-region details
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
index 7f44244..5449d93 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
@@ -17,7 +17,6 @@
package org.onosproject.ui.impl.topo;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.ui.RequestHandler;
@@ -25,9 +24,6 @@
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.impl.UiWebSocket;
import org.onosproject.ui.model.topo.UiClusterMember;
-import org.onosproject.ui.model.topo.UiDevice;
-import org.onosproject.ui.model.topo.UiHost;
-import org.onosproject.ui.model.topo.UiLink;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.slf4j.Logger;
@@ -37,8 +33,6 @@
import java.util.List;
import java.util.Set;
-import static org.onosproject.ui.model.topo.UiNode.LAYER_DEFAULT;
-
/*
NOTES:
@@ -69,7 +63,6 @@
private static final String CURRENT_LAYOUT = "topo2CurrentLayout";
private static final String CURRENT_REGION = "topo2CurrentRegion";
private static final String PEER_REGIONS = "topo2PeerRegions";
- private static final String ORPHANS = "topo2Orphans";
private static final String TOPO_START_DONE = "topo2StartDone";
@@ -109,6 +102,12 @@
log.debug("topo2Start: {}", payload);
+ // this may be a little heavyweight, but it might be safer to do
+ // this than make assumptions about the order in which devices
+ // and regions are added... and thus internal linkages set up
+ // correctly
+ topoSession.refreshModel();
+
// this is the list of ONOS cluster members
List<UiClusterMember> instances = topoSession.getAllInstances();
sendMessage(ALL_INSTANCES, t2json.instances(instances));
@@ -131,14 +130,7 @@
peersPayload.set("peers", t2json.closedRegions(peers));
sendMessage(PEER_REGIONS, peersPayload);
- // return devices, hosts, links belonging to no region
- Set<UiDevice> oDevices = topoSession.getOrphanDevices();
- Set<UiHost> oHosts = topoSession.getOrphanHosts();
- Set<UiLink> oLinks = topoSession.getOrphanLinks();
- List<String> oLayers = getOrphanLayerOrder();
- sendMessage(ORPHANS, t2json.orphans(oDevices, oHosts, oLinks, oLayers));
-
- // finally, tell the UI that we are done
+ // finally, tell the UI that we are done : TODO review / delete??
sendMessage(TOPO_START_DONE, null);
@@ -154,14 +146,6 @@
}
- // TODO: we need to decide on how this should really get populated.
- // For example, to be "backward compatible", this should really be
- // [ LAYER_OPTICAL, LAYER_PACKET, LAYER_DEFAULT ]
- private List<String> getOrphanLayerOrder() {
- // NOTE that LAYER_DEFAULT must always be last in the array
- return ImmutableList.of(LAYER_DEFAULT);
- }
-
private final class Topo2Stop extends RequestHandler {
private Topo2Stop() {
super(TOPO2_STOP);
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoLayoutManager.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoLayoutManager.java
index a597f24..28e345c 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoLayoutManager.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoLayoutManager.java
@@ -34,6 +34,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -110,6 +111,21 @@
}
@Override
+ public Set<UiTopoLayout> getPeers(UiTopoLayoutId layoutId) {
+ checkNotNull(layoutId, ID_NULL);
+ UiTopoLayout layout = layoutMap.get(layoutId);
+ if (layout == null) {
+ return Collections.emptySet();
+ }
+
+ UiTopoLayoutId parentId = layout.parent();
+ return layoutMap.values().stream()
+ .filter(l -> !Objects.equals(l.id(), layoutId) &&
+ Objects.equals(l.parent(), parentId))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) {
checkNotNull(layoutId, ID_NULL);
return layoutMap.values().stream()
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoSession.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoSession.java
index 611a22d..47907d4 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoSession.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoSession.java
@@ -16,21 +16,19 @@
package org.onosproject.ui.impl.topo;
+import org.onosproject.net.region.RegionId;
import org.onosproject.ui.UiTopoLayoutService;
import org.onosproject.ui.impl.UiWebSocket;
import org.onosproject.ui.impl.topo.model.UiModelEvent;
import org.onosproject.ui.impl.topo.model.UiModelListener;
import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel;
import org.onosproject.ui.model.topo.UiClusterMember;
-import org.onosproject.ui.model.topo.UiDevice;
-import org.onosproject.ui.model.topo.UiHost;
-import org.onosproject.ui.model.topo.UiLink;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -167,23 +165,23 @@
* @return region that the layout is based upon
*/
public UiRegion getRegion(UiTopoLayout layout) {
- return sharedModel.getRegion(layout.regionId());
+ RegionId rid = layout.regionId();
+ return rid == null ? sharedModel.getNullRegion() : sharedModel.getRegion(rid);
}
/**
* Returns the regions that are "peers" to this region. That is, based on
* the layout the user is viewing, all the regions that are associated with
- * layouts that are children of the parent layout to this layout.
+ * layouts that share the same parent layout as this layout.
*
* @param layout the layout being viewed
* @return all regions that are "siblings" to this layout's region
*/
public Set<UiRegion> getPeerRegions(UiTopoLayout layout) {
- UiRegion currentRegion = getRegion(layout);
-
- // TODO: consult topo layout service to get hierarchy info...
- // TODO: then consult shared model to get regions
- return Collections.emptySet();
+ Set<UiTopoLayout> peerLayouts = layoutService.getPeers(layout.id());
+ Set<UiRegion> peers = new HashSet<>();
+ peerLayouts.forEach(l -> peers.add(sharedModel.getRegion(l.regionId())));
+ return peers;
}
/**
@@ -193,42 +191,16 @@
* @return all regions that are "contained within" this layout's region
*/
public Set<UiRegion> getSubRegions(UiTopoLayout layout) {
- UiRegion currentRegion = getRegion(layout);
-
- // TODO: consult topo layout service to get child layouts...
- // TODO: then consult shared model to get regions
- return Collections.emptySet();
- }
-
-
- /**
- * Returns all devices that are not in a region.
- *
- * @return all devices not in a region
- */
- public Set<UiDevice> getOrphanDevices() {
- // TODO: get devices with no region
- return Collections.emptySet();
+ Set<UiTopoLayout> kidLayouts = layoutService.getChildren(layout.id());
+ Set<UiRegion> kids = new HashSet<>();
+ kidLayouts.forEach(l -> kids.add(sharedModel.getRegion(l.regionId())));
+ return kids;
}
/**
- * Returns all hosts that are not in a region.
- *
- * @return all hosts not in a region
+ * Refreshes the model's internal state.
*/
- public Set<UiHost> getOrphanHosts() {
- // TODO: get hosts with no region
- return Collections.emptySet();
+ public void refreshModel() {
+ sharedModel.refresh();
}
-
- /**
- * Returns all links that are not in a region.
- *
- * @return all links not in a region
- */
- public Set<UiLink> getOrphanLinks() {
- // TODO: get links with no region
- return Collections.emptySet();
- }
-
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
index 8754550..8647c59 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
@@ -41,6 +41,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -169,18 +170,38 @@
// TODO: post event
}
+ // === THE NULL REGION
+
+ UiRegion nullRegion() {
+ return uiTopology.nullRegion();
+ }
// === REGIONS
private UiRegion addNewRegion(Region r) {
UiRegion region = new UiRegion(uiTopology, r);
uiTopology.add(region);
+ log.debug("Region {} added to topology", region);
return region;
}
private void updateRegion(UiRegion region) {
- Set<DeviceId> devs = services.region().getRegionDevices(region.id());
- region.reconcileDevices(devs);
+ RegionId rid = region.id();
+ Set<DeviceId> deviceIds = services.region().getRegionDevices(rid);
+
+ // Make sure device objects refer to their region
+ deviceIds.forEach(d -> {
+ UiDevice dev = uiTopology.findDevice(d);
+ if (dev != null) {
+ dev.setRegionId(rid);
+ } else {
+ // if we don't have the UiDevice in the topology, what can we do?
+ log.warn("Region device {}, but we don't have UiDevice in topology", d);
+ }
+ });
+
+ // Make sure the region object refers to the devices
+ region.reconcileDevices(deviceIds);
}
private void loadRegions() {
@@ -224,21 +245,22 @@
private UiDevice addNewDevice(Device d) {
UiDevice device = new UiDevice(uiTopology, d);
+ updateDevice(device);
uiTopology.add(device);
+ log.debug("Device {} added to topology", device);
return device;
}
+ // make sure the UiDevice is tagged with the region it belongs to
private void updateDevice(UiDevice device) {
- Region regionForDevice = services.region().getRegionForDevice(device.id());
- if (regionForDevice != null) {
- device.setRegionId(regionForDevice.id());
- }
+ Region r = services.region().getRegionForDevice(device.id());
+ RegionId rid = r == null ? UiRegion.NULL_ID : r.id();
+ device.setRegionId(rid);
}
private void loadDevices() {
for (Device d : services.device().getDevices()) {
- UiDevice device = addNewDevice(d);
- updateDevice(device);
+ addNewDevice(d);
}
}
@@ -248,8 +270,9 @@
UiDevice uiDevice = uiTopology.findDevice(id);
if (uiDevice == null) {
uiDevice = addNewDevice(device);
+ } else {
+ updateDevice(uiDevice);
}
- updateDevice(uiDevice);
postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice);
}
@@ -434,6 +457,43 @@
}
+ /**
+ * Refreshes the internal state.
+ */
+ public void refresh() {
+ // fix up internal linkages if they aren't correct
+
+ // at the moment, this is making sure devices are in the correct region
+ Set<UiDevice> allDevices = uiTopology.allDevices();
+
+ services.region().getRegions().forEach(r -> {
+ RegionId rid = r.id();
+ UiRegion region = uiTopology.findRegion(rid);
+ if (region != null) {
+ Set<DeviceId> deviceIds = services.region().getRegionDevices(rid);
+ region.reconcileDevices(deviceIds);
+
+ deviceIds.forEach(devId -> {
+ UiDevice dev = uiTopology.findDevice(devId);
+ if (dev != null) {
+ dev.setRegionId(r.id());
+ allDevices.remove(dev);
+ } else {
+ log.warn("Region device ID {} but no UiDevice in topology",
+ devId);
+ }
+ });
+ } else {
+ log.warn("No UiRegion in topology for ID {}", rid);
+ }
+ });
+
+ // what is left over, must belong to the null-region
+ Set<DeviceId> leftOver = new HashSet<>(allDevices.size());
+ allDevices.forEach(d -> leftOver.add(d.id()));
+ uiTopology.nullRegion().reconcileDevices(leftOver);
+ }
+
// === CACHE STATISTICS
/**
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/UiSharedTopologyModel.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/UiSharedTopologyModel.java
index 50ebb06..4fbf707 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/UiSharedTopologyModel.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/UiSharedTopologyModel.java
@@ -217,6 +217,22 @@
return cache.accessRegion(id);
}
+ /**
+ * Returns the null region.
+ *
+ * @return the null region
+ */
+ public UiRegion getNullRegion() {
+ return cache.nullRegion();
+ }
+
+ /**
+ * Refreshes the cache's internal state.
+ */
+ public void refresh() {
+ cache.refresh();
+ }
+
// =====================================================================