f88162ef698fa96aadab15c856b2ac841422eee9
[honeycomb.git] / vbd / gui / module / src / main / resources / vpp / controllers / bdm.controller.js
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 define(['app/vpp/vpp.module'], function(vpp) {
10     vpp.register.controller('bdmCtrl', ['$scope', '$rootScope','$filter', 'dataService', 'toastService', function ($scope, $rootScope, filter, dataService, toastService) {
11
12     }]);
13
14     vpp.register.controller('TableController', ['$scope', '$rootScope','$filter', 'dataService', 'toastService', 'bdmInterfaceService',
15         function ($scope, $rootScope, filter, dataService, toastService, bdmInterfaceService) {
16             $scope.interfaceList = [];
17             $scope.unassignedInterfaceList = [];
18             $scope.assignedInterfaces = [];
19
20             var vm = this;
21
22             vm.updateAssignment = function(receivedInterface) {
23                 if (receivedInterface.assigned){
24                     receivedInterface.vbdName = $scope.selectedBd['topology-id'];
25                     vm.assignInterface($scope.selectedBd, receivedInterface);
26
27                 } else {
28                     vm.unassignInterface(receivedInterface);
29                 }
30             };
31
32             vm.assignInterface = function(bridgeDomain, interface) {
33                 var interfaceObject = bdmInterfaceService.createObj(interface['tp-id'], interface['tp-id']);
34
35                 var successCallback = function() {
36                     toastService.showToast('Interface assigned');
37                     $scope.assignedInterfaces.push(interface);
38
39                     $scope.$emit('INTERFACE_CHANGED', interface);
40                 };
41
42                 var errorCallback = function() {
43                     toastService.showToast('Unable to assign interface');
44                 };
45
46                 bdmInterfaceService.add(interfaceObject, bridgeDomain['topology-id'], interface.vppName, successCallback, errorCallback);
47             };
48
49             vm.unassignInterface = function(interface) {
50                 var interfaceObject = bdmInterfaceService.createObj(interface['tp-id'], interface['tp-id']);
51
52                 var successCallback = function() {
53                     toastService.showToast('Interface unassigned');
54                     $scope.assignedInterfaces.splice($scope.assignedInterfaces.indexOf(interface), 1);
55                     interface.vbdName = '';
56
57                     $scope.$emit('INTERFACE_CHANGED', interface);
58                 };
59
60                 var errorCallback = function() {
61                     toastService.showToast('Unable to unassign interface');
62                 };
63
64                 bdmInterfaceService.delete(interfaceObject, interface.vbdName, interface.vppName, successCallback, errorCallback);
65
66             };
67
68             $scope.$on('BUILD_INTERFACES_TABLE', function(event) {
69                 $scope.interfaceList = [];
70                 $scope.unassignedInterfaceList = [];
71                 $scope.assignedInterfaces = $scope.getAssignedInterfaces();
72
73                 $scope.assignedInterfacesFlat = [];
74
75                 var getAssignedInterfacesFlat = function() {
76                     var keys = Object.keys($scope.assignedInterfaces);
77
78                     if(keys.length) {
79                         keys.forEach(function (k) {
80                             if($scope.assignedInterfaces[k]) {
81                                 $scope.assignedInterfaces[k].forEach(function(ai) {
82                                     checkAndPushIntoArray($scope.assignedInterfacesFlat, ai);
83                                 });
84                             }
85                         });
86                     }
87                 };
88
89                 var checkAndPushIntoArray = function(array, item) {
90                     var check = array.some(function(i) {
91                         return i['tp-id'] === item['tp-id'] && i.vppName === item.vppName;
92                     });
93
94                     if(!check) {
95                         array.push(item);
96                     }
97                 };
98
99                 getAssignedInterfacesFlat();
100
101                 dataService.vpps.forEach(function(vpp){
102                      vpp.interfaces.forEach(function(interface){
103                          var interfaceObject = bdmInterfaceService.createObj(interface.name, interface.name);
104
105                          var check = $scope.assignedInterfacesFlat.some(function (ai) {
106                              return interfaceObject['tp-id'] === ai['tp-id'] && vpp.name === ai.vppName;
107                          });
108
109                          if(!check) {
110                              interfaceObject.vppName = vpp.name;
111                              checkAndPushIntoArray($scope.unassignedInterfaceList, interfaceObject);
112                          }
113                     });
114                 });
115
116                 if($scope.selectedBd) {
117                     $scope.interfaceList = $scope.assignedInterfaces[$scope.selectedBd['topology-id']] ? $scope.assignedInterfaces[$scope.selectedBd['topology-id']].concat($scope.unassignedInterfaceList) : $scope.unassignedInterfaceList;
118                 }
119
120                 $scope.interfaceDisplayList = [].concat($scope.interfaceList);
121             });
122
123             $scope.$on('INIT_INTERFACES_TABLE', function(event) {
124                 $scope.interfaceList = [];
125                 $scope.unassignedInterfaceList = [];
126                 $scope.assignedInterfaces = [];
127                 $scope.assignedInterfacesFlat = [];
128             });
129
130
131
132     }]);
133
134     vpp.register.controller('BridgeDomainsController', ['$scope', '$rootScope','$filter', 'dataService', 'bdmBridgeDomainService', 'toastService', '$mdDialog', 'bdmTunnelService',
135         function($scope, $rootScope, $filter, dataService, bdmBridgeDomainService, toastService, $mdDialog, bdmTunnelService) {
136             $scope.bridgeDomainList = [];
137             $scope.showOverlay = true;
138
139             $scope.loadBridgeDomains = function(bridgeDomain, successCallback) {
140                 bdmBridgeDomainService.get(function(data) {
141                     $scope.bridgeDomainList = data;
142
143                     if(bridgeDomain) {
144                         $scope.selectedBd = $scope.bridgeDomainList.filter(function(bd) {
145                            return bd['topology-id'] ===  bridgeDomain['topology-id'];
146                         })[0];
147
148                         $scope.showTopology($scope.selectedBd);
149                     }
150
151                     successCallback();
152
153                 }, function(data,status) {
154                     //error callback
155                     console.log(status);
156                 });
157             };
158
159             $scope.getInterfacesForBridgeDomain = function(bridgeDomain) {
160                 var interfaceList = [];
161
162                 if(bridgeDomain.node) {
163                     bridgeDomain.node.forEach(function (n) {
164                         if (n['termination-point']) {
165                             n['termination-point'].forEach(function (tp) {
166                                 tp.vppName = n['node-id'];
167                                 tp.vbdName = bridgeDomain['topology-id'];
168                                 tp.assigned = true;
169
170                                 interfaceList.push(tp);
171                             });
172                         }
173                     });
174                 }
175
176                 return interfaceList;
177             };
178
179             $scope.getAssignedInterfaces = function() {
180                 var interfaces = [];
181
182                 $scope.bridgeDomainList.forEach(function(bd) {
183                     var bdCopy = {};
184                     angular.copy(bd, bdCopy);
185
186                     interfaces[bdCopy['topology-id']] = $scope.getInterfacesForBridgeDomain(bdCopy);
187                 });
188
189                 return interfaces;
190             };
191
192             $scope.addBd = function() {
193                 //show dialog
194                 $mdDialog.show({
195                     controller: function() {
196                         var vm = this;
197                         vm.bd = {};
198                         vm.waiting = false;
199
200                         //function called when the cancel button ( 'x' in the top right) is clicked
201                         vm.close = function() {
202                             $mdDialog.cancel();
203                         };
204
205                         vm.isDone = function(status, bridgeDomain) {
206                             vm.waiting = false;
207                             if (status === 'success') {
208                                 $scope.reload(bridgeDomain);
209                                 vm.close();
210                             }
211                         };
212
213                         //function called when the update button is clicked
214                         vm.updateConfig = function() {
215                             vm.waiting = true;
216                             //send a POST with the entered content in the form field
217
218                             var obj = bdmBridgeDomainService.createObj(vm.bd.name);
219
220                             bdmBridgeDomainService.add(obj,
221                                 function(data) {
222                                     vm.isDone('success', obj);
223                                 },
224                                 function() {
225                                     vm.isDone('failed');
226                                 });
227
228                         };
229                     },
230                     controllerAs: 'NewBdDialogCtrl',
231                     templateUrl: $scope.view_path + 'new-bd-dialog.html',
232                     parent: angular.element(document.body),
233                     clickOutsideToClose:false
234                 })
235             };
236
237             $scope.removeBd = function() {
238                 if($scope.selectedBd['topology-id']) {
239                     var successCallback = function(success) {
240                         $scope.selectedBd = null;
241                         $scope.loadBridgeDomains(null, function() {
242                             $scope.$broadcast('INIT_INTERFACES_TABLE');
243                             $scope.clearTopologies();
244                         });
245
246                     };
247                     bdmBridgeDomainService.remove($scope.selectedBd['topology-id'], function(){successCallback(true)}, function(){successCallback(false)});
248                 }
249             };
250
251             $scope.bdChanged = function() {
252                 $scope.loadBridgeDomains($scope.selectedBd, function() {
253                     $scope.$broadcast('BUILD_INTERFACES_TABLE');
254
255                     $scope.showTopology($scope.selectedBd);
256                 });
257
258             };
259
260             nx.graphic.Icons.registerIcon("bd", "src/app/vpp/assets/images/bd1.svg", 45, 45);
261             nx.graphic.Icons.registerIcon("interf", "src/app/vpp/assets/images/interf.svg", 45, 45);
262
263             $scope.showOverlayTopology = function(bridgeDomain) {
264                 var bdCopy = {};
265                 angular.copy(bridgeDomain, bdCopy);
266
267                 $scope.bridgeDomainsTopo = new nx.graphic.Topology({
268                     adaptive: true,
269                     scalable: true,
270                     theme: 'blue',
271                     enableGradualScaling: true,
272                     nodeConfig: {
273                         color: '#414040',
274                         label: 'model.label',
275                         scale: 'model.scale',
276                         iconType: function (vertex) {
277                             var type = vertex.get().type;
278                             if (type === 'bd') {
279                                 return 'bd'
280                             } else {
281                                 return 'interf';
282                             }
283                         }
284                     },
285                     linkConfig: {
286                         label: 'model.label',
287                         linkType: 'parallel',
288                         color: function (link) {
289                             if (link.getData().type === 'tunnel') {
290                                 return '#00FF00';
291                             } else {
292                                 return '#ffffff';
293                             }
294                         },
295                         width: function (link) {
296                             if (link.getData().type === 'tunnel') {
297                                 return 5;
298                             }
299                         }
300                     },
301                     showIcon: true,
302                     dataProcessor: 'force',
303                     autoLayout: true,
304                     enableSmartNode: false,
305                     tooltipManagerConfig: {
306                         nodeTooltipContentClass: 'TooltipNode',
307                         linkTooltipContentClass: 'TooltipLink'
308                     }
309                 });
310
311                 $scope.overlayNextApp =  new nx.ui.Application;
312
313                 var bdNode = {
314                     "data": bdCopy,
315                     "type": "bd",
316                     "label": bdCopy['topology-id']
317                 };
318
319                 var nodes = [].concat(bdNode);
320                 var links = [];
321
322                 _.forEach($scope.getInterfacesForBridgeDomain(bdCopy), function(tp, index){
323                     var ifNode = {
324                         "data": tp,
325                         "type": "interf",
326                         "label": tp['tp-id']
327                     };
328                     nodes.push(ifNode);
329                     links.push({source: 0, target: nodes.length-1});
330                 });
331
332
333                 $scope.bridgeDomainsTopo.data({
334                     nodes: nodes,
335                     links: links
336                 });
337
338                 $scope.overlayNextApp.container(document.getElementById('overlay-next-app'));
339                 $scope.bridgeDomainsTopo.attach($scope.overlayNextApp);
340             };
341
342             $scope.fillOverlayTopology = function(bridgeDomain) {
343                 var bdCopy = {};
344                 angular.copy(bridgeDomain, bdCopy);
345
346                 var bdNode = {
347                     "data": bdCopy,
348                     "type": "bd",
349                     "label": bdCopy['topology-id']
350                 };
351
352                 var nodes = [].concat(bdNode);
353                 var links = [];
354
355                 _.forEach($scope.getInterfacesForBridgeDomain(bdCopy), function(tp, index){
356                     var ifNode = {
357                         "data": tp,
358                         "type": "interf",
359                         "label": tp['tp-id']
360                     };
361                     nodes.push(ifNode);
362                     links.push({source: 0, target: nodes.length-1});
363                 });
364
365
366                 $scope.bridgeDomainsTopo.data({
367                     nodes: nodes,
368                     links: links
369                 });
370
371             };
372
373             $scope.showUnderTopology = function(bridgeDomain) {
374                 //var bdCopy = {};
375                 //angular.copy(bridgeDomain, bdCopy);
376
377                 $scope.underlayTopo = new nx.graphic.Topology({
378                     adaptive: true,
379                     scalable: true,
380                     theme:'blue',
381                     enableGradualScaling:true,
382                     nodeConfig: {
383                         color: '#414040',
384                         label: 'model.label',
385                         scale: 'model.scale',
386                         iconType: function(vertex) {
387                             var type = vertex.get().type;
388                             if (type === 'bd') {
389                                 return 'bd';
390                             } else if (type==='vpp') {
391                                 return 'switch';
392                             } else {
393                                 return 'interf';
394                             }
395                         }
396                     },
397                     linkConfig: {
398                         label: 'model.label',
399                         linkType: 'parallel',
400                         color: function(link) {
401                             if (link.getData().type === 'tunnel') {
402                                 return '#00FF00';
403                             } else {
404                                 return '#ffffff';
405                             }
406                         },
407                         width: function(link) {
408                             if (link.getData().type === 'tunnel') {
409                                 return 5;
410                             }
411                         }
412                     },
413                     showIcon: true,
414                     enableSmartNode: false
415                 });
416
417                 $scope.underlayNextApp =  new nx.ui.Application;
418
419                 $scope.fillUnderlayTopology(bridgeDomain);
420
421                 $scope.underlayNextApp.container(document.getElementById('underlay-next-app'));
422                 $scope.underlayTopo.attach($scope.underlayNextApp);
423             };
424
425             $scope.fillUnderlayTopology = function(bridgeDomain) {
426                 var bdCopy = {};
427                 angular.copy(bridgeDomain, bdCopy);
428
429                 var nodes = [];
430                 var links = [];
431
432                 _.forEach(bdCopy.node, function(node, index){
433                     var i = index + 1;
434
435                     nodes.push({
436                         label: node['node-id'],
437                         x: (-1+(2*(i%2)))*((i+1)/2 * 500),
438                         y: 700,
439                         scale: 1.25,
440                         type: 'vpp'
441                     });
442
443
444                     bdmTunnelService.get(
445                         bdCopy['topology-id'],
446                         function(data) {
447                             //success
448                             console.log(data);
449
450                             var link = data;
451                             var sourceNode = link[0].source['source-node'];
452                             var targetNode = link[0].destination['dest-node'];
453
454                             links.push({
455                                 source: _.findIndex(nodes, {label: sourceNode, type: 'vpp'}),
456                                 target: _.findIndex(nodes, {label: targetNode, type: 'vpp'}),
457                                 type: 'tunnel'
458                             });
459
460                             $scope.underlayTopo.data({
461                                 nodes: nodes,
462                                 links: links
463                             });
464
465                         }, function(res) {
466                             $scope.underlayTopo.data({
467                                 nodes: nodes,
468                                 links: links
469                             });
470                         });
471                 });
472
473
474                 $scope.underlayTopo.data({
475                     nodes: nodes,
476                     links: links
477                 });
478             };
479
480             $scope.reload = function(bridgeDomain) {
481                 $scope.loadBridgeDomains(bridgeDomain, function() {
482                     $scope.$broadcast('BUILD_INTERFACES_TABLE');
483
484                     $scope.showTopology($scope.selectedBd);
485                 });
486
487             };
488
489             $scope.toggleUnderlay = function() {
490                 $scope.showOverlay = !$scope.showOverlay;
491
492                 $scope.reload($scope.selectedBd);
493             };
494
495             $scope.showTopology = function(bridgeDomain) {
496                 if($scope.showOverlay) {
497                     if(!$scope.bridgeDomainsTopo) {
498                         $scope.showOverlayTopology(bridgeDomain);
499                     }
500                     else {
501                         $scope.fillOverlayTopology(bridgeDomain);
502                     }
503                 } else {
504                     if(!$scope.underlayTopo) {
505                         $scope.showUnderTopology(bridgeDomain);
506                     }
507                     else {
508                         $scope.fillUnderlayTopology(bridgeDomain);
509                     }
510                 }
511             };
512
513             $scope.clearTopologies = function() {
514                 if($scope.bridgeDomainsTopo) {
515                     $scope.bridgeDomainsTopo.data({
516                         nodes: [],
517                         links: []
518                     });
519                 }
520
521                 if($scope.bridgeDomainsTopo) {
522                     $scope.underlayTopo.data({
523                         nodes: [],
524                         links: []
525                     });
526                     }
527             };
528
529             $scope.$on('INTERFACE_CHANGED', function(event, data) {
530                 bdmBridgeDomainService.getOne($scope.selectedBd['topology-id'],
531                     function(bdData) {
532                         $scope.fillOverlayTopology(bdData);
533                     },
534                     function() {
535                         console.log('error getting vbd');
536                     });
537             });
538
539             $scope.loadBridgeDomains(null, function() {});
540         }]);
541 });