blob: 1a45f03a0aad614bafb843f9187c390d68e92666 [file] [log] [blame]
Matteo Scandolo38ba3312016-02-09 16:01:49 -08001(function () {
2 'use strict';
3
4 const shapes = {
5 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'
6 }
7
Matteo Scandolo14183932016-02-11 08:58:04 -08008 var computeNodeId = 0;
9 var instanceId = 0;
10
Matteo Scandolo38ba3312016-02-09 16:01:49 -080011 angular.module('xos.serviceTopology')
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080012 .service('NodeDrawer', function(d3, serviceTopologyConfig, RackHelper){
Matteo Scandolo38ba3312016-02-09 16:01:49 -080013 this.addNetworks = (nodes) => {
14 nodes.append('path')
15 .attr({
16 d: shapes.cloud,
17 transform: 'translate(-63, -52), scale(0.5)',
18 class: 'cloud'
19 });
20
21 nodes.append('text')
22 .attr({
23 'text-anchor': 'middle'
24 })
25 .text(d => d.name)
26 }
27
28 this.addRack = (nodes) => {
Matteo Scandolo14183932016-02-11 08:58:04 -080029
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080030 // loop because of D3
31 // rack will be only one
32 nodes.each(d => {
33 let [w, h] = RackHelper.getRackSize(d.computeNodes);
Matteo Scandolob785b572016-02-16 11:50:51 -080034
35 let rack = nodes
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080036 .append('g');
37
38 rack
39 .attr({
40 transform: `translate(0,0)`
41 })
42 .transition()
43 .duration(serviceTopologyConfig.duration)
44 .attr({
Matteo Scandolob785b572016-02-16 11:50:51 -080045 transform: d => `translate(${- (w / 2)}, ${- (h / 2)})`
46 });
47
48 rack
49 .append('rect')
50 .attr({
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080051 width: 0,
52 height: 0
53 })
54 .transition()
55 .duration(serviceTopologyConfig.duration)
56 .attr({
Matteo Scandolob785b572016-02-16 11:50:51 -080057 width: w,
58 height: h
59 });
60
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080061 rack.append('text')
Matteo Scandolob785b572016-02-16 11:50:51 -080062 .attr({
63 'text-anchor': 'middle',
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080064 y: - 10,
65 x: w / 2,
66 opacity: 0
Matteo Scandolob785b572016-02-16 11:50:51 -080067 })
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080068 .text(d => d.name)
69 .transition()
70 .duration(serviceTopologyConfig.duration)
71 .attr({
72 opacity: 1
73 })
Matteo Scandolob785b572016-02-16 11:50:51 -080074
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080075 this.drawComputeNodes(rack, d.computeNodes);
76
Matteo Scandolo14183932016-02-11 08:58:04 -080077 });
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080078
Matteo Scandolo14183932016-02-11 08:58:04 -080079 };
80
81 this.drawComputeNodes = (container, nodes) => {
Matteo Scandolob785b572016-02-16 11:50:51 -080082
Matteo Scandolo14183932016-02-11 08:58:04 -080083 let elements = container.selectAll('.compute-nodes')
84 .data(nodes, d => {
85 if(!angular.isString(d.d3Id)){
86 d.d3Id = `compute-node-${++computeNodeId}`;
87 }
88 return d.d3Id;
89 });
90
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080091 let {width, height} = container.node().getBoundingClientRect();
92
93 var nodeContainer = elements.enter().append('g');
94
95 nodeContainer
Matteo Scandolo14183932016-02-11 08:58:04 -080096 .attr({
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080097 transform: `translate(${width / 2}, ${ height / 2})`,
Matteo Scandolob785b572016-02-16 11:50:51 -080098 class: 'compute-node',
Matteo Scandolo7fd4d042016-02-16 14:44:51 -080099 })
100 .transition()
101 .duration(serviceTopologyConfig.duration)
102 .attr({
Matteo Scandolob785b572016-02-16 11:50:51 -0800103 transform: (d) => `translate(${RackHelper.getComputeNodePosition(nodes, d.d3Id.replace('compute-node-', '') - 1)})`
Matteo Scandolo14183932016-02-11 08:58:04 -0800104 });
105
106 nodeContainer.append('rect')
Matteo Scandolob785b572016-02-16 11:50:51 -0800107 .attr({
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800108 width: 0,
109 height: 0
110 })
111 .transition()
112 .duration(serviceTopologyConfig.duration)
113 .attr({
Matteo Scandolob785b572016-02-16 11:50:51 -0800114 width: d => RackHelper.getComputeNodeSize(d.instances)[0],
115 height: d => RackHelper.getComputeNodeSize(d.instances)[1],
116 });
117
118 nodeContainer.append('text')
119 .attr({
120 'text-anchor': 'start',
121 y: 15, //FIXME
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800122 x: 10, //FIXME
123 opacity: 0
Matteo Scandolob785b572016-02-16 11:50:51 -0800124 })
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800125 .text(d => d.humanReadableName.split('.')[0])
126 .transition()
127 .duration(serviceTopologyConfig.duration)
128 .attr({
129 opacity: 1
130 })
Matteo Scandolo14183932016-02-11 08:58:04 -0800131
132 // if there are Compute Nodes
133 if(nodeContainer.length > 0){
134 angular.forEach(nodeContainer.data(), (computeNode) => {
135 this.drawInstances(nodeContainer, computeNode.instances);
136 });
137 }
138
139 };
140
Matteo Scandolo0cfd5a22016-02-16 13:29:26 -0800141 // NOTE Stripping unuseful names to shorten labels.
142 // This is not elegant
143 const formatInstanceName = (name) => {
144 return name
145 .replace('app_', '')
146 .replace('service_', '')
147 .replace('ovs_', '')
148 .replace('mysite_', '')
149 .replace('_instance', '');
150 };
151
Matteo Scandolo14183932016-02-11 08:58:04 -0800152 this.drawInstances = (container, instances) => {
Matteo Scandolo14183932016-02-11 08:58:04 -0800153
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800154 let {width, height} = container.node().getBoundingClientRect();
155
Matteo Scandolo14183932016-02-11 08:58:04 -0800156 let elements = container.selectAll('.instances')
157 .data(instances, d => angular.isString(d.d3Id) ? d.d3Id : d.d3Id = `instance-${++instanceId}`)
158
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800159 var instanceContainer = elements.enter().append('g');
160
161 instanceContainer
Matteo Scandolo14183932016-02-11 08:58:04 -0800162 .attr({
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800163 transform: `translate(${width / 2}, ${ height / 2})`,
Matteo Scandoloedd3d6f2016-02-16 15:06:11 -0800164 class: d => {
165 console.log(d.name, d.selected);
166 return `instance ${d.selected ? 'active' : ''}`
167 },
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800168 })
169 .transition()
170 .duration(serviceTopologyConfig.duration)
171 .attr({
Matteo Scandolob785b572016-02-16 11:50:51 -0800172 transform: d => `translate(${RackHelper.getInstancePosition(d.d3Id.replace('instance-', '') - 1)})`
Matteo Scandolo14183932016-02-11 08:58:04 -0800173 });
174
175 instanceContainer.append('rect')
Matteo Scandolob785b572016-02-16 11:50:51 -0800176 .attr({
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800177 width: 0,
178 height: 0
179 })
180 .transition()
181 .duration(serviceTopologyConfig.duration)
182 .attr({
Matteo Scandolob785b572016-02-16 11:50:51 -0800183 width: serviceTopologyConfig.instance.width,
184 height: serviceTopologyConfig.instance.height
185 });
186
187 instanceContainer.append('text')
188 .attr({
Matteo Scandolo0cfd5a22016-02-16 13:29:26 -0800189 'text-anchor': 'middle',
190 y: 23, //FIXME
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800191 x: 40, //FIXME
192 opacity: 0
Matteo Scandolob785b572016-02-16 11:50:51 -0800193 })
Matteo Scandolo7fd4d042016-02-16 14:44:51 -0800194 .text(d => formatInstanceName(d.name))
195 .transition()
196 .duration(serviceTopologyConfig.duration)
197 .attr({
198 opacity: 1
199 });
Matteo Scandolo0cfd5a22016-02-16 13:29:26 -0800200
201 instanceContainer
202 .on('click', d => {
203 console.log(d);
204 });
Matteo Scandolo14183932016-02-11 08:58:04 -0800205 };
Matteo Scandolo38ba3312016-02-09 16:01:49 -0800206
207 this.addPhisical = (nodes) => {
208 nodes.append('rect')
209 .attr(serviceTopologyConfig.square);
210
211 nodes.append('text')
212 .attr({
213 'text-anchor': 'middle',
214 y: serviceTopologyConfig.square.y - 10
215 })
216 .text(d => d.name);
217 }
218
219 this.addDevice = (nodes) => {
220 nodes.append('circle')
221 .attr(serviceTopologyConfig.circle);
222
223 nodes.append('text')
224 .attr({
225 'text-anchor': 'end',
226 x: - serviceTopologyConfig.circle.r - 10,
227 y: serviceTopologyConfig.circle.r / 2
228 })
229 .text(d => d.name);
230 }
231 });
232})();