blob: a3a534cc8756ea59a7da51fce26393b11367fe99 [file] [log] [blame]
Matteo Scandolodf35ca92016-02-25 09:19:41 -08001'use strict';
2
3angular.module('xos.mcordTopology', [
4 'ngResource',
5 'ngCookies',
6 'ngLodash',
7 'ui.router',
8 'xos.helpers'
9])
10.config(($stateProvider) => {
11 $stateProvider
12 .state('topology', {
13 url: '/',
14 template: '<m-cord-topology></m-cord-topology>'
15 });
16})
17.config(function($httpProvider){
18 $httpProvider.interceptors.push('NoHyperlinks');
19})
Matteo Scandolo97646d62016-03-07 14:14:00 -080020.service('Traffic', function($http, $q){
21 this.get = () => {
22 var deferred = $q.defer();
23 $http.get('videoLocal.txt')
24 .then(res => {
25 deferred.resolve(res.data);
26 });
27 return deferred.promise;
28 }
29})
Matteo Scandolodf35ca92016-02-25 09:19:41 -080030.directive('mCordTopology', function(){
31 return {
32 restrict: 'E',
33 scope: {},
34 bindToController: true,
35 controllerAs: 'vm',
36 template: '',
Matteo Scandolo97646d62016-03-07 14:14:00 -080037 controller: function($element, $interval, $rootScope, XosApi, lodash, TopologyElements, NodeDrawer, Traffic){
Matteo Scandolodf35ca92016-02-25 09:19:41 -080038
39 const el = $element[0];
40
41 let nodes = [];
42 let links = [];
Matteo Scandolo97646d62016-03-07 14:14:00 -080043 let traffic = 0;
44 let linkWidth = 1;
Matteo Scandolo0ddc2572016-03-07 15:05:24 -080045 let trafficCorrection = 5;
Matteo Scandolodf35ca92016-02-25 09:19:41 -080046
47 const filterBBU = (instances) => {
48 return lodash.filter(instances, i => i.name.indexOf('BBU') >= 0);
49 };
50
51 const filterOthers = (instances) => {
Matteo Scandolo89667d32016-03-07 13:34:05 -080052 return TopologyElements.fakedInstance;
Matteo Scandolodf35ca92016-02-25 09:19:41 -080053 };
54
55 // retrieving instances list
56 const getData = () => {
57
Matteo Scandolodab95002016-02-26 13:50:45 -080058 d3.select('svg')
59 .style('width', `${el.clientWidth}px`)
60 .style('height', `${el.clientHeight}px`);
61
Matteo Scandolodf35ca92016-02-25 09:19:41 -080062 nodes = TopologyElements.nodes;
63 links = TopologyElements.links;
64
Matteo Scandolo97646d62016-03-07 14:14:00 -080065 Traffic.get()
Matteo Scandolo0ddc2572016-03-07 15:05:24 -080066 .then((newTraffic) => {
Matteo Scandolo97646d62016-03-07 14:14:00 -080067
Matteo Scandolo0ddc2572016-03-07 15:05:24 -080068 // calculating link size
69 // it should change between 1 and 10
70 if(!traffic){
71 linkWidth = 2;
72 }
73 else if(newTraffic === traffic){
74 linkWidth = linkWidth;
75 }
76 else{
77 let delta = newTraffic - traffic;
78
79 if(delta > 0){
80 linkWidth = linkWidth + (delta / trafficCorrection);
81 }
82 else{
83 linkWidth = linkWidth - ((delta * -1) / trafficCorrection);
84 }
85
86 console.log(`previous traffic: ${traffic}`, `current traffic: ${newTraffic}`, `linkWidth: ${linkWidth}`);
87 console.log('************************');
Matteo Scandolo97646d62016-03-07 14:14:00 -080088 }
89
Matteo Scandolo0ddc2572016-03-07 15:05:24 -080090 if(linkWidth < 0.2){
91 linkWidth = 0.2
92 };
93
94 traffic = newTraffic;
95
Matteo Scandolo97646d62016-03-07 14:14:00 -080096 return XosApi.Instance_List_GET()
97 })
Matteo Scandolodf35ca92016-02-25 09:19:41 -080098 .then((instances) => {
99 addBbuNodes(filterBBU(instances));
100 addOtherNodes(filterOthers(instances));
101
102 draw(svg, nodes, links);
103 })
104 .catch((e) => {
105 throw new Error(e);
106 });
107 };
108
109 const force = d3.layout.force();
110
111 // create svg elements
112 const svg = d3.select(el)
113 .append('svg')
114 .style('width', `${el.clientWidth}px`)
115 .style('height', `${el.clientHeight}px`);
116
117 const linkContainer = svg.append('g')
118 .attr({
119 class: 'link-container'
120 });
121
122 const nodeContainer = svg.append('g')
123 .attr({
124 class: 'node-container'
125 });
126
127 // replace human readable ids with d3 ids
128 // NOTE now ids are not manatined on update...
129 const buildLinks = (links, nodes) => {
130 return links.map((l) => {
131
132
133 let source = lodash.findIndex(nodes, {id: l.source});
134 let target = lodash.findIndex(nodes, {id: l.target});
135 // console.log(`link-${source}-${target}`, source, target);
136 return {
137 source: source,
138 target: target,
139 value: 1,
140 id: `link-${source}-${target}`,
141 type: l.source.indexOf('fabric') >= 0 ? 'big':'small'
142 };
143
144 });
145 };
146
147 // find fabric nodes and center horizontally
148 const positionFabricNodes = (nodes) => {
149 return lodash.map(nodes, n => {
150 if(n.type !== 'fabric'){
151 return n;
152 }
153
154 n.x = n.x * hStep;
155 n.y = n.y * vStep;
156
157 return n;
158 });
159 };
160
161 const addBbuNodes = (instances) => {
162
163 // calculate bbu hStep
164 let bbuHStep = ((el.clientWidth / 2) / (instances.length + 1));
165
166 // create nodes
167 let bbuNodes = instances.map((n, i) => {
168 return {
169 type: 'bbu',
170 name: n.name,
171 id: `bbu-${n.id}`,
172 fixed: true,
173 y: vStep * 3,
174 x: bbuHStep * (i + 1)
175 };
176 });
177
178 // create links
179 let bbuLinks = bbuNodes.map(n => {
180 return {
181 source: n.id,
182 target: 'fabric2'
183 };
184 });
185
186 // fake RRU nodes and links
187 instances.forEach((n, i) => {
188 bbuNodes.push({
189 type: 'rru',
190 name: 'rru',
191 id: `rru-${n.id}`,
192 fixed: true,
193 y: vStep * 4,
194 x: bbuHStep * (i + 1)
195 });
196
197 bbuLinks.push({
198 source: `rru-${n.id}`,
199 target: `bbu-${n.id}`
200 });
201 })
202
203 nodes = nodes.concat(bbuNodes);
204
205
206 links = links.concat(bbuLinks);
207 };
208
209 // add MME, PGW, SGW nodes
210 const addOtherNodes = (instances) => {
211 let hStep = ((el.clientWidth / 2) / (instances.length + 1));
212
213 // create nodes
214 let otherNodes = instances.map((n, i) => {
215 return {
216 type: n.name.substring(0, 3),
217 name: n.name,
218 id: `${n.name.substring(0, 3)}-${n.id}`,
219 fixed: true,
220 y: vStep * 3,
221 x: (el.clientWidth / 2) + (hStep * (i + 1))
222 };
223 });
224
225 // create links
226 let otherLinks = otherNodes.map(n => {
227 return {
228 source: n.id,
229 target: 'fabric4'
230 };
231 });
232
233
234 nodes = nodes.concat(otherNodes);
235 links = links.concat(otherLinks);
236 }
237
238 let hStep, vStep;
239
240 hStep = el.clientWidth / 3;
241 vStep = el.clientHeight / 5;
242
243 const draw = (svg, nodes, links) => {
244
245 hStep = el.clientWidth / 3;
246 vStep = el.clientHeight / 5;
247
248 links = buildLinks(links, nodes);
249
250 nodes = positionFabricNodes(nodes);
251
252
253 // start force layout
254 force
255 .nodes(nodes)
256 .links(links)
257 .size([el.clientWidth, el.clientHeight])
258 .charge(-20)
259 .chargeDistance(200)
260 .linkDistance(80)
261 .linkStrength(0.1)
262 .start();
263
264
265 const linkContainer = d3.select('.link-container');
266 const nodeContainer = d3.select('.node-container');
267
268 NodeDrawer.drawFabricBox(nodeContainer, hStep, vStep);
269
270 // draw links
271 var link = linkContainer.selectAll('.link')
272 .data(links, d => d.id);
273
274 link.enter().append('line')
275 .attr({
Matteo Scandolo97646d62016-03-07 14:14:00 -0800276 class: d => `link ${d.type}`,
277 'stroke-width': linkWidth,
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800278 id: d => d.id,
Matteo Scandolo97646d62016-03-07 14:14:00 -0800279 opacity: 0
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800280 })
281 .transition()
282 .duration(1000)
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800283 .attr({
284 opacity: 1
285 });
286
Matteo Scandolo97646d62016-03-07 14:14:00 -0800287 link
288 .transition()
289 .duration(1000)
290 .attr({
291 'stroke-width': linkWidth,
292 opacity: 1
293 });
294
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800295 link.exit()
296 .remove();
297
298 //draw nodes
299 var node = nodeContainer.selectAll('.node')
300 .data(nodes, d => {
301 return d.id
302 });
303
304 // append a group for any new node
305 var enter = node.enter()
306 .append('g', d => d.interfaceCfgIdentifier)
307 .attr({
308 class: d => `${d.type} node`,
309 transform: d => `translate(${d.x}, ${d.y})`
310 });
311
312 // draw nodes
313 NodeDrawer.drawBbus(enter.filter('.bbu'))
314 NodeDrawer.drawRrus(enter.filter('.rru'))
315 NodeDrawer.drawFabric(enter.filter('.fabric'))
316 NodeDrawer.drawOthers(enter.filter(d => {
Matteo Scandolo89667d32016-03-07 13:34:05 -0800317 console.log(d.type);
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800318 return (
319 d.type === 'MME' ||
320 d.type === 'SGW' ||
Matteo Scandolo89667d32016-03-07 13:34:05 -0800321 d.type === 'PGW' ||
322 d.type === 'Vid'
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800323 )
324 }));
325
326 // remove nodes
327 var exit = node.exit();
328
329 NodeDrawer.removeElements(exit);
330
331 force.on('tick', function() {
332 link
333 .attr('x1', d => d.source.x )
334 .attr('y1', d => d.source.y )
335 .attr('x2', d => d.target.x )
336 .attr('y2', d => d.target.y );
337
338 node.attr('transform', (d) => `translate(${d.x},${d.y})`);
339 });
340 };
341
342 $interval(() => {
343 getData();
Matteo Scandolo97646d62016-03-07 14:14:00 -0800344 }, 3000);
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800345 getData();
346
347
348 }
349 };
350});