blob: 22e2b473d5770bfde848f55949067ae90fc7b319 [file] [log] [blame]
Simon Hunt4b668592015-01-29 17:33:53 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Simon Hunt4b668592015-01-29 17:33:53 -08003 *
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 Instances Module.
19 Defines modeling of ONOS instances.
20 */
21
22(function () {
23 'use strict';
24
25 // injected refs
Simon Huntee7a3ce2015-04-09 13:28:37 -070026 var $log, ps, sus, gs, ts, fs, flash;
Simon Hunt4b668592015-01-29 17:33:53 -080027
Simon Hunta142dd22015-02-12 22:07:51 -080028 // api from topo
29 var api;
30 /*
31 showMastership( id )
32 */
33
Simon Hunt4b668592015-01-29 17:33:53 -080034 // configuration
Simon Hunta9761342016-06-10 18:02:53 -070035 var showLogicErrors = true,
Simon Hunt4b668592015-01-29 17:33:53 -080036 idIns = 'topo-p-instance',
37 instOpts = {
38 edge: 'left',
39 width: 20
40 };
41
42 // internal state
43 var onosInstances,
44 onosOrder,
45 oiShowMaster,
Simon Huntf51bf462016-06-29 16:22:57 -070046 oiBox;
Simon Hunt4b668592015-01-29 17:33:53 -080047
48
Simon Hunt4b668592015-01-29 17:33:53 -080049 function addInstance(data) {
50 var id = data.id;
51
52 if (onosInstances[id]) {
53 updateInstance(data);
54 return;
55 }
56 onosInstances[id] = data;
57 onosOrder.push(data);
58 updateInstances();
59 }
60
61 function updateInstance(data) {
62 var id = data.id,
63 d = onosInstances[id];
64 if (d) {
65 angular.extend(d, data);
66 updateInstances();
67 } else {
68 logicError('updateInstance: lookup fail: ID = "' + id + '"');
69 }
70 }
71
Simon Hunt48e61672015-01-30 14:48:25 -080072 function removeInstance(data) {
73 var id = data.id,
74 d = onosInstances[id];
75 if (d) {
76 var idx = fs.find(id, onosOrder);
77 if (idx >= 0) {
78 onosOrder.splice(idx, 1);
79 }
80 delete onosInstances[id];
81 updateInstances();
82 } else {
83 logicError('removeInstance lookup fail. ID = "' + id + '"');
84 }
85 }
86
87 // ==========================
88
Simon Hunt4b668592015-01-29 17:33:53 -080089 function clickInst(d) {
90 var el = d3.select(this),
91 aff = el.classed('affinity');
92 if (!aff) {
93 setAffinity(el, d);
94 } else {
95 cancelAffinity();
96 }
97 }
98
99 function setAffinity(el, d) {
100 d3.selectAll('.onosInst')
101 .classed('mastership', true)
102 .classed('affinity', false);
103 el.classed('affinity', true);
104
Simon Hunta142dd22015-02-12 22:07:51 -0800105 // suppress all elements except nodes whose master is this instance
106 api.showMastership(d.id);
Simon Hunt4b668592015-01-29 17:33:53 -0800107 oiShowMaster = true;
108 }
109
110 function cancelAffinity() {
111 d3.selectAll('.onosInst')
112 .classed('mastership affinity', false);
113
Simon Hunta142dd22015-02-12 22:07:51 -0800114 api.showMastership(null);
Simon Hunt4b668592015-01-29 17:33:53 -0800115 oiShowMaster = false;
116 }
117
Simon Hunt4b668592015-01-29 17:33:53 -0800118 function attachUiBadge(svg) {
Simon Hunta9761342016-06-10 18:02:53 -0700119 gs.addGlyph(svg, 'uiAttached', 24, true, [14, 54])
Simon Hunt4b668592015-01-29 17:33:53 -0800120 .classed('badgeIcon uiBadge', true);
121 }
122
Thomas Vachuskafba7f3d2016-03-23 15:46:25 -0700123 function attachReadyBadge(svg) {
Simon Hunta9761342016-06-10 18:02:53 -0700124 gs.addGlyph(svg, 'checkMark', 16, true, [18, 40])
Thomas Vachuskafba7f3d2016-03-23 15:46:25 -0700125 .classed('badgeIcon readyBadge', true);
126 }
127
Simon Hunt4b668592015-01-29 17:33:53 -0800128 function instColor(id, online) {
Simon Hunt48e61672015-01-30 14:48:25 -0800129 return sus.cat7().getColor(id, !online, ts.theme());
Simon Hunt4b668592015-01-29 17:33:53 -0800130 }
131
132 // ==============================
133
134 function updateInstances() {
Simon Hunta9761342016-06-10 18:02:53 -0700135 var rox = 5,
136 roy = 5,
137 rw = 160,
138 rhh = 30,
139 rbh = 45,
140 tx = 48,
141 instSvg = {
142 width: 170,
143 height: 85,
144 viewBox: '0 0 170 85'
145 },
146 headRect = {
147 x: rox,
148 y: roy,
149 width: rw,
150 height: rhh
151 },
152 bodyRect = {
153 x: rox,
154 y: roy + rhh,
155 width: rw,
156 height: rbh
157 },
158 titleAttr = {
159 class: 'instTitle',
160 x: tx,
161 y: 27
162 };
163
Simon Hunt4b668592015-01-29 17:33:53 -0800164 var onoses = oiBox.el().selectAll('.onosInst')
Simon Hunta9761342016-06-10 18:02:53 -0700165 .data(onosOrder, function (d) { return d.id; });
Simon Hunt4b668592015-01-29 17:33:53 -0800166
167 function nSw(n) {
Simon Hunta9761342016-06-10 18:02:53 -0700168 return 'Switches: ' + n;
Simon Hunt4b668592015-01-29 17:33:53 -0800169 }
170
171 // operate on existing onos instances if necessary
172 onoses.each(function (d) {
173 var el = d3.select(this),
174 svg = el.select('svg');
Simon Hunt4b668592015-01-29 17:33:53 -0800175
176 // update online state
177 el.classed('online', d.online);
Simon Hunta9761342016-06-10 18:02:53 -0700178 el.classed('ready', d.ready);
Simon Hunt4b668592015-01-29 17:33:53 -0800179
180 // update ui-attached state
181 svg.select('use.uiBadge').remove();
182 if (d.uiAttached) {
183 attachUiBadge(svg);
184 }
185
186 function updAttr(id, value) {
187 svg.select('text.instLabel.'+id).text(value);
188 }
189
190 updAttr('ip', d.ip);
191 updAttr('ns', nSw(d.switches));
192 });
193
194
195 // operate on new onos instances
196 var entering = onoses.enter()
197 .append('div')
Simon Hunta9761342016-06-10 18:02:53 -0700198 .classed('onosInst', true)
Simon Hunt4b668592015-01-29 17:33:53 -0800199 .classed('online', function (d) { return d.online; })
Simon Hunta9761342016-06-10 18:02:53 -0700200 .classed('ready', function (d) { return d.ready; })
Simon Hunt4b668592015-01-29 17:33:53 -0800201 .on('click', clickInst);
202
203 entering.each(function (d) {
204 var el = d3.select(this),
Simon Hunta9761342016-06-10 18:02:53 -0700205 svg = el.append('svg').attr(instSvg);
Simon Hunt4b668592015-01-29 17:33:53 -0800206
Simon Hunta9761342016-06-10 18:02:53 -0700207 svg.append('rect').attr(headRect);
208 svg.append('rect').attr(bodyRect);
Simon Hunt4b668592015-01-29 17:33:53 -0800209
Simon Hunta9761342016-06-10 18:02:53 -0700210 gs.addGlyph(svg, 'bird', 20, false, [15, 10])
211 .classed('badgeIcon bird', true);
Simon Hunt4b668592015-01-29 17:33:53 -0800212
Simon Hunta9761342016-06-10 18:02:53 -0700213 attachReadyBadge(svg);
Simon Hunt4b668592015-01-29 17:33:53 -0800214
215 if (d.uiAttached) {
216 attachUiBadge(svg);
217 }
218
Simon Hunt4b668592015-01-29 17:33:53 -0800219 svg.append('text')
Simon Hunta9761342016-06-10 18:02:53 -0700220 .attr(titleAttr)
Simon Hunt4b668592015-01-29 17:33:53 -0800221 .text(d.id);
222
Simon Hunta9761342016-06-10 18:02:53 -0700223 var ty = 55;
Simon Hunt4b668592015-01-29 17:33:53 -0800224 function addAttr(id, label) {
225 svg.append('text').attr({
226 class: 'instLabel ' + id,
Simon Hunta9761342016-06-10 18:02:53 -0700227 x: tx,
Simon Hunt4b668592015-01-29 17:33:53 -0800228 y: ty
229 }).text(label);
Simon Hunta9761342016-06-10 18:02:53 -0700230 ty += 18;
Simon Hunt4b668592015-01-29 17:33:53 -0800231 }
232
233 addAttr('ip', d.ip);
234 addAttr('ns', nSw(d.switches));
235 });
236
237 // operate on existing + new onoses here
238 // set the affinity colors...
239 onoses.each(function (d) {
240 var el = d3.select(this),
241 rect = el.select('svg').select('rect'),
242 col = instColor(d.id, d.online);
243 rect.style('fill', col);
244 });
245
246 // adjust the panel size appropriately...
Simon Hunta9761342016-06-10 18:02:53 -0700247 oiBox.width(instSvg.width * onosOrder.length);
248 oiBox.height(instSvg.height);
Simon Hunt4b668592015-01-29 17:33:53 -0800249
250 // remove any outgoing instances
251 onoses.exit().remove();
252 }
253
254
255 // ==========================
256
257 function logicError(msg) {
258 if (showLogicErrors) {
259 $log.warn('TopoInstService: ' + msg);
260 }
261 }
262
Simon Hunta142dd22015-02-12 22:07:51 -0800263 function initInst(_api_) {
264 api = _api_;
Simon Hunt4b668592015-01-29 17:33:53 -0800265 oiBox = ps.createPanel(idIns, instOpts);
266 oiBox.show();
267
268 onosInstances = {};
269 onosOrder = [];
270 oiShowMaster = false;
Simon Hunt245a88e2015-02-02 13:26:04 -0800271
272 // we want to update the instances, each time the theme changes
Simon Huntf51bf462016-06-29 16:22:57 -0700273 ts.addListener(updateInstances);
Simon Hunt4b668592015-01-29 17:33:53 -0800274 }
275
276 function destroyInst() {
Simon Huntf51bf462016-06-29 16:22:57 -0700277 ts.removeListener(updateInstances);
Simon Hunt245a88e2015-02-02 13:26:04 -0800278
Simon Hunt4b668592015-01-29 17:33:53 -0800279 ps.destroyPanel(idIns);
280 oiBox = null;
Simon Hunt3ab20282015-02-26 20:32:19 -0800281
282 onosInstances = {};
283 onosOrder = [];
284 oiShowMaster = false;
Simon Hunt4b668592015-01-29 17:33:53 -0800285 }
286
Simon Huntee7a3ce2015-04-09 13:28:37 -0700287 function showInsts() {
288 oiBox.show();
289 }
290
291 function hideInsts() {
292 oiBox.hide();
293 }
294
295 function toggleInsts(x) {
296 var kev = (x === 'keyev'),
297 on,
298 verb;
299
300 if (kev) {
301 on = oiBox.toggle();
302 } else {
303 on = !!x;
304 if (on) {
305 showInsts();
306 } else {
307 hideInsts();
308 }
309 }
310 verb = on ? 'Show' : 'Hide';
311 flash.flash(verb + ' instances panel');
312 return on;
313 }
314
Simon Hunt4b668592015-01-29 17:33:53 -0800315 // ==========================
316
317 angular.module('ovTopo')
318 .factory('TopoInstService',
319 ['$log', 'PanelService', 'SvgUtilService', 'GlyphService',
Simon Huntee7a3ce2015-04-09 13:28:37 -0700320 'ThemeService', 'FnService', 'FlashService',
Simon Hunt4b668592015-01-29 17:33:53 -0800321
Simon Huntee7a3ce2015-04-09 13:28:37 -0700322 function (_$log_, _ps_, _sus_, _gs_, _ts_, _fs_, _flash_) {
Simon Hunt4b668592015-01-29 17:33:53 -0800323 $log = _$log_;
324 ps = _ps_;
325 sus = _sus_;
326 gs = _gs_;
Simon Hunt48e61672015-01-30 14:48:25 -0800327 ts = _ts_;
328 fs = _fs_;
Simon Huntee7a3ce2015-04-09 13:28:37 -0700329 flash = _flash_;
Simon Hunt4b668592015-01-29 17:33:53 -0800330
331 return {
332 initInst: initInst,
333 destroyInst: destroyInst,
Simon Hunt1894d792015-02-04 17:09:20 -0800334
Simon Hunt48e61672015-01-30 14:48:25 -0800335 addInstance: addInstance,
336 updateInstance: updateInstance,
Simon Huntac4c6f72015-02-03 19:50:53 -0800337 removeInstance: removeInstance,
Simon Hunt1894d792015-02-04 17:09:20 -0800338
Simon Hunta142dd22015-02-12 22:07:51 -0800339 cancelAffinity: cancelAffinity,
340
Simon Huntac4c6f72015-02-03 19:50:53 -0800341 isVisible: function () { return oiBox.isVisible(); },
Simon Huntee7a3ce2015-04-09 13:28:37 -0700342 show: showInsts,
343 hide: hideInsts,
344 toggle: toggleInsts,
Simon Hunta142dd22015-02-12 22:07:51 -0800345 showMaster: function () { return oiShowMaster; }
Simon Hunt4b668592015-01-29 17:33:53 -0800346 };
347 }]);
348}());