blob: 6560a8e6e1ee0845c8bc714374e9452697af0d5a [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001
2/*
3 * Copyright 2017-present Open Networking Foundation
4
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8
9 * http://www.apache.org/licenses/LICENSE-2.0
10
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080019(function () {
20 'use strict';
21
22 const shapes = {
23 cloud: ' M 79.72 49.60 C 86.00 37.29 98.57 29.01 111.96 26.42 C 124.27 24.11 137.53 26.15 148.18 32.90 C 158.08 38.78 165.39 48.87 167.65 60.20 C 176.20 57.90 185.14 56.01 194.00 57.73 C 206.08 59.59 217.92 66.01 224.37 76.66 C 227.51 81.54 228.85 87.33 229.23 93.06 C 237.59 93.33 246.22 95.10 253.04 100.19 C 256.69 103.13 259.87 107.67 258.91 112.59 C 257.95 118.43 252.78 122.38 247.78 124.82 C 235.27 130.43 220.23 130.09 207.98 123.93 C 199.33 127.88 189.76 129.43 180.30 128.57 C 173.70 139.92 161.70 147.65 148.86 149.93 C 133.10 153.26 116.06 148.15 104.42 137.08 C 92.98 143.04 78.96 143.87 66.97 139.04 C 57.75 135.41 49.70 128.00 46.60 118.43 C 43.87 109.95 45.81 100.29 51.30 93.32 C 57.38 85.18 67.10 80.44 76.99 78.89 C 74.38 69.20 74.87 58.52 79.72 49.60 Z'
24 }
25
Matteo Scandolo170d3be2016-02-11 08:58:04 -080026 var computeNodeId = 0;
27 var instanceId = 0;
28
Matteo Scandolo04564952016-02-24 11:22:48 -080029 angular.module('xos.diagnostic')
Matteo Scandolofe307b12016-05-17 14:29:01 -070030 .service('NodeDrawer', function(d3, serviceTopologyConfig, RackHelper, _){
Matteo Scandolo51031482016-02-17 13:54:11 -080031
32 var _this = this;
33
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080034 this.addNetworks = (nodes) => {
Matteo Scandolof81130f2016-03-11 11:16:58 -080035
36 // clean childs
37 nodes.selectAll('*').remove();
38
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080039 nodes.append('path')
40 .attr({
41 d: shapes.cloud,
Matteo Scandolof81130f2016-03-11 11:16:58 -080042 transform: 'translate(-100, -72), scale(0.7)',
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080043 class: 'cloud'
44 });
45
46 nodes.append('text')
47 .attr({
Matteo Scandolo19acf7c2016-03-07 16:07:13 -080048 'text-anchor': 'middle',
49 y: -5,
50 x: 5,
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080051 })
52 .text(d => d.name)
Matteo Scandolo45fba732016-02-22 14:53:44 -080053
Matteo Scandolo19acf7c2016-03-07 16:07:13 -080054 nodes.append('text')
55 .attr({
56 'text-anchor': 'middle',
57 y: 8,
58 x: 5,
59 class: 'small'
60 })
61 .text(d => d.subtitle)
62
Matteo Scandolo45fba732016-02-22 14:53:44 -080063 nodes.each(function(n){
64 let currentNode = d3.select(this);
65 // cicle trouch node to add Tags and Public IP
Matteo Scandolo79108192016-03-08 09:33:26 -080066 if(n.name === 'LAN-Side' && angular.isDefined(n.subscriberTag)){
Matteo Scandolo45fba732016-02-22 14:53:44 -080067 currentNode.append('text')
68 .attr({
69 'text-anchor': 'middle',
Matteo Scandolof81130f2016-03-11 11:16:58 -080070 y: 50
Matteo Scandolo45fba732016-02-22 14:53:44 -080071 })
72 .text(() => `C-Tag: ${n.subscriberTag.cTag}`);
73
74 currentNode.append('text')
75 .attr({
76 'text-anchor': 'middle',
Matteo Scandolof81130f2016-03-11 11:16:58 -080077 y: 70
Matteo Scandolo45fba732016-02-22 14:53:44 -080078 })
79 .text(() => `S-Tag: ${n.subscriberTag.sTag}`);
80 }
Matteo Scandolo012dddb2016-02-22 16:53:22 -080081
Matteo Scandolo79108192016-03-08 09:33:26 -080082 if(n.name === 'WAN-Side' && angular.isDefined(n.subscriberIP)){
Matteo Scandolo012dddb2016-02-22 16:53:22 -080083 currentNode.append('text')
84 .attr({
85 'text-anchor': 'middle',
Matteo Scandolof81130f2016-03-11 11:16:58 -080086 y: 50
Matteo Scandolo012dddb2016-02-22 16:53:22 -080087 })
88 .text(() => `Public IP: ${n.subscriberIP}`);
89 }
Matteo Scandolo45fba732016-02-22 14:53:44 -080090 });
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080091 }
92
93 this.addRack = (nodes) => {
Matteo Scandolo170d3be2016-02-11 08:58:04 -080094
Matteo Scandolo35d53c82016-02-16 14:44:51 -080095 // loop because of D3
96 // rack will be only one
97 nodes.each(d => {
98 let [w, h] = RackHelper.getRackSize(d.computeNodes);
Matteo Scandoload5b2282016-02-16 11:50:51 -080099
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800100 // TODO update instead of delete and redraw
101 nodes.select('g').remove();
102
Matteo Scandoload5b2282016-02-16 11:50:51 -0800103 let rack = nodes
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800104 .append('g');
105
106 rack
107 .attr({
108 transform: `translate(0,0)`
109 })
110 .transition()
111 .duration(serviceTopologyConfig.duration)
112 .attr({
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800113 transform: () => `translate(${- (w / 2)}, ${- (h / 2)})`
Matteo Scandoload5b2282016-02-16 11:50:51 -0800114 });
115
116 rack
117 .append('rect')
118 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800119 width: 0,
120 height: 0
121 })
122 .transition()
123 .duration(serviceTopologyConfig.duration)
124 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -0800125 width: w,
126 height: h
127 });
128
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800129 rack.append('text')
Matteo Scandoload5b2282016-02-16 11:50:51 -0800130 .attr({
131 'text-anchor': 'middle',
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800132 y: - 10,
133 x: w / 2,
134 opacity: 0
Matteo Scandoload5b2282016-02-16 11:50:51 -0800135 })
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800136 .text(d => d.name)
137 .transition()
138 .duration(serviceTopologyConfig.duration)
139 .attr({
140 opacity: 1
141 })
Matteo Scandoload5b2282016-02-16 11:50:51 -0800142
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800143 this.drawComputeNodes(rack, d.computeNodes);
144
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800145 });
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800146
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800147 };
148
149 this.drawComputeNodes = (container, nodes) => {
Matteo Scandoload5b2282016-02-16 11:50:51 -0800150
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800151 let elements = container.selectAll('.compute-nodes')
152 .data(nodes, d => {
153 if(!angular.isString(d.d3Id)){
154 d.d3Id = `compute-node-${++computeNodeId}`;
155 }
156 return d.d3Id;
157 });
158
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800159 let {width, height} = container.node().getBoundingClientRect();
160
161 var nodeContainer = elements.enter().append('g');
162
163 nodeContainer
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800164 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800165 transform: `translate(${width / 2}, ${ height / 2})`,
Matteo Scandoload5b2282016-02-16 11:50:51 -0800166 class: 'compute-node',
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800167 })
168 .transition()
169 .duration(serviceTopologyConfig.duration)
170 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -0800171 transform: (d) => `translate(${RackHelper.getComputeNodePosition(nodes, d.d3Id.replace('compute-node-', '') - 1)})`
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800172 });
173
174 nodeContainer.append('rect')
Matteo Scandoload5b2282016-02-16 11:50:51 -0800175 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800176 width: 0,
177 height: 0
178 })
179 .transition()
180 .duration(serviceTopologyConfig.duration)
181 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -0800182 width: d => RackHelper.getComputeNodeSize(d.instances)[0],
183 height: d => RackHelper.getComputeNodeSize(d.instances)[1],
184 });
185
186 nodeContainer.append('text')
187 .attr({
188 'text-anchor': 'start',
Matteo Scandolof81130f2016-03-11 11:16:58 -0800189 y: 17, //FIXME
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800190 x: 10, //FIXME
191 opacity: 0
Matteo Scandoload5b2282016-02-16 11:50:51 -0800192 })
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800193 .text(d => d.humanReadableName.split('.')[0])
194 .transition()
195 .duration(serviceTopologyConfig.duration)
196 .attr({
197 opacity: 1
198 })
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800199
200 // if there are Compute Nodes
201 if(nodeContainer.length > 0){
Matteo Scandolo51031482016-02-17 13:54:11 -0800202 // draw instances for each compute node
203 nodeContainer.each(function(a){
204 _this.drawInstances(d3.select(this), a.instances);
205 })
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800206 }
207
208 };
209
Matteo Scandolo7030ceb2016-02-16 13:29:26 -0800210 // NOTE Stripping unuseful names to shorten labels.
211 // This is not elegant
212 const formatInstanceName = (name) => {
213 return name
214 .replace('app_', '')
215 .replace('service_', '')
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800216 // .replace('ovs_', '')
Matteo Scandolo7030ceb2016-02-16 13:29:26 -0800217 .replace('mysite_', '')
218 .replace('_instance', '');
219 };
220
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800221 const getInstanceStatusColor = (instance) => {
222 function startWith(val, string){
223 return string.substring(0, val.length) === val;
224 }
225
226 if(startWith('0 - ', instance.backend_status)){
227 return 'provisioning';
228 }
229 if(startWith('1 - ', instance.backend_status)){
230 return 'good';
231 }
232 if(startWith('2 - ', instance.backend_status)){
233 return 'bad';
234 }
235 else {
236 return '';
237 }
238 };
239
Matteo Scandolof0d6e692016-02-24 11:14:01 -0800240 const drawContainer = (container, docker) => {
241
242 const containerBox = container.append('g')
243 .attr({
244 class: 'container',
245 transform: `translate(${serviceTopologyConfig.instance.margin}, 115)`
246 });
247
248 containerBox.append('rect')
249 .attr({
250 width: 250 - (serviceTopologyConfig.container.margin * 2),
251 height: serviceTopologyConfig.container.height,
252 });
253
254 containerBox.append('text')
255 .attr({
256 y: 20,
257 x: serviceTopologyConfig.instance.margin,
258 class: 'name'
259 })
260 .text(docker.name)
261
262 // add stats
263 const interestingMeters = ['memory', 'memory.usage', 'cpu_util'];
264
265 interestingMeters.forEach((m, i) => {
Matteo Scandolofe307b12016-05-17 14:29:01 -0700266 const meter = _.find(docker.stats, {meter: m});
Matteo Scandolof0d6e692016-02-24 11:14:01 -0800267 // if there is no meter stats skip rendering
268 if(!angular.isDefined(meter)){
269 return;
270 }
271 containerBox.append('text')
272 .attr({
273 y: 40 + (i * 15),
274 x: serviceTopologyConfig.instance.margin,
275 opacity: 0
276 })
277 .text(`${meter.description}: ${Math.round(meter.value)} ${meter.unit}`)
278 .transition()
279 .duration(serviceTopologyConfig.duration)
280 .attr({
281 opacity: 1
282 });
283 });
284
285 // add port stats
286 const ports = ['eth0', 'eth1'];
287 const interestingPortMeters = [
288 {
289 meter: 'network.incoming.bytes.rate',
290 label: 'Incoming'
291 },
292 {
293 meter: 'network.outgoing.bytes.rate',
294 label: 'Outgoing'
295 }
296 ];
297
298 ports.forEach((p, j) => {
299
300 // if there are no port stats skip rendering
301 if(docker.port[p].length === 0){
302 return;
303 }
304
305 containerBox.append('text')
306 .attr({
307 y: 90,
308 x: serviceTopologyConfig.instance.margin + (120 * j),
309 class: 'name'
310 })
311 .text(`${docker.name}-${p}`)
312
313 interestingPortMeters.forEach((m, i) => {
314
Matteo Scandolofe307b12016-05-17 14:29:01 -0700315 const meter = _.find(docker.port[p], {meter: m.meter});
Matteo Scandolof0d6e692016-02-24 11:14:01 -0800316 // if there is no meter stats skip rendering
317 if(!angular.isDefined(meter)){
318 return;
319 }
320 containerBox.append('text')
321 .attr({
322 y: 105 + (i * 15),
323 x: serviceTopologyConfig.instance.margin + (120 * j),
324 opacity: 0
325 })
326 .text(`${m.label}: ${Math.round(meter.value)} ${meter.unit}`)
327 .transition()
328 .duration(serviceTopologyConfig.duration)
329 .attr({
330 opacity: 1
331 });
332 });
333 });
334 }
335
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800336 const showInstanceStats = (container, instance) => {
337
338 // NOTE this should be dinamically positioned
339 // base on the number of element present
Matteo Scandolo963efd72016-03-10 08:59:27 -0800340
341 // fake the position
342 let translation = {
343 'mysite_vsg-1': '200, -120',
344 'mysite_vsg-2': '-300, 30',
345 'mysite_vsg-3': '-300, -250',
346 };
347
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800348 const statsContainer = container.append('g')
349 .attr({
Matteo Scandolo7360f752016-03-10 11:21:19 -0800350 transform: `translate(${translation[instance.humanReadableName] || translation['mysite_vsg-1']})`,
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800351 class: 'stats-container'
Matteo Scandolo963efd72016-03-10 08:59:27 -0800352 })
353 .on('click', function(d) {
354 // toggling visisbility
355 d.fade = !d.fade;
356 let opacity;
357 if(d.fade){
358 opacity = 0.1;
359 }
360 else{
361 opacity = 1;
362 }
363
364 d3.select(this)
365 .transition()
366 .duration(serviceTopologyConfig.duration)
367 .attr({
368 opacity: opacity
369 })
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800370 });
371
Matteo Scandolo963efd72016-03-10 08:59:27 -0800372 let lines = {
373 'mysite_vsg-1': {
Matteo Scandolof0d6e692016-02-24 11:14:01 -0800374 x1: -160,
375 y1: 120,
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800376 x2: 0,
377 y2: 50,
Matteo Scandolo963efd72016-03-10 08:59:27 -0800378 },
379 'mysite_vsg-2': {
380 x1: 250,
381 y1: 50,
382 x2: 300,
383 y2: -10
384 },
385 'mysite_vsg-3': {
386 x1: 250,
387 y1: 50,
388 x2: 300,
389 y2: 270
390 }
391 }
392
393 statsContainer.append('line')
394 .attr({
Matteo Scandolo39a56f52016-03-11 11:54:47 -0800395 x1: d => lines[d.humanReadableName].x1 || lines['mysite_vsg-1'].x1,
396 y1: d => lines[d.humanReadableName].y1 || lines['mysite_vsg-1'].y1,
397 x2: d => lines[d.humanReadableName].x2 || lines['mysite_vsg-1'].x2,
398 y2: d => lines[d.humanReadableName].y2 || lines['mysite_vsg-1'].y2,
Matteo Scandolo6aa165f2016-02-23 14:03:03 -0800399 stroke: 'black',
400 opacity: 0
401 })
402 .transition()
403 .duration(serviceTopologyConfig.duration)
404 .attr({
405 opacity: 1
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800406 })
407
408 // NOTE rect should be dinamically sized base on the presence of a container
409 let statsHeight = 110;
Matteo Scandolof0d6e692016-02-24 11:14:01 -0800410 let statsWidth = 250;
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800411
412 if (instance.container){
413 statsHeight += serviceTopologyConfig.container.height + (serviceTopologyConfig.container.margin * 2)
414 }
415
Matteo Scandolo963efd72016-03-10 08:59:27 -0800416 const statsVignette = statsContainer.append('rect')
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800417 .attr({
418 width: statsWidth,
Matteo Scandolo6aa165f2016-02-23 14:03:03 -0800419 height: statsHeight,
420 opacity: 0
421 })
422 .transition()
423 .duration(serviceTopologyConfig.duration)
424 .attr({
425 opacity: 1
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800426 });
427
Matteo Scandolo963efd72016-03-10 08:59:27 -0800428
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800429 // add instance info
430 statsContainer.append('text')
431 .attr({
432 y: 15,
433 x: serviceTopologyConfig.instance.margin,
Matteo Scandolo6aa165f2016-02-23 14:03:03 -0800434 class: 'name',
435 opacity: 0
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800436 })
437 .text(instance.humanReadableName)
Matteo Scandolo6aa165f2016-02-23 14:03:03 -0800438 .transition()
439 .duration(serviceTopologyConfig.duration)
440 .attr({
441 opacity: 1
442 })
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800443
444 statsContainer.append('text')
445 .attr({
446 y: 30,
447 x: serviceTopologyConfig.instance.margin,
Matteo Scandolo6aa165f2016-02-23 14:03:03 -0800448 class: 'ip',
449 opacity: 0
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800450 })
451 .text(instance.ip)
Matteo Scandolo6aa165f2016-02-23 14:03:03 -0800452 .transition()
453 .duration(serviceTopologyConfig.duration)
454 .attr({
455 opacity: 1
456 })
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800457
458 // add stats
Matteo Scandolo963efd72016-03-10 08:59:27 -0800459 const interestingMeters = ['memory', 'memory.usage', 'cpu', 'cpu_util'];
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800460
461 interestingMeters.forEach((m, i) => {
Matteo Scandolofe307b12016-05-17 14:29:01 -0700462 const meter = _.find(instance.stats, {meter: m});
Matteo Scandolo963efd72016-03-10 08:59:27 -0800463
464 if(meter){
465
466 statsContainer.append('text')
467 .attr({
468 y: 55 + (i * 15),
469 x: serviceTopologyConfig.instance.margin,
470 opacity: 0
471 })
472 .text(`${meter.description}: ${Math.round(meter.value)} ${meter.unit}`)
473 .transition()
474 .duration(serviceTopologyConfig.duration)
475 .attr({
476 opacity: 1
477 });
478 }
479
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800480 });
481
482 if(instance.container){
483 // draw container
Matteo Scandolof0d6e692016-02-24 11:14:01 -0800484 drawContainer(statsContainer, instance.container);
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800485 }
486
487 };
488
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800489 this.drawInstances = (container, instances) => {
Matteo Scandolo51031482016-02-17 13:54:11 -0800490
Matteo Scandoloc49ff702016-02-17 15:11:33 -0800491 // TODO check for stats field in instance and draw popup
492
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800493 let {width, height} = container.node().getBoundingClientRect();
494
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800495 let elements = container.selectAll('.instances')
496 .data(instances, d => angular.isString(d.d3Id) ? d.d3Id : d.d3Id = `instance-${++instanceId}`)
497
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800498 var instanceContainer = elements.enter().append('g');
499
500 instanceContainer
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800501 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800502 transform: `translate(${width / 2}, ${ height / 2})`,
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800503 class: d => `instance ${d.selected ? 'active' : ''} ${getInstanceStatusColor(d)}`,
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800504 })
505 .transition()
506 .duration(serviceTopologyConfig.duration)
507 .attr({
Matteo Scandolo51031482016-02-17 13:54:11 -0800508 transform: (d, i) => `translate(${RackHelper.getInstancePosition(i)})`
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800509 });
510
511 instanceContainer.append('rect')
Matteo Scandoload5b2282016-02-16 11:50:51 -0800512 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800513 width: 0,
514 height: 0
515 })
516 .transition()
517 .duration(serviceTopologyConfig.duration)
518 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -0800519 width: serviceTopologyConfig.instance.width,
520 height: serviceTopologyConfig.instance.height
521 });
522
523 instanceContainer.append('text')
524 .attr({
Matteo Scandolo7030ceb2016-02-16 13:29:26 -0800525 'text-anchor': 'middle',
526 y: 23, //FIXME
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800527 x: 40, //FIXME
528 opacity: 0
Matteo Scandoload5b2282016-02-16 11:50:51 -0800529 })
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800530 .text(d => formatInstanceName(d.humanReadableName))
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800531 .transition()
532 .duration(serviceTopologyConfig.duration)
533 .attr({
534 opacity: 1
535 });
Matteo Scandolo7030ceb2016-02-16 13:29:26 -0800536
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800537 // if stats are attached and instance is active,
538 // draw stats
Matteo Scandolo6aa165f2016-02-23 14:03:03 -0800539 instanceContainer.each(function(instance, i){
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800540
541 const container = d3.select(this);
542
543 if(angular.isDefined(instance.stats) && instance.selected){
Matteo Scandolo6aa165f2016-02-23 14:03:03 -0800544 showInstanceStats(container, instance, i);
Matteo Scandolo26d17e12016-02-23 13:47:14 -0800545 }
546 });
547
Matteo Scandolo963efd72016-03-10 08:59:27 -0800548 // instanceContainer
549 // .on('click', function(d){
550 // console.log(`Draw vignette with stats for instance: ${d.name}`);
551 // });
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800552 };
Matteo Scandolo9fe01af2016-02-09 16:01:49 -0800553
554 this.addPhisical = (nodes) => {
Matteo Scandolo3a176a22016-03-07 16:42:03 -0800555
556 nodes.select('rect').remove();
557 nodes.select('text').remove();
558
Matteo Scandolo9fe01af2016-02-09 16:01:49 -0800559 nodes.append('rect')
560 .attr(serviceTopologyConfig.square);
561
562 nodes.append('text')
563 .attr({
564 'text-anchor': 'middle',
565 y: serviceTopologyConfig.square.y - 10
566 })
Matteo Scandolod4ea8772016-03-01 15:20:29 -0800567 .text(d => {
568 return d.name || d.humanReadableName
569 });
Matteo Scandolo9fe01af2016-02-09 16:01:49 -0800570 }
571
572 this.addDevice = (nodes) => {
573 nodes.append('circle')
574 .attr(serviceTopologyConfig.circle);
575
576 nodes.append('text')
577 .attr({
578 'text-anchor': 'end',
579 x: - serviceTopologyConfig.circle.r - 10,
580 y: serviceTopologyConfig.circle.r / 2
581 })
Matteo Scandolo50eeec62016-02-23 10:04:36 -0800582 .text(d => d.name || d.mac);
Matteo Scandolo9fe01af2016-02-09 16:01:49 -0800583 }
584 });
585})();