Implementing region hosts for topology 2
Change-Id: I6d1e45b1152b2387d4ff981dc0666868235eb1c3
diff --git a/core/api/src/main/java/org/onosproject/net/region/RegionService.java b/core/api/src/main/java/org/onosproject/net/region/RegionService.java
index 259c8b0..b2b9b14 100644
--- a/core/api/src/main/java/org/onosproject/net/region/RegionService.java
+++ b/core/api/src/main/java/org/onosproject/net/region/RegionService.java
@@ -18,6 +18,7 @@
import org.onosproject.event.ListenerService;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
import java.util.Set;
@@ -59,4 +60,12 @@
*/
Set<DeviceId> getRegionDevices(RegionId regionId);
+ /**
+ * Returns the set of hosts that belong to the specified region.
+ *
+ * @param regionId region identifier
+ * @return set of identifiers for hosts in the given region
+ */
+ Set<HostId> getRegionHosts(RegionId regionId);
+
}
diff --git a/core/api/src/main/java/org/onosproject/net/region/RegionStore.java b/core/api/src/main/java/org/onosproject/net/region/RegionStore.java
index 49cc378..a21a1f9 100644
--- a/core/api/src/main/java/org/onosproject/net/region/RegionStore.java
+++ b/core/api/src/main/java/org/onosproject/net/region/RegionStore.java
@@ -17,6 +17,7 @@
import org.onosproject.cluster.NodeId;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
import org.onosproject.store.Store;
import java.util.Collection;
@@ -110,4 +111,12 @@
*/
void removeDevices(RegionId regionId, Collection<DeviceId> deviceIds);
+ /**
+ * Returns the set of hosts that belong to the specified region.
+ *
+ * @param regionId region identifier
+ * @return set of identifiers for hosts in the given region
+ */
+ Set<HostId> getRegionHosts(RegionId regionId);
+
}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
index 8c5107e..ff22116 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
@@ -20,6 +20,7 @@
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.region.RegionId;
import static com.google.common.base.MoreObjects.toStringHelper;
@@ -36,6 +37,7 @@
private PortNumber locPort;
private UiLinkId edgeLinkId;
+ private RegionId regionId;
/**
* Creates a new UI host.
@@ -70,6 +72,15 @@
return host.id();
}
+ /**
+ * Sets the ID of the region to which this device belongs.
+ *
+ * @param regionId region identifier
+ */
+ public void setRegionId(RegionId regionId) {
+ this.regionId = regionId;
+ }
+
@Override
public String idAsString() {
return id().toString();
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
index 40dec55..7cd0da9 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
@@ -241,6 +241,17 @@
return topology.deviceSet(deviceIds);
}
+
+ /**
+ * Make sure we have only these hosts in the region.
+ *
+ * @param hosts hosts in the region
+ */
+ public void reconcileHosts(Set<HostId> hosts) {
+ hostIds.clear();
+ hostIds.addAll(hosts);
+ }
+
/**
* Returns the set of host identifiers for this region.
*
@@ -260,6 +271,15 @@
}
/**
+ * Returns the count of devices in this region.
+ *
+ * @return the device count
+ */
+ public int hostCount() {
+ return hostIds.size();
+ }
+
+ /**
* Returns the order in which layers should be rendered. Lower layers
* come earlier in the list. For example, to indicate that nodes in the
* optical layer should be rendered "below" nodes in the packet layer,
diff --git a/core/net/src/main/java/org/onosproject/net/region/impl/RegionManager.java b/core/net/src/main/java/org/onosproject/net/region/impl/RegionManager.java
index 81a9dfa..75d96ed 100644
--- a/core/net/src/main/java/org/onosproject/net/region/impl/RegionManager.java
+++ b/core/net/src/main/java/org/onosproject/net/region/impl/RegionManager.java
@@ -25,6 +25,7 @@
import org.onosproject.cluster.NodeId;
import org.onosproject.event.AbstractListenerManager;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionAdminService;
import org.onosproject.net.region.RegionEvent;
@@ -149,4 +150,11 @@
return store.getRegionDevices(regionId);
}
+ @Override
+ public Set<HostId> getRegionHosts(RegionId regionId) {
+ checkPermission(REGION_READ);
+ checkNotNull(regionId, REGION_ID_NULL);
+ return store.getRegionHosts(regionId);
+ }
+
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/region/impl/DistributedRegionStore.java b/core/store/dist/src/main/java/org/onosproject/store/region/impl/DistributedRegionStore.java
index 6d70376..e101514 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/region/impl/DistributedRegionStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/region/impl/DistributedRegionStore.java
@@ -27,6 +27,7 @@
import org.onlab.util.Identifier;
import org.onosproject.cluster.NodeId;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
import org.onosproject.net.region.DefaultRegion;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionEvent;
@@ -78,6 +79,7 @@
private ConsistentMap<RegionId, Set<DeviceId>> membershipRepo;
private Map<RegionId, Set<DeviceId>> regionDevices;
+ private Map<RegionId, Set<HostId>> regionHosts;
private Map<DeviceId, Region> regionsByDevice = new HashMap<>();
@@ -140,6 +142,12 @@
}
@Override
+ public Set<HostId> getRegionHosts(RegionId regionId) {
+ Set<HostId> hostIds = regionHosts.get(regionId);
+ return hostIds != null ? ImmutableSet.copyOf(hostIds) : ImmutableSet.of();
+ }
+
+ @Override
public Region createRegion(RegionId regionId, String name, Region.Type type,
List<Set<NodeId>> masterNodeIds) {
return regionsRepo.compute(regionId, (id, region) -> {
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 e895214..9e4beb6 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
@@ -387,7 +387,8 @@
.put("id", region.idAsString())
.put("name", region.name())
.put("nodeType", REGION)
- .put("nDevs", region.deviceCount());
+ .put("nDevs", region.deviceCount())
+ .put("nHosts", region.hostCount());
// TODO: complete closed-region details
addMetaUi(node, region.idAsString());
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 30c1b80..684be94 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
@@ -193,6 +193,7 @@
private void updateRegion(UiRegion region) {
RegionId rid = region.id();
Set<DeviceId> deviceIds = services.region().getRegionDevices(rid);
+ Set<HostId> hostIds = services.region().getRegionHosts(rid);
// Make sure device objects refer to their region
deviceIds.forEach(d -> {
@@ -205,8 +206,19 @@
}
});
+ hostIds.forEach(d -> {
+ UiHost host = uiTopology.findHost(d);
+ if (host != null) {
+ host.setRegionId(rid);
+ } else {
+ // if we don't have the UiDevice in the topology, what can we do?
+ log.warn("Region host {}, but we don't have UiHost in topology", d);
+ }
+ });
+
// Make sure the region object refers to the devices
region.reconcileDevices(deviceIds);
+ region.reconcileHosts(hostIds);
fixupContainmentHierarchy(region);
}
@@ -526,26 +538,17 @@
fixupContainmentHierarchy(uiTopology.nullRegion());
uiTopology.allRegions().forEach(this::fixupContainmentHierarchy);
- // make sure devices are in the correct region
+ // make sure devices and hosts are in the correct region
Set<UiDevice> allDevices = uiTopology.allDevices();
+ Set<UiHost> allHosts = uiTopology.allHosts();
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);
+ reconcileDevicesWithRegion(allDevices, r, rid, region);
+ reconcileHostsWithRegion(allHosts, r, rid, region);
- 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);
}
@@ -556,11 +559,49 @@
allDevices.forEach(d -> leftOver.add(d.id()));
uiTopology.nullRegion().reconcileDevices(leftOver);
+ Set<HostId> leftOverHosts = new HashSet<>(allHosts.size());
+ allHosts.forEach(h -> leftOverHosts.add(h.id()));
+ uiTopology.nullRegion().reconcileHosts(leftOverHosts);
+
// now that we have correct region hierarchy, and devices are in their
// respective regions, we can compute synthetic links for each region.
uiTopology.computeSynthLinks();
}
+ private void reconcileHostsWithRegion(Set<UiHost> allHosts, Region r,
+ RegionId rid, UiRegion region) {
+ Set<HostId> hostIds = services.region().getRegionHosts(rid);
+ region.reconcileHosts(hostIds);
+
+ hostIds.forEach(hId -> {
+ UiHost h = uiTopology.findHost(hId);
+ if (h != null) {
+ h.setRegionId(r.id());
+ allHosts.remove(h);
+ } else {
+ log.warn("Region host ID {} but no UiHost in topology",
+ hId);
+ }
+ });
+ }
+
+ private void reconcileDevicesWithRegion(Set<UiDevice> allDevices, Region r,
+ RegionId rid, UiRegion region) {
+ 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);
+ }
+ });
+ }
+
// === CACHE STATISTICS
diff --git a/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/AbstractTopoModelTest.java b/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/AbstractTopoModelTest.java
index de7ec9a..ea48bb1 100644
--- a/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/AbstractTopoModelTest.java
+++ b/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/AbstractTopoModelTest.java
@@ -52,7 +52,6 @@
import org.onosproject.net.region.DefaultRegion;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionId;
-import org.onosproject.net.region.RegionListener;
import org.onosproject.net.region.RegionService;
import org.onosproject.ui.UiTopoLayoutService;
import org.onosproject.ui.impl.AbstractUiImplTest;
@@ -501,8 +500,7 @@
}
}
- // TODO: consider implementing RegionServiceAdapter and extending that here
- private static class MockRegionService implements RegionService {
+ private static class MockRegionService extends RegionServiceAdapter {
private final Map<RegionId, Region> lookup = new HashMap<>();
@@ -549,14 +547,6 @@
}
return Collections.emptySet();
}
-
- @Override
- public void addListener(RegionListener listener) {
- }
-
- @Override
- public void removeListener(RegionListener listener) {
- }
}
diff --git a/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/RegionServiceAdapter.java b/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/RegionServiceAdapter.java
new file mode 100644
index 0000000..4f7ec4c
--- /dev/null
+++ b/web/gui/src/test/java/org/onosproject/ui/impl/topo/model/RegionServiceAdapter.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.ui.impl.topo.model;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionId;
+import org.onosproject.net.region.RegionListener;
+import org.onosproject.net.region.RegionService;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Adapter for {@link RegionService}.
+ */
+public class RegionServiceAdapter implements RegionService {
+ @Override
+ public void addListener(RegionListener listener) {
+ }
+
+ @Override
+ public void removeListener(RegionListener listener) {
+ }
+
+ @Override
+ public Set<Region> getRegions() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Region getRegion(RegionId regionId) {
+ return null;
+ }
+
+ @Override
+ public Region getRegionForDevice(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public Set<DeviceId> getRegionDevices(RegionId regionId) {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<HostId> getRegionHosts(RegionId regionId) {
+ return Collections.emptySet();
+ }
+}