1 package org.opendaylight.ovsdb.neutron;
3 import java.math.BigInteger;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.LinkedList;
9 import java.util.Queue;
12 import org.opendaylight.controller.containermanager.ContainerConfig;
13 import org.opendaylight.controller.containermanager.ContainerFlowConfig;
14 import org.opendaylight.controller.containermanager.IContainerManager;
15 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
16 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
17 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
18 import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
19 import org.opendaylight.controller.sal.core.Node;
20 import org.opendaylight.controller.sal.core.NodeConnector;
21 import org.opendaylight.controller.sal.utils.HexEncode;
22 import org.opendaylight.controller.sal.utils.ServiceHelper;
23 import org.opendaylight.controller.sal.utils.Status;
24 import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
25 import org.opendaylight.ovsdb.lib.notation.UUID;
26 import org.opendaylight.ovsdb.lib.table.Bridge;
27 import org.opendaylight.ovsdb.lib.table.Interface;
28 import org.opendaylight.ovsdb.lib.table.Port;
29 import org.opendaylight.ovsdb.lib.table.internal.Table;
30 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 public class TenantNetworkManager {
35 static final Logger logger = LoggerFactory.getLogger(TenantNetworkManager.class);
37 private static final int MAX_VLAN = 4096;
38 private static final String EXTERNAL_ID_VM_ID = "vm-id";
39 private static final String EXTERNAL_ID_INTERFACE_ID = "iface-id";
40 private static final String EXTERNAL_ID_VM_MAC = "attached-mac";
41 private static TenantNetworkManager tenantHelper = new TenantNetworkManager();
42 private Queue<Integer> internalVlans = new LinkedList<Integer>();
43 private Map<String, Integer> tenantVlanMap = new HashMap<String, Integer>();
44 private boolean enableContainer = false;
45 private TenantNetworkManager() {
46 for (int i = 1; i < MAX_VLAN ; i++) {
49 String isTenantContainer = System.getProperty("TenantIsContainer");
50 if (isTenantContainer != null && isTenantContainer.equalsIgnoreCase("true")) {
51 enableContainer = true;
55 public static TenantNetworkManager getManager() {
59 private int assignInternalVlan (String networkId) {
60 Integer mappedVlan = tenantVlanMap.get(networkId);
61 if (mappedVlan != null) return mappedVlan;
62 mappedVlan = internalVlans.poll();
63 if (mappedVlan != null) tenantVlanMap.put(networkId, mappedVlan);
67 public void internalVlanInUse (int vlan) {
68 internalVlans.remove(vlan);
71 public int getInternalVlan (String networkId) {
72 Integer vlan = tenantVlanMap.get(networkId);
73 if (vlan == null) return 0;
74 return vlan.intValue();
77 public int networkCreated (String networkId) {
78 int internalVlan = this.assignInternalVlan(networkId);
79 if (enableContainer && internalVlan != 0) {
80 IContainerManager containerManager = (IContainerManager)ServiceHelper.getGlobalInstance(IContainerManager.class, this);
81 if (containerManager == null) {
82 logger.error("ContainerManager is null. Failed to create Container for {}", networkId);
86 ContainerConfig config = new ContainerConfig();
87 config.setContainer(BaseHandler.convertNeutronIDToKey(networkId));
88 Status status = containerManager.addContainer(config);
89 logger.debug("Container Creation Status for {} : {}", networkId, status.toString());
91 ContainerFlowConfig flowConfig = new ContainerFlowConfig("InternalVlan", internalVlan+"",
92 null, null, null, null, null);
93 List<ContainerFlowConfig> containerFlowConfigs = new ArrayList<ContainerFlowConfig>();
94 containerFlowConfigs.add(flowConfig);
95 containerManager.addContainerFlows(BaseHandler.convertNeutronIDToKey(networkId), containerFlowConfigs);
101 * Are there any TenantNetwork VM present on this Node ?
102 * This method uses Interface Table's external-id field to locate the VM.
104 public boolean isTenantNetworkPresentInNode(Node node, String segmentationId) {
105 String networkId = this.getNetworkIdForSegmentationId(segmentationId);
106 if (networkId == null) {
107 logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId);
110 int internalVlan = this.getInternalVlan(networkId);
111 if (internalVlan == 0) {
112 logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
115 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
118 // Vlan Tag based identification
119 Map<String, Table<?>> portTable = ovsdbTable.getRows(node, Port.NAME.getName());
120 if (portTable == null) {
121 logger.debug("Port table is null for Node {} ", node);
125 for (Table<?> row : portTable.values()) {
126 Port port = (Port)row;
127 Set<BigInteger> tags = port.getTag();
128 if (tags.contains(internalVlan)) {
129 logger.debug("Tenant Network {} with Segmenation-id {} is present in Node {} / Port {}",
130 networkId, segmentationId, node, port);
135 // External-id based more accurate VM Location identification
136 Map<String, Table<?>> ifTable = ovsdbTable.getRows(node, Interface.NAME.getName());
137 if (ifTable == null) {
138 logger.debug("Interface table is null for Node {} ", node);
142 for (Table<?> row : ifTable.values()) {
143 Interface intf = (Interface)row;
144 Map<String, String> externalIds = intf.getExternal_ids();
145 if (externalIds != null) {
146 if (this.isInterfacePresentInTenantNetwork(externalIds.get(EXTERNAL_ID_INTERFACE_ID), networkId)) {
147 logger.debug("Tenant Network {} with Segmenation-id {} is present in Node {} / Interface {}",
148 networkId, segmentationId, node, intf);
154 } catch (Exception e) {
159 logger.debug("Tenant Network {} with Segmenation-id {} is NOT present in Node {}",
160 networkId, segmentationId, node);
165 private String getNetworkIdForSegmentationId (String segmentationId) {
166 INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
167 List <NeutronNetwork> networks = neutronNetworkService.getAllNetworks();
168 for (NeutronNetwork network : networks) {
169 if (network.getProviderSegmentationID().equalsIgnoreCase(segmentationId)) return network.getNetworkUUID();
174 private boolean isInterfacePresentInTenantNetwork (String portId, String networkId) {
175 INeutronPortCRUD neutronPortService = (INeutronPortCRUD)ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, this);
176 NeutronPort neutronPort = neutronPortService.getPort(portId);
177 if (neutronPort.getNetworkUUID().equalsIgnoreCase(networkId)) return true;
181 public NeutronNetwork getTenantNetworkForInterface (Interface intf) {
182 logger.trace("getTenantNetworkForInterface for {}", intf);
183 if (intf == null) return null;
184 Map<String, String> externalIds = intf.getExternal_ids();
185 logger.trace("externalIds {}", externalIds);
186 if (externalIds == null) return null;
187 String neutronPortId = externalIds.get(EXTERNAL_ID_INTERFACE_ID);
188 if (neutronPortId == null) return null;
189 INeutronPortCRUD neutronPortService = (INeutronPortCRUD)ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, this);
190 NeutronPort neutronPort = neutronPortService.getPort(neutronPortId);
191 logger.trace("neutronPort {}", neutronPort);
192 if (neutronPort == null) return null;
193 INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
194 NeutronNetwork neutronNetwork = neutronNetworkService.getNetwork(neutronPort.getNetworkUUID());
195 logger.debug("{} mappped to {}", intf, neutronNetwork);
196 return neutronNetwork;
199 public void programTenantNetworkInternalVlan(Node node, String portUUID, NeutronNetwork network) {
200 int vlan = this.getInternalVlan(network.getID());
201 logger.debug("Programming Vlan {} on {}", vlan, portUUID);
203 logger.error("Unable to get an internalVlan for Network {}", network);
206 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
207 Port port = new Port();
208 OvsDBSet<BigInteger> tags = new OvsDBSet<BigInteger>();
209 tags.add(BigInteger.valueOf(vlan));
211 ovsdbTable.updateRow(node, Port.NAME.getName(), null, portUUID, port);
212 if (enableContainer) this.addPortToTenantNetworkContainer(node, portUUID, network);
215 private void addPortToTenantNetworkContainer(Node node, String portUUID, NeutronNetwork network) {
216 IContainerManager containerManager = (IContainerManager)ServiceHelper.getGlobalInstance(IContainerManager.class, this);
217 if (containerManager == null) {
218 logger.error("ContainerManager is not accessible");
221 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
223 Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID);
225 logger.trace("Unable to identify Port with UUID {}", portUUID);
228 Set<UUID> interfaces = port.getInterfaces();
229 if (interfaces == null) {
230 logger.trace("No interfaces available to fetch the OF Port");
233 Bridge bridge = this.getBridgeIdForPort(node, portUUID);
234 if (bridge == null) {
235 logger.debug("Unable to spot Bridge for Port {} in node {}", port, node);
238 Set<String> dpids = bridge.getDatapath_id();
239 if (dpids == null || dpids.size() == 0) return;
240 Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
242 for (UUID intfUUID : interfaces) {
243 Interface intf = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), intfUUID.toString());
244 if (intf == null) continue;
245 Set<BigInteger> of_ports = intf.getOfport();
246 if (of_ports == null) continue;
247 for (BigInteger of_port : of_ports) {
248 ContainerConfig config = new ContainerConfig();
249 config.setContainer(BaseHandler.convertNeutronIDToKey(network.getID()));
250 logger.debug("Adding Port {} to Container : {}", port.toString(), config.getContainer());
251 List<String> ncList = new ArrayList<String>();
252 Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
253 NodeConnector nc = NodeConnector.fromStringNoNode(Node.NodeIDType.OPENFLOW.toString(),
254 Long.valueOf(of_port.longValue()).intValue()+"",
256 ncList.add(nc.toString());
257 config.addNodeConnectors(ncList);
259 Status status = containerManager.addContainerEntry(BaseHandler.convertNeutronIDToKey(network.getID()), ncList);
261 if (!status.isSuccess()) {
262 logger.error(" Failed {} : to add port {} to container - {}",
263 status, nc, network.getID());
265 logger.error(" Successfully added port {} to container - {}",
266 nc, network.getID());
270 } catch (Exception e) {
271 // TODO Auto-generated catch block
276 private Bridge getBridgeIdForPort (Node node, String uuid) {
277 OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
279 Map<String, Table<?>> bridges = ovsdbTable.getRows(node, Bridge.NAME.getName());
280 if (bridges == null) return null;
281 for (String bridgeUUID : bridges.keySet()) {
282 Bridge bridge = (Bridge)bridges.get(bridgeUUID);
283 Set<UUID> portUUIDs = bridge.getPorts();
284 logger.trace("Scanning Bridge {} to identify Port : {} ",bridge, uuid);
285 for (UUID portUUID : portUUIDs) {
286 if (portUUID.toString().equalsIgnoreCase(uuid)) {
287 logger.trace("Found Port {} -> ", uuid, bridgeUUID);
292 } catch (Exception e) {
293 logger.debug("Failed to get BridgeId port {} in Node {}", uuid, node);
298 public void networkDeleted(String id) {
299 if (!enableContainer) return;
301 IContainerManager containerManager = (IContainerManager)ServiceHelper.getGlobalInstance(IContainerManager.class, this);
302 if (containerManager == null) {
303 logger.error("ContainerManager is not accessible");
307 String networkID = BaseHandler.convertNeutronIDToKey(id);
308 ContainerConfig config = new ContainerConfig();
309 config.setContainer(networkID);
310 containerManager.removeContainer(config);