blob: d37acd7645602f533d757fb6b89510a4279865fb [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 Scandolodf35ca92016-02-25 09:19:41 -080019'use strict';
20
21angular.module('xos.mcordTopology', [
22 'ngResource',
23 'ngCookies',
Matteo Scandolodf35ca92016-02-25 09:19:41 -080024 'ui.router',
25 'xos.helpers'
26])
27.config(($stateProvider) => {
28 $stateProvider
29 .state('topology', {
30 url: '/',
31 template: '<m-cord-topology></m-cord-topology>'
32 });
33})
34.config(function($httpProvider){
35 $httpProvider.interceptors.push('NoHyperlinks');
36})
Matteo Scandolo1778b742016-04-22 09:47:50 -070037.factory('_', $window => $window._)
Matteo Scandolo97646d62016-03-07 14:14:00 -080038.service('Traffic', function($http, $q){
39 this.get = () => {
40 var deferred = $q.defer();
41 $http.get('videoLocal.txt')
42 .then(res => {
43 deferred.resolve(res.data);
Matteo Scandolo1778b742016-04-22 09:47:50 -070044 })
45 .catch(e => {
46 console.log(e);
47 deferred.resolve(Math.random() * 10)
Matteo Scandolo97646d62016-03-07 14:14:00 -080048 });
49 return deferred.promise;
50 }
51})
Matteo Scandolodf35ca92016-02-25 09:19:41 -080052.directive('mCordTopology', function(){
53 return {
54 restrict: 'E',
55 scope: {},
56 bindToController: true,
57 controllerAs: 'vm',
58 template: '',
Matteo Scandolo1778b742016-04-22 09:47:50 -070059 controller: function($element, $interval, $rootScope, _, $http, TopologyElements, NodeDrawer, Traffic){
Matteo Scandolodf35ca92016-02-25 09:19:41 -080060
61 const el = $element[0];
62
63 let nodes = [];
64 let links = [];
Matteo Scandolo97646d62016-03-07 14:14:00 -080065 let traffic = 0;
66 let linkWidth = 1;
Matteo Scandolo0ddc2572016-03-07 15:05:24 -080067 let trafficCorrection = 5;
Matteo Scandolodf35ca92016-02-25 09:19:41 -080068
69 const filterBBU = (instances) => {
Max Klyus61420862016-04-25 09:14:07 -070070 return _.filter(instances, i => i.name.indexOf("bbu") >= 0);
Matteo Scandolodf35ca92016-02-25 09:19:41 -080071 };
72
73 const filterOthers = (instances) => {
Matteo Scandolo89667d32016-03-07 13:34:05 -080074 return TopologyElements.fakedInstance;
Matteo Scandolodf35ca92016-02-25 09:19:41 -080075 };
76
77 // retrieving instances list
78 const getData = () => {
79
Matteo Scandolodab95002016-02-26 13:50:45 -080080 d3.select('svg')
81 .style('width', `${el.clientWidth}px`)
82 .style('height', `${el.clientHeight}px`);
83
Matteo Scandolodf35ca92016-02-25 09:19:41 -080084 nodes = TopologyElements.nodes;
85 links = TopologyElements.links;
86
Matteo Scandolo97646d62016-03-07 14:14:00 -080087 Traffic.get()
Matteo Scandolo0ddc2572016-03-07 15:05:24 -080088 .then((newTraffic) => {
Matteo Scandolo97646d62016-03-07 14:14:00 -080089
Matteo Scandolo0ddc2572016-03-07 15:05:24 -080090 // calculating link size
91 // it should change between 1 and 10
92 if(!traffic){
93 linkWidth = 2;
94 }
95 else if(newTraffic === traffic){
96 linkWidth = linkWidth;
97 }
98 else{
99 let delta = newTraffic - traffic;
100
101 if(delta > 0){
102 linkWidth = linkWidth + (delta / trafficCorrection);
103 }
104 else{
105 linkWidth = linkWidth - ((delta * -1) / trafficCorrection);
106 }
107
Matteo Scandolo97646d62016-03-07 14:14:00 -0800108 }
109
Matteo Scandolo0ddc2572016-03-07 15:05:24 -0800110 if(linkWidth < 0.2){
111 linkWidth = 0.2
112 };
113
114 traffic = newTraffic;
115
Matteo Scandolo1778b742016-04-22 09:47:50 -0700116 return $http.get('/api/core/xos/instances');
117 // return XosApi.Instance_List_GET()
Matteo Scandolo97646d62016-03-07 14:14:00 -0800118 })
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800119 .then((instances) => {
Matteo Scandolo1778b742016-04-22 09:47:50 -0700120
121 addBbuNodes(filterBBU(instances.data));
122 addOtherNodes(filterOthers(instances.data));
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800123
124 draw(svg, nodes, links);
125 })
126 .catch((e) => {
127 throw new Error(e);
128 });
129 };
130
131 const force = d3.layout.force();
132
133 // create svg elements
134 const svg = d3.select(el)
135 .append('svg')
136 .style('width', `${el.clientWidth}px`)
137 .style('height', `${el.clientHeight}px`);
138
139 const linkContainer = svg.append('g')
140 .attr({
141 class: 'link-container'
142 });
143
144 const nodeContainer = svg.append('g')
145 .attr({
146 class: 'node-container'
147 });
148
149 // replace human readable ids with d3 ids
150 // NOTE now ids are not manatined on update...
151 const buildLinks = (links, nodes) => {
152 return links.map((l) => {
153
Matteo Scandolo1778b742016-04-22 09:47:50 -0700154 console.log(_.find);
155 let source = _.findIndex(nodes, {id: l.source});
156 let target = _.findIndex(nodes, {id: l.target});
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800157 // console.log(`link-${source}-${target}`, source, target);
158 return {
159 source: source,
160 target: target,
161 value: 1,
162 id: `link-${source}-${target}`,
163 type: l.source.indexOf('fabric') >= 0 ? 'big':'small'
164 };
165
166 });
167 };
168
169 // find fabric nodes and center horizontally
170 const positionFabricNodes = (nodes) => {
Matteo Scandolo1778b742016-04-22 09:47:50 -0700171 return _.map(nodes, n => {
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800172 if(n.type !== 'fabric'){
173 return n;
174 }
175
176 n.x = n.x * hStep;
177 n.y = n.y * vStep;
178
179 return n;
180 });
181 };
182
183 const addBbuNodes = (instances) => {
184
185 // calculate bbu hStep
186 let bbuHStep = ((el.clientWidth / 2) / (instances.length + 1));
187
188 // create nodes
189 let bbuNodes = instances.map((n, i) => {
190 return {
191 type: 'bbu',
192 name: n.name,
193 id: `bbu-${n.id}`,
194 fixed: true,
195 y: vStep * 3,
196 x: bbuHStep * (i + 1)
197 };
198 });
199
200 // create links
201 let bbuLinks = bbuNodes.map(n => {
202 return {
203 source: n.id,
Matteo Scandoloaa3cc502016-03-09 17:58:51 -0800204 target: 'fabric4'
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800205 };
206 });
207
208 // fake RRU nodes and links
209 instances.forEach((n, i) => {
210 bbuNodes.push({
211 type: 'rru',
212 name: 'rru',
213 id: `rru-${n.id}`,
214 fixed: true,
215 y: vStep * 4,
216 x: bbuHStep * (i + 1)
217 });
218
219 bbuLinks.push({
220 source: `rru-${n.id}`,
221 target: `bbu-${n.id}`
222 });
223 })
224
225 nodes = nodes.concat(bbuNodes);
226
227
228 links = links.concat(bbuLinks);
229 };
230
231 // add MME, PGW, SGW nodes
232 const addOtherNodes = (instances) => {
233 let hStep = ((el.clientWidth / 2) / (instances.length + 1));
234
235 // create nodes
236 let otherNodes = instances.map((n, i) => {
237 return {
238 type: n.name.substring(0, 3),
239 name: n.name,
240 id: `${n.name.substring(0, 3)}-${n.id}`,
241 fixed: true,
242 y: vStep * 3,
243 x: (el.clientWidth / 2) + (hStep * (i + 1))
244 };
245 });
246
247 // create links
248 let otherLinks = otherNodes.map(n => {
249 return {
250 source: n.id,
251 target: 'fabric4'
252 };
253 });
254
255
256 nodes = nodes.concat(otherNodes);
257 links = links.concat(otherLinks);
258 }
259
260 let hStep, vStep;
261
262 hStep = el.clientWidth / 3;
263 vStep = el.clientHeight / 5;
264
265 const draw = (svg, nodes, links) => {
266
267 hStep = el.clientWidth / 3;
268 vStep = el.clientHeight / 5;
269
270 links = buildLinks(links, nodes);
271
272 nodes = positionFabricNodes(nodes);
273
Matteo Scandoloaa3cc502016-03-09 17:58:51 -0800274 console.log(nodes);
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800275 // start force layout
276 force
277 .nodes(nodes)
278 .links(links)
279 .size([el.clientWidth, el.clientHeight])
280 .charge(-20)
281 .chargeDistance(200)
282 .linkDistance(80)
283 .linkStrength(0.1)
284 .start();
285
286
287 const linkContainer = d3.select('.link-container');
288 const nodeContainer = d3.select('.node-container');
289
290 NodeDrawer.drawFabricBox(nodeContainer, hStep, vStep);
291
292 // draw links
293 var link = linkContainer.selectAll('.link')
294 .data(links, d => d.id);
295
296 link.enter().append('line')
297 .attr({
Matteo Scandolo97646d62016-03-07 14:14:00 -0800298 class: d => `link ${d.type}`,
299 'stroke-width': linkWidth,
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800300 id: d => d.id,
Matteo Scandolo97646d62016-03-07 14:14:00 -0800301 opacity: 0
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800302 })
303 .transition()
304 .duration(1000)
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800305 .attr({
306 opacity: 1
307 });
308
Matteo Scandolo97646d62016-03-07 14:14:00 -0800309 link
310 .transition()
311 .duration(1000)
312 .attr({
313 'stroke-width': linkWidth,
314 opacity: 1
315 });
316
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800317 link.exit()
318 .remove();
319
320 //draw nodes
321 var node = nodeContainer.selectAll('.node')
322 .data(nodes, d => {
323 return d.id
324 });
325
326 // append a group for any new node
327 var enter = node.enter()
328 .append('g', d => d.interfaceCfgIdentifier)
329 .attr({
330 class: d => `${d.type} node`,
331 transform: d => `translate(${d.x}, ${d.y})`
332 });
333
334 // draw nodes
335 NodeDrawer.drawBbus(enter.filter('.bbu'))
336 NodeDrawer.drawRrus(enter.filter('.rru'))
337 NodeDrawer.drawFabric(enter.filter('.fabric'))
338 NodeDrawer.drawOthers(enter.filter(d => {
Matteo Scandolo89667d32016-03-07 13:34:05 -0800339 console.log(d.type);
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800340 return (
341 d.type === 'MME' ||
342 d.type === 'SGW' ||
Matteo Scandolo89667d32016-03-07 13:34:05 -0800343 d.type === 'PGW' ||
344 d.type === 'Vid'
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800345 )
346 }));
347
348 // remove nodes
349 var exit = node.exit();
350
351 NodeDrawer.removeElements(exit);
352
353 force.on('tick', function() {
354 link
355 .attr('x1', d => d.source.x )
356 .attr('y1', d => d.source.y )
357 .attr('x2', d => d.target.x )
358 .attr('y2', d => d.target.y );
359
360 node.attr('transform', (d) => `translate(${d.x},${d.y})`);
361 });
362 };
363
Matteo Scandoloaa3cc502016-03-09 17:58:51 -0800364 // $interval(() => {
365 // getData();
366 // }, 3000);
Matteo Scandolodf35ca92016-02-25 09:19:41 -0800367 getData();
368
369
370 }
371 };
Max Klyus61420862016-04-25 09:14:07 -0700372});