blob: 128848dda0c35ffad65f615771908cf3e0e624a1 [file] [log] [blame]
Matteo Scandolo9fe01af2016-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 Scandolo170d3be2016-02-11 08:58:04 -08008 var computeNodeId = 0;
9 var instanceId = 0;
10
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080011 angular.module('xos.serviceTopology')
Matteo Scandolo35d53c82016-02-16 14:44:51 -080012 .service('NodeDrawer', function(d3, serviceTopologyConfig, RackHelper){
Matteo Scandolo51031482016-02-17 13:54:11 -080013
14 var _this = this;
15
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080016 this.addNetworks = (nodes) => {
17 nodes.append('path')
18 .attr({
19 d: shapes.cloud,
20 transform: 'translate(-63, -52), scale(0.5)',
21 class: 'cloud'
22 });
23
24 nodes.append('text')
25 .attr({
26 'text-anchor': 'middle'
27 })
28 .text(d => d.name)
29 }
30
31 this.addRack = (nodes) => {
Matteo Scandolo170d3be2016-02-11 08:58:04 -080032
Matteo Scandolo35d53c82016-02-16 14:44:51 -080033 // loop because of D3
34 // rack will be only one
35 nodes.each(d => {
36 let [w, h] = RackHelper.getRackSize(d.computeNodes);
Matteo Scandoload5b2282016-02-16 11:50:51 -080037
38 let rack = nodes
Matteo Scandolo35d53c82016-02-16 14:44:51 -080039 .append('g');
40
41 rack
42 .attr({
43 transform: `translate(0,0)`
44 })
45 .transition()
46 .duration(serviceTopologyConfig.duration)
47 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -080048 transform: d => `translate(${- (w / 2)}, ${- (h / 2)})`
49 });
50
51 rack
52 .append('rect')
53 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -080054 width: 0,
55 height: 0
56 })
57 .transition()
58 .duration(serviceTopologyConfig.duration)
59 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -080060 width: w,
61 height: h
62 });
63
Matteo Scandolo35d53c82016-02-16 14:44:51 -080064 rack.append('text')
Matteo Scandoload5b2282016-02-16 11:50:51 -080065 .attr({
66 'text-anchor': 'middle',
Matteo Scandolo35d53c82016-02-16 14:44:51 -080067 y: - 10,
68 x: w / 2,
69 opacity: 0
Matteo Scandoload5b2282016-02-16 11:50:51 -080070 })
Matteo Scandolo35d53c82016-02-16 14:44:51 -080071 .text(d => d.name)
72 .transition()
73 .duration(serviceTopologyConfig.duration)
74 .attr({
75 opacity: 1
76 })
Matteo Scandoload5b2282016-02-16 11:50:51 -080077
Matteo Scandolo35d53c82016-02-16 14:44:51 -080078 this.drawComputeNodes(rack, d.computeNodes);
79
Matteo Scandolo170d3be2016-02-11 08:58:04 -080080 });
Matteo Scandolo35d53c82016-02-16 14:44:51 -080081
Matteo Scandolo170d3be2016-02-11 08:58:04 -080082 };
83
84 this.drawComputeNodes = (container, nodes) => {
Matteo Scandoload5b2282016-02-16 11:50:51 -080085
Matteo Scandolo170d3be2016-02-11 08:58:04 -080086 let elements = container.selectAll('.compute-nodes')
87 .data(nodes, d => {
88 if(!angular.isString(d.d3Id)){
89 d.d3Id = `compute-node-${++computeNodeId}`;
90 }
91 return d.d3Id;
92 });
93
Matteo Scandolo35d53c82016-02-16 14:44:51 -080094 let {width, height} = container.node().getBoundingClientRect();
95
96 var nodeContainer = elements.enter().append('g');
97
98 nodeContainer
Matteo Scandolo170d3be2016-02-11 08:58:04 -080099 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800100 transform: `translate(${width / 2}, ${ height / 2})`,
Matteo Scandoload5b2282016-02-16 11:50:51 -0800101 class: 'compute-node',
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800102 })
103 .transition()
104 .duration(serviceTopologyConfig.duration)
105 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -0800106 transform: (d) => `translate(${RackHelper.getComputeNodePosition(nodes, d.d3Id.replace('compute-node-', '') - 1)})`
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800107 });
108
109 nodeContainer.append('rect')
Matteo Scandoload5b2282016-02-16 11:50:51 -0800110 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800111 width: 0,
112 height: 0
113 })
114 .transition()
115 .duration(serviceTopologyConfig.duration)
116 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -0800117 width: d => RackHelper.getComputeNodeSize(d.instances)[0],
118 height: d => RackHelper.getComputeNodeSize(d.instances)[1],
119 });
120
121 nodeContainer.append('text')
122 .attr({
123 'text-anchor': 'start',
124 y: 15, //FIXME
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800125 x: 10, //FIXME
126 opacity: 0
Matteo Scandoload5b2282016-02-16 11:50:51 -0800127 })
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800128 .text(d => d.humanReadableName.split('.')[0])
129 .transition()
130 .duration(serviceTopologyConfig.duration)
131 .attr({
132 opacity: 1
133 })
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800134
135 // if there are Compute Nodes
136 if(nodeContainer.length > 0){
Matteo Scandolo51031482016-02-17 13:54:11 -0800137 // draw instances for each compute node
138 nodeContainer.each(function(a){
139 _this.drawInstances(d3.select(this), a.instances);
140 })
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800141 }
142
143 };
144
Matteo Scandolo7030ceb2016-02-16 13:29:26 -0800145 // NOTE Stripping unuseful names to shorten labels.
146 // This is not elegant
147 const formatInstanceName = (name) => {
148 return name
149 .replace('app_', '')
150 .replace('service_', '')
151 .replace('ovs_', '')
152 .replace('mysite_', '')
153 .replace('_instance', '');
154 };
155
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800156 this.drawInstances = (container, instances) => {
Matteo Scandolo51031482016-02-17 13:54:11 -0800157
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800158 let {width, height} = container.node().getBoundingClientRect();
159
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800160 let elements = container.selectAll('.instances')
161 .data(instances, d => angular.isString(d.d3Id) ? d.d3Id : d.d3Id = `instance-${++instanceId}`)
162
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800163 var instanceContainer = elements.enter().append('g');
164
165 instanceContainer
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800166 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800167 transform: `translate(${width / 2}, ${ height / 2})`,
Matteo Scandolo7e67a9a2016-02-16 16:33:26 -0800168 class: d => `instance ${d.selected ? 'active' : ''}`,
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800169 })
170 .transition()
171 .duration(serviceTopologyConfig.duration)
172 .attr({
Matteo Scandolo51031482016-02-17 13:54:11 -0800173 transform: (d, i) => `translate(${RackHelper.getInstancePosition(i)})`
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800174 });
175
176 instanceContainer.append('rect')
Matteo Scandoload5b2282016-02-16 11:50:51 -0800177 .attr({
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800178 width: 0,
179 height: 0
180 })
181 .transition()
182 .duration(serviceTopologyConfig.duration)
183 .attr({
Matteo Scandoload5b2282016-02-16 11:50:51 -0800184 width: serviceTopologyConfig.instance.width,
185 height: serviceTopologyConfig.instance.height
186 });
187
188 instanceContainer.append('text')
189 .attr({
Matteo Scandolo7030ceb2016-02-16 13:29:26 -0800190 'text-anchor': 'middle',
191 y: 23, //FIXME
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800192 x: 40, //FIXME
193 opacity: 0
Matteo Scandoload5b2282016-02-16 11:50:51 -0800194 })
Matteo Scandolo35d53c82016-02-16 14:44:51 -0800195 .text(d => formatInstanceName(d.name))
196 .transition()
197 .duration(serviceTopologyConfig.duration)
198 .attr({
199 opacity: 1
200 });
Matteo Scandolo7030ceb2016-02-16 13:29:26 -0800201
202 instanceContainer
203 .on('click', d => {
204 console.log(d);
205 });
Matteo Scandolo170d3be2016-02-11 08:58:04 -0800206 };
Matteo Scandolo9fe01af2016-02-09 16:01:49 -0800207
208 this.addPhisical = (nodes) => {
209 nodes.append('rect')
210 .attr(serviceTopologyConfig.square);
211
212 nodes.append('text')
213 .attr({
214 'text-anchor': 'middle',
215 y: serviceTopologyConfig.square.y - 10
216 })
217 .text(d => d.name);
218 }
219
220 this.addDevice = (nodes) => {
221 nodes.append('circle')
222 .attr(serviceTopologyConfig.circle);
223
224 nodes.append('text')
225 .attr({
226 'text-anchor': 'end',
227 x: - serviceTopologyConfig.circle.r - 10,
228 y: serviceTopologyConfig.circle.r / 2
229 })
230 .text(d => d.name);
231 }
232 });
233})();