blob: 1d0cbed643d8b15fe866278620a8474417e57807 [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 Hunt245a88e2015-02-02 13:26:04 -080046 oiBox,
47 themeListener;
Simon Hunt4b668592015-01-29 17:33:53 -080048
49
50 // ==========================
Simon Hunt4b668592015-01-29 17:33:53 -080051
52 function addInstance(data) {
53 var id = data.id;
54
55 if (onosInstances[id]) {
56 updateInstance(data);
57 return;
58 }
59 onosInstances[id] = data;
60 onosOrder.push(data);
61 updateInstances();
62 }
63
64 function updateInstance(data) {
65 var id = data.id,
66 d = onosInstances[id];
67 if (d) {
68 angular.extend(d, data);
69 updateInstances();
70 } else {
71 logicError('updateInstance: lookup fail: ID = "' + id + '"');
72 }
73 }
74
Simon Hunt48e61672015-01-30 14:48:25 -080075 function removeInstance(data) {
76 var id = data.id,
77 d = onosInstances[id];
78 if (d) {
79 var idx = fs.find(id, onosOrder);
80 if (idx >= 0) {
81 onosOrder.splice(idx, 1);
82 }
83 delete onosInstances[id];
84 updateInstances();
85 } else {
86 logicError('removeInstance lookup fail. ID = "' + id + '"');
87 }
88 }
89
90 // ==========================
91
Simon Hunt4b668592015-01-29 17:33:53 -080092 function clickInst(d) {
93 var el = d3.select(this),
94 aff = el.classed('affinity');
95 if (!aff) {
96 setAffinity(el, d);
97 } else {
98 cancelAffinity();
99 }
100 }
101
102 function setAffinity(el, d) {
103 d3.selectAll('.onosInst')
104 .classed('mastership', true)
105 .classed('affinity', false);
106 el.classed('affinity', true);
107
Simon Hunta142dd22015-02-12 22:07:51 -0800108 // suppress all elements except nodes whose master is this instance
109 api.showMastership(d.id);
Simon Hunt4b668592015-01-29 17:33:53 -0800110 oiShowMaster = true;
111 }
112
113 function cancelAffinity() {
114 d3.selectAll('.onosInst')
115 .classed('mastership affinity', false);
116
Simon Hunta142dd22015-02-12 22:07:51 -0800117 api.showMastership(null);
Simon Hunt4b668592015-01-29 17:33:53 -0800118 oiShowMaster = false;
119 }
120
Simon Hunt4b668592015-01-29 17:33:53 -0800121 function attachUiBadge(svg) {
Simon Hunta9761342016-06-10 18:02:53 -0700122 gs.addGlyph(svg, 'uiAttached', 24, true, [14, 54])
Simon Hunt4b668592015-01-29 17:33:53 -0800123 .classed('badgeIcon uiBadge', true);
124 }
125
Thomas Vachuskafba7f3d2016-03-23 15:46:25 -0700126 function attachReadyBadge(svg) {
Simon Hunta9761342016-06-10 18:02:53 -0700127 gs.addGlyph(svg, 'checkMark', 16, true, [18, 40])
Thomas Vachuskafba7f3d2016-03-23 15:46:25 -0700128 .classed('badgeIcon readyBadge', true);
129 }
130
Simon Hunt4b668592015-01-29 17:33:53 -0800131 function instColor(id, online) {
Simon Hunt48e61672015-01-30 14:48:25 -0800132 return sus.cat7().getColor(id, !online, ts.theme());
Simon Hunt4b668592015-01-29 17:33:53 -0800133 }
134
135 // ==============================
136
137 function updateInstances() {
Simon Hunta9761342016-06-10 18:02:53 -0700138 var rox = 5,
139 roy = 5,
140 rw = 160,
141 rhh = 30,
142 rbh = 45,
143 tx = 48,
144 instSvg = {
145 width: 170,
146 height: 85,
147 viewBox: '0 0 170 85'
148 },
149 headRect = {
150 x: rox,
151 y: roy,
152 width: rw,
153 height: rhh
154 },
155 bodyRect = {
156 x: rox,
157 y: roy + rhh,
158 width: rw,
159 height: rbh
160 },
161 titleAttr = {
162 class: 'instTitle',
163 x: tx,
164 y: 27
165 };
166
Simon Hunt4b668592015-01-29 17:33:53 -0800167 var onoses = oiBox.el().selectAll('.onosInst')
Simon Hunta9761342016-06-10 18:02:53 -0700168 .data(onosOrder, function (d) { return d.id; });
Simon Hunt4b668592015-01-29 17:33:53 -0800169
170 function nSw(n) {
Simon Hunta9761342016-06-10 18:02:53 -0700171 return 'Switches: ' + n;
Simon Hunt4b668592015-01-29 17:33:53 -0800172 }
173
174 // operate on existing onos instances if necessary
175 onoses.each(function (d) {
176 var el = d3.select(this),
177 svg = el.select('svg');
Simon Hunt4b668592015-01-29 17:33:53 -0800178
179 // update online state
180 el.classed('online', d.online);
Simon Hunta9761342016-06-10 18:02:53 -0700181 el.classed('ready', d.ready);
Simon Hunt4b668592015-01-29 17:33:53 -0800182
183 // update ui-attached state
184 svg.select('use.uiBadge').remove();
185 if (d.uiAttached) {
186 attachUiBadge(svg);
187 }
188
189 function updAttr(id, value) {
190 svg.select('text.instLabel.'+id).text(value);
191 }
192
193 updAttr('ip', d.ip);
194 updAttr('ns', nSw(d.switches));
195 });
196
197
198 // operate on new onos instances
199 var entering = onoses.enter()
200 .append('div')
Simon Hunta9761342016-06-10 18:02:53 -0700201 .classed('onosInst', true)
Simon Hunt4b668592015-01-29 17:33:53 -0800202 .classed('online', function (d) { return d.online; })
Simon Hunta9761342016-06-10 18:02:53 -0700203 .classed('ready', function (d) { return d.ready; })
Simon Hunt4b668592015-01-29 17:33:53 -0800204 .on('click', clickInst);
205
206 entering.each(function (d) {
207 var el = d3.select(this),
Simon Hunta9761342016-06-10 18:02:53 -0700208 svg = el.append('svg').attr(instSvg);
Simon Hunt4b668592015-01-29 17:33:53 -0800209
Simon Hunta9761342016-06-10 18:02:53 -0700210 svg.append('rect').attr(headRect);
211 svg.append('rect').attr(bodyRect);
Simon Hunt4b668592015-01-29 17:33:53 -0800212
Simon Hunta9761342016-06-10 18:02:53 -0700213 gs.addGlyph(svg, 'bird', 20, false, [15, 10])
214 .classed('badgeIcon bird', true);
Simon Hunt4b668592015-01-29 17:33:53 -0800215
Simon Hunta9761342016-06-10 18:02:53 -0700216 attachReadyBadge(svg);
Simon Hunt4b668592015-01-29 17:33:53 -0800217
218 if (d.uiAttached) {
219 attachUiBadge(svg);
220 }
221
Simon Hunt4b668592015-01-29 17:33:53 -0800222 svg.append('text')
Simon Hunta9761342016-06-10 18:02:53 -0700223 .attr(titleAttr)
Simon Hunt4b668592015-01-29 17:33:53 -0800224 .text(d.id);
225
Simon Hunta9761342016-06-10 18:02:53 -0700226 var ty = 55;
Simon Hunt4b668592015-01-29 17:33:53 -0800227 function addAttr(id, label) {
228 svg.append('text').attr({
229 class: 'instLabel ' + id,
Simon Hunta9761342016-06-10 18:02:53 -0700230 x: tx,
Simon Hunt4b668592015-01-29 17:33:53 -0800231 y: ty
232 }).text(label);
Simon Hunta9761342016-06-10 18:02:53 -0700233 ty += 18;
Simon Hunt4b668592015-01-29 17:33:53 -0800234 }
235
236 addAttr('ip', d.ip);
237 addAttr('ns', nSw(d.switches));
238 });
239
240 // operate on existing + new onoses here
241 // set the affinity colors...
242 onoses.each(function (d) {
243 var el = d3.select(this),
244 rect = el.select('svg').select('rect'),
245 col = instColor(d.id, d.online);
246 rect.style('fill', col);
247 });
248
249 // adjust the panel size appropriately...
Simon Hunta9761342016-06-10 18:02:53 -0700250 oiBox.width(instSvg.width * onosOrder.length);
251 oiBox.height(instSvg.height);
Simon Hunt4b668592015-01-29 17:33:53 -0800252
253 // remove any outgoing instances
254 onoses.exit().remove();
255 }
256
257
258 // ==========================
259
260 function logicError(msg) {
261 if (showLogicErrors) {
262 $log.warn('TopoInstService: ' + msg);
263 }
264 }
265
Simon Hunta142dd22015-02-12 22:07:51 -0800266 function initInst(_api_) {
267 api = _api_;
Simon Hunt4b668592015-01-29 17:33:53 -0800268 oiBox = ps.createPanel(idIns, instOpts);
269 oiBox.show();
270
271 onosInstances = {};
272 onosOrder = [];
273 oiShowMaster = false;
Simon Hunt245a88e2015-02-02 13:26:04 -0800274
275 // we want to update the instances, each time the theme changes
276 themeListener = ts.addListener(updateInstances);
Simon Hunt4b668592015-01-29 17:33:53 -0800277 }
278
279 function destroyInst() {
Simon Hunt245a88e2015-02-02 13:26:04 -0800280 ts.removeListener(themeListener);
281 themeListener = null;
282
Simon Hunt4b668592015-01-29 17:33:53 -0800283 ps.destroyPanel(idIns);
284 oiBox = null;
Simon Hunt3ab20282015-02-26 20:32:19 -0800285
286 onosInstances = {};
287 onosOrder = [];
288 oiShowMaster = false;
Simon Hunt4b668592015-01-29 17:33:53 -0800289 }
290
Simon Huntee7a3ce2015-04-09 13:28:37 -0700291 function showInsts() {
292 oiBox.show();
293 }
294
295 function hideInsts() {
296 oiBox.hide();
297 }
298
299 function toggleInsts(x) {
300 var kev = (x === 'keyev'),
301 on,
302 verb;
303
304 if (kev) {
305 on = oiBox.toggle();
306 } else {
307 on = !!x;
308 if (on) {
309 showInsts();
310 } else {
311 hideInsts();
312 }
313 }
314 verb = on ? 'Show' : 'Hide';
315 flash.flash(verb + ' instances panel');
316 return on;
317 }
318
Simon Hunt4b668592015-01-29 17:33:53 -0800319 // ==========================
320
321 angular.module('ovTopo')
322 .factory('TopoInstService',
323 ['$log', 'PanelService', 'SvgUtilService', 'GlyphService',
Simon Huntee7a3ce2015-04-09 13:28:37 -0700324 'ThemeService', 'FnService', 'FlashService',
Simon Hunt4b668592015-01-29 17:33:53 -0800325
Simon Huntee7a3ce2015-04-09 13:28:37 -0700326 function (_$log_, _ps_, _sus_, _gs_, _ts_, _fs_, _flash_) {
Simon Hunt4b668592015-01-29 17:33:53 -0800327 $log = _$log_;
328 ps = _ps_;
329 sus = _sus_;
330 gs = _gs_;
Simon Hunt48e61672015-01-30 14:48:25 -0800331 ts = _ts_;
332 fs = _fs_;
Simon Huntee7a3ce2015-04-09 13:28:37 -0700333 flash = _flash_;
Simon Hunt4b668592015-01-29 17:33:53 -0800334
335 return {
336 initInst: initInst,
337 destroyInst: destroyInst,
Simon Hunt1894d792015-02-04 17:09:20 -0800338
Simon Hunt48e61672015-01-30 14:48:25 -0800339 addInstance: addInstance,
340 updateInstance: updateInstance,
Simon Huntac4c6f72015-02-03 19:50:53 -0800341 removeInstance: removeInstance,
Simon Hunt1894d792015-02-04 17:09:20 -0800342
Simon Hunta142dd22015-02-12 22:07:51 -0800343 cancelAffinity: cancelAffinity,
344
Simon Huntac4c6f72015-02-03 19:50:53 -0800345 isVisible: function () { return oiBox.isVisible(); },
Simon Huntee7a3ce2015-04-09 13:28:37 -0700346 show: showInsts,
347 hide: hideInsts,
348 toggle: toggleInsts,
Simon Hunta142dd22015-02-12 22:07:51 -0800349 showMaster: function () { return oiShowMaster; }
Simon Hunt4b668592015-01-29 17:33:53 -0800350 };
351 }]);
352}());