ONOS-6259: Topo2 - Implement server-side highlighting model (WIP)
- added locType parameter to region-add command
- created RegionABC sample topology
- fixed possible NPE in Topo2Jsonifier.jsonClosedRegion()
- added "plain" sprite layout
- check for undefined sprite layout and log a warning
- updated logger.sh script
- fixed Topo2Model to have a reference to colleciton before initialization
Change-Id: Ie6af28516338f5d64576bf465373cb5df3dff52c
diff --git a/cli/src/main/java/org/onosproject/cli/net/RegionAddCommand.java b/cli/src/main/java/org/onosproject/cli/net/RegionAddCommand.java
index eff8fb5..db91db6 100644
--- a/cli/src/main/java/org/onosproject/cli/net/RegionAddCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/RegionAddCommand.java
@@ -39,10 +39,13 @@
description = "Adds a new region.")
public class RegionAddCommand extends AbstractShellCommand {
+ private static final String E_BAD_LOC_TYPE = "locType must be {geo|grid}";
+
+ private static final String GEO = "geo";
+ private static final String GRID = "grid";
private static final String SLASH = "/";
- private static final BiMap<String, Region.Type> REGION_TYPE_MAP
- = HashBiMap.create();
+ private static final BiMap<String, Region.Type> REGION_TYPE_MAP = HashBiMap.create();
static {
for (Region.Type t : Region.Type.values()) {
@@ -63,15 +66,21 @@
required = true, multiValued = false)
String type = null;
- @Argument(index = 3, name = "latitude", description = "Geo latitude",
+ @Argument(index = 3, name = "latOrY",
+ description = "Geo latitude / Grid y-coord",
required = true, multiValued = false)
- Double latitude = null;
+ Double latOrY = null;
- @Argument(index = 4, name = "longitude", description = "Geo longitude",
+ @Argument(index = 4, name = "longOrX",
+ description = "Geo longitude / Grid x-coord",
required = true, multiValued = false)
- Double longitude = null;
+ Double longOrX = null;
- @Argument(index = 5, name = "masters", description = "Region Master, a set " +
+ @Argument(index = 5, name = "locType", description = "Location type {geo|grid}",
+ required = false, multiValued = false)
+ String locType = GEO;
+
+ @Argument(index = 6, name = "masters", description = "Region Master, a set " +
"of nodeIds should be split with '/' delimiter (e.g., 1 2 3 / 4 5 6)",
required = true, multiValued = true)
List<String> masterArgs = null;
@@ -81,6 +90,33 @@
RegionAdminService service = get(RegionAdminService.class);
RegionId regionId = RegionId.regionId(id);
+ NetworkConfigService cfgService = get(NetworkConfigService.class);
+ BasicRegionConfig cfg = cfgService.addConfig(regionId, BasicRegionConfig.class);
+ setConfigurationData(cfg);
+
+ List<Set<NodeId>> masters = parseMasterArgs();
+ service.createRegion(regionId, name, REGION_TYPE_MAP.get(type), masters);
+ print("Region successfully added.");
+ }
+
+ private void setConfigurationData(BasicRegionConfig cfg) {
+ cfg.name(name).locType(locType);
+
+ if (GEO.equals(locType)) {
+ cfg.latitude(latOrY).longitude(longOrX);
+
+ } else if (GRID.equals(locType)) {
+ cfg.gridY(latOrY).gridX(longOrX);
+
+ } else {
+ throw new IllegalArgumentException(E_BAD_LOC_TYPE);
+
+ }
+
+ cfg.apply();
+ }
+
+ private List<Set<NodeId>> parseMasterArgs() {
List<Set<NodeId>> masters = Lists.newArrayList();
Set<NodeId> nodeIds = Sets.newHashSet();
for (String masterArg : masterArgs) {
@@ -92,15 +128,6 @@
}
}
masters.add(nodeIds);
-
- NetworkConfigService cfgService = get(NetworkConfigService.class);
- BasicRegionConfig cfg = cfgService.addConfig(regionId, BasicRegionConfig.class);
- cfg.name(name)
- .latitude(latitude)
- .longitude(longitude)
- .apply();
-
- service.createRegion(regionId, name, REGION_TYPE_MAP.get(type), masters);
- print("Region successfully added.");
+ return masters;
}
}
\ No newline at end of file
diff --git a/tools/test/topos/regionabc-onos.py b/tools/test/topos/regionabc-onos.py
new file mode 100644
index 0000000..f2c8218
--- /dev/null
+++ b/tools/test/topos/regionabc-onos.py
@@ -0,0 +1,6 @@
+#!/usr/bin/python
+
+from onosnet import run
+from regionabc import RegionABC
+
+run( RegionABC() )
diff --git a/tools/test/topos/regionabc.json b/tools/test/topos/regionabc.json
new file mode 100644
index 0000000..b5d15e0
--- /dev/null
+++ b/tools/test/topos/regionabc.json
@@ -0,0 +1,49 @@
+{
+ "devices": {
+ "of:0000000000000001": {
+ "basic": {
+ "name": "S1",
+ "gridX": 40,
+ "gridY": 20
+ }
+ },
+ "of:0000000000000002": {
+ "basic": {
+ "name": "S2",
+ "gridX": 40,
+ "gridY": 40
+ }
+ },
+
+ "of:0000000000000003": {
+ "basic": {
+ "name": "S3",
+ "gridX": 40,
+ "gridY": 20
+ }
+ },
+ "of:0000000000000004": {
+ "basic": {
+ "name": "S4",
+ "gridX": 40,
+ "gridY": 40
+ }
+ },
+
+ "of:0000000000000005": {
+ "basic": {
+ "name": "S5",
+ "gridX": 40,
+ "gridY": 20
+ }
+ },
+ "of:0000000000000006": {
+ "basic": {
+ "name": "S6",
+ "gridX": 40,
+ "gridY": 40
+ }
+ }
+
+ }
+}
diff --git a/tools/test/topos/regionabc.py b/tools/test/topos/regionabc.py
new file mode 100644
index 0000000..a26d3d3
--- /dev/null
+++ b/tools/test/topos/regionabc.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+"""
+ [1] ----- [3] ----- [5]
+ | ____/ | \ |
+ | / | \____ |
+ | / | \ |
+ [2] ----- [4] ----- [6]
+"""
+from mininet.topo import Topo
+
+class RegionABC( Topo ):
+ """Simple 6 switch example"""
+
+ def __init__( self ):
+ """Create a topology."""
+
+ # Initialize Topology
+ Topo.__init__( self )
+
+ # add nodes, switches first...
+ S1 = self.addSwitch( 's1' )
+ S2 = self.addSwitch( 's2' )
+ S3 = self.addSwitch( 's3' )
+ S4 = self.addSwitch( 's4' )
+ S5 = self.addSwitch( 's5' )
+ S6 = self.addSwitch( 's6' )
+
+ # ... and now hosts
+ S1_host = self.addHost( 'h1' )
+ S2_host = self.addHost( 'h2' )
+ S3_host = self.addHost( 'h3' )
+ S4_host = self.addHost( 'h4' )
+ S5_host = self.addHost( 'h5' )
+ S6_host = self.addHost( 'h6' )
+
+ # add edges between switch and corresponding host
+ self.addLink( S1, S1_host )
+ self.addLink( S2, S2_host )
+ self.addLink( S3, S3_host )
+ self.addLink( S4, S4_host )
+ self.addLink( S5, S5_host )
+ self.addLink( S6, S6_host )
+
+ # add edges between switches as diagrammed above
+ self.addLink( S1, S2, bw=10, delay='1.0ms')
+ self.addLink( S1, S3, bw=10, delay='1.0ms')
+ self.addLink( S2, S3, bw=10, delay='1.0ms')
+ self.addLink( S2, S4, bw=10, delay='1.0ms')
+ self.addLink( S3, S4, bw=10, delay='1.0ms')
+ self.addLink( S3, S5, bw=10, delay='1.0ms')
+ self.addLink( S3, S6, bw=10, delay='1.0ms')
+ self.addLink( S4, S6, bw=10, delay='1.0ms')
+ self.addLink( S5, S6, bw=10, delay='1.0ms')
+
+topos = { 'regionabc': ( lambda: RegionABC() ) }
+
+if __name__ == '__main__':
+ from onosnet import run
+ run( RegionABC() )
diff --git a/tools/test/topos/regionabc.sh b/tools/test/topos/regionabc.sh
new file mode 100755
index 0000000..64e205a
--- /dev/null
+++ b/tools/test/topos/regionabc.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+#
+# A simple test topology of three regions, A, B, and C.
+#
+# Script Configuration:
+#
+# host : the controller instance against which this script is run
+
+host=${1:-127.0.0.1}
+
+
+###------------------------------------------------------
+### Start by adding the three regions A, B, and C
+
+# region-add <region-id> <region-name> <region-type> \
+# <lat/Y> <long/X> <locType> <region-master>
+
+onos ${host} <<-EOF
+
+# -- define regions
+region-add rA "Region A" LOGICAL_GROUP 30 20 grid ${host}
+region-add rB "Region B" LOGICAL_GROUP 30 40 grid ${host}
+region-add rC "Region C" LOGICAL_GROUP 30 60 grid ${host}
+
+# -- set peer locations
+region-add-peer-loc rA rB 40 70
+region-add-peer-loc rA rC 50 70
+
+region-add-peer-loc rB rA 30 10
+region-add-peer-loc rB rC 30 70
+
+region-add-peer-loc rC rA 10 10
+region-add-peer-loc rC rB 20 10
+
+EOF
+
+###------------------------------------------------------
+### Add layouts, associating backing regions, and optional parent
+
+# layout-add <layout-id> <bg-ref> \
+# [ <region-id> <parent-layout-id> <scale> <offset-x> <offset-y> ]
+#
+
+onos ${host} <<-EOF
+
+# -- top level
+layout-add root +plain . . 1.0 0.0 0.0
+
+# -- layouts for top level regions
+layout-add lA +plain rA root 1.0 0.0 0.0
+layout-add lB +plain rB root 1.0 0.0 0.0
+layout-add lC +plain rC root 1.0 0.0 0.0
+
+# -- summary
+layouts
+EOF
+
+###------------------------------------------------------
+### Assign devices to each of their regions
+
+onos ${host} <<-EOF
+
+region-add-devices rA \
+ of:0000000000000001 \
+ of:0000000000000002 \
+
+region-add-devices rB \
+ of:0000000000000003 \
+ of:0000000000000004 \
+
+region-add-devices rC \
+ of:0000000000000005 \
+ of:0000000000000006 \
+
+EOF
+
+###------------------------------------------------------
+### Configure devices and hosts
+
+onos-netcfg ${host} regionabc.json
+
+
diff --git a/tools/test/topos/regions-bayarea-grid.sh b/tools/test/topos/regions-bayarea-grid.sh
index ba7ec95..03b2813 100755
--- a/tools/test/topos/regions-bayarea-grid.sh
+++ b/tools/test/topos/regions-bayarea-grid.sh
@@ -206,15 +206,16 @@
### Add regions and associate devices with them
#
-# region-add <region-id> <region-name> <region-type> <lat/Y> <long/X> <region-master>
+# region-add <region-id> <region-name> <region-type> \
+# <lat/Y> <long/X> <locType> <region-master>
# region-add-devices <region-id> <device-id>...
onos ${host} <<-EOF
-region-add c01 "San Francisco" DATA_CENTER 37.75394143914288 -122.45945851660800 ${host}
-region-add c02 "Palo Alto" DATA_CENTER 37.45466637790734 -122.21838933304870 ${host}
-region-add c03 "San Jose" DATA_CENTER 37.34425619809433 -121.94768095808017 ${host}
-region-add c04 "Fremont" DATA_CENTER 37.54328280574901 -122.01205548699211 ${host}
+region-add c01 "San Francisco" DATA_CENTER 37.75394143914288 -122.45945851660800 geo ${host}
+region-add c02 "Palo Alto" DATA_CENTER 37.45466637790734 -122.21838933304870 geo ${host}
+region-add c03 "San Jose" DATA_CENTER 37.34425619809433 -121.94768095808017 geo ${host}
+region-add c04 "Fremont" DATA_CENTER 37.54328280574901 -122.01205548699211 geo ${host}
region-add-devices c01 \
null:0000000000000001 \
diff --git a/tools/test/topos/regions-bayarea.sh b/tools/test/topos/regions-bayarea.sh
index ae0ef10..f37373f 100755
--- a/tools/test/topos/regions-bayarea.sh
+++ b/tools/test/topos/regions-bayarea.sh
@@ -206,15 +206,16 @@
### Add regions and associate devices with them
#
-# region-add <region-id> <region-name> <region-type> <region-master>
+# region-add <region-id> <region-name> <region-type> \
+# <lat/Y> <long/X> <locType> <region-master>
# region-add-devices <region-id> <device-id>...
onos ${host} <<-EOF
-region-add c01 SanFrancisco DATA_CENTER 37.75394143914288 -122.45945851660800 ${host}
-region-add c02 PaloAlto DATA_CENTER 37.45466637790734 -122.21838933304870 ${host}
-region-add c03 SanJose DATA_CENTER 37.34425619809433 -121.94768095808017 ${host}
-region-add c04 Fremont DATA_CENTER 37.54328280574901 -122.01205548699211 ${host}
+region-add c01 SanFrancisco DATA_CENTER 37.75394143914288 -122.45945851660800 geo ${host}
+region-add c02 PaloAlto DATA_CENTER 37.45466637790734 -122.21838933304870 geo ${host}
+region-add c03 SanJose DATA_CENTER 37.34425619809433 -121.94768095808017 geo ${host}
+region-add c04 Fremont DATA_CENTER 37.54328280574901 -122.01205548699211 geo ${host}
region-add-devices c01 \
null:0000000000000001 \
diff --git a/tools/test/topos/regions-europe.sh b/tools/test/topos/regions-europe.sh
index 58f2944..44e64fc 100755
--- a/tools/test/topos/regions-europe.sh
+++ b/tools/test/topos/regions-europe.sh
@@ -28,17 +28,18 @@
### Start by adding Country regions
# Note that Long/Lat places region icon nicely in the country center
-# region-add <region-id> <region-name> <region-type> <lat/Y> <long/X> <region-master>
+# region-add <region-id> <region-name> <region-type> \
+# <lat/Y> <long/X> <locType> <region-master>
onos ${host} <<-EOF
-region-add rUK "United Kingdom" COUNTRY 52.206035 -1.310384 ${host}
-region-add rIT "Italy" COUNTRY 44.447951 11.093161 ${host}
-region-add rFR "France" COUNTRY 47.066264 2.711458 ${host}
-region-add rDE "Germany" COUNTRY 50.863152 9.761971 ${host}
-region-add rES "Spain" COUNTRY 40.416704 -3.7035824 ${host}
+region-add rUK "United Kingdom" COUNTRY 52.206035 -1.310384 geo ${host}
+region-add rIT "Italy" COUNTRY 44.447951 11.093161 geo ${host}
+region-add rFR "France" COUNTRY 47.066264 2.711458 geo ${host}
+region-add rDE "Germany" COUNTRY 50.863152 9.761971 geo ${host}
+region-add rES "Spain" COUNTRY 40.416704 -3.7035824 geo ${host}
-region-add rMilan "Milan" METRO 45.4654 9.1859 ${host}
+region-add rMilan "Milan" METRO 45.4654 9.1859 geo ${host}
EOF
diff --git a/web/gui/logger.sh b/web/gui/logger.sh
index 53c3ddad..93a9048 100755
--- a/web/gui/logger.sh
+++ b/web/gui/logger.sh
@@ -3,16 +3,22 @@
host=${1:-localhost}
### Set up debug log messages for classes we care about
+#
+# -- NOTE: leave commented out for checked-in source
+# developer can uncomment locally
+
onos ${host} <<-EOF
-log:set DEBUG org.onosproject.ui.impl.topo.Topo2ViewMessageHandler
-log:set DEBUG org.onosproject.ui.impl.topo.Topo2Jsonifier
-log:set DEBUG org.onosproject.ui.impl.topo.Topo2TrafficMessageHandler
-log:set DEBUG org.onosproject.ui.impl.topo.Traffic2Monitor
+#log:set DEBUG org.onosproject.ui.impl.topo.Topo2ViewMessageHandler
+#log:set DEBUG org.onosproject.ui.impl.topo.Topo2Jsonifier
+#log:set DEBUG org.onosproject.ui.impl.topo.Topo2TrafficMessageHandler
+#log:set DEBUG org.onosproject.ui.impl.topo.Traffic2Monitor
-log:set DEBUG org.onosproject.ui.impl.UiWebSocket
+#log:set DEBUG org.onosproject.ui.impl.UiWebSocket
#log:set DEBUG org.onosproject.ui.impl.UiTopoSession
+#log:set DEBUG org.onosproject.ui.impl.topo.model.ModelCache
+
log:list
EOF
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 c7a223f..da1f8e4 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
@@ -611,9 +611,11 @@
// all descendant subregions.
Region r = region.backingRegion();
- // this is location data, as injected via network configuration script
- addGeoGridLocation(node, r);
- addProps(node, r);
+ if (r != null) {
+ // add data injected via network configuration script
+ addGeoGridLocation(node, r);
+ addProps(node, r);
+ }
// this may contain location data, as dragged by user
// (which should take precedence, over configured data)
diff --git a/web/gui/src/main/webapp/app/fw/svg/sprite.js b/web/gui/src/main/webapp/app/fw/svg/sprite.js
index 6eafe66..b64f58d 100644
--- a/web/gui/src/main/webapp/app/fw/svg/sprite.js
+++ b/web/gui/src/main/webapp/app/fw/svg/sprite.js
@@ -215,9 +215,9 @@
// Returns a layout "builder", which can be used to programmatically
// define a layout.
- function createLayout(id, w, h, grid) {
- $log.debug('createLayout:', id, w, 'x', h, '(grid=' + grid + ')');
- return layoutBuilder(id, w, h, grid);
+ function createLayout(id, w, h, opts) {
+ $log.debug('createLayout:', id, w, 'x', h, '(opts:', opts, ')');
+ return layoutBuilder(id, w, h, opts);
}
// Registers a sprite defined by the given object (JSON structure).
diff --git a/web/gui/src/main/webapp/app/fw/svg/spriteData.js b/web/gui/src/main/webapp/app/fw/svg/spriteData.js
index 1625a46..d970af9 100644
--- a/web/gui/src/main/webapp/app/fw/svg/spriteData.js
+++ b/web/gui/src/main/webapp/app/fw/svg/spriteData.js
@@ -77,6 +77,9 @@
.addLabel('Segment Routing 2', 120, 10, {anchor: 'right'})
.register();
+ ssApi.createLayout('plain', 80, 60)
+ .register();
+
ssApi.dump();
// ----------------------------------------------------------$$$
}
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Model.js b/web/gui/src/main/webapp/app/view/topo2/topo2Model.js
index efcd201..6da29c4 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Model.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Model.js
@@ -25,6 +25,7 @@
function Model(attributes, collection) {
this.attributes = {};
this.set(angular.extend({}, attributes || {}), { silent: true });
+ this.collection = collection;
this.initialize.apply(this, arguments);
}
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Overlay.js b/web/gui/src/main/webapp/app/view/topo2/topo2Overlay.js
index 1227c30..222e837 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Overlay.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Overlay.js
@@ -141,7 +141,8 @@
// TODO: Inconsistent host id's (currentRegion and LinkLabel)
var id = link.id.replace('/None/0', '/None').replace('-', '~'),
lab = t2rs.getLink(id);
- // TODO: There's a bug in backend where link id is in reverse
+ // DONE: There's a bug in backend where link id is in reverse
+ // This is fixed -- SDH
if (lab) {
t2lc.addLabel(LinkLabel, link, linkLabelsDOM, {
link: lab
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js b/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
index 98e890b..f53ccc6 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
@@ -31,9 +31,10 @@
angular.module('ovTopo2')
.factory('Topo2SpriteLayerService', [
- 'FnService', 'Topo2ViewController', 'SpriteService', 'ThemeService',
+ '$log', 'FnService',
+ 'Topo2ViewController', 'SpriteService', 'ThemeService',
- function (fs, ViewController, ss, ts) {
+ function ($log, fs, ViewController, ss, ts) {
var SpriteLayer = ViewController.extend({
@@ -50,13 +51,17 @@
this.container.selectAll("*").remove();
this.layout = ss.layout(id);
- this.width = this.layout.data.w;
- this.height = this.layout.data.h;
+ if (this.layout) {
+ this.width = this.layout.data.w;
+ this.height = this.layout.data.h;
- this.renderLayout();
+ this.renderLayout();
- if (fs.debugOn('sprite_grid')) {
- this.renderGrid();
+ if (fs.debugOn('sprite_grid')) {
+ this.renderGrid();
+ }
+ } else {
+ $log.warn('no sprite layout registered:', id);
}
// Returns a promise for consistency with Topo2MapService