diff options
author | Daniel Malachovsky <daniel.malachovsky@pantheon.sk> | 2016-02-11 14:13:09 +0100 |
---|---|---|
committer | Dave Wallace <dwallacelf@gmail.com> | 2016-02-12 02:12:20 +0000 |
commit | 73353537994c067cd6eea24545efc53df08b4a1a (patch) | |
tree | ce9007eca2a2a437e9c3e1086086085c419d0676 /vbd/gui | |
parent | ea8d1af7f75565cee845ce0b4672d64bc7cb676f (diff) |
Underlay added
- 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>
Diffstat (limited to 'vbd/gui')
12 files changed, 549 insertions, 448 deletions
diff --git a/vbd/gui/module/src/main/resources/vpp/controllers/bdm.controller.js b/vbd/gui/module/src/main/resources/vpp/controllers/bdm.controller.js index 7c24690c5..f88162ef6 100644 --- a/vbd/gui/module/src/main/resources/vpp/controllers/bdm.controller.js +++ b/vbd/gui/module/src/main/resources/vpp/controllers/bdm.controller.js @@ -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 diff --git a/vbd/gui/module/src/main/resources/vpp/controllers/inventory.controller.js b/vbd/gui/module/src/main/resources/vpp/controllers/inventory.controller.js index b1797534a..6d994c152 100644 --- a/vbd/gui/module/src/main/resources/vpp/controllers/inventory.controller.js +++ b/vbd/gui/module/src/main/resources/vpp/controllers/inventory.controller.js @@ -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 }) }; diff --git a/vbd/gui/module/src/main/resources/vpp/controllers/vpp.controller.js b/vbd/gui/module/src/main/resources/vpp/controllers/vpp.controller.js index 16ce20402..5bd2c955e 100644 --- a/vbd/gui/module/src/main/resources/vpp/controllers/vpp.controller.js +++ b/vbd/gui/module/src/main/resources/vpp/controllers/vpp.controller.js @@ -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); }; }]); diff --git a/vbd/gui/module/src/main/resources/vpp/services/bdm.bridgedomain.service.js b/vbd/gui/module/src/main/resources/vpp/services/bdm.bridgedomain.service.js index 1438208d2..e0fcee68f 100644 --- a/vbd/gui/module/src/main/resources/vpp/services/bdm.bridgedomain.service.js +++ b/vbd/gui/module/src/main/resources/vpp/services/bdm.bridgedomain.service.js @@ -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); }); diff --git a/vbd/gui/module/src/main/resources/vpp/services/bdm.interface.service.js b/vbd/gui/module/src/main/resources/vpp/services/bdm.interface.service.js index d2abc77b1..5fc907b7f 100644 --- a/vbd/gui/module/src/main/resources/vpp/services/bdm.interface.service.js +++ b/vbd/gui/module/src/main/resources/vpp/services/bdm.interface.service.js @@ -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 index 000000000..7c8f1492f --- /dev/null +++ b/vbd/gui/module/src/main/resources/vpp/services/bdm.tunnel.service.js @@ -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 diff --git a/vbd/gui/module/src/main/resources/vpp/services/bdm.vpp.service.js b/vbd/gui/module/src/main/resources/vpp/services/bdm.vpp.service.js index 0a24c2329..a86fa06fc 100644 --- a/vbd/gui/module/src/main/resources/vpp/services/bdm.vpp.service.js +++ b/vbd/gui/module/src/main/resources/vpp/services/bdm.vpp.service.js @@ -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 diff --git a/vbd/gui/module/src/main/resources/vpp/services/vpp.services.js b/vbd/gui/module/src/main/resources/vpp/services/vpp.services.js index 1e9d20b23..19cee135b 100644 --- a/vbd/gui/module/src/main/resources/vpp/services/vpp.services.js +++ b/vbd/gui/module/src/main/resources/vpp/services/vpp.services.js @@ -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(); - }; }]); diff --git a/vbd/gui/module/src/main/resources/vpp/views/bridge-domains.tpl.html b/vbd/gui/module/src/main/resources/vpp/views/bridge-domains.tpl.html index ab4d83dfb..91b9d0aa4 100644 --- a/vbd/gui/module/src/main/resources/vpp/views/bridge-domains.tpl.html +++ b/vbd/gui/module/src/main/resources/vpp/views/bridge-domains.tpl.html @@ -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 diff --git a/vbd/gui/module/src/main/resources/vpp/views/index.tpl.html b/vbd/gui/module/src/main/resources/vpp/views/index.tpl.html index 72115cf7b..5e6d1094e 100644 --- a/vbd/gui/module/src/main/resources/vpp/views/index.tpl.html +++ b/vbd/gui/module/src/main/resources/vpp/views/index.tpl.html @@ -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 diff --git a/vbd/gui/module/src/main/resources/vpp/views/inventory-detail.tpl.html b/vbd/gui/module/src/main/resources/vpp/views/inventory-detail.tpl.html index 9d08cf67d..a5a5dc5d7 100644 --- a/vbd/gui/module/src/main/resources/vpp/views/inventory-detail.tpl.html +++ b/vbd/gui/module/src/main/resources/vpp/views/inventory-detail.tpl.html @@ -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> diff --git a/vbd/gui/module/src/main/resources/vpp/views/new-vpp-dialog.html b/vbd/gui/module/src/main/resources/vpp/views/new-vpp-dialog.html index bd502b31c..d8d2600f3 100644 --- a/vbd/gui/module/src/main/resources/vpp/views/new-vpp-dialog.html +++ b/vbd/gui/module/src/main/resources/vpp/views/new-vpp-dialog.html @@ -58,9 +58,12 @@ <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 |