Underlay added 78/278/6
authorDaniel Malachovsky <daniel.malachovsky@pantheon.sk>
Thu, 11 Feb 2016 13:13:09 +0000 (14:13 +0100)
committerDave Wallace <dwallacelf@gmail.com>
Fri, 12 Feb 2016 02:12:20 +0000 (02:12 +0000)
- bd manager rewritten
- underlay topo functional
- lot of cleaning

Change-Id: I48e259aaf341eb0a1c09e6b25dd411d525d854c1
Signed-off-by: Varun Seereeram <vseereer@cisco.com>
Signed-off-by: Daniel Malachovsky <daniel.malachovsky@pantheon.sk>
12 files changed:
vbd/gui/module/src/main/resources/vpp/controllers/bdm.controller.js
vbd/gui/module/src/main/resources/vpp/controllers/inventory.controller.js
vbd/gui/module/src/main/resources/vpp/controllers/vpp.controller.js
vbd/gui/module/src/main/resources/vpp/services/bdm.bridgedomain.service.js
vbd/gui/module/src/main/resources/vpp/services/bdm.interface.service.js
vbd/gui/module/src/main/resources/vpp/services/bdm.tunnel.service.js [new file with mode: 0644]
vbd/gui/module/src/main/resources/vpp/services/bdm.vpp.service.js
vbd/gui/module/src/main/resources/vpp/services/vpp.services.js
vbd/gui/module/src/main/resources/vpp/views/bridge-domains.tpl.html
vbd/gui/module/src/main/resources/vpp/views/index.tpl.html
vbd/gui/module/src/main/resources/vpp/views/inventory-detail.tpl.html
vbd/gui/module/src/main/resources/vpp/views/new-vpp-dialog.html

index 7c24690..f88162e 100644 (file)
@@ -13,124 +13,180 @@ define(['app/vpp/vpp.module'], function(vpp) {
 
     vpp.register.controller('TableController', ['$scope', '$rootScope','$filter', 'dataService', 'toastService', 'bdmInterfaceService',
         function ($scope, $rootScope, filter, dataService, toastService, bdmInterfaceService) {
+            $scope.interfaceList = [];
+            $scope.unassignedInterfaceList = [];
+            $scope.assignedInterfaces = [];
+
             var vm = this;
-            vm.rowCollection = dataService.tableContent;
-            vm.displayedCollection = [].concat(vm.rowCollection);
 
             vm.updateAssignment = function(receivedInterface) {
-                console.log(receivedInterface);
-                var interf = _.find(dataService.interfaces, {name: receivedInterface.name, 'vppName': receivedInterface.vppName});
                 if (receivedInterface.assigned){
-                    interf.assigned = true;
-                    interf.vbd = dataService.selectedBd.name;
-                    receivedInterface.vbd = dataService.selectedBd.name;
+                    receivedInterface.vbdName = $scope.selectedBd['topology-id'];
+                    vm.assignInterface($scope.selectedBd, receivedInterface);
 
-                    vm.assignInterface(interf);
                 } else {
-                    var vbdName = receivedInterface.vbd,
-                        vppName = receivedInterface.vppName;
-
-                    interf.assigned = false;
-                    interf.vbd = '';
-                    receivedInterface.vbd = '';
-
-                    vm.unassignInterface(interf, vbdName, vppName);
+                    vm.unassignInterface(receivedInterface);
                 }
-                //dataService.buildTableContent();
-                var previouslyChangedInterface = _.find(dataService.changedInterfaces, {name: interf.name, 'vppName': interf.vppName});
-                if (!previouslyChangedInterface) {
-                    dataService.changedInterfaces.push(interf);
-                }
-                console.log(dataService.changedInterfaces);
-                dataService.injectBridgeDomainsTopoElements();
-
             };
 
-            vm.assignInterface = function(interface) {
-                var interfaceObject = bdmInterfaceService.createObj(interface.name, interface.name);
+            vm.assignInterface = function(bridgeDomain, interface) {
+                var interfaceObject = bdmInterfaceService.createObj(interface['tp-id'], interface['tp-id']);
 
                 var successCallback = function() {
                     toastService.showToast('Interface assigned');
+                    $scope.assignedInterfaces.push(interface);
+
+                    $scope.$emit('INTERFACE_CHANGED', interface);
                 };
 
                 var errorCallback = function() {
                     toastService.showToast('Unable to assign interface');
                 };
 
-                bdmInterfaceService.add(interfaceObject, interface.vbd, interface.vppName, successCallback, errorCallback);
+                bdmInterfaceService.add(interfaceObject, bridgeDomain['topology-id'], interface.vppName, successCallback, errorCallback);
             };
 
-            vm.unassignInterface = function(interface, vbdname, vppName) {
-                var interfaceObject = bdmInterfaceService.createObj(interface.name, interface.name);
+            vm.unassignInterface = function(interface) {
+                var interfaceObject = bdmInterfaceService.createObj(interface['tp-id'], interface['tp-id']);
 
                 var successCallback = function() {
                     toastService.showToast('Interface unassigned');
+                    $scope.assignedInterfaces.splice($scope.assignedInterfaces.indexOf(interface), 1);
+                    interface.vbdName = '';
+
+                    $scope.$emit('INTERFACE_CHANGED', interface);
                 };
 
                 var errorCallback = function() {
                     toastService.showToast('Unable to unassign interface');
                 };
 
-                bdmInterfaceService.delete(interfaceObject, vbdname, vppName, successCallback, errorCallback);
+                bdmInterfaceService.delete(interfaceObject, interface.vbdName, interface.vppName, successCallback, errorCallback);
 
             };
-    }]);
 
-    vpp.register.controller('BridgeDomainsController', ['$scope', '$rootScope','$filter', 'dataService', 'bdmBridgeDomainService', 'toastService', '$mdDialog','bdmInterfaceService',
-        function($scope, $rootScope, $filter, dataService, bdmBridgeDomainService, toastService, $mdDialog,bdmInterfaceService) {
+            $scope.$on('BUILD_INTERFACES_TABLE', function(event) {
+                $scope.interfaceList = [];
+                $scope.unassignedInterfaceList = [];
+                $scope.assignedInterfaces = $scope.getAssignedInterfaces();
 
-            console.log('Bridge Domains Controller executed.');
+                $scope.assignedInterfacesFlat = [];
 
-            $scope.dataService = dataService;
-            $scope.bridgedomains = dataService.bridgedomains;
-            $scope.selectedBd = dataService.selectedBd;
+                var getAssignedInterfacesFlat = function() {
+                    var keys = Object.keys($scope.assignedInterfaces);
 
-            dataService.nextApp.container(document.getElementById('bridge-domains-next-app'));
-            dataService.bridgeDomainsTopo.attach(dataService.nextApp);
+                    if(keys.length) {
+                        keys.forEach(function (k) {
+                            if($scope.assignedInterfaces[k]) {
+                                $scope.assignedInterfaces[k].forEach(function(ai) {
+                                    checkAndPushIntoArray($scope.assignedInterfacesFlat, ai);
+                                });
+                            }
+                        });
+                    }
+                };
 
-            if (!dataService.bridgedomainsLoaded) {
-                dataService.generateInterfaces();
-                bdmBridgeDomainService.get(function(data) {
-                    //success callback
-                    angular.copy(data['network-topology'].topology, dataService.bridgedomains);
-                    dataService.bridgedomainsLoaded = true;
-                    console.log('Loaded BridgeDomains:');
-                    console.log(dataService.bridgedomains);
-                    dataService.buildAssignedInterfaces();
-                }, function(data,status) {
-                    //error callback
-                    console.log(status);
+                var checkAndPushIntoArray = function(array, item) {
+                    var check = array.some(function(i) {
+                        return i['tp-id'] === item['tp-id'] && i.vppName === item.vppName;
+                    });
+
+                    if(!check) {
+                        array.push(item);
+                    }
+                };
+
+                getAssignedInterfacesFlat();
+
+                dataService.vpps.forEach(function(vpp){
+                     vpp.interfaces.forEach(function(interface){
+                         var interfaceObject = bdmInterfaceService.createObj(interface.name, interface.name);
+
+                         var check = $scope.assignedInterfacesFlat.some(function (ai) {
+                             return interfaceObject['tp-id'] === ai['tp-id'] && vpp.name === ai.vppName;
+                         });
+
+                         if(!check) {
+                             interfaceObject.vppName = vpp.name;
+                             checkAndPushIntoArray($scope.unassignedInterfaceList, interfaceObject);
+                         }
+                    });
                 });
-            }
 
-            dataService.bridgeDomainsTopo.on('clickNode',function(topo,node) {
-                console.log(node);
+                if($scope.selectedBd) {
+                    $scope.interfaceList = $scope.assignedInterfaces[$scope.selectedBd['topology-id']] ? $scope.assignedInterfaces[$scope.selectedBd['topology-id']].concat($scope.unassignedInterfaceList) : $scope.unassignedInterfaceList;
+                }
+
+                $scope.interfaceDisplayList = [].concat($scope.interfaceList);
+            });
+
+            $scope.$on('INIT_INTERFACES_TABLE', function(event) {
+                $scope.interfaceList = [];
+                $scope.unassignedInterfaceList = [];
+                $scope.assignedInterfaces = [];
+                $scope.assignedInterfacesFlat = [];
             });
 
-            $scope.reload = function() {
-                dataService.selectedBd.name = '';
-                dataService.changedInterfaces.length = 0;
-                dataService.originalAssignments.length = 0;
-                dataService.interfaces.length = 0;
-                dataService.tableContent.length = 0;
-                dataService.bridgeDomainsTopo.clear();
-                dataService.injectedInterfaces.length = 0;
-                dataService.generateInterfaces();
+
+
+    }]);
+
+    vpp.register.controller('BridgeDomainsController', ['$scope', '$rootScope','$filter', 'dataService', 'bdmBridgeDomainService', 'toastService', '$mdDialog', 'bdmTunnelService',
+        function($scope, $rootScope, $filter, dataService, bdmBridgeDomainService, toastService, $mdDialog, bdmTunnelService) {
+            $scope.bridgeDomainList = [];
+            $scope.showOverlay = true;
+
+            $scope.loadBridgeDomains = function(bridgeDomain, successCallback) {
                 bdmBridgeDomainService.get(function(data) {
-                    //success callback
-                    angular.copy(data['network-topology'].topology, dataService.bridgedomains);
-                    dataService.bridgedomainsLoaded = true;
-                    console.log('Loaded BridgeDomains:');
-                    console.log(dataService.bridgedomains);
-                    dataService.buildAssignedInterfaces();
+                    $scope.bridgeDomainList = data;
+
+                    if(bridgeDomain) {
+                        $scope.selectedBd = $scope.bridgeDomainList.filter(function(bd) {
+                           return bd['topology-id'] ===  bridgeDomain['topology-id'];
+                        })[0];
+
+                        $scope.showTopology($scope.selectedBd);
+                    }
+
+                    successCallback();
+
                 }, function(data,status) {
                     //error callback
                     console.log(status);
                 });
             };
 
-            $scope.bdChanged = function() {
-                dataService.buildTableContent();
+            $scope.getInterfacesForBridgeDomain = function(bridgeDomain) {
+                var interfaceList = [];
+
+                if(bridgeDomain.node) {
+                    bridgeDomain.node.forEach(function (n) {
+                        if (n['termination-point']) {
+                            n['termination-point'].forEach(function (tp) {
+                                tp.vppName = n['node-id'];
+                                tp.vbdName = bridgeDomain['topology-id'];
+                                tp.assigned = true;
+
+                                interfaceList.push(tp);
+                            });
+                        }
+                    });
+                }
+
+                return interfaceList;
+            };
+
+            $scope.getAssignedInterfaces = function() {
+                var interfaces = [];
+
+                $scope.bridgeDomainList.forEach(function(bd) {
+                    var bdCopy = {};
+                    angular.copy(bd, bdCopy);
+
+                    interfaces[bdCopy['topology-id']] = $scope.getInterfacesForBridgeDomain(bdCopy);
+                });
+
+                return interfaces;
             };
 
             $scope.addBd = function() {
@@ -146,12 +202,10 @@ define(['app/vpp/vpp.module'], function(vpp) {
                             $mdDialog.cancel();
                         };
 
-                        vm.isDone = function(status) {
+                        vm.isDone = function(status, bridgeDomain) {
                             vm.waiting = false;
                             if (status === 'success') {
-                                dataService.bridgedomains.push(vm.bd);
-                                dataService.selectedBd.name = vm.bd.name;
-                                $scope.reload();
+                                $scope.reload(bridgeDomain);
                                 vm.close();
                             }
                         };
@@ -165,7 +219,7 @@ define(['app/vpp/vpp.module'], function(vpp) {
 
                             bdmBridgeDomainService.add(obj,
                                 function(data) {
-                                    vm.isDone('success');
+                                    vm.isDone('success', obj);
                                 },
                                 function() {
                                     vm.isDone('failed');
@@ -180,105 +234,308 @@ define(['app/vpp/vpp.module'], function(vpp) {
                 })
             };
 
+            $scope.removeBd = function() {
+                if($scope.selectedBd['topology-id']) {
+                    var successCallback = function(success) {
+                        $scope.selectedBd = null;
+                        $scope.loadBridgeDomains(null, function() {
+                            $scope.$broadcast('INIT_INTERFACES_TABLE');
+                            $scope.clearTopologies();
+                        });
 
-            /* FIXME: remove after testing */
-            $scope.deploy = function() {
-                var successfulRequestsRequired = dataService.changedInterfaces.length;
-                var successfulRequests = 0;
+                    };
+                    bdmBridgeDomainService.remove($scope.selectedBd['topology-id'], function(){successCallback(true)}, function(){successCallback(false)});
+                }
+            };
 
-                console.log('Removing previous assignments...');
-                _.forEach(dataService.changedInterfaces, function(interf) {
+            $scope.bdChanged = function() {
+                $scope.loadBridgeDomains($scope.selectedBd, function() {
+                    $scope.$broadcast('BUILD_INTERFACES_TABLE');
 
-                    //Check if previously assigned.. then DELETE
-                    //....
-                    var previousAssignment = _.find(dataService.originalAssignments, {
-                        'vbridge-topology:user-interface': interf.name,
-                        vppName: interf.vppName
-                    });
+                    $scope.showTopology($scope.selectedBd);
+                });
 
-                    if (previousAssignment) {
-                        successfulRequestsRequired++;
-                        bdmInterfaceService.delete(
-                            {
-                                "tp-id":previousAssignment['tp-id'],
-                                "vbridge-topology:user-interface": previousAssignment['vbridge-topology:user-interface']
-                            },
-                            previousAssignment.vbd,
-                            previousAssignment.vppName,
-                            function() {
-                                //success callback
-                                console.log('Removed previous assignment:',previousAssignment);
-                                successfulRequests++;
-
-                                if (successfulRequests >= successfulRequestsRequired) {
-                                    toastService.showToast('Deployed! Bridge Domain Validated.');
-                                    dataService.changedInterfaces.length = 0;
-                                    console.log('Changed interfaces tracker has been reset.');
-                                    $scope.reload();
-                                }
-                            },
-                            function() {
-                                //error callback
-                                console.error('ERROR removing assignment:',previousAssignment);
+            };
+
+            nx.graphic.Icons.registerIcon("bd", "src/app/vpp/assets/images/bd1.svg", 45, 45);
+            nx.graphic.Icons.registerIcon("interf", "src/app/vpp/assets/images/interf.svg", 45, 45);
+
+            $scope.showOverlayTopology = function(bridgeDomain) {
+                var bdCopy = {};
+                angular.copy(bridgeDomain, bdCopy);
+
+                $scope.bridgeDomainsTopo = new nx.graphic.Topology({
+                    adaptive: true,
+                    scalable: true,
+                    theme: 'blue',
+                    enableGradualScaling: true,
+                    nodeConfig: {
+                        color: '#414040',
+                        label: 'model.label',
+                        scale: 'model.scale',
+                        iconType: function (vertex) {
+                            var type = vertex.get().type;
+                            if (type === 'bd') {
+                                return 'bd'
+                            } else {
+                                return 'interf';
                             }
-                        )
-                    }
-                    if (interf.assigned) {
-                        //Send PUT to correct vBD
-                        bdmInterfaceService.add(
-                            {
-                                "tp-id":interf.vppName+'-'+interf.name,
-                                "vbridge-topology:user-interface": interf.name
-                            },
-                            interf.vbd,
-                            interf.vppName,
-                            function() {
-                                //success callback
-                                console.log('Added assignment:',interf);
-                                successfulRequests++;
-
-                                if (successfulRequests >= successfulRequestsRequired) {
-                                    toastService.showToast('Deployed! Bridge Domain Validated.');
-                                    dataService.changedInterfaces.length = 0;
-                                    console.log('Changed interfaces tracker has been reset.')
-                                    $scope.reload();
-                                }
-                            },
-                            function() {
-                                //error callback
-                                console.error('ERROR adding assignment:',interf);
+                        }
+                    },
+                    linkConfig: {
+                        label: 'model.label',
+                        linkType: 'parallel',
+                        color: function (link) {
+                            if (link.getData().type === 'tunnel') {
+                                return '#00FF00';
+                            } else {
+                                return '#ffffff';
                             }
-                        )
-                    } else {
-                        successfulRequests++;
+                        },
+                        width: function (link) {
+                            if (link.getData().type === 'tunnel') {
+                                return 5;
+                            }
+                        }
+                    },
+                    showIcon: true,
+                    dataProcessor: 'force',
+                    autoLayout: true,
+                    enableSmartNode: false,
+                    tooltipManagerConfig: {
+                        nodeTooltipContentClass: 'TooltipNode',
+                        linkTooltipContentClass: 'TooltipLink'
                     }
                 });
+
+                $scope.overlayNextApp =  new nx.ui.Application;
+
+                var bdNode = {
+                    "data": bdCopy,
+                    "type": "bd",
+                    "label": bdCopy['topology-id']
+                };
+
+                var nodes = [].concat(bdNode);
+                var links = [];
+
+                _.forEach($scope.getInterfacesForBridgeDomain(bdCopy), function(tp, index){
+                    var ifNode = {
+                        "data": tp,
+                        "type": "interf",
+                        "label": tp['tp-id']
+                    };
+                    nodes.push(ifNode);
+                    links.push({source: 0, target: nodes.length-1});
+                });
+
+
+                $scope.bridgeDomainsTopo.data({
+                    nodes: nodes,
+                    links: links
+                });
+
+                $scope.overlayNextApp.container(document.getElementById('overlay-next-app'));
+                $scope.bridgeDomainsTopo.attach($scope.overlayNextApp);
             };
 
-            $scope.removeBd = function() {
-                if(dataService.selectedBd.name) {
-                    var successCallback = function(success) {
-                        if (success) {
-                            console.log($scope.bridgedomains);
-                            _.remove($scope.bridgedomains, {
-                                name: $scope.selectedBd.name
-                            });
-                            toastService.showToast('Bridge Domain Removed!');
-                            $scope.selectedBd.name = '';
-                            dataService.clearTopology();
-                            dataService.tableContent.length = 0;
-                            $scope.reload();
-                        } else {
-                            toastService.showToast('Error removing Bridge Domain!');
-                        }
+            $scope.fillOverlayTopology = function(bridgeDomain) {
+                var bdCopy = {};
+                angular.copy(bridgeDomain, bdCopy);
+
+                var bdNode = {
+                    "data": bdCopy,
+                    "type": "bd",
+                    "label": bdCopy['topology-id']
+                };
+
+                var nodes = [].concat(bdNode);
+                var links = [];
+
+                _.forEach($scope.getInterfacesForBridgeDomain(bdCopy), function(tp, index){
+                    var ifNode = {
+                        "data": tp,
+                        "type": "interf",
+                        "label": tp['tp-id']
                     };
-                    bdmBridgeDomainService.remove(dataService.selectedBd.name, function(){successCallback(true)}, function(){successCallback(false)});
+                    nodes.push(ifNode);
+                    links.push({source: 0, target: nodes.length-1});
+                });
+
+
+                $scope.bridgeDomainsTopo.data({
+                    nodes: nodes,
+                    links: links
+                });
+
+            };
+
+            $scope.showUnderTopology = function(bridgeDomain) {
+                //var bdCopy = {};
+                //angular.copy(bridgeDomain, bdCopy);
+
+                $scope.underlayTopo = new nx.graphic.Topology({
+                    adaptive: true,
+                    scalable: true,
+                    theme:'blue',
+                    enableGradualScaling:true,
+                    nodeConfig: {
+                        color: '#414040',
+                        label: 'model.label',
+                        scale: 'model.scale',
+                        iconType: function(vertex) {
+                            var type = vertex.get().type;
+                            if (type === 'bd') {
+                                return 'bd';
+                            } else if (type==='vpp') {
+                                return 'switch';
+                            } else {
+                                return 'interf';
+                            }
+                        }
+                    },
+                    linkConfig: {
+                        label: 'model.label',
+                        linkType: 'parallel',
+                        color: function(link) {
+                            if (link.getData().type === 'tunnel') {
+                                return '#00FF00';
+                            } else {
+                                return '#ffffff';
+                            }
+                        },
+                        width: function(link) {
+                            if (link.getData().type === 'tunnel') {
+                                return 5;
+                            }
+                        }
+                    },
+                    showIcon: true,
+                    enableSmartNode: false
+                });
+
+                $scope.underlayNextApp =  new nx.ui.Application;
+
+                $scope.fillUnderlayTopology(bridgeDomain);
+
+                $scope.underlayNextApp.container(document.getElementById('underlay-next-app'));
+                $scope.underlayTopo.attach($scope.underlayNextApp);
+            };
+
+            $scope.fillUnderlayTopology = function(bridgeDomain) {
+                var bdCopy = {};
+                angular.copy(bridgeDomain, bdCopy);
+
+                var nodes = [];
+                var links = [];
+
+                _.forEach(bdCopy.node, function(node, index){
+                    var i = index + 1;
+
+                    nodes.push({
+                        label: node['node-id'],
+                        x: (-1+(2*(i%2)))*((i+1)/2 * 500),
+                        y: 700,
+                        scale: 1.25,
+                        type: 'vpp'
+                    });
+
+
+                    bdmTunnelService.get(
+                        bdCopy['topology-id'],
+                        function(data) {
+                            //success
+                            console.log(data);
+
+                            var link = data;
+                            var sourceNode = link[0].source['source-node'];
+                            var targetNode = link[0].destination['dest-node'];
+
+                            links.push({
+                                source: _.findIndex(nodes, {label: sourceNode, type: 'vpp'}),
+                                target: _.findIndex(nodes, {label: targetNode, type: 'vpp'}),
+                                type: 'tunnel'
+                            });
+
+                            $scope.underlayTopo.data({
+                                nodes: nodes,
+                                links: links
+                            });
+
+                        }, function(res) {
+                            $scope.underlayTopo.data({
+                                nodes: nodes,
+                                links: links
+                            });
+                        });
+                });
+
+
+                $scope.underlayTopo.data({
+                    nodes: nodes,
+                    links: links
+                });
+            };
+
+            $scope.reload = function(bridgeDomain) {
+                $scope.loadBridgeDomains(bridgeDomain, function() {
+                    $scope.$broadcast('BUILD_INTERFACES_TABLE');
+
+                    $scope.showTopology($scope.selectedBd);
+                });
+
+            };
+
+            $scope.toggleUnderlay = function() {
+                $scope.showOverlay = !$scope.showOverlay;
+
+                $scope.reload($scope.selectedBd);
+            };
+
+            $scope.showTopology = function(bridgeDomain) {
+                if($scope.showOverlay) {
+                    if(!$scope.bridgeDomainsTopo) {
+                        $scope.showOverlayTopology(bridgeDomain);
+                    }
+                    else {
+                        $scope.fillOverlayTopology(bridgeDomain);
+                    }
+                } else {
+                    if(!$scope.underlayTopo) {
+                        $scope.showUnderTopology(bridgeDomain);
+                    }
+                    else {
+                        $scope.fillUnderlayTopology(bridgeDomain);
+                    }
+                }
+            };
+
+            $scope.clearTopologies = function() {
+                if($scope.bridgeDomainsTopo) {
+                    $scope.bridgeDomainsTopo.data({
+                        nodes: [],
+                        links: []
+                    });
                 }
+
+                if($scope.bridgeDomainsTopo) {
+                    $scope.underlayTopo.data({
+                        nodes: [],
+                        links: []
+                    });
+                    }
             };
 
-            window.addEventListener('resize', function () {
-                dataService.bridgeDomainsTopo.adaptToContainer();
+            $scope.$on('INTERFACE_CHANGED', function(event, data) {
+                bdmBridgeDomainService.getOne($scope.selectedBd['topology-id'],
+                    function(bdData) {
+                        $scope.fillOverlayTopology(bdData);
+                    },
+                    function() {
+                        console.log('error getting vbd');
+                    });
             });
 
-    }]);
+            $scope.loadBridgeDomains(null, function() {});
+        }]);
 });
\ No newline at end of file
index b179753..6d994c1 100644 (file)
@@ -20,7 +20,7 @@ define(['app/vpp/vpp.module'], function(vpp) {
                         $scope.vppList = data;
                         $scope.displayVppList = [].concat($scope.vppList);
                         dataService.vpps = $scope.vppList;
-console.log($scope.vppList);
+
                         $scope.$broadcast('RELOAD_VPP_TABLE');
 
                         //for vppList access in BDM
@@ -69,7 +69,7 @@ console.log($scope.vppList);
                     controllerAs: 'NewVppDialogCtrl',
                     templateUrl: $scope.view_path + 'new-vpp-dialog.html',
                     parent: angular.element(document.body),
-                    clickOutsideToClose:true
+                    clickOutsideToClose:false
                 })
             };
 
index 16ce204..5bd2c95 100644 (file)
@@ -16,6 +16,7 @@ var modules = [
     'app/vpp/services/bdm.bridgedomain.service',
     'app/vpp/services/bdm.interface.service',
     'app/vpp/services/bdm.vpp.service',
+    'app/vpp/services/bdm.tunnel.service',
     //controllers
     'app/vpp/controllers/inventory.controller',
     'app/vpp/controllers/bdm.controller',
@@ -47,12 +48,12 @@ define(modules, function(vpp) {
 
             // filter used in inventory to filter interfaceList of vxlan_tunnel interfaces
             $scope.filterRemoveVxlanIf = function (item) {
-                return item.name.indexOf('vxlan') !== 0;
+                return (item.name && item.name.indexOf('vxlan') !== 0) || (item['tp-id'] && item['tp-id'].indexOf('vxlan') !== 0);
             };
 
             // filter used in inventory to return vxlan_tunnel interfaces
             $scope.filterGetVxlanIf = function (item) {
-                return item.name.indexOf('vxlan') === 0;
+                return (item.name && item.name.indexOf('vxlan') === 0) || (item['tp-id'] && item['tp-id'].indexOf('vxlan') === 0);
             };
 
        }]);
index 1438208..e0fcee6 100644 (file)
@@ -47,9 +47,27 @@ define(['app/vpp/vpp.module'], function(vpp) {
 
         s.get = function(successCallback, errorCallback) {
             var restObj = VPPRestangular.one('restconf').one('config').one('network-topology:network-topology');
+            var bridgeDomainList = [];
 
             restObj.get().then(function(data) {
-                successCallback(data);
+                if(data['network-topology'].topology) {
+                    bridgeDomainList = data['network-topology'].topology.filter(function (topology) {
+                        if (topology['topology-types'] && topology['topology-types']['vbridge-topology:vbridge-topology']) {
+                            return topology['topology-types']['vbridge-topology:vbridge-topology'] !== undefined;
+                        }
+                    });
+                }
+                successCallback(bridgeDomainList);
+            }, function(res) {
+                errorCallback(res.data, res.status);
+            });
+        };
+
+        s.getOne = function(bdId, successCallback, errorCallback) {
+            var restObj = VPPRestangular.one('restconf').one('config').one('network-topology:network-topology').one('topology').one(bdId);
+
+            restObj.get().then(function(data) {
+                successCallback(data.topology[0]);
             }, function(res) {
                 errorCallback(res.data, res.status);
             });
index d2abc77..5fc907b 100644 (file)
@@ -44,7 +44,15 @@ define(['app/vpp/vpp.module'], function(vpp) {
                 .one('topology').one(bridgeDomainId).one('node').one(vppId).one('termination-point').one(encodeURIComponent(interf['tp-id']));
 
             restObj.remove().then(function(data) {
-                successCallback(data);
+                bdmVppService.checkAndDeleteVpp(bridgeDomainId, vppId,
+                    function() {
+                        successCallback(data);
+                    },
+                    function() {
+
+                    }
+                );
+
             }, function(res) {
                 errorCallback(res.data, res.status);
             });
diff --git a/vbd/gui/module/src/main/resources/vpp/services/bdm.tunnel.service.js b/vbd/gui/module/src/main/resources/vpp/services/bdm.tunnel.service.js
new file mode 100644 (file)
index 0000000..7c8f149
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+define(['app/vpp/vpp.module'], function(vpp) {
+    vpp.register.factory('bdmTunnelService', function(VPPRestangular) {
+        var s = {};
+
+        s.get = function(bridgeDomainId, successCallback, errorCallback) {
+            var restObj = VPPRestangular.one('restconf').one('operational').one('network-topology:network-topology')
+                .one('topology').one(bridgeDomainId);
+
+            restObj.get().then(function(data) {
+                successCallback(data.topology[0].link);
+            }, function(res) {
+                errorCallback(res.data, res.status);
+            });
+        };
+
+        return s;
+    });
+});
\ No newline at end of file
index 0a24c23..a86fa06 100644 (file)
@@ -55,6 +55,16 @@ define(['app/vpp/vpp.module'], function(vpp) {
             });
         };
 
+        s.delete = function(bridgeDomainId, vppId, successCallback, errorCallback) {
+            var restObj = VPPRestangular.one('restconf').one('config').one('network-topology:network-topology').one('topology').one(bridgeDomainId).one('node').one(vppId);
+
+            return restObj.remove().then(function(data) {
+                successCallback(data);
+            }, function(res) {
+                errorCallback(res.data, res.status);
+            });
+        };
+
         s.checkAndWriteVpp = function(bridgeDomainId, vppId, successCallback, errorCallback) {
              s.getOne(bridgeDomainId, vppId,
                 function() {
@@ -69,9 +79,28 @@ define(['app/vpp/vpp.module'], function(vpp) {
                     });
                 }
             );
+        };
 
-            //getPromise.then
+        s.checkAndDeleteVpp = function(bridgeDomainId, vppId, successCallback, errorCallback) {
+            s.getOne(bridgeDomainId, vppId,
+                function(data) {
+                    if(!data['termination-point']) {
+                        s.delete(bridgeDomainId, vppId,
+                            function(){
+                                successCallback();
+                            },
+                            function() {
+                                errorCallback();
+                            }
+                        );
+                    }
+                },
+                function() {
+                    errorCallback();
+                }
+            );
         };
+
         return s;
     });
 });
\ No newline at end of file
index 1e9d20b..19cee13 100644 (file)
@@ -30,251 +30,17 @@ define(['app/vpp/vpp.module', 'next'], function(vpp) {
         }
     });
 
-    vpp.register.service('dataService', ['$timeout', function($timeout) {
+    vpp.register.service('dataService', ['$timeout', 'bdmTunnelService',function($timeout, bdmTunnelService) {
 
         var self = this;
 
-        nx.graphic.Icons.registerIcon("bd", "src/app/vpp/assets/images/bd1.svg", 45, 45);
-        nx.graphic.Icons.registerIcon("interf", "src/app/vpp/assets/images/interf.svg", 45, 45);
-
-        this.bridgeDomainsTopo = new nx.graphic.Topology({
-            adaptive: true,
-            scalable: true,
-            theme:'blue',
-            enableGradualScaling:true,
-            nodeConfig: {
-                color: '#414040',
-                label: 'model.label',
-                scale: 'model.scale',
-                iconType: function(vertex) {
-                    var type = vertex.get().type;
-                    if (type === 'bd') {
-                        return 'bd'
-                    } else {
-                        return 'interf';
-                    }
-                }
-            },
-            linkConfig: {
-                label: 'model.label',
-                linkType: 'parallel',
-                color: function(link) {
-                    if (link.getData().type === 'tunnel') {
-                        return '#00FF00';
-                    } else {
-                        return '#ffffff';
-                    }
-                },
-                width: function(link) {
-                    if (link.getData().type === 'tunnel') {
-                        return 5;
-                    }
-                }
-            },
-            showIcon: true,
-            dataProcessor: 'force',
-            autoLayout: true,
-            enableSmartNode: false,
-            tooltipManagerConfig: {
-                nodeTooltipContentClass: 'TooltipNode',
-                linkTooltipContentClass: 'TooltipLink'
-            }
-        });
-        this.nextApp =  new nx.ui.Application;
-        this.bridgedomainsLoaded = false;
-
         this.vpps = [];
-        this.tableContent = [];
-        this.originalAssignments = [];
         this.interfaces = [];
-        this.injectedInterfaces = [];
-        this.bridgedomains = [];
-        this.changedInterfaces = [];
         this.selectedBd = {
             name: ''
         };
 
-        this.generateInterfaces = function() {
-            self.interfaces.length = 0;
-            _.forEach(this.vpps, function(vpp) {
-                _.forEach(vpp.interfaces, function(interf) {
-                    interf.vppName = vpp.name;
-                    interf.label = vpp.name+'/'+interf.name;
-                    interf.scale = 0.5;
-                    self.interfaces.push(interf);
-                });
-            });
-            console.log(this.interfaces);
-        };
-
-        this.buildAssignedInterfaces = function() {
-            this.originalAssignments.length = 0;
-            _.forEach(this.bridgedomains, function(bd){
-                var bdName = bd['topology-id'];
-                var nodes = bd.node;
-                if (nodes) {
-                    _.forEach(nodes, function(vpp) {
-                        var vppName = vpp['node-id'];
-                        var tps = vpp['termination-point'];
-                        if (tps) {
-                            _.forEach(tps, function(tp) {
-                                tp.vppName = vppName;
-                                tp.vbd = bdName;
-                                self.originalAssignments.push(tp);
-                            })
-                        }
-                    })
-                }
-            });
-
-            console.log('Assigned Interfaces: ');
-            console.log(this.originalAssignments);
-        };
-
-        this.buildTableContent = function() {
-            this.tableContent.length = 0;
-            angular.copy(this.interfaces,this.tableContent);
-
-
-            //Makes assignements based on previously changed interfaces, or assignments retrieved from ODL
-            _.forEach(this.tableContent, function(interf) {
-                var matchedChangedInterface = _.find(self.changedInterfaces, {
-                    name: interf.name,
-                    vppName: interf.vppName
-                });
-
-                var matchedOriginalAssignment = _.find(self.originalAssignments, {
-                    'vbridge-topology:user-interface': interf.name,
-                    vppName: interf.vppName
-                });
-
-                if (matchedChangedInterface) {
-                    interf.assigned = matchedChangedInterface.assigned;
-                    interf.vbd = matchedChangedInterface.vbd;
-                } else if (matchedOriginalAssignment) {
-                    interf.assigned = true;
-                    interf.vbd = matchedOriginalAssignment.vbd;
-                } else {
-                    interf.assigned = false;
-                    interf.vbd = '';
-                }
-            });
-
-            _.remove(self.tableContent, function(interf){
-                var isAssigned = interf.assigned === true;
-                var isNotCorrectBd = !(interf.vbd === self.selectedBd.name);
-                return(isAssigned && isNotCorrectBd);
-            });
-
-            //_.forEach(this.originalAssignments, function(origAssignment) {
-            //    if (origAssignment.vbd === self.selectedBd.name) {
-            //        var matchedInterface = _.find(self.tableContent, {
-            //            name: origAssignment['vbridge-topology:user-interface'],
-            //            vppName: origAssignment.vppName
-            //        });
-            //        if (matchedInterface) {
-            //            matchedInterface.assigned = true;
-            //            matchedInterface.vbd = origAssignment.vbd;
-            //        } else {
-            //            console.error('Interface "'+origAssignment['vbridge-topology:user-interface']+'" on VPP "'+origAssignment.vppName+'" in vBD "'+origAssignment.vbd+'" was not found at mount point!');
-            //        }
-            //    } else {
-            //        _.remove(self.tableContent, {
-            //            name: origAssignment['vbridge-topology:user-interface'],
-            //            vppName: origAssignment.vppName
-            //        });
-            //    }
-            //});
-            //
-            //_.forEach(this.changedInterfaces, function(changedInterface) {
-            //
-            //    var matchedInterface = _.find(self.tableContent, {
-            //        name: changedInterface.name,
-            //        vppName: changedInterface.vppName
-            //    });
-            //
-            //    if (matchedInterface) {
-            //        if (changedInterface.assigned) {
-            //            if (changedInterface.vbd === self.selectedBd.name) {
-            //                matchedInterface.assigned = true;
-            //                matchedInterface.vbd = changedInterface.vbd;
-            //            }
-            //            else {
-            //                _.remove(self.tableContent, {
-            //                    name: changedInterface.name,
-            //                    vppName: changedInterface.vppName
-            //                });
-            //            }
-            //        } else {
-            //            matchedInterface.assigned = false;
-            //            matchedInterface.vbd = '';
-            //        }
-            //    }
-            //});
-
-            //..
-
-            //_.remove(self.tableContent, {
-            //    name: origAssignment['vbridge-topology:user-interface'],
-            //    vppName: origAssignment.vppName
-            //});
-
-            this.injectBridgeDomainsTopoElements();
-
-        };
-
-
-        this.clearTopology = function() {
-            this.bridgeDomainsTopo.clear();
-            this.injectedInterfaces.length = 0;
-
-        };
-
-        //this.generateUnassignedInterfaces = function() {
-        //    this.unassignedInterfaces.length = 0;
-        //    for (var x=0; x<this.interfaces.length; x++) {
-        //        if (!this.interfaces[x]['v3po:l2']['bridge-domain']) {
-        //            this.unassignedInterfaces.push(this.interfaces[x]);
-        //        }
-        //    }
-        //};
 
-        this.setData = function() {
-
-            for (var x=0; x<this.tableContent.length; x++) {
-                if (this.tableContent[x].assigned) {
-                    this.bridgeDomainsTopo.addNode(this.tableContent[x]);
-                    this.injectedInterfaces.push(this.tableContent[x]);
-                }
-            }
-
-            var nodes = [{
-                name : this.selectedBd.name,
-                label: this.selectedBd.name,
-                type:'bd',
-                x: 0,
-                y: 0,
-                scale: 1
-            }].concat(this.injectedInterfaces);
-
-            var links = [];
-            for (var x=1; x<nodes.length; x++){
-                links.push({'source':0, 'target': x});
-            }
-
-            var topoData = {
-                nodes: nodes,
-                links: links
-            };
-
-            this.bridgeDomainsTopo.data(topoData);
-        };
-
-        this.injectBridgeDomainsTopoElements = function() {
-            this.clearTopology();
-            this.setData();
-            self.bridgeDomainsTopo.adaptToContainer();
-        };
     }]);
 
 
index ab4d83d..91b9d0a 100644 (file)
@@ -1,46 +1,56 @@
 <div ng-controller="BridgeDomainsController">
-    <div layout="row" layout-xs="column" style="height: 550px; width: 100%">
-        <div id="bridge-domains-next-app" style="height: 550px; width: 60%"></div>
-        <div class="md-sidenav-left md-whiteframe-z2" style="height: 550px; background-color: #414042; overflow-y: scroll" flex>
-            <md-content layout-padding ng-controller="TableController as TableCtrl">
-                <md-input-container style="margin-right: 5px;" layout="row">
-                <md-select ng-model='selectedBd.name' placeholder="Select BD" ng-change="bdChanged()" style="width: 100%;">
-                    <md-option ng-repeat="bd in bridgedomains" value="{{bd['topology-id']}}">{{bd['topology-id']}}</md-option>
+    <div layout="row" style="height: 1000px; width: 100%">
+        <div layout="column" style="height:100%; width:60%">
+            <div ng-show="showOverlay" style="height: 100%; width: 100%">
+                <h3>Overlay topology</h3>
+                <md-button class="md-raised" md-no-ink ng-click="toggleUnderlay()" style="width: 25%;" ng-disabled="!selectedBd['topology-id']">Show Underlay</md-button>
+                <div id="overlay-next-app" style="height: 50%; width: 100%"></div>
+            </div>
+            <div ng-show="!showOverlay" style="height: 100%; width: 100%">
+                <h3>Underlay topology</h3>
+                <md-button class="md-raised" md-no-ink ng-click="toggleUnderlay()" style="width: 25%;" ng-disabled="!selectedBd['topology-id']">Show Overlay</md-button>
+                <div id="underlay-next-app" style="height: 50%; width: 100%"></div>
+            </div>
+        </div>
+        <div class="md-sidenav-left md-whiteframe-z2" style="height: 100%; width: 40%; background-color: #414042;">
+
+            <md-input-container style="margin-right: 5px;" layout="row">
+
+                <md-select ng-model='selectedBd' placeholder="Select BD" ng-change="bdChanged()" style="width: 100%;">
+                    <md-option ng-repeat="bd in bridgeDomainList" ng-value="bd">{{bd['topology-id']}}</md-option>
                 </md-select>
+
                 <md-button class="md-raised" md-no-ink ng-click="addBd()" style="width: 25%;">Add BD</md-button>
-                <md-button class="md-raised" md-no-ink ng-click="removeBd()" style="width: 35%;" ng-if="dataService.injectedInterfaces.length===0 && dataService.selectedBd.name && dataService.changedInterfaces.length===0">Remove BD</md-button>
-                    <md-button class="md-raised" md-no-ink ng-click="reload()" style="width: 25%;">Reload</md-button>
+                <md-button class="md-raised" md-no-ink ng-click="removeBd()" style="width: 35%;" ng-if="selectedBd['topology-id'] && !selectedBd.node">Remove BD</md-button>
+                <!--<md-button class="md-raised" md-no-ink ng-click="reload()" style="width: 25%;">Reload</md-button>-->
+
+            </md-input-container>
 
-                </md-input-container>
-                <table st-table="TableCtrl.displayedCollection" class="table" st-safe-src="TableCtrl.rowCollection">
+            <div ng-controller="TableController as TableCtrl">
+                <table st-table="interfaceDisplayList" class="table" st-safe-src="interfaceList">
                     <thead>
                     <tr>
-                        <th>Assigned</th>
-                        <th st-sort="vppName" st-sort-default="true">Vpp</th>
-                        <th st-sort="name" st-sort-default="true">Interface Name</th>
-                        <!--<th st-sort="description">Description</th>-->
-                        <th st-sort="bridge-domain">Bridge Domain</th>
+                        <th st-sort="assigned" class="interactive">Assigned</th>
+                        <th st-sort="vppName" st-sort-default="true" class="interactive">Vpp</th>
+                        <th st-sort="'tp-id'" class="interactive">Interface Name</th>
+                        <th st-sort="vbdName" class="interactive">Bridge Domain</th>
                     </tr>
                     </thead>
                     <tbody>
-                    <tr ng-repeat="row in TableCtrl.displayedCollection | filter: filterRemoveVxlanIf">
+                    <tr ng-repeat="row in interfaceDisplayList | filter: filterRemoveVxlanIf">
                         <div ng-hide="row.hidden">
                             <td>
                                 <md-switch ng-model="row.assigned" aria-label="Assign Switch" ng-change="TableCtrl.updateAssignment(row);">
                                 </md-switch>
                             </td>
                             <td>{{row.vppName}}</td>
-                            <td>{{row.name}}</td>
-                            <!--<td>{{row.description}}</td>-->
-                            <td>{{row.vbd}}</td>
+                            <td>{{row['tp-id']}}</td>
+                            <td>{{row.vbdName}}</td>
                         </div>
                     </tr>
                     </tbody>
                 </table>
-                <!--<md-input-container style="bottom: 10px">-->
-                    <md-button class="md-raised" md-no-ink ng-click="deploy()" style="width: 94%;" ng-if="dataService.changedInterfaces.length">Deploy</md-button>
-                <!--</md-input-container>-->
-            </md-content>
+            </div>
         </div>
     </div>
 </div>
\ No newline at end of file
index 72115cf..5e6d109 100644 (file)
@@ -8,24 +8,8 @@
         </md-tab>
         <md-tab label="Bridge Domains" md-on-select="setMainView('bridgeDomains')">
             <md-content class="md-padding">
-                <section ng-if="mainView === 'bridgeDomains'" ng-include src="view_path+'bridge-domains.tpl.html'"></section>
+                <section ng-if="mainView === 'bridgeDomains'" ng-include src="view_path+'bridge-domains.tpl.html'" style="height:80%; overflow: hidden"></section>
             </md-content>
         </md-tab>
     </md-tabs>
-
-    <!--<md-toolbar>
-        <div class="md-toolbar-tools float-left">
-            <span flex></span>
-            <md-button ng-click="setMainView('inventory')">Inventory</md-button>
-            <span flex></span>
-            <md-button ng-click="setMainView('bridgeDomains')">Bridge Domains</md-button>
-            <span flex></span>
-        </div>
-    </md-toolbar>
-
-    <div ng-view style="height: 100%">
-
-
-
-    </div>-->
 </div>
\ No newline at end of file
index 9d08cf6..a5a5dc5 100644 (file)
@@ -3,7 +3,7 @@
         <!-- Topology -->
         <div class="md-whiteframe-z2" flex="60" layout-margin>
             <md-content layout-padding>
-                <h3>Topology</h3>
+                <h3>Vpp and Interfaces</h3>
                 <div id="next-vpp-topo"></div>
             </md-content>
         </div>
@@ -52,8 +52,8 @@
                         <th st-sort="name" class="interactive">Name</th>
                         <th st-sort="oper-status" class="interactive" >Oper Status</th>
                         <th st-sort="admin-status" class="interactive">Admin Status</th>
-                        <th st-sort="v3po:vxlan.src" class="interactive">Source IP</th>
-                        <th st-sort="v3po:vxlan.src" class="interactive">Destination IP</th>
+                        <th st-sort="'v3po:vxlan.src'" class="interactive">Source IP</th>
+                        <th st-sort="'v3po:vxlan.src'" class="interactive">Destination IP</th>
                     </tr>
                     </thead>
                     <tbody>
index bd502b3..d8d2600 100644 (file)
         <md-progress-linear md-mode="indeterminate" ng-show="NewVppDialogCtrl.waiting"></md-progress-linear>
         <md-dialog-actions layout="row">
             <span flex></span>
-            <md-button ng-click="NewVppDialogCtrl.updateConfig();" style="margin-right:20px;" class="md-raised">
+            <md-button ng-click="NewVppDialogCtrl.updateConfig();" style="margin-right:20px;" class="md-raised" type="submit">
                 <span>Mount</span>
             </md-button>
+            <md-button ng-click="NewVppDialogCtrl.close();" style="margin-right:20px;" class="md-raised" type="button">
+                <span>Close</span>
+            </md-button>
         </md-dialog-actions>
     </form>
 </md-dialog>
\ No newline at end of file