Steven Burrows
Committed by Simon Hunt

Added Collections and Models for a Region.

Change-Id: Ic033b2890dad18e47b057e6b1d1c8535d812590d
...@@ -22,5 +22,7 @@ bucklets/plugins/ ...@@ -22,5 +22,7 @@ bucklets/plugins/
22 /bin/ 22 /bin/
23 23
24 web/gui/src/main/webapp/tests/node_modules 24 web/gui/src/main/webapp/tests/node_modules
25 +web/gui/src/test/_karma/node_modules
25 web/gui/src/main/webapp/node_modules/ 26 web/gui/src/main/webapp/node_modules/
27 +
26 npm-debug.log 28 npm-debug.log
......
1 /* 1 /*
2 - * Copyright 2016-present Open Networking Laboratory 2 +* Copyright 2016-present Open Networking Laboratory
3 - * 3 +*
4 - * Licensed under the Apache License, Version 2.0 (the "License"); 4 +* Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License. 5 +* you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at 6 +* You may obtain a copy of the License at
7 - * 7 +*
8 - * http://www.apache.org/licenses/LICENSE-2.0 8 +* http://www.apache.org/licenses/LICENSE-2.0
9 - * 9 +*
10 - * Unless required by applicable law or agreed to in writing, software 10 +* Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS, 11 +* distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and 13 +* See the License for the specific language governing permissions and
14 - * limitations under the License. 14 +* limitations under the License.
15 - */ 15 +*/
16 16
17 /* 17 /*
18 ONOS GUI -- Topology View Module 18 ONOS GUI -- Topology View Module
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
28 fs, mast, ks, zs, 28 fs, mast, ks, zs,
29 gs, ms, sus, flash, 29 gs, ms, sus, flash,
30 wss, ps, th, 30 wss, ps, th,
31 - t2es, t2fs; 31 + t2es, t2fs, t2is;
32 32
33 // DOM elements 33 // DOM elements
34 var ovtopo2, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer; 34 var ovtopo2, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;
...@@ -37,32 +37,66 @@ ...@@ -37,32 +37,66 @@
37 var zoomer, actionMap; 37 var zoomer, actionMap;
38 38
39 39
40 - // === Helper Functions 40 + // --- Glyphs, Icons, and the like -----------------------------------
41 +
42 + function setUpDefs() {
43 + defs = svg.append('defs');
44 + gs.loadDefs(defs);
45 + sus.loadGlowDefs(defs);
46 + }
41 47
42 // callback invoked when the SVG view has been resized.. 48 // callback invoked when the SVG view has been resized..
43 function svgResized(s) { 49 function svgResized(s) {
44 - $log.debug("topo2 view resized", s); 50 + $log.debug('topo2 view resized', s);
45 } 51 }
46 52
47 function setUpKeys(overlayKeys) { 53 function setUpKeys(overlayKeys) {
48 $log.debug('topo2: set up keys....'); 54 $log.debug('topo2: set up keys....');
49 } 55 }
50 56
57 + // --- Pan and Zoom --------------------------------------------------
58 +
59 + // zoom enabled predicate. ev is a D3 source event.
60 + function zoomEnabled(ev) {
61 + return fs.isMobile() || (ev.metaKey || ev.altKey);
62 + }
63 +
64 + function zoomCallback() {
65 + var sc = zoomer.scale(),
66 + tr = zoomer.translate();
67 +
68 + ps.setPrefs('topo_zoom', {tx:tr[0], ty:tr[1], sc:sc});
69 +
70 + // keep the map lines constant width while zooming
71 + mapG.style('stroke-width', (2.0 / sc) + 'px');
72 + }
73 +
74 + function setUpZoom() {
75 + zoomLayer = svg.append('g').attr('id', 'topo-zoomlayer');
76 + zoomer = zs.createZoomer({
77 + svg: svg,
78 + zoomLayer: zoomLayer,
79 + zoomEnabled: zoomEnabled,
80 + zoomCallback: zoomCallback
81 + });
82 + }
83 +
84 +
51 // === Controller Definition ----------------------------------------- 85 // === Controller Definition -----------------------------------------
52 86
53 angular.module('ovTopo2', ['onosUtil', 'onosSvg', 'onosRemote']) 87 angular.module('ovTopo2', ['onosUtil', 'onosSvg', 'onosRemote'])
54 - .controller('OvTopo2Ctrl', 88 + .controller('OvTopo2Ctrl',
55 ['$scope', '$log', '$location', 89 ['$scope', '$log', '$location',
56 'FnService', 'MastService', 'KeyService', 'ZoomService', 90 'FnService', 'MastService', 'KeyService', 'ZoomService',
57 'GlyphService', 'MapService', 'SvgUtilService', 'FlashService', 91 'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
58 'WebSocketService', 'PrefsService', 'ThemeService', 92 'WebSocketService', 'PrefsService', 'ThemeService',
59 - 'Topo2EventService', 'Topo2ForceService', 93 + 'Topo2EventService', 'Topo2ForceService', 'Topo2InstanceService',
60 94
61 function (_$scope_, _$log_, _$loc_, 95 function (_$scope_, _$log_, _$loc_,
62 - _fs_, _mast_, _ks_, _zs_, 96 + _fs_, _mast_, _ks_, _zs_,
63 - _gs_, _ms_, _sus_, _flash_, 97 + _gs_, _ms_, _sus_, _flash_,
64 - _wss_, _ps_, _th_, 98 + _wss_, _ps_, _th_,
65 - _t2es_, _t2fs_) { 99 + _t2es_, _t2fs_, _t2is_) {
66 100
67 var params = _$loc_.search(), 101 var params = _$loc_.search(),
68 projection, 102 projection,
...@@ -95,9 +129,10 @@ ...@@ -95,9 +129,10 @@
95 wss = _wss_; 129 wss = _wss_;
96 ps = _ps_; 130 ps = _ps_;
97 th = _th_; 131 th = _th_;
98 - 132 +
99 t2es = _t2es_; 133 t2es = _t2es_;
100 t2fs = _t2fs_; 134 t2fs = _t2fs_;
135 + t2is = _t2is_;
101 136
102 // capture selected intent parameters (if they are set in the 137 // capture selected intent parameters (if they are set in the
103 // query string) so that the traffic overlay can highlight 138 // query string) so that the traffic overlay can highlight
...@@ -134,24 +169,32 @@ ...@@ -134,24 +169,32 @@
134 169
135 // set up our keyboard shortcut bindings 170 // set up our keyboard shortcut bindings
136 setUpKeys(); 171 setUpKeys();
172 + setUpZoom();
173 + setUpDefs();
137 174
138 // make sure we can respond to topology events from the server 175 // make sure we can respond to topology events from the server
139 t2es.bindHandlers(); 176 t2es.bindHandlers();
140 177
141 // initialize the force layout, ready to render the topology 178 // initialize the force layout, ready to render the topology
142 - t2fs.init(); 179 + forceG = zoomLayer.append('g').attr('id', 'topo-force');
180 + t2fs.init(svg, forceG, uplink, dim);
143 181
144 182
145 // =-=-=-=-=-=-=-=- 183 // =-=-=-=-=-=-=-=-
146 // TODO: in future, we will load background map data 184 // TODO: in future, we will load background map data
147 - // asynchronously (hence the promise) and then chain off 185 + // asynchronously (hence the promise) and then chain off
148 // there to send the topo2start event to the server. 186 // there to send the topo2start event to the server.
149 // For now, we'll send the event inline... 187 // For now, we'll send the event inline...
150 t2es.start(); 188 t2es.start();
151 189
152 - 190 +
191 +
192 + t2is.initInst({ showMastership: t2fs.showMastership });
193 +
194 +
195 +
153 // === ORIGINAL CODE === 196 // === ORIGINAL CODE ===
154 - 197 +
155 // setUpKeys(); 198 // setUpKeys();
156 // setUpToolbar(); 199 // setUpToolbar();
157 // setUpDefs(); 200 // setUpDefs();
...@@ -192,7 +235,7 @@ ...@@ -192,7 +235,7 @@
192 // ttbs.setDefaultOverlay(prefsState.ovidx); 235 // ttbs.setDefaultOverlay(prefsState.ovidx);
193 236
194 // $log.debug('registered overlays...', tov.list()); 237 // $log.debug('registered overlays...', tov.list());
195 - 238 +
196 $log.log('OvTopo2Ctrl has been created'); 239 $log.log('OvTopo2Ctrl has been created');
197 }]); 240 }]);
198 }()); 241 }());
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology Collection Module.
19 + A Data Store that contains model data from the server
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + var Model;
26 +
27 + function Collection(models, options) {
28 +
29 + options || (options = {});
30 +
31 + this.models = [];
32 + this._reset();
33 +
34 + if (options.comparator !== void 0) this.comparator = options.comparator;
35 +
36 + if (models) {
37 + this.add(models);
38 + }
39 + }
40 +
41 + Collection.prototype = {
42 + model: Model,
43 + add: function (data) {
44 +
45 + var _this = this;
46 +
47 + if (angular.isArray(data)) {
48 +
49 + data.forEach(function (d) {
50 +
51 + var model = new _this.model(d);
52 + model.collection = _this;
53 +
54 + _this.models.push(model);
55 + _this._byId[d.id] = model;
56 + });
57 + }
58 +
59 +// this.sort();
60 + },
61 + get: function (id) {
62 + if (!id) {
63 + return void 0;
64 + }
65 + return this._byId[id] || null;
66 + },
67 + sort: function () {
68 +
69 + var comparator = this.comparator;
70 +
71 + // Check if function
72 + comparator = comparator.bind(this);
73 + this.models.sort(comparator);
74 +
75 + return this;
76 + },
77 + _reset: function () {
78 + this._byId = [];
79 + this.models = [];
80 + }
81 + };
82 +
83 + Collection.extend = function (protoProps, staticProps) {
84 +
85 + var parent = this;
86 + var child;
87 +
88 + child = function () {
89 + return parent.apply(this, arguments);
90 + };
91 +
92 + angular.extend(child, parent, staticProps);
93 +
94 + // Set the prototype chain to inherit from `parent`, without calling
95 + // `parent`'s constructor function and add the prototype properties.
96 + child.prototype = angular.extend({}, parent.prototype, protoProps);
97 + child.prototype.constructor = child;
98 +
99 + // Set a convenience property in case the parent's prototype is needed
100 + // later.
101 + child.__super__ = parent.prototype;
102 +
103 + return child;
104 + };
105 +
106 + angular.module('ovTopo2')
107 + .factory('Topo2Collection',
108 + ['Topo2Model',
109 + function (_Model_) {
110 +
111 + Model = _Model_;
112 + return Collection;
113 + }
114 + ]);
115 +
116 +})();
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology Devices Module.
19 + Module that holds the devices for a region
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + var Collection, Model;
26 +
27 + function createDeviceCollection(data, region) {
28 +
29 + var DeviceCollection = Collection.extend({
30 + model: Model,
31 + get: function () {},
32 + comparator: function(a, b) {
33 +
34 + var order = region.layerOrder;
35 + return order.indexOf(a.get('layer')) - order.indexOf(b.get('layer'));
36 + }
37 + });
38 +
39 + var devices = [];
40 + data.forEach(function (deviceLayer) {
41 + deviceLayer.forEach(function (device) {
42 + devices.push(device);
43 + });
44 + });
45 +
46 + var deviceCollection = new DeviceCollection(devices);
47 + deviceCollection.sort();
48 +
49 + return deviceCollection;
50 + }
51 +
52 + angular.module('ovTopo2')
53 + .factory('Topo2DeviceService',
54 + ['Topo2Collection', 'Topo2Model',
55 +
56 + function (_Collection_, _Model_) {
57 +
58 + Collection = _Collection_;
59 + Model = _Model_.extend({});
60 +
61 + return {
62 + createDeviceCollection: createDeviceCollection
63 + };
64 + }
65 + ]);
66 +
67 +})();
...@@ -23,12 +23,99 @@ ...@@ -23,12 +23,99 @@
23 'use strict'; 23 'use strict';
24 24
25 // injected refs 25 // injected refs
26 - var $log, wss; 26 + var $log,
27 + wss;
28 +
29 + // SVG elements;
30 + var linkG,
31 + linkLabelG,
32 + numLinkLblsG,
33 + portLabelG,
34 + nodeG;
35 +
36 + // internal state
37 + var settings, // merged default settings and options
38 + force, // force layout object
39 + drag, // drag behavior handler
40 + network = {
41 + nodes: [],
42 + links: [],
43 + linksByDevice: {},
44 + lookup: {},
45 + revLinkToKey: {}
46 + },
47 + lu, // shorthand for lookup
48 + rlk, // shorthand for revLinktoKey
49 + showHosts = false, // whether hosts are displayed
50 + showOffline = true, // whether offline devices are displayed
51 + nodeLock = false, // whether nodes can be dragged or not (locked)
52 + fTimer, // timer for delayed force layout
53 + fNodesTimer, // timer for delayed nodes update
54 + fLinksTimer, // timer for delayed links update
55 + dim, // the dimensions of the force layout [w,h]
56 + linkNums = []; // array of link number labels
57 +
58 + // D3 selections;
59 + var link,
60 + linkLabel,
61 + node;
62 +
63 + var $log, wss, t2is, t2rs;
27 64
28 // ========================== Helper Functions 65 // ========================== Helper Functions
29 66
30 - function init() { 67 + function init(_svg_, forceG, _uplink_, _dim_, opts) {
68 +
31 $log.debug('Initialize topo force layout'); 69 $log.debug('Initialize topo force layout');
70 +
71 + nodeG = forceG.append('g').attr('id', 'topo-nodes');
72 + node = nodeG.selectAll('.node');
73 +
74 + linkG = forceG.append('g').attr('id', 'topo-links');
75 + linkLabelG = forceG.append('g').attr('id', 'topo-linkLabels');
76 + numLinkLblsG = forceG.append('g').attr('id', 'topo-numLinkLabels');
77 + nodeG = forceG.append('g').attr('id', 'topo-nodes');
78 + portLabelG = forceG.append('g').attr('id', 'topo-portLabels');
79 +
80 + link = linkG.selectAll('.link');
81 + linkLabel = linkLabelG.selectAll('.linkLabel');
82 + node = nodeG.selectAll('.node');
83 +
84 + var width = 640,
85 + height = 480;
86 +
87 + var nodes = [
88 + { x: width/3, y: height/2 },
89 + { x: 2*width/3, y: height/2 }
90 + ];
91 +
92 + var links = [
93 + { source: 0, target: 1 }
94 + ];
95 +
96 + var svg = d3.select('body').append('svg')
97 + .attr('width', width)
98 + .attr('height', height);
99 +
100 + var force = d3.layout.force()
101 + .size([width, height])
102 + .nodes(nodes)
103 + .links(links);
104 +
105 + force.linkDistance(width/2);
106 +
107 +
108 + var link = svg.selectAll('.link')
109 + .data(links)
110 + .enter().append('line')
111 + .attr('class', 'link');
112 +
113 + var node = svg.selectAll('.node')
114 + .data(nodes)
115 + .enter().append('circle')
116 + .attr('class', 'node');
117 +
118 + force.start();
32 } 119 }
33 120
34 function destroy() { 121 function destroy() {
...@@ -106,17 +193,19 @@ ...@@ -106,17 +193,19 @@
106 // ========================== Event Handlers 193 // ========================== Event Handlers
107 194
108 function allInstances(data) { 195 function allInstances(data) {
109 - $log.debug('>> topo2AllInstances event:', data) 196 + $log.debug('>> topo2AllInstances event:', data);
110 doTmpCurrentLayout(data); 197 doTmpCurrentLayout(data);
198 + t2is.allInstances(data);
111 } 199 }
112 200
113 function currentLayout(data) { 201 function currentLayout(data) {
114 - $log.debug('>> topo2CurrentLayout event:', data) 202 + $log.debug('>> topo2CurrentLayout event:', data);
115 } 203 }
116 204
117 function currentRegion(data) { 205 function currentRegion(data) {
118 - $log.debug('>> topo2CurrentRegion event:', data) 206 + $log.debug('>> topo2CurrentRegion event:', data);
119 doTmpCurrentRegion(data); 207 doTmpCurrentRegion(data);
208 + t2rs.addRegion(data);
120 } 209 }
121 210
122 function topo2PeerRegions(data) { 211 function topo2PeerRegions(data) {
...@@ -129,27 +218,68 @@ ...@@ -129,27 +218,68 @@
129 } 218 }
130 219
131 function startDone(data) { 220 function startDone(data) {
132 - $log.debug('>> topo2StartDone event:', data) 221 + $log.debug('>> topo2StartDone event:', data);
133 } 222 }
134 - 223 +
224 +
225 + function showMastership(masterId) {
226 + if (!masterId) {
227 + restoreLayerState();
228 + } else {
229 + showMastershipFor(masterId);
230 + }
231 + }
232 +
233 + function restoreLayerState() {
234 + // NOTE: this level of indirection required, for when we have
235 + // the layer filter functionality re-implemented
236 + suppressLayers(false);
237 + }
238 +
239 + // ========================== Main Service Definition
240 +
241 + function showMastershipFor(id) {
242 + suppressLayers(true);
243 + node.each(function (n) {
244 + if (n.master === id) {
245 + n.el.classed('suppressedmax', false);
246 + }
247 + });
248 + }
249 +
250 + function supAmt(less) {
251 + return less ? 'suppressed' : 'suppressedmax';
252 + }
253 +
254 + function suppressLayers(b, less) {
255 + var cls = supAmt(less);
256 + node.classed(cls, b);
257 + // link.classed(cls, b);
258 + }
259 +
135 // ========================== Main Service Definition 260 // ========================== Main Service Definition
136 261
137 angular.module('ovTopo2') 262 angular.module('ovTopo2')
138 .factory('Topo2ForceService', 263 .factory('Topo2ForceService',
139 - ['$log', 'WebSocketService', 264 + ['$log', 'WebSocketService', 'Topo2InstanceService', 'Topo2RegionService',
140 - 265 + function (_$log_, _wss_, _t2is_, _t2rs_) {
141 - function (_$log_, _wss_) {
142 $log = _$log_; 266 $log = _$log_;
143 wss = _wss_; 267 wss = _wss_;
144 - 268 + t2is = _t2is_;
269 + t2rs = _t2rs_;
270 +
145 return { 271 return {
272 +
146 init: init, 273 init: init,
274 +
147 destroy: destroy, 275 destroy: destroy,
148 topo2AllInstances: allInstances, 276 topo2AllInstances: allInstances,
149 topo2CurrentLayout: currentLayout, 277 topo2CurrentLayout: currentLayout,
150 topo2CurrentRegion: currentRegion, 278 topo2CurrentRegion: currentRegion,
151 - topo2PeerRegions: topo2PeerRegions, 279 + topo2StartDone: startDone,
152 - topo2StartDone: startDone 280 +
281 + showMastership: showMastership,
282 + topo2PeerRegions: topo2PeerRegions
153 }; 283 };
154 }]); 284 }]);
155 }()); 285 }());
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology Hosts Module.
19 + Module that holds the hosts for a region
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + var Collection, Model;
26 +
27 + function createHostCollection(data, region) {
28 +
29 + var HostCollection = Collection.extend({
30 + model: Model
31 + });
32 +
33 + var hosts = [];
34 + data.forEach(function (hostsLayer) {
35 + hostsLayer.forEach(function (host) {
36 + hosts.push(host);
37 + });
38 + });
39 +
40 + return new HostCollection(hosts);
41 + }
42 +
43 + angular.module('ovTopo2')
44 + .factory('Topo2HostService',
45 + ['Topo2Collection', 'Topo2Model',
46 +
47 + function (_Collection_, _Model_) {
48 +
49 + Collection = _Collection_;
50 + Model = _Model_.extend();
51 +
52 + return {
53 + createHostCollection: createHostCollection
54 + };
55 + }
56 + ]);
57 +
58 +})();
1 +(function () {
2 + 'use strict';
3 +
4 + // injected refs
5 + var $log,
6 + ps,
7 + sus,
8 + gs,
9 + ts,
10 + fs,
11 + flash;
12 +
13 + // api from topo
14 + var api;
15 +
16 + // configuration
17 + var showLogicErrors = true,
18 + idIns = 'topo-p-instance',
19 + instOpts = {
20 + edge: 'left',
21 + width: 20
22 + };
23 +
24 + // internal state
25 + var onosInstances,
26 + onosOrder,
27 + oiShowMaster,
28 + oiBox;
29 +
30 +
31 + function addInstance(data) {
32 + var id = data.id;
33 +
34 + if (onosInstances[id]) {
35 + updateInstance(data);
36 + return;
37 + }
38 + onosInstances[id] = data;
39 + onosOrder.push(data);
40 + updateInstances();
41 + }
42 +
43 + function updateInstance(data) {
44 + var id = data.id,
45 + d = onosInstances[id];
46 + if (d) {
47 + angular.extend(d, data);
48 + updateInstances();
49 + } else {
50 + logicError('updateInstance: lookup fail: ID = "' + id + '"');
51 + }
52 + }
53 +
54 + function removeInstance(data) {
55 + var id = data.id,
56 + d = onosInstances[id];
57 + if (d) {
58 + var idx = fs.find(id, onosOrder);
59 + if (idx >= 0) {
60 + onosOrder.splice(idx, 1);
61 + }
62 + delete onosInstances[id];
63 + updateInstances();
64 + } else {
65 + logicError('removeInstance lookup fail. ID = "' + id + '"');
66 + }
67 + }
68 +
69 + // ==========================
70 +
71 + function clickInst(d) {
72 + var el = d3.select(this),
73 + aff = el.classed('affinity');
74 + if (!aff) {
75 + setAffinity(el, d);
76 + } else {
77 + cancelAffinity();
78 + }
79 + }
80 +
81 + function setAffinity(el, d) {
82 + d3.selectAll('.onosInst')
83 + .classed('mastership', true)
84 + .classed('affinity', false);
85 + el.classed('affinity', true);
86 +
87 + // suppress all elements except nodes whose master is this instance
88 + api.showMastership(d.id);
89 + oiShowMaster = true;
90 + }
91 +
92 + function cancelAffinity() {
93 + d3.selectAll('.onosInst')
94 + .classed('mastership affinity', false);
95 +
96 + api.showMastership(null);
97 + oiShowMaster = false;
98 + }
99 +
100 + function attachUiBadge(svg) {
101 + gs.addGlyph(svg, 'uiAttached', 24, true, [14, 54])
102 + .classed('badgeIcon uiBadge', true);
103 + }
104 +
105 + function attachReadyBadge(svg) {
106 + gs.addGlyph(svg, 'checkMark', 16, true, [18, 40])
107 + .classed('badgeIcon readyBadge', true);
108 + }
109 +
110 + function instColor(id, online) {
111 + return sus.cat7().getColor(id, !online, ts.theme());
112 + }
113 +
114 + // ==============================
115 +
116 + function updateInstances() {
117 + var rox = 5,
118 + roy = 5,
119 + rw = 160,
120 + rhh = 30,
121 + rbh = 45,
122 + tx = 48,
123 + instSvg = {
124 + width: 170,
125 + height: 85,
126 + viewBox: '0 0 170 85'
127 + },
128 + headRect = {
129 + x: rox,
130 + y: roy,
131 + width: rw,
132 + height: rhh
133 + },
134 + bodyRect = {
135 + x: rox,
136 + y: roy + rhh,
137 + width: rw,
138 + height: rbh
139 + },
140 + titleAttr = {
141 + class: 'instTitle',
142 + x: tx,
143 + y: 27
144 + };
145 +
146 + var onoses = oiBox.el().selectAll('.onosInst')
147 + .data(onosOrder, function (d) { return d.id; });
148 +
149 + function nSw(n) {
150 + return 'Devices: ' + n;
151 + }
152 +
153 + // operate on existing onos instances if necessary
154 + onoses.each(function (d) {
155 + var el = d3.select(this),
156 + svg = el.select('svg');
157 +
158 + // update online state
159 + el.classed('online', d.online);
160 + el.classed('ready', d.ready);
161 +
162 + // update ui-attached state
163 + svg.select('use.uiBadge').remove();
164 + if (d.uiAttached) {
165 + attachUiBadge(svg);
166 + }
167 +
168 + function updAttr(id, value) {
169 + svg.select('text.instLabel.' + id).text(value);
170 + }
171 +
172 + updAttr('ip', d.ip);
173 + updAttr('ns', nSw(d.switches));
174 + });
175 +
176 +
177 + // operate on new onos instances
178 + var entering = onoses.enter()
179 + .append('div')
180 + .classed('onosInst', true)
181 + .classed('online', function (d) { return d.online; })
182 + .classed('ready', function (d) { return d.ready; })
183 + .on('click', clickInst);
184 +
185 + entering.each(function (d) {
186 + var el = d3.select(this),
187 + svg = el.append('svg').attr(instSvg);
188 +
189 + svg.append('rect').attr(headRect);
190 + svg.append('rect').attr(bodyRect);
191 +
192 + gs.addGlyph(svg, 'bird', 20, false, [15, 10])
193 + .classed('badgeIcon bird', true);
194 +
195 + attachReadyBadge(svg);
196 +
197 + if (d.uiAttached) {
198 + attachUiBadge(svg);
199 + }
200 +
201 + svg.append('text')
202 + .attr(titleAttr)
203 + .text(d.id);
204 +
205 + var ty = 55;
206 + function addAttr(id, label) {
207 + svg.append('text').attr({
208 + class: 'instLabel ' + id,
209 + x: tx,
210 + y: ty
211 + }).text(label);
212 + ty += 18;
213 + }
214 +
215 + addAttr('ip', d.ip);
216 + addAttr('ns', nSw(d.switches));
217 + });
218 +
219 + // operate on existing + new onoses here
220 + // set the affinity colors...
221 + onoses.each(function (d) {
222 +
223 + var el = d3.select(this),
224 + rect = el.select('svg').select('rect'),
225 + col = instColor(d.id, d.online);
226 +
227 + rect.style('fill', col);
228 + });
229 +
230 + // adjust the panel size appropriately...
231 + oiBox.width(instSvg.width * onosOrder.length);
232 + oiBox.height(instSvg.height);
233 +
234 + // remove any outgoing instances
235 + onoses.exit().remove();
236 + }
237 +
238 +
239 + // ==========================
240 +
241 + function logicError(msg) {
242 + if (showLogicErrors) {
243 + $log.warn('TopoInstService: ' + msg);
244 + }
245 + }
246 +
247 + function initInst(_api_) {
248 + api = _api_;
249 + oiBox = ps.createPanel(idIns, instOpts);
250 + oiBox.show();
251 +
252 + onosInstances = {};
253 + onosOrder = [];
254 + oiShowMaster = false;
255 +
256 + // we want to update the instances, each time the theme changes
257 + ts.addListener(updateInstances);
258 + }
259 +
260 + function destroyInst() {
261 + ts.removeListener(updateInstances);
262 +
263 + ps.destroyPanel(idIns);
264 + oiBox = null;
265 +
266 + onosInstances = {};
267 + onosOrder = [];
268 + oiShowMaster = false;
269 + }
270 +
271 + function allInstances(data) {
272 + $log.debug('Update all instances', data);
273 +
274 + var members = data.members;
275 +
276 + members.forEach(function (member) {
277 + addInstance(member);
278 + });
279 + }
280 +
281 + angular.module('ovTopo2')
282 + .factory('Topo2InstanceService',
283 + ['$log', 'PanelService', 'SvgUtilService', 'GlyphService',
284 + 'ThemeService', 'FnService', 'FlashService',
285 +
286 + function (_$log_, _ps_, _sus_, _gs_, _ts_, _fs_, _flash_) {
287 + $log = _$log_;
288 + ps = _ps_;
289 + sus = _sus_;
290 + gs = _gs_;
291 + ts = _ts_;
292 + fs = _fs_;
293 + flash = _flash_;
294 +
295 + return {
296 + initInst: initInst,
297 + allInstances: allInstances
298 + };
299 + }]);
300 +
301 +}());
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology Links Module.
19 + Module that holds the links for a region
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + var Collection, Model;
26 +
27 + function createLinkCollection(data, region) {
28 +
29 + var LinkCollection = Collection.extend({
30 + model: Model
31 + });
32 +
33 + return new LinkCollection(data);
34 + }
35 +
36 + angular.module('ovTopo2')
37 + .factory('Topo2LinkService',
38 + ['Topo2Collection', 'Topo2Model',
39 +
40 + function (_Collection_, _Model_) {
41 +
42 + Collection = _Collection_;
43 + Model = _Model_.extend({});
44 +
45 + return {
46 + createLinkCollection: createLinkCollection
47 + };
48 + }
49 + ]);
50 +
51 +})();
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology Force Module.
19 + Visualization of the topology in an SVG layer, using a D3 Force Layout.
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + function Model(attributes) {
26 +
27 + var attrs = attributes || {};
28 + this.attributes = {};
29 +
30 + attrs = angular.extend({}, attrs);
31 + this.set(attrs);
32 + }
33 +
34 + Model.prototype = {
35 +
36 + get: function (attr) {
37 + return this.attributes[attr];
38 + },
39 +
40 + set: function(data) {
41 + angular.extend(this.attributes, data);
42 + },
43 + };
44 +
45 +
46 + Model.extend = function (protoProps, staticProps) {
47 +
48 + var parent = this;
49 + var child;
50 +
51 + child = function () {
52 + return parent.apply(this, arguments);
53 + };
54 +
55 + angular.extend(child, parent, staticProps);
56 +
57 + // Set the prototype chain to inherit from `parent`, without calling
58 + // `parent`'s constructor function and add the prototype properties.
59 + child.prototype = angular.extend({}, parent.prototype, protoProps);
60 + child.prototype.constructor = child;
61 +
62 + // Set a convenience property in case the parent's prototype is needed
63 + // later.
64 + child.__super__ = parent.prototype;
65 +
66 + return child;
67 + };
68 +
69 + angular.module('ovTopo2')
70 + .factory('Topo2Model',
71 + [
72 + function () {
73 + return Model;
74 + }
75 + ]);
76 +
77 +})();
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology Region Module.
19 + Module that holds the current region in memory
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + var $log,
26 + wss,
27 + t2sr,
28 + t2ds,
29 + t2hs,
30 + t2ls;
31 +
32 + var regions;
33 +
34 + function init() {
35 + regions = {};
36 + }
37 +
38 + function addRegion(data) {
39 +
40 + var region = {
41 + subregions: t2sr.createSubRegionCollection(data.subregions),
42 + devices: t2ds.createDeviceCollection(data.devices, data),
43 + hosts: t2hs.createHostCollection(data.hosts),
44 + links: t2ls.createLinkCollection(data.links),
45 + };
46 +
47 + $log.debug('Region: ', region);
48 + }
49 +
50 + angular.module('ovTopo2')
51 + .factory('Topo2RegionService',
52 + ['$log', 'WebSocketService', 'Topo2SubRegionService', 'Topo2DeviceService',
53 + 'Topo2HostService', 'Topo2LinkService',
54 +
55 + function (_$log_, _wss_, _t2sr_, _t2ds_, _t2hs_, _t2ls_) {
56 +
57 + $log = _$log_;
58 + wss = _wss_;
59 + t2sr = _t2sr_;
60 + t2ds = _t2ds_;
61 + t2hs = _t2hs_;
62 + t2ls = _t2ls_;
63 +
64 + return {
65 + init: init,
66 +
67 + addRegion: addRegion,
68 + getSubRegions: t2sr.getSubRegions
69 + };
70 + }]);
71 +
72 +})();
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology SubRegion Module.
19 + Module that holds the sub-regions for a region
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + var Collection, Model;
26 +
27 + function createSubRegionCollection(data, region) {
28 +
29 + var SubRegionCollection = Collection.extend({
30 + model: Model
31 + });
32 +
33 + return new SubRegionCollection(data);
34 + }
35 +
36 + angular.module('ovTopo2')
37 + .factory('Topo2SubRegionService',
38 + ['Topo2Collection', 'Topo2Model',
39 +
40 + function (_Collection_, _Model_) {
41 +
42 + Collection = _Collection_;
43 + Model = _Model_.extend({});
44 +
45 + return {
46 + createSubRegionCollection: createSubRegionCollection
47 + };
48 + }
49 + ]);
50 +
51 +})();
...@@ -127,8 +127,16 @@ ...@@ -127,8 +127,16 @@
127 127
128 <!-- Under development for Region support. --> 128 <!-- Under development for Region support. -->
129 <script src="app/view/topo2/topo2.js"></script> 129 <script src="app/view/topo2/topo2.js"></script>
130 + <script src="app/view/topo2/topo2Collection.js"></script>
131 + <script src="app/view/topo2/topo2Device.js"></script>
132 + <script src="app/view/topo2/topo2Model.js"></script>
130 <script src="app/view/topo2/topo2Event.js"></script> 133 <script src="app/view/topo2/topo2Event.js"></script>
131 <script src="app/view/topo2/topo2Force.js"></script> 134 <script src="app/view/topo2/topo2Force.js"></script>
135 + <script src="app/view/topo2/topo2Host.js"></script>
136 + <script src="app/view/topo2/topo2Instance.js"></script>
137 + <script src="app/view/topo2/topo2Link.js"></script>
138 + <script src="app/view/topo2/topo2Region.js"></script>
139 + <script src="app/view/topo2/topo2SubRegion.js"></script>
132 <link rel="stylesheet" href="app/view/topo2/topo2.css"> 140 <link rel="stylesheet" href="app/view/topo2/topo2.css">
133 <link rel="stylesheet" href="app/view/topo2/topo2-theme.css"> 141 <link rel="stylesheet" href="app/view/topo2/topo2-theme.css">
134 142
......