Simon Hunt

ONOS-4971: Synthetic Link Data -- WIP, merge anyway

- created temp Topology2 View (topoX) to "process" and display topology data.
- made root layout parent of itself (just like /.. = /) to simplify layout hierarchy operations.
- added nodeType property to JSON rep of regions/devices/hosts.
- augmented peers to include devices.
- added skeleton topo2NavRegion event.

Change-Id: I8219125d7dfe33d211350ae27111a3d9de6eb4ca
......@@ -63,7 +63,7 @@ public interface UiTopoLayoutService {
* @param layoutId layout identifier
* @return set of peer layouts; empty set if layout has no peers
*/
Set<UiTopoLayout> getPeers(UiTopoLayoutId layoutId);
Set<UiTopoLayout> getPeerLayouts(UiTopoLayoutId layoutId);
/**
* Returns the set of the child layouts of the specified layout.
......
......@@ -39,7 +39,8 @@ public class UiTopoLayout {
public UiTopoLayout(UiTopoLayoutId id, Region region, UiTopoLayoutId parent) {
this.id = id;
this.region = region;
this.parent = parent;
// NOTE: root layout is its own parent...
this.parent = parent != null ? parent : this.id;
}
@Override
......@@ -85,5 +86,13 @@ public class UiTopoLayout {
return parent;
}
// TODO: additional properties pertinent to the layout
/**
* Returns true if this layout instance is at the top of the
* hierarchy tree.
*
* @return true if this is the root layout
*/
public boolean isRoot() {
return id.equals(parent);
}
}
......
......@@ -134,6 +134,7 @@ public class UiExtensionManager
// FIXME: leave commented out for now, while still under development
// new UiView(NETWORK, "topo2", "New-Topo"),
// new UiView(NETWORK, "topoX", "Topo-X"),
new UiView(NETWORK, "device", "Devices", "nav_devs"),
new UiViewHidden("flow"),
......
......@@ -40,6 +40,8 @@ import org.onosproject.ui.model.topo.UiLink;
import org.onosproject.ui.model.topo.UiNode;
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.ArrayList;
import java.util.HashMap;
......@@ -62,6 +64,12 @@ class Topo2Jsonifier {
private static final String E_UNKNOWN_UI_NODE =
"Unknown subclass of UiNode: ";
private static final String REGION = "region";
private static final String DEVICE = "device";
private static final String HOST = "host";
private final Logger log = LoggerFactory.getLogger(getClass());
private final ObjectMapper mapper = new ObjectMapper();
private ServiceDirectory directory;
......@@ -245,6 +253,7 @@ class Topo2Jsonifier {
private ObjectNode json(UiDevice device) {
ObjectNode node = objectNode()
.put("id", device.idAsString())
.put("nodeType", DEVICE)
.put("type", device.type())
.put("online", device.isOnline())
.put("master", nullIsEmpty(device.master()))
......@@ -266,6 +275,7 @@ class Topo2Jsonifier {
private ObjectNode json(UiHost host) {
return objectNode()
.put("id", host.idAsString())
.put("nodeType", HOST)
.put("layer", host.layer());
// TODO: complete host details
}
......@@ -281,10 +291,31 @@ class Topo2Jsonifier {
private ObjectNode jsonClosedRegion(UiRegion region) {
return objectNode()
.put("id", region.idAsString())
.put("nodeType", REGION)
.put("nDevs", region.deviceCount());
// TODO: complete closed-region details
}
/**
* Returns a JSON array representation of a set of regions/devices. Note
* that the information is sufficient for showing regions as nodes.
*
* @param nodes the nodes
* @return a JSON representation of the nodes
*/
public ArrayNode closedNodes(Set<UiNode> nodes) {
ArrayNode array = arrayNode();
for (UiNode node: nodes) {
if (node instanceof UiRegion) {
array.add(jsonClosedRegion((UiRegion) node));
} else if (node instanceof UiDevice) {
array.add(json((UiDevice) node));
} else {
log.warn("Unexpected node instance: {}", node.getClass());
}
}
return array;
}
/**
* Returns a JSON array representation of a list of regions. Note that the
......
......@@ -24,6 +24,7 @@ import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.impl.UiWebSocket;
import org.onosproject.ui.model.topo.UiClusterMember;
import org.onosproject.ui.model.topo.UiNode;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.slf4j.Logger;
......@@ -55,8 +56,9 @@ public class Topo2ViewMessageHandler extends UiMessageHandler {
private final Logger log = LoggerFactory.getLogger(getClass());
// === Inbound event identifiers
private static final String TOPO2_START = "topo2Start";
private static final String TOPO2_STOP = "topo2Stop";
private static final String START = "topo2Start";
private static final String NAV_REGION = "topo2navRegion";
private static final String STOP = "topo2Stop";
// === Outbound event identifiers
private static final String ALL_INSTANCES = "topo2AllInstances";
......@@ -83,6 +85,7 @@ public class Topo2ViewMessageHandler extends UiMessageHandler {
protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(
new Topo2Start(),
new Topo2NavRegion(),
new Topo2Stop()
);
}
......@@ -92,7 +95,7 @@ public class Topo2ViewMessageHandler extends UiMessageHandler {
private final class Topo2Start extends RequestHandler {
private Topo2Start() {
super(TOPO2_START);
super(START);
}
@Override
......@@ -124,10 +127,10 @@ public class Topo2ViewMessageHandler extends UiMessageHandler {
Set<UiRegion> kids = topoSession.getSubRegions(currentLayout);
sendMessage(CURRENT_REGION, t2json.region(region, kids));
// these are the regions that are siblings to this one
Set<UiRegion> peers = topoSession.getPeerRegions(currentLayout);
// these are the regions/devices that are siblings to this region
Set<UiNode> peers = topoSession.getPeerNodes(currentLayout);
ObjectNode peersPayload = objectNode();
peersPayload.set("peers", t2json.closedRegions(peers));
peersPayload.set("peers", t2json.closedNodes(peers));
sendMessage(PEER_REGIONS, peersPayload);
// finally, tell the UI that we are done : TODO review / delete??
......@@ -146,9 +149,22 @@ public class Topo2ViewMessageHandler extends UiMessageHandler {
}
private final class Topo2NavRegion extends RequestHandler {
private Topo2NavRegion() {
super(NAV_REGION);
}
@Override
public void process(long sid, ObjectNode payload) {
String dir = string(payload, "dir");
String rid = string(payload, "rid");
log.debug("NavRegion: dir={}, rid={}", dir, rid);
}
}
private final class Topo2Stop extends RequestHandler {
private Topo2Stop() {
super(TOPO2_STOP);
super(STOP);
}
@Override
......
......@@ -111,15 +111,17 @@ public class UiTopoLayoutManager implements UiTopoLayoutService {
}
@Override
public Set<UiTopoLayout> getPeers(UiTopoLayoutId layoutId) {
public Set<UiTopoLayout> getPeerLayouts(UiTopoLayoutId layoutId) {
checkNotNull(layoutId, ID_NULL);
UiTopoLayout layout = layoutMap.get(layoutId);
if (layout == null) {
if (layout == null || layout.isRoot()) {
return Collections.emptySet();
}
UiTopoLayoutId parentId = layout.parent();
return layoutMap.values().stream()
// all layouts who are NOT me and who share my parent...
.filter(l -> !Objects.equals(l.id(), layoutId) &&
Objects.equals(l.parent(), parentId))
.collect(Collectors.toSet());
......@@ -129,7 +131,7 @@ public class UiTopoLayoutManager implements UiTopoLayoutService {
public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) {
checkNotNull(layoutId, ID_NULL);
return layoutMap.values().stream()
.filter(l -> Objects.equals(l.parent(), layoutId))
.filter(l -> !l.isRoot() && Objects.equals(l.parent(), layoutId))
.collect(Collectors.toSet());
}
......
......@@ -23,6 +23,7 @@ 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.UiNode;
import org.onosproject.ui.model.topo.UiRegion;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.slf4j.Logger;
......@@ -170,17 +171,32 @@ public class UiTopoSession implements UiModelListener {
}
/**
* 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 share the same parent layout as this layout.
* Returns the regions/devices that are "peers" to this region. That is,
* based on the layout the user is viewing, all the regions/devices that
* are associated with layouts that share the same parent layout as this
* layout, AND that are linked to an element within this region.
*
* @param layout the layout being viewed
* @return all regions that are "siblings" to this layout's region
* @return all regions/devices that are "siblings" to this layout's region
*/
public Set<UiRegion> getPeerRegions(UiTopoLayout layout) {
Set<UiTopoLayout> peerLayouts = layoutService.getPeers(layout.id());
Set<UiRegion> peers = new HashSet<>();
peerLayouts.forEach(l -> peers.add(sharedModel.getRegion(l.regionId())));
public Set<UiNode> getPeerNodes(UiTopoLayout layout) {
Set<UiNode> peers = new HashSet<>();
// first, get the peer regions
Set<UiTopoLayout> peerLayouts = layoutService.getPeerLayouts(layout.id());
peerLayouts.forEach(l -> {
RegionId peerRegion = l.regionId();
peers.add(sharedModel.getRegion(peerRegion));
});
// now add the devices that reside in the parent region
if (!layout.isRoot()) {
UiTopoLayout parentLayout = layoutService.getLayout(layout.parent());
getRegion(parentLayout).devices().forEach(peers::add);
}
// TODO: Finally, filter out regions / devices that are not connected
// directly to this region by an implicit link
return peers;
}
......
......@@ -25,3 +25,28 @@
/* prevents the little cut/copy/paste square that would appear on iPad */
-webkit-user-select: none;
}
/* -- TEMPORARY CSS (to be deleted) -- */
#topo2tmp div {
padding: 8px 24px;
margin: 8px;
background-color: #ddddff;
}
#topo2tmp div div {
padding: 4px 10px;
}
#topo2tmp h4 {
margin: 0
}
#topo2tmp p {
margin: 0
}
#topo2tmp .nav-me:hover {
background-color: #bbbbdd;
}
#topo2tmp .nav-me {
font-weight: bold;
text-decoration: underline;
cursor: pointer;
}
......
<!-- Topology View partial HTML -->
<div id="ov-topo2">
<div id="topo2tmp">
<div class="parentRegion">
Parent Region: <span> - </span>
</div>
<div class="thisRegion">
This Region: <span> - </span>
</div>
<div class="subRegions">
<h4>Subregions</h4>
<div></div>
</div>
<div class="devices">
<h4>Devices</h4>
<div></div>
</div>
<div class="hosts">
<h4>Hosts</h4>
<div></div>
</div>
<div class="links">
<h4>Links</h4>
<div></div>
</div>
<div class="peers">
<h4>Peers</h4>
<div></div>
</div>
</div>
<!-- Below here is good; Above here is temporary, for debugging -->
<svg viewBox="0 0 1000 1000"
resize offset-height="56" offset-width="12"
notifier="notifyResize()">
......
......@@ -42,6 +42,7 @@
topo2AllInstances: t2fs,
topo2CurrentLayout: t2fs,
topo2CurrentRegion: t2fs,
topo2PeerRegions: t2fs,
topo2StartDone: t2fs
// Add further event names / module references as needed
......
......@@ -35,10 +35,79 @@
$log.debug('Destroy topo force layout');
}
// ========================== Temporary Code (to be deleted later)
function request(dir, rid) {
wss.sendEvent('topo2navRegion', {
dir: dir,
rid: rid
});
}
function doTmpCurrentLayout(data) {
var topdiv = d3.select('#topo2tmp');
var parentRegion = data.parent;
var span = topdiv.select('.parentRegion').select('span');
span.text(parentRegion || '[no parent]');
span.classed('nav-me', !!parentRegion);
}
function doTmpCurrentRegion(data) {
var topdiv = d3.select('#topo2tmp');
var span = topdiv.select('.thisRegion').select('span');
var div;
span.text(data.id);
div = topdiv.select('.subRegions').select('div');
data.subregions.forEach(function (r) {
function nav() {
request('down', r.id);
}
div.append('p')
.classed('nav-me', true)
.text(r.id)
.on('click', nav);
});
div = topdiv.select('.devices').select('div');
data.layerOrder.forEach(function (tag, idx) {
var devs = data.devices[idx];
devs.forEach(function (d) {
div.append('p')
.text('[' + tag + '] ' + d.id);
});
});
div = topdiv.select('.hosts').select('div');
data.layerOrder.forEach(function (tag, idx) {
var hosts = data.hosts[idx];
hosts.forEach(function (h) {
div.append('p')
.text('[' + tag + '] ' + h.id);
});
});
div = topdiv.select('.links').select('div');
var links = data.links;
links.forEach(function (lnk) {
div.append('p')
.text(lnk.id);
});
}
function doTmpPeerRegions(data) {
}
// ========================== Event Handlers
function allInstances(data) {
$log.debug('>> topo2AllInstances event:', data)
doTmpCurrentLayout(data);
}
function currentLayout(data) {
......@@ -47,6 +116,16 @@
function currentRegion(data) {
$log.debug('>> topo2CurrentRegion event:', data)
doTmpCurrentRegion(data);
}
function topo2PeerRegions(data) {
$log.debug('>> topo2PeerRegions event:', data)
doTmpPeerRegions(data);
}
function topo2PeerRegions(data) {
$log.debug('>> topo2PeerRegions event:', data)
}
function startDone(data) {
......@@ -69,6 +148,7 @@
topo2AllInstances: allInstances,
topo2CurrentLayout: currentLayout,
topo2CurrentRegion: currentRegion,
topo2PeerRegions: topo2PeerRegions,
topo2StartDone: startDone
};
}]);
......
/*
* 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.
*/
/*
* 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.
*/
/*
ONOS GUI -- Topology View (theme) -- CSS file
*/
/* --- Base SVG Layer --- */
#ov-topoX svg {
/*background-color: #f4f4f4;*/
background-color: goldenrod; /* just for testing */
}
/* --- "No Devices" Layer --- */
#ov-topoX svg .noDevsBird {
fill: #db7773;
}
#ov-topoX svg #topoX-noDevsLayer text {
fill: #7e9aa8;
}
/* --- Topo Map --- */
#ov-topoX svg #topoX-map {
stroke-width: 2px;
stroke: #f4f4f4;
fill: #e5e5e6;
}
/*
* 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.
*/
/*
ONOS GUI -- Topology View (layout) -- CSS file
*/
/* --- Base SVG Layer --- */
#ov-topoX svg {
/* prevents the little cut/copy/paste square that would appear on iPad */
-webkit-user-select: none;
}
/* -- TEMPORARY CSS (to be deleted) -- */
#topoXtmp div {
padding: 8px 24px;
margin: 8px;
background-color: #ddddff;
}
#topoXtmp div div {
padding: 4px 10px;
}
#topoXtmp h4 {
margin: 0
}
#topoXtmp p {
margin: 0
}
#topoXtmp .nav-me:hover {
background-color: #bbbbdd;
}
#topoXtmp .nav-me {
font-weight: bold;
text-decoration: underline;
cursor: pointer;
}
<!--
~ 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.
-->
<!-- Topology View partial HTML -->
<div id="ov-topoX">
<div id="topoXtmp">
<div class="parentRegion">
Parent Region: <span> - </span>
</div>
<div class="thisRegion">
This Region: <span> - </span>
</div>
<div class="subRegions">
<h4>Subregions</h4>
<div></div>
</div>
<div class="devices">
<h4>Devices</h4>
<div></div>
</div>
<div class="hosts">
<h4>Hosts</h4>
<div></div>
</div>
<div class="links">
<h4>Links</h4>
<div></div>
</div>
<div class="peers">
<h4>Peers</h4>
<div></div>
</div>
</div>
</div>
/*
* 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.
*/
/*
* 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.
*/
/*
ONOS GUI -- Topology View Module
NOTE: currently under development to support Regions.
*/
(function () {
'use strict';
// references to injected services
var $scope, $log, $loc,
fs, mast, ks, zs,
gs, ms, sus, flash,
wss, ps, th,
tXes, tXfs;
// DOM elements
var ovtopoX, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;
// Internal state
var zoomer, actionMap;
// === Helper Functions
// callback invoked when the SVG view has been resized..
function svgResized(s) {
$log.debug("topoX view resized", s);
}
function setUpKeys(overlayKeys) {
$log.debug('topoX: set up keys....');
}
// === Controller Definition -----------------------------------------
angular.module('ovTopoX', ['onosUtil', 'onosSvg', 'onosRemote'])
.controller('OvTopoXCtrl',
['$scope', '$log', '$location',
'FnService', 'MastService', 'KeyService', 'ZoomService',
'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
'WebSocketService', 'PrefsService', 'ThemeService',
'TopoXEventService', 'TopoXForceService',
function (_$scope_, _$log_, _$loc_,
_fs_, _mast_, _ks_, _zs_,
_gs_, _ms_, _sus_, _flash_,
_wss_, _ps_, _th_,
_tXes_, _tXfs_) {
var params = _$loc_.search(),
projection,
dim,
wh,
uplink = {
// provides function calls back into this space
// showNoDevs: showNoDevs,
// projection: function () { return projection; },
// zoomLayer: function () { return zoomLayer; },
// zoomer: function () { return zoomer; },
// opacifyMap: opacifyMap,
// topoStartDone: topoStartDone
};
$scope = _$scope_;
$log = _$log_;
$loc = _$loc_;
fs = _fs_;
mast = _mast_;
ks = _ks_;
zs = _zs_;
gs = _gs_;
ms = _ms_;
sus = _sus_;
flash = _flash_;
wss = _wss_;
ps = _ps_;
th = _th_;
tXes = _tXes_;
tXfs = _tXfs_;
// capture selected intent parameters (if they are set in the
// query string) so that the traffic overlay can highlight
// the path for that intent
if (params.intentKey && params.intentAppId && params.intentAppName) {
$scope.intentData = {
key: params.intentKey,
appId: params.intentAppId,
appName: params.intentAppName
};
}
$scope.notifyResize = function () {
svgResized(fs.windowSize(mast.mastHeight()));
};
// Cleanup on destroyed scope..
$scope.$on('$destroy', function () {
$log.log('OvTopoXCtrl is saying Buh-Bye!');
tXes.stop();
ks.unbindKeys();
tXfs.destroy();
});
// svg layer and initialization of components
ovtopoX = d3.select('#ov-topoX');
svg = ovtopoX.select('svg');
// set the svg size to match that of the window, less the masthead
wh = fs.windowSize(mast.mastHeight());
$log.debug('setting topo SVG size to', wh);
svg.attr(wh);
dim = [wh.width, wh.height];
// set up our keyboard shortcut bindings
setUpKeys();
// make sure we can respond to topology events from the server
tXes.bindHandlers();
// initialize the force layout, ready to render the topology
tXfs.init();
// =-=-=-=-=-=-=-=-
// TODO: in future, we will load background map data
// asynchronously (hence the promise) and then chain off
// there to send the topoXstart event to the server.
// For now, we'll send the event inline...
tXes.start();
// === ORIGINAL CODE ===
// setUpKeys();
// setUpToolbar();
// setUpDefs();
// setUpZoom();
// setUpNoDevs();
/*
setUpMap().then(
function (proj) {
var z = ps.getPrefs('topo_zoom', { tx:0, ty:0, sc:1 });
zoomer.panZoom([z.tx, z.ty], z.sc);
$log.debug('** Zoom restored:', z);
projection = proj;
$log.debug('** We installed the projection:', proj);
flash.enable(false);
toggleMap(prefsState.bg);
flash.enable(true);
mapShader(true);
// now we have the map projection, we are ready for
// the server to send us device/host data...
tes.start();
// need to do the following so we immediately get
// the summary panel data back from the server
restoreSummaryFromPrefs();
}
);
*/
// tes.bindHandlers();
// setUpSprites();
// forceG = zoomLayer.append('g').attr('id', 'topo-force');
// tfs.initForce(svg, forceG, uplink, dim);
// tis.initInst({ showMastership: tfs.showMastership });
// tps.initPanels();
// restoreConfigFromPrefs();
// ttbs.setDefaultOverlay(prefsState.ovidx);
// $log.debug('registered overlays...', tov.list());
$log.log('OvTopoXCtrl has been created');
}]);
}());
/*
* 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.
*/
/*
ONOS GUI -- Topology Event Module.
Defines the conduit between the client and the server:
- provides a clean API for sending events to the server
- dispatches incoming events from the server to the appropriate sub-module
*/
(function () {
'use strict';
// injected refs
var $log, wss, tXfs;
// internal state
var handlerMap,
openListener;
// ========================== Helper Functions
function createHandlerMap() {
handlerMap = {
topo2AllInstances: tXfs,
topo2CurrentLayout: tXfs,
topo2CurrentRegion: tXfs,
topo2PeerRegions: tXfs,
topo2StartDone: tXfs
// Add further event names / module references as needed
};
}
function wsOpen(host, url) {
$log.debug('topoXEvent: WSopen - cluster node:', host, 'URL:', url);
// tell the server we are ready to receive topo events
wss.sendEvent('topo2Start');
}
// bind our event handlers to the web socket service, so that our
// callbacks get invoked for incoming events
function bindHandlers() {
wss.bindHandlers(handlerMap);
$log.debug('topoX event handlers bound');
}
// tell the server we are ready to receive topology events
function start() {
// in case we fail over to a new server,
// listen for wsock-open events
openListener = wss.addOpenListener(wsOpen);
wss.sendEvent('topo2Start');
$log.debug('topoX comms started');
}
// tell the server we no longer wish to receive topology events
function stop() {
wss.sendEvent('topo2Stop');
wss.unbindHandlers(handlerMap);
wss.removeOpenListener(openListener);
openListener = null;
$log.debug('topoX comms stopped');
}
// ========================== Main Service Definition
angular.module('ovTopoX')
.factory('TopoXEventService',
['$log', 'WebSocketService', 'TopoXForceService',
function (_$log_, _wss_, _tXfs_) {
$log = _$log_;
wss = _wss_;
tXfs = _tXfs_;
// deferred creation of handler map, so module references are good
createHandlerMap();
return {
bindHandlers: bindHandlers,
start: start,
stop: stop
};
}]);
}());
/*
* 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.
*/
/*
ONOS GUI -- Topology Force Module.
Visualization of the topology in an SVG layer, using a D3 Force Layout.
*/
(function () {
'use strict';
// injected refs
var $log, wss;
// ========================== Helper Functions
function init() {
$log.debug('Initialize topo force layout');
}
function destroy() {
$log.debug('Destroy topo force layout');
}
// ========================== Temporary Code (to be deleted later)
function request(dir, rid) {
wss.sendEvent('topo2navRegion', {
dir: dir,
rid: rid
});
}
function doTmpCurrentLayout(data) {
var topdiv = d3.select('#topoXtmp');
var parentRegion = data.parent;
var span = topdiv.select('.parentRegion').select('span');
span.text(parentRegion || '[no parent]');
span.classed('nav-me', !!parentRegion);
}
function doTmpCurrentRegion(data) {
var topdiv = d3.select('#topoXtmp');
var span = topdiv.select('.thisRegion').select('span');
var div;
span.text(data.id);
div = topdiv.select('.subRegions').select('div');
data.subregions.forEach(function (r) {
function nav() {
request('down', r.id);
}
div.append('p')
.classed('nav-me', true)
.text(r.id)
.on('click', nav);
});
div = topdiv.select('.devices').select('div');
data.layerOrder.forEach(function (tag, idx) {
var devs = data.devices[idx];
devs.forEach(function (d) {
div.append('p')
.text('[' + tag + '] ' + d.id);
});
});
div = topdiv.select('.hosts').select('div');
data.layerOrder.forEach(function (tag, idx) {
var hosts = data.hosts[idx];
hosts.forEach(function (h) {
div.append('p')
.text('[' + tag + '] ' + h.id);
});
});
div = topdiv.select('.links').select('div');
var links = data.links;
links.forEach(function (lnk) {
div.append('p')
.text(lnk.id);
});
}
function doTmpPeerRegions(data) {
}
// ========================== Event Handlers
function allInstances(data) {
$log.debug('>> topo2AllInstances event:', data)
doTmpCurrentLayout(data);
}
function currentLayout(data) {
$log.debug('>> topo2CurrentLayout event:', data)
}
function currentRegion(data) {
$log.debug('>> topo2CurrentRegion event:', data)
doTmpCurrentRegion(data);
}
function peerRegions(data) {
$log.debug('>> topo2PeerRegions event:', data)
doTmpPeerRegions(data);
}
function startDone(data) {
$log.debug('>> topo2StartDone event:', data)
}
// ========================== Main Service Definition
angular.module('ovTopoX')
.factory('TopoXForceService',
['$log', 'WebSocketService',
function (_$log_, _wss_) {
$log = _$log_;
wss = _wss_;
return {
init: init,
destroy: destroy,
topo2AllInstances: allInstances,
topo2CurrentLayout: currentLayout,
topo2CurrentRegion: currentRegion,
topo2PeerRegions: peerRegions,
topo2StartDone: startDone
};
}]);
}());
......@@ -133,6 +133,12 @@
<link rel="stylesheet" href="app/view/topo2/topo2.css">
<link rel="stylesheet" href="app/view/topo2/topo2-theme.css">
<script src="app/view/topoX/topoX.js"></script>
<script src="app/view/topoX/topoXEvent.js"></script>
<script src="app/view/topoX/topoXForce.js"></script>
<link rel="stylesheet" href="app/view/topoX/topoX.css">
<link rel="stylesheet" href="app/view/topoX/topoX-theme.css">
<!-- Builtin views javascript. -->
<script src="app/view/topo/topo.js"></script>
<script src="app/view/topo/topoD3.js"></script>
......
......@@ -4,9 +4,11 @@
"id": "<null-region>",
"subregions": [{
"id": "r2",
"nodeType":"region",
"nDevs": 2
}, {
"id": "r1",
"nodeType":"region",
"nDevs": 3
}],
"devices": [
......@@ -14,6 +16,7 @@
[],
[{
"id": "null:0000000000000001",
"nodeType":"device",
"type": "switch",
"online": false,
"master": "",
......