summaryrefslogtreecommitdiffstats
path: root/vbd/gui
diff options
context:
space:
mode:
authorDaniel Malachovsky <daniel.malachovsky@pantheon.sk>2016-02-11 14:13:09 +0100
committerDave Wallace <dwallacelf@gmail.com>2016-02-12 02:12:20 +0000
commit73353537994c067cd6eea24545efc53df08b4a1a (patch)
treece9007eca2a2a437e9c3e1086086085c419d0676 /vbd/gui
parentea8d1af7f75565cee845ce0b4672d64bc7cb676f (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')
-rw-r--r--vbd/gui/module/src/main/resources/vpp/controllers/bdm.controller.js579
-rw-r--r--vbd/gui/module/src/main/resources/vpp/controllers/inventory.controller.js4
-rw-r--r--vbd/gui/module/src/main/resources/vpp/controllers/vpp.controller.js5
-rw-r--r--vbd/gui/module/src/main/resources/vpp/services/bdm.bridgedomain.service.js20
-rw-r--r--vbd/gui/module/src/main/resources/vpp/services/bdm.interface.service.js10
-rw-r--r--vbd/gui/module/src/main/resources/vpp/services/bdm.tunnel.service.js25
-rw-r--r--vbd/gui/module/src/main/resources/vpp/services/bdm.vpp.service.js31
-rw-r--r--vbd/gui/module/src/main/resources/vpp/services/vpp.services.js236
-rw-r--r--vbd/gui/module/src/main/resources/vpp/views/bridge-domains.tpl.html58
-rw-r--r--vbd/gui/module/src/main/resources/vpp/views/index.tpl.html18
-rw-r--r--vbd/gui/module/src/main/resources/vpp/views/inventory-detail.tpl.html6
-rw-r--r--vbd/gui/module/src/main/resources/vpp/views/new-vpp-dialog.html5
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