-/*\r
- * Copyright (c) 2015 Inocybe Technologies and others. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-define(['app/ovsdb/ovsdb.module'],function(ovsdb) {\r
- 'use strict';\r
-\r
- ovsdb.register.factory('TopologyNetworkRestangular', function(Restangular, ENV) {\r
- return Restangular.withConfig(function(RestangularConfig) {\r
- RestangularConfig.setBaseUrl(ENV.getBaseURL("AD_SAL"));\r
- });\r
- });\r
-\r
- ovsdb.register.factory('TopologyNetworkSvc', function(TopologyNetworkRestangular) {\r
- var svc = {\r
- base: function(name) {\r
- return TopologyNetworkRestangular.one('restconf', name).one('network-topology:network-topology');\r
- },\r
- data : null\r
- };\r
-\r
- svc.getCurrentData = function() {\r
- return svc.data;\r
- };\r
-\r
- svc.getTopologiesIds = function() {\r
- svc.data = svc.base('operational').getList();\r
- return svc.data;\r
- };\r
-\r
- svc.getConfigNode = function(topologyId, nodeId) {\r
- return svc.base('config').one('topology', topologyId).one('node', nodeId).get();\r
- };\r
-\r
- svc.addConfigNode = function(topologyId, nodeId, data) {\r
- return svc.base('config').one('topology', topologyId).one('node').put(nodeId, data);\r
- };\r
-\r
- svc.addConfigBridge = function(topologyId, nodeId, data) {\r
- return svc.base('config').one('topology', topologyId).put(nodeId, data);\r
- };\r
-\r
- svc.removeConfigNode = function(topologyId, nodeId) {\r
- return svc.base('config').one('topology', topologyId).one('node', nodeId).remove();\r
- };\r
-\r
- svc.addTerminationPointConfig = function(topologyId, nodeId, terminationId, data) {\r
- return svc.base('config').one('topology', topologyId).one('node', nodeId).one('termination-point').put(terminationId, data);\r
- };\r
-\r
- svc.getTerminationPointConfig = function(topologyId, nodeId, terminationId) {\r
- return svc.base('config').one('topology', topologyId).one('node', nodeId).one('termination-point', terminationId).get();\r
- };\r
-\r
- svc.removeTerminationPointConfig = function(topologyId, nodeId, terminationId) {\r
- return svc.base('config').one('topology', topologyId).one('node', nodeId).one('termination-point', terminationId).remove();\r
- };\r
- return svc;\r
- });\r
-\r
-\r
- ovsdb.register.factory('TopologyNetworkFactory', function() {\r
-\r
- var factory = {\r
- createOvsdbNodeObject: function(nodeId, nodePort, nodeRemoteIp) {\r
- return {\r
- "network-topology:node": [\r
- {\r
- "node-id": nodeId,\r
- "connection-info": {\r
- "ovsdb:remote-port": nodePort,\r
- "ovsdb:remote-ip": nodeRemoteIp\r
- }\r
- }\r
- ]\r
- };\r
- },\r
- createConfigNode: function(nodeId, bridgeName,datapathId, protocolEntries, controllerEntries, managedBy) {\r
- var configNode = {\r
- "network-topology:node": [\r
- {\r
- "node-id": nodeId,\r
- "ovsdb:bridge-name": bridgeName,\r
- "ovsdb:datapath-id": datapathId,\r
- "ovsdb:protocol-entry": [ ],\r
- "ovsdb:controller-entry": [ ],\r
- "ovsdb:managed-by": managedBy\r
- }\r
- ]\r
- };\r
-\r
- for (var protocolEntry in protocolEntries) {\r
- configNode[0]['ovsdb:protocal-entry'].push({\r
- "protocol": protocolEntry\r
- });\r
- }\r
-\r
- for (var controllerEntry in controllerEntries) {\r
- configNode[0]['ovsdb:controller-entry'].push({\r
- "protocol" : controllerEntry\r
- });\r
- }\r
-\r
- return configNode;\r
-\r
- },\r
- createEndPoint: function(ovsdb_options, name, interface_type, tp_id, vlan_tag, trunks, vlan_mode) {\r
- var termination_point = {\r
- "network-topology:termination-point": [\r
- {\r
- "ovsdb:options": [ ],\r
- "ovsdb:name": name,\r
- "ovsdb:interface-type": interface_type,\r
- "tp-id": tp_id,\r
- "vlan-tag": vlan_tag,\r
- "trunks": [ ],\r
- "vlan-mode":vlan_mode\r
- }\r
- ]\r
- };\r
-\r
- for (var ovsdb_option in ovsdb_options) {\r
- termination_point[0]['ovsdb:options'].push({\r
- "ovsdb:option": ovsdb_option.option,\r
- "ovsdb:value" : ovsdb_option.value\r
- });\r
- }\r
-\r
- for (var trunk in trunks) {\r
- termination_point[0]['trunks'].push({\r
- "trunk":trunk\r
- });\r
- }\r
-\r
- return termination_point;\r
- }\r
- };\r
-\r
- return factory;\r
-\r
- });\r
-\r
-});\r
+/*
+ * Copyright (c) 2015 Inocybe Technologies 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/ovsdb/ovsdb.module', 'app/ovsdb/OvsCore', 'underscore', 'app/ovsdb/ovsdb.constant'], function (ovsdb, OvsCore, _) {
+ 'use strict';
+
+ ovsdb.register.factory('OvsdbRestangular', ['Restangular', 'ENV', function (Restangular, ENV) {
+ return Restangular.withConfig(function (RestangularConfig) {
+ RestangularConfig.setBaseUrl(ENV.getBaseURL("MD_SAL"));
+ });
+ }]);
+
+ // nbv2 support depricated in dlux
+ ovsdb.register.factory('NeutronRestangular', ['Restangular', function (Restangular) {
+ return Restangular.withConfig(function (RestangularConfig) {
+ var baseUrl = window.location.protocol + '//' + window.location.hostname;
+ RestangularConfig.setBaseUrl(baseUrl + ':8080/controller/nb/v2/neutron');
+ });
+ }]);
+
+ ovsdb.register.factory('CacheFactory', function ($q) {
+ var svc = {},
+ ovsCache = {};
+ /*BUG : Using the persistant cache make the physical
+ * graph links to stop reacting with the force layout
+ * algorithm. The current behavior is to use the cache
+ * only the pile up the datas.
+ */
+ svc.obtainDataFromCache = function (key, fn, ctx) {
+ var cacheDefer = $q.defer();
+
+ if (angular.isUndefined(ovsCache[key])) {
+ fn.call(ctx, function (data) {
+ ovsCache[key] = {
+ obj: data,
+ timestamp: Date.now() + 2000 //300000 // 5 mintues
+ };
+ cacheDefer.resolve(data);
+ });
+ } else {
+ var cacheObj = ovsCache[key];
+ if (cacheObj.timestamp < Date.now() || _.isEmpty(cacheObj.obj)) {
+ fn.call(ctx, function (data) {
+ ovsCache[key] = {
+ obj: data,
+ timestamp: Date.now() + 2000 //300000 // 5 mintues
+ };
+ cacheDefer.resolve(data);
+ });
+ } else {
+ cacheDefer.resolve(cacheObj.obj);
+ }
+ }
+
+ return cacheDefer.promise;
+ };
+
+ svc.getCacheObj = function (key) {
+ if (angular.isUndefined(ovsCache[key])) {
+ ovsCache[key] = {};
+ }
+ return ovsCache[key];
+ };
+
+ return svc;
+ });
+
+ var TopologySvc = function (OvsdbRestangular, nodeIdentifier, ovsNodeKeys, bridgeNodeKeys, tpKeys, flowInfoKeys, linkIdentifier, OVSConstant, $q, $http, CacheFactory) {
+ var svc = {
+ base: function (type) {
+ return OvsdbRestangular.one('restconf').one(type);
+ }
+ };
+
+ function parseOvsdbNode(node) {
+ var inetMgr = '',
+ inetNode = '',
+ otherLocalIp = '',
+ otherInfo = null,
+ connectionInfo = null;
+
+ connectionInfo = node[ovsNodeKeys.CONNECTION_INFO];
+ otherInfo = node[ovsNodeKeys.OTHER_CONFIG];
+
+ if (_.isObject(connectionInfo)) {
+ inetMgr = connectionInfo[ovsNodeKeys.LOCAL_IP] + ':' + connectionInfo[ovsNodeKeys.LOCAL_PORT];
+ inetNode = connectionInfo[ovsNodeKeys.REMOTE_IP] + ':' + connectionInfo[ovsNodeKeys.REMOTE_PORT];
+ }
+
+ if (_.isArray(otherInfo)) {
+ _.each(otherInfo, function (value) {
+ if (value[ovsNodeKeys.OTHER_CONFIG_KEY] === 'local_ip') {
+ otherLocalIp = value[ovsNodeKeys.OTHER_CONFIG_VALUE];
+ }
+ });
+ }
+
+ return new OvsCore.OvsNode(node[ovsNodeKeys.NODE_ID], inetMgr, inetNode, otherLocalIp, node[ovsNodeKeys.OVS_VERSION]);
+ }
+
+ function parseBridgeNode(node) {
+ var bridgeNode = null,
+ controllerTarget = '',
+ controllerConnected = false,
+ tp = node[bridgeNodeKeys.TP],
+ controllerEntries = node[bridgeNodeKeys.CONTROLLER_ENTRY];
+
+ _.each(controllerEntries, function (value) {
+ controllerTarget = value[bridgeNodeKeys.TARGET];
+ controllerEntries = value[bridgeNodeKeys.IS_CONNECTED];
+ return false; // break the anonymus function
+ });
+
+ bridgeNode = new OvsCore.BridgeNode(node[bridgeNodeKeys.NODE_ID], node[bridgeNodeKeys.DATA_PATH], node[bridgeNodeKeys.BRIDGE_NAME], controllerTarget, controllerConnected);
+
+ _.each(tp, function (value) {
+ var tp = parseBridgeTP(value);
+
+ if (tp.ofPort == '65534' && (tp.name === 'br-ex' || tp.name === 'br-int')) {
+ return;
+ } else {
+ bridgeNode.addTerminationPoint(tp);
+ }
+
+ });
+
+ return bridgeNode;
+ }
+
+ function parseBridgeTP(tp) {
+ var mac = '',
+ ifaceId = '',
+ extInfo = tp['ovsdb:port-external-ids'] || tp['ovsdb:interface-external-ids'],
+ type = tp[tpKeys.INTERFACE_TYPE];
+
+ _.each(extInfo, function (ext) {
+ if (ext[tpKeys.EXTERNAL_KEY_ID] === tpKeys.ATTACHED_MAC) {
+ mac = ext[tpKeys.EXTERNAL_KEY_VALUE];
+ }
+ if (ext[tpKeys.EXTERNAL_KEY_ID] === tpKeys.IFACE_ID) {
+ ifaceId = ext[tpKeys.EXTERNAL_KEY_VALUE] || '';
+ }
+ });
+ if (type === OVSConstant.TP_TYPE.VXLAN) {
+ var localIp = null,
+ remoteIp = null;
+ _.each(tp['ovsdb:options'], function (option) {
+ switch (option.option) {
+ case 'local_ip':
+ localIp = option.value;
+ break;
+ case 'remote_ip':
+ remoteIp = option.value;
+ break;
+ }
+ });
+ return new OvsCore.Tunnel(tp[tpKeys.NAME], tp[tpKeys.OF_PORT], type, mac, ifaceId, localIp, remoteIp);
+ }
+ return new OvsCore.TerminationPoint(tp[tpKeys.NAME], tp[tpKeys.OF_PORT], type, mac, ifaceId);
+
+ }
+
+ function fetchTopology(cb) {
+ var invNodeDefer = this.base('operational').one('opendaylight-inventory:nodes').get();
+ var netTopoDefer = this.base('operational').one('network-topology:network-topology').get();
+
+ // be sure all data are loaded
+ $q.all([invNodeDefer, netTopoDefer]).then(function (values) {
+ var invNode = values[0],
+ netTopo = values[1],
+ index_hash = [],
+ i = 0;
+
+ // check if the data look fine in network topology
+ if (!netTopo || !netTopo['network-topology'] || !netTopo['network-topology'].topology) {
+ throw new Error('Invalid json format while parsing network-topology');
+ }
+
+ // check if the data look fine in inventory node
+ if (!invNode || !invNode.nodes || !invNode.nodes.node) {
+ throw new Error('Invalid JSON format while parsing inventory-node');
+ }
+
+ // get all topologies and start looping
+ var topologies = netTopo['network-topology'].topology,
+ nodes = invNode.nodes.node,
+ topo = new OvsCore.Topology();
+
+ _.each(topologies, function (topology, topo_index) {
+ if (!topology.hasOwnProperty('topology-id')) {
+ throw new Error('Invalide JSON format, no topology-id for the topology [' + topo_index + ']');
+ }
+
+ // if there no node it will be an empty array so noop
+ (topology.node || []).forEach(function (node) {
+ if (!node[nodeIdentifier.ID]) {
+ throw new Error('Unexpected node : undefined ' + nodeIdentifier.ID + ' key');
+ }
+ index_hash[node[nodeIdentifier.ID]] = i++;
+
+ if (node['ovsdb:bridge-name']) {
+ //bridge Node
+ topo.registerBridgeNode(parseBridgeNode(node));
+ } else if (node['ovsdb:connection-info']) {
+ // obsvdb Node
+ topo.registerOvsdbNode(parseOvsdbNode(node));
+ }
+ });
+
+ // if there no link it will be an empty array so noop
+ (topology.link || []).forEach(function (link) {
+
+ var source = link[linkIdentifier.SRC]['source-node'],
+ dest = link[linkIdentifier.DEST]['dest-node'];
+
+ topo.registerLink(new OvsCore.Link(link[linkIdentifier.ID], source, dest));
+ });
+
+ });
+
+ _.each(nodes, function (node, index) {
+ if (!node.id) {
+ return;
+ }
+
+ var bridgeId = node.id;
+
+ var bridgeNode = _.filter(topo.bridgeNodes, function (bridgeNode) {
+ return bridgeNode.getFLowName() === bridgeId;
+ })[0];
+
+ // match info for bridge node
+ if (bridgeNode) {
+ bridgeNode.flowInfo.features = node[flowInfoKeys.FEATURE];
+ bridgeNode.flowInfo.software = node[flowInfoKeys.SOFTWARE];
+ bridgeNode.flowInfo.hardware = node[flowInfoKeys.HARDWARE];
+ bridgeNode.flowInfo.manufacturer = node[flowInfoKeys.MANUFACTURER];
+ bridgeNode.flowInfo.ip = node[flowInfoKeys.IP];
+
+ _.each(node[flowInfoKeys.TABLE], function (entry) {
+ if (!_.isUndefined(entry.id)) {
+ _.each(entry.flow, function (flow) {
+ bridgeNode.addFlowTableInfo({
+ key: flow.table_id,
+ value: flow.id
+ });
+ });
+ }
+ });
+ }
+ });
+
+ // show relation between ovsNode and switch with a link
+ _.each(topo.ovsdbNodes, function (node, index) {
+ var bridges = _.filter(topo.bridgeNodes, function (bnode) {
+ return bnode.nodeId.indexOf(node.nodeId) > -1;
+ });
+ _.each(bridges, function (bridge) {
+ var size = _.size(topo.links),
+ link = new OvsCore.BridgeOvsLink(++size, node.nodeId, bridge.nodeId);
+ topo.registerLink(link);
+ });
+ });
+
+ function findVxlan(bridgeNode) {
+ var tunnels = [];
+
+ _.each(bridgeNode, function (node) {
+ var ovsdbNode = _.find(topo.ovsdbNodes, function (oNode) {
+ return node.nodeId.indexOf(oNode.nodeId) > -1;
+ });
+ if (!ovsdbNode) {
+ return false;
+ }
+ _.each(node.tPs, function (tp, index) {
+ if (tp instanceof OvsCore.Tunnel) {
+ tunnels.push({
+ port: tp,
+ bridge: node
+ });
+ }
+ });
+ });
+
+ return tunnels;
+ }
+
+ // extract all tunnel paired with their bridge
+ var tunnels = findVxlan(topo.bridgeNodes);
+ // loop over all pairs
+ for (var index = 0; index < tunnels.length; ++index) {
+ var tunnel = tunnels[index],
+ currIp = tunnel.port.localIp,
+ destIp = tunnel.port.remoteIp,
+ pairIndex = 0,
+ linkedBridge = _.find(tunnels, function (t, i) {
+ pairIndex = i;
+ return t.port.remoteIp === currIp && t.port.localIp == destIp;
+ });
+
+ if (linkedBridge) {
+ tunnels.splice(pairIndex, 1);
+ topo.registerLink(new OvsCore.TunnelLink(tunnel.port.name + linkedBridge.port.name, tunnel.bridge.nodeId, linkedBridge.bridge.nodeId));
+ }
+ }
+
+ topo.updateLink();
+ cb(topo);
+ },
+ function (err) {
+ throw err;
+ }
+ );
+ }
+
+ svc.getTopologies = function () {
+ return CacheFactory.obtainDataFromCache('topologies', fetchTopology, this);
+ };
+
+ return svc;
+ };
+ TopologySvc.$inject = ['OvsdbRestangular', 'nodeIdentifier', 'ovsNodeKeys', 'bridgeNodeKeys', 'tpKeys', 'flowInfoKeys', 'linkIdentifier', 'OVSConstant', '$q', '$http', 'CacheFactory'];
+
+ var NeutronSvc = function (NeutronRestangular, CacheFactory, $q, $http) {
+ var svc = {
+ base: function (type) {
+ return NeutronRestangular.one(type);
+ }
+ },
+ tenant_hash = {};
+
+ function fetchSubNetworks(cb) {
+ var subnetskDefer = svc.base('subnets').get();
+ subnetskDefer.then(function (data) {
+ var subnets = data,
+ subnetHash = {};
+
+ if (!subnets || !subnets.subnets) {
+ throw new Error('Invalid format from neutron subnets');
+ }
+
+ _.each(subnets.subnets, function (subnet) {
+ if (!subnetHash[subnet.network_id]) {
+ subnetHash[subnet.network_id] = [];
+ }
+ tenant_hash[subnet.tenant_id] = {};
+ subnetHash[subnet.network_id].push(new OvsCore.Neutron.SubNet(
+ subnet.id,
+ subnet.network_id,
+ subnet.name,
+ subnet.ip_version,
+ subnet.cidr,
+ subnet.gateway_ip,
+ subnet.tenant_id
+ ));
+ });
+ cb(subnetHash);
+ });
+ }
+
+ function fetchNetworks(cb) {
+ var networkDefer = svc.base('networks').get();
+ var subnetskDefer = svc.getSubNets();
+
+ $q.all([subnetskDefer, networkDefer]).then(function (datas) {
+ var subnetsHash = datas[0],
+ networks = datas[1],
+ networkArray = [];
+
+ if (!networks || !networks.networks) {
+ throw new Error('Invalid format from neutron networks');
+ }
+
+ _.each(networks.networks, function (network) {
+ var net = new OvsCore.Neutron.Network(
+ network.id,
+ network.name,
+ network.shared,
+ network.status,
+ network['router:external'],
+ network.tenant_id
+ );
+ tenant_hash[net.tenantId] = {};
+ net.addSubNets(subnetsHash[net.id]);
+ networkArray.push(net);
+ });
+ cb(networkArray);
+ });
+ }
+
+ function fetchRouters(cb) {
+ var routerDefer = svc.base('routers').get();
+ routerDefer.then(function (data) {
+ var routers = data.routers,
+ routerArray = [];
+
+ if (!routers) {
+ throw new Error('Invalid format from neutron routers');
+ }
+ _.each(routers, function (router) {
+ var id = router.id,
+ name = router.name,
+ status = router.status,
+ tenantId = router.tenant_id,
+ extGateWayInfo = router.external_gateway_info;
+ tenant_hash[tenantId] = {};
+ routerArray.push(new OvsCore.Neutron.Router(
+ id, name, status, tenantId, extGateWayInfo
+ ));
+ });
+ cb(routerArray);
+ });
+ }
+
+ function fetchPorts(cb) {
+ var portDefer = svc.base('ports').get();
+ portDefer.then(function (data) {
+ var ports = data.ports,
+ portArray = [];
+
+ if (!ports) {
+ throw new Error('Invalid format from neutron ports');
+ }
+ _.each(ports, function (port) {
+ tenant_hash[port.tenant_id] = {};
+ portArray.push(new OvsCore.Neutron.Port(
+ port.id,
+ port.network_id,
+ port.name,
+ port.tenant_id,
+ port.device_id,
+ port.device_owner,
+ port.fixed_ips,
+ port.mac_address
+ ));
+ });
+ cb(portArray);
+ });
+ }
+
+ function fetchFloatingIps(cb) {
+ var floatingIpDefer = svc.base('floatingips').get();
+ floatingIpDefer.then(function (data) {
+ var floatingIps = data.floatingips,
+ floatingIpArray = [];
+
+ if (!floatingIps) {
+ throw new Error('Invalid format from neutron floatingIps');
+ }
+
+ _.each(floatingIps, function (fIp) {
+ tenant_hash[fIp.tenant_id] = {};
+ floatingIpArray.push(new OvsCore.Neutron.FloatingIp(
+ fIp.id,
+ fIp.floating_network_id,
+ fIp.port_id,
+ fIp.fixed_ip_address,
+ fIp.floating_ip_address,
+ fIp.tenant_id,
+ fIp.status
+ ));
+ });
+
+ cb(floatingIpArray);
+ });
+ }
+
+ svc.getNetworks = function () {
+ return CacheFactory.obtainDataFromCache('networks', fetchNetworks, this);
+ };
+
+ svc.getSubNets = function () {
+ return CacheFactory.obtainDataFromCache('subnet', fetchSubNetworks, this);
+ };
+
+ svc.getPorts = function () {
+ return CacheFactory.obtainDataFromCache('ports', fetchPorts, this);
+ };
+
+ svc.getRouters = function () {
+ return CacheFactory.obtainDataFromCache('routers', fetchRouters, this);
+ };
+
+ svc.getFloatingIps = function () {
+ return CacheFactory.obtainDataFromCache('floatingips', fetchFloatingIps, this);
+ };
+
+ svc.getAllTenants = function () {
+ return Object.keys(tenant_hash);
+ };
+
+ return svc;
+ };
+ NeutronSvc.$inject = ['NeutronRestangular', 'CacheFactory', '$q', '$http'];
+
+ var OvsUtil = function (NeutronSvc, TopologySvc, CacheFactory, $q) {
+ var svc = {};
+
+ function findOvsdbNodeForBridge(ovsdbNodes, bridge) {
+ return _.find(ovsdbNodes, function (node) {
+ return bridge.nodeId.indexOf(node.nodeId) > -1;
+ });
+ }
+
+ function pileUpTopologyData(cb) {
+ var networksDefer = NeutronSvc.getNetworks(),
+ routersDefer = NeutronSvc.getRouters(),
+ portsDefer = NeutronSvc.getPorts(),
+ floatingDefer = NeutronSvc.getFloatingIps(),
+ netTopoDefer = TopologySvc.getTopologies();
+
+ $q.all([networksDefer, routersDefer, portsDefer, floatingDefer, netTopoDefer]).then(function (datas) {
+ var networks = datas[0],
+ routers = datas[1],
+ ports = datas[2],
+ floatingIps = datas[3],
+ topo = datas[4];
+
+ // match ports with elements
+ _.each(ports, function (port) {
+ port.topoInfo = [];
+ // corelate port.topoInfo data with network topology termination point
+ _.each(topo.bridgeNodes, function (bridge) {
+ _.each(bridge.tPs, function (tp) {
+ if (tp.ifaceId === port.id) {
+ port.topoInfo.push({
+ name: tp.name,
+ ofPort: tp.ofPort,
+ mac: bridge.dpIp,
+ bridge: bridge,
+ ovsNode: findOvsdbNodeForBridge(topo.ovsdbNodes, bridge)
+ });
+ }
+ });
+ });
+
+ switch (port.deviceOwner) {
+ case 'network:router_gateway':
+ case 'network:router_interface':
+ var router = _.find(routers, function (r) {
+ return r.id === port.deviceId;
+ });
+ if (router) {
+ router.interfaces.push({
+ id: port.id,
+ networkId: port.networkId,
+ ip: port.fixed_ips[0],
+ mac: port.mac,
+ type: port.deviceOwner.replace('network:', ''),
+ tenantId: port.tenantId,
+ topoInfo: port.topoInfo
+ });
+ }
+ break;
+ case 'compute:None':
+ case 'compute:nova':
+ case 'network:dhcp':
+ var network = _.find(networks, function (n) {
+ return n.id === port.networkId;
+ }),
+ inst = null;
+
+ if (network) {
+ inst = new OvsCore.Neutron.Instance(port.id, port.networkId,
+ port.name, port.fixed_ips[0].ip_address, port.mac,
+ port.deviceOwner, port.tenantId, port.topoInfo);
+
+ inst.extractFloatingIps(floatingIps);
+ network.instances.push(inst);
+ }
+ break;
+ }
+
+ });
+
+ // find all routers for a specific network
+ _.each(networks, function (network) {
+ network.routers = _.filter(routers, function (router) {
+ return network.id === router.externalGateway.network_id;
+ });
+
+ // order instance by ip
+ network.instances.sort(function (a, b) {
+ var ipA = a.ip.slice(a.ip.lastIndexOf('.') + 1),
+ ipB = b.ip.slice(b.ip.lastIndexOf('.') + 1);
+ return ipA - ipB;
+ });
+ });
+
+ cb(networks);
+ });
+ }
+
+ svc.getLogicalTopology = function () {
+ return CacheFactory.obtainDataFromCache('logicalTopology', pileUpTopologyData, this);
+ };
+
+ svc.extractLogicalByTenant = function (tenantId, subSet) {
+ var lTopoDefer = svc.getLogicalTopology(),
+ resultDefer = $q.defer();
+ lTopoDefer.then(function () {
+ var ports = CacheFactory.getCacheObj('ports').obj,
+ filteredPorts = _.filter(ports, function (p) {
+ return p.tenantId === tenantId;
+ });
+
+ if (!_.isEmpty(filteredPorts)) {
+ var bridgeHash = {};
+ _.each(filteredPorts, function (p) {
+ if (!_.isEmpty(p.topoInfo) && !bridgeHash[p.topoInfo[0].bridge.nodeId]) {
+ bridgeHash[p.topoInfo[0].bridge.nodeId] = {};
+ }
+ });
+ var ovsdbHash = {};
+ _.each(filteredPorts, function (p) {
+ if (!_.isEmpty(p.topoInfo) && !ovsdbHash[p.topoInfo[0].ovsNode.nodeId]) {
+ ovsdbHash[p.topoInfo[0].ovsNode.nodeId] = {};
+ }
+ });
+
+ resultDefer.resolve([Object.keys(bridgeHash), Object.keys(ovsdbHash)]);
+ } else {
+ resultDefer.resolve([], []);
+ }
+ });
+ return resultDefer.promise;
+ };
+
+ svc.extractLogicalBySubnet = function (subnets, subSet) {
+ var lTopoDefer = svc.getLogicalTopology(),
+ resultDefer = $q.defer();
+ lTopoDefer.then(function () {
+ var ports = CacheFactory.getCacheObj('ports').obj,
+ networks = CacheFactory.getCacheObj('networks').obj;
+
+ var filteredPorts = _.filter(ports, function (p) {
+ var net = _.find(networks, function (d) {
+ return d.id === p.networkId;
+ });
+
+ return net.asSubnet(subnets);
+ });
+ if (!_.isEmpty(filteredPorts)) {
+ var bridgeHash = {};
+ _.each(filteredPorts, function (p) {
+ if (!_.isEmpty(p.topoInfo) && !bridgeHash[p.topoInfo[0].bridge.nodeId]) {
+ bridgeHash[p.topoInfo[0].bridge.nodeId] = {};
+ }
+ });
+ var ovsdbHash = {};
+ _.each(filteredPorts, function (p) {
+ if (!_.isEmpty(p.topoInfo) && !ovsdbHash[p.topoInfo[0].ovsNode.nodeId]) {
+ ovsdbHash[p.topoInfo[0].ovsNode.nodeId] = {};
+ }
+ });
+ resultDefer.resolve([Object.keys(bridgeHash), Object.keys(ovsdbHash)]);
+ } else {
+ resultDefer.resolve([], []);
+ }
+ });
+ return resultDefer.promise;
+ };
+
+ return svc;
+ };
+
+ OvsUtil.$inject = ['NeutronSvc', 'TopologySvc', 'CacheFactory', '$q'];
+
+ ovsdb.register.factory('TopologySvc', TopologySvc);
+ ovsdb.register.factory('NeutronSvc', NeutronSvc);
+ ovsdb.register.factory('OvsUtil', OvsUtil);
+});