Bug 1385 : Adding support for toString, equals and hashCode for the Typed Interfaces.
[netvirt.git] / neutron / src / main / java / org / opendaylight / ovsdb / neutron / TenantNetworkManager.java
index 9107ee4bff12156c6560a606c749ceb511ef9123..fc7aa2b164e98d42e1147bb6aa506c3c74cd16e5 100644 (file)
@@ -1,13 +1,20 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. and others...
+ *
+ * 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
+ *
+ * Authors : Madhu Venugopal, Brent Salisbury, Dave Tucker
+ */
 package org.opendaylight.ovsdb.neutron;
 
-import java.math.BigInteger;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Queue;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.containermanager.ContainerConfig;
 import org.opendaylight.controller.containermanager.ContainerFlowConfig;
@@ -21,62 +28,137 @@ import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
+import org.opendaylight.ovsdb.lib.notation.OvsdbSet;
+import org.opendaylight.ovsdb.lib.notation.Row;
 import org.opendaylight.ovsdb.lib.notation.UUID;
-import org.opendaylight.ovsdb.lib.table.Bridge;
-import org.opendaylight.ovsdb.lib.table.Interface;
-import org.opendaylight.ovsdb.lib.table.Port;
-import org.opendaylight.ovsdb.lib.table.internal.Table;
-import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
+import org.opendaylight.ovsdb.neutron.provider.IProviderNetworkManager;
+import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
+import org.opendaylight.ovsdb.plugin.OvsdbConfigService;
+import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
+import org.opendaylight.ovsdb.schema.openvswitch.Interface;
+import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
+import org.opendaylight.ovsdb.schema.openvswitch.Port;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class TenantNetworkManager {
+public class TenantNetworkManager implements ITenantNetworkManager {
     static final Logger logger = LoggerFactory.getLogger(TenantNetworkManager.class);
+    private ConcurrentMap<String, NodeConfiguration> nodeConfigurationCache = new ConcurrentHashMap<>();
 
-    private static final int MAX_VLAN = 4096;
-    private static final String EXTERNAL_ID_VM_ID = "vm-id";
-    private static final String EXTERNAL_ID_INTERFACE_ID = "iface-id";
-    private static final String EXTERNAL_ID_VM_MAC = "attached-mac";
-    private static TenantNetworkManager tenantHelper = new TenantNetworkManager();
-    private Queue<Integer> internalVlans = new LinkedList<Integer>();
-    private Map<String, Integer> tenantVlanMap = new HashMap<String, Integer>();
-    private TenantNetworkManager() {
-        for (int i = 1; i < MAX_VLAN ; i++) {
-            internalVlans.add(i);
+    // The implementation for each of these services is resolved by the OSGi Service Manager
+    private volatile IProviderNetworkManager providerNetworkManager;
+
+    private boolean enableContainer = false;
+    public TenantNetworkManager() {
+        String isTenantContainer = System.getProperty("TenantIsContainer");
+        if (isTenantContainer != null && isTenantContainer.equalsIgnoreCase("true")) {
+            enableContainer =  true;
         }
     }
 
-    public static TenantNetworkManager getManager() {
-        return tenantHelper;
+    @Override
+    public int getInternalVlan(Node node, String networkId) {
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Unable to get UUID for Node {}", node);
+            return 0;
+        }
+
+        NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+        if (nodeConfiguration == null) {
+            nodeConfiguration = addNodeConfigurationToCache(node);
+        }
+        Integer vlan = nodeConfiguration.getInternalVlan(networkId);
+        if (vlan == null) return 0;
+        return vlan.intValue();
     }
 
-    private int assignInternalVlan (String networkId) {
-        Integer mappedVlan = tenantVlanMap.get(networkId);
-        if (mappedVlan != null) return mappedVlan;
-        mappedVlan = internalVlans.poll();
-        if (mappedVlan != null) tenantVlanMap.put(networkId, mappedVlan);
-        return mappedVlan;
+    private NodeConfiguration addNodeConfigurationToCache(Node node) {
+        NodeConfiguration nodeConfiguration = new NodeConfiguration(node, this);
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Cannot get Node UUID for Node {}", node);
+            return null;
+        }
+        this.nodeConfigurationCache.put(nodeUuid, nodeConfiguration);
+        return nodeConfigurationCache.get(nodeUuid);
     }
 
-    public void internalVlanInUse (int vlan) {
-        internalVlans.remove(vlan);
+    @Override
+    public void reclaimTenantNetworkInternalVlan(Node node, String portUUID, NeutronNetwork network) {
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Unable to get UUID for Node {}", node);
+            return;
+        }
+
+        NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+        // Cache miss
+        if (nodeConfiguration == null)
+        {
+            logger.error("Configuration data unavailable for Node {} ", node);
+            return;
+        }
+
+        int vlan = nodeConfiguration.reclaimInternalVlan(network.getID());
+        if (vlan <= 0) {
+            logger.error("Unable to get an internalVlan for Network {}", network);
+            return;
+        }
+        logger.debug("Removed Vlan {} on {}", vlan, portUUID);
     }
 
-    public int getInternalVlan (String networkId) {
-        Integer vlan = tenantVlanMap.get(networkId);
-        if (vlan == null) return 0;
-        return vlan.intValue();
+    @Override
+    public void networkCreated (String networkId) {
+        IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+        List<Node> nodes = connectionService.getNodes();
+
+        for (Node node : nodes) {
+            this.networkCreated(node, networkId);
+        }
+
     }
 
-    public int networkCreated (String networkId) {
-        IContainerManager containerManager = (IContainerManager)ServiceHelper.getGlobalInstance(IContainerManager.class, this);
-        if (containerManager == null) {
-            logger.error("ContainerManager is null. Failed to create Container for {}", networkId);
+    private String getNodeUUID(Node node) {
+        String nodeUuid = new String();
+        OvsdbConfigService ovsdbConfigService = (OvsdbConfigService)ServiceHelper.getGlobalInstance(OvsdbConfigService.class, this);
+        try {
+            Map<String, Row> ovsTable = ovsdbConfigService.getRows(node, ovsdbConfigService.getTableName(node, OpenVSwitch.class));
+            nodeUuid = (String)ovsTable.keySet().toArray()[0];
+        }
+        catch (Exception e) {
+            logger.error("Unable to get the Open_vSwitch table for Node {}: {}", node, e);
+        }
+
+        return nodeUuid;
+    }
+
+    @Override
+    public int networkCreated (Node node, String networkId) {
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Unable to get UUID for Node {}", node);
             return 0;
         }
-        int internalVlan = this.assignInternalVlan(networkId);
-        if (internalVlan != 0) {
+
+        NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+        // Cache miss
+        if (nodeConfiguration == null)
+        {
+            nodeConfiguration = addNodeConfigurationToCache(node);
+        }
+
+        int internalVlan = nodeConfiguration.assignInternalVlan(networkId);
+        if (enableContainer && internalVlan != 0) {
+            IContainerManager containerManager = (IContainerManager)ServiceHelper.getGlobalInstance(IContainerManager.class, this);
+            if (containerManager == null) {
+                logger.error("ContainerManager is null. Failed to create Container for {}", networkId);
+                return 0;
+            }
+
             ContainerConfig config = new ContainerConfig();
             config.setContainer(BaseHandler.convertNeutronIDToKey(networkId));
             Status status = containerManager.addContainer(config);
@@ -95,28 +177,46 @@ public class TenantNetworkManager {
      * Are there any TenantNetwork VM present on this Node ?
      * This method uses Interface Table's external-id field to locate the VM.
      */
+    @Override
     public boolean isTenantNetworkPresentInNode(Node node, String segmentationId) {
         String networkId = this.getNetworkIdForSegmentationId(segmentationId);
         if (networkId == null) {
             logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId);
             return false;
         }
-        int internalVlan = this.getInternalVlan(networkId);
-        if (internalVlan == 0) {
-            logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
-            return false;
+        if (providerNetworkManager.getProvider().hasPerTenantTunneling()) {
+            String nodeUuid = getNodeUUID(node);
+            if (nodeUuid == null) {
+                logger.debug("Unable to get UUID for Node {}", node);
+                return false;
+            }
+
+            NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+            // Cache miss
+            if (nodeConfiguration == null)
+            {
+                logger.error("Configuration data unavailable for Node {} ", node);
+                return false;
+            }
+
+            int internalVlan = nodeConfiguration.getInternalVlan(networkId);
+            if (internalVlan == 0) {
+                logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
+                return false;
+            }
         }
-        OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+        OvsdbConfigService ovsdbTable = (OvsdbConfigService)ServiceHelper.getGlobalInstance(OvsdbConfigService.class, this);
         try {
             /*
             // Vlan Tag based identification
-            Map<String, Table<?>> portTable = ovsdbTable.getRows(node, Port.NAME.getName());
+            Map<String, Row> portTable = ovsdbTable.getRows(node, Port.NAME.getName());
             if (portTable == null) {
                 logger.debug("Port table is null for Node {} ", node);
                 return false;
             }
 
-            for (Table<?> row : portTable.values()) {
+            for (Row row : portTable.values()) {
                 Port port = (Port)row;
                 Set<BigInteger> tags = port.getTag();
                 if (tags.contains(internalVlan)) {
@@ -127,18 +227,18 @@ public class TenantNetworkManager {
             }
              */
             // External-id based more accurate VM Location identification
-            Map<String, Table<?>> ifTable = ovsdbTable.getRows(node, Interface.NAME.getName());
+            Map<String, Row> ifTable = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Interface.class));
             if (ifTable == null) {
                 logger.debug("Interface table is null for Node {} ", node);
                 return false;
             }
 
-            for (Table<?> row : ifTable.values()) {
-                Interface intf = (Interface)row;
-                Map<String, String> externalIds = intf.getExternal_ids();
-                if (externalIds != null) {
+            for (Row row : ifTable.values()) {
+                Interface intf = ovsdbTable.getTypedRow(node, Interface.class, row);
+                Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
+                if (externalIds != null && externalIds.get(EXTERNAL_ID_INTERFACE_ID) != null) {
                     if (this.isInterfacePresentInTenantNetwork(externalIds.get(EXTERNAL_ID_INTERFACE_ID), networkId)) {
-                        logger.debug("Tenant Network {} with Segmenation-id {} is present in Node {} / Interface {}",
+                        logger.debug("Tenant Network {} with Segmentation-id {} is present in Node {} / Interface {}",
                                       networkId, segmentationId, node, intf);
                         return true;
                     }
@@ -146,7 +246,7 @@ public class TenantNetworkManager {
             }
 
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error("Error while trying to determine if network is present on node", e);
             return false;
         }
 
@@ -156,7 +256,8 @@ public class TenantNetworkManager {
         return false;
     }
 
-    private String getNetworkIdForSegmentationId (String segmentationId) {
+    @Override
+    public String getNetworkIdForSegmentationId (String segmentationId) {
         INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
         List <NeutronNetwork> networks = neutronNetworkService.getAllNetworks();
         for (NeutronNetwork network : networks) {
@@ -168,14 +269,15 @@ public class TenantNetworkManager {
     private boolean isInterfacePresentInTenantNetwork (String portId, String networkId) {
         INeutronPortCRUD neutronPortService = (INeutronPortCRUD)ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, this);
         NeutronPort neutronPort = neutronPortService.getPort(portId);
-        if (neutronPort.getNetworkUUID().equalsIgnoreCase(networkId)) return true;
+        if (neutronPort != null && neutronPort.getNetworkUUID().equalsIgnoreCase(networkId)) return true;
         return false;
     }
 
+    @Override
     public NeutronNetwork getTenantNetworkForInterface (Interface intf) {
         logger.trace("getTenantNetworkForInterface for {}", intf);
         if (intf == null) return null;
-        Map<String, String> externalIds = intf.getExternal_ids();
+        Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
         logger.trace("externalIds {}", externalIds);
         if (externalIds == null) return null;
         String neutronPortId = externalIds.get(EXTERNAL_ID_INTERFACE_ID);
@@ -190,20 +292,37 @@ public class TenantNetworkManager {
         return neutronNetwork;
     }
 
+    @Override
     public void programTenantNetworkInternalVlan(Node node, String portUUID, NeutronNetwork network) {
-        int vlan = this.getInternalVlan(network.getID());
+
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Unable to get UUID for Node {}", node);
+            return;
+        }
+
+        NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+        // Cache miss
+        if (nodeConfiguration == null)
+        {
+            logger.error("Configuration data unavailable for Node {} ", node);
+            return;
+        }
+
+        int vlan = nodeConfiguration.getInternalVlan(network.getID());
         logger.debug("Programming Vlan {} on {}", vlan, portUUID);
         if (vlan <= 0) {
             logger.error("Unable to get an internalVlan for Network {}", network);
             return;
         }
-        OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
-        Port port = new Port();
-        OvsDBSet<BigInteger> tags = new OvsDBSet<BigInteger>();
-        tags.add(BigInteger.valueOf(vlan));
+        OvsdbConfigService ovsdbTable = (OvsdbConfigService)ServiceHelper.getGlobalInstance(OvsdbConfigService.class, this);
+        Port port = ovsdbTable.createTypedRow(node, Port.class);
+        OvsdbSet<Long> tags = new OvsdbSet<Long>();
+        tags.add(Long.valueOf(vlan));
         port.setTag(tags);
-        ovsdbTable.updateRow(node, Port.NAME.getName(), null, portUUID, port);
-        this.addPortToTenantNetworkContainer(node, portUUID, network);
+        ovsdbTable.updateRow(node, port.getSchema().getName(), null, portUUID, port.getRow());
+        if (enableContainer) this.addPortToTenantNetworkContainer(node, portUUID, network);
     }
 
     private void addPortToTenantNetworkContainer(Node node, String portUUID, NeutronNetwork network) {
@@ -212,14 +331,15 @@ public class TenantNetworkManager {
             logger.error("ContainerManager is not accessible");
             return;
         }
-        OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+        OvsdbConfigService ovsdbTable = (OvsdbConfigService)ServiceHelper.getGlobalInstance(OvsdbConfigService.class, this);
         try {
-            Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID);
+            Row portRow = ovsdbTable.getRow(node, ovsdbTable.getTableName(node, Port.class), portUUID);
+            Port port = ovsdbTable.getTypedRow(node, Port.class, portRow);
             if (port == null) {
                 logger.trace("Unable to identify Port with UUID {}", portUUID);
                 return;
             }
-            Set<UUID> interfaces = port.getInterfaces();
+            Set<UUID> interfaces = port.getInterfacesColumn().getData();
             if (interfaces == null) {
                 logger.trace("No interfaces available to fetch the OF Port");
                 return;
@@ -229,23 +349,23 @@ public class TenantNetworkManager {
                 logger.debug("Unable to spot Bridge for Port {} in node {}", port, node);
                 return;
             }
-            Set<String> dpids = bridge.getDatapath_id();
+            Set<String> dpids = bridge.getDatapathIdColumn().getData();
             if (dpids == null || dpids.size() ==  0) return;
             Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
 
             for (UUID intfUUID : interfaces) {
-                Interface intf = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), intfUUID.toString());
+                Interface intf = (Interface)ovsdbTable.getRow(node,ovsdbTable.getTableName(node, Interface.class), intfUUID.toString());
                 if (intf == null) continue;
-                Set<BigInteger> of_ports = intf.getOfport();
+                Set<Long> of_ports = intf.getOpenFlowPortColumn().getData();
                 if (of_ports == null) continue;
-                for (BigInteger of_port : of_ports) {
+                for (Long of_port : of_ports) {
                     ContainerConfig config = new ContainerConfig();
                     config.setContainer(BaseHandler.convertNeutronIDToKey(network.getID()));
                     logger.debug("Adding Port {} to Container : {}", port.toString(), config.getContainer());
                     List<String> ncList = new ArrayList<String>();
                     Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
                     NodeConnector nc = NodeConnector.fromStringNoNode(Node.NodeIDType.OPENFLOW.toString(),
-                                                                      Long.valueOf(of_port.longValue()).intValue()+"",
+                                                                      of_port.intValue()+"",
                                                                       ofNode);
                     ncList.add(nc.toString());
                     config.addNodeConnectors(ncList);
@@ -262,19 +382,18 @@ public class TenantNetworkManager {
                 }
             }
         } catch (Exception e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
+            logger.error("Exception in addPortToTenantNetworkContainer", e);
         }
     }
 
     private Bridge getBridgeIdForPort (Node node, String uuid) {
-        OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+        OvsdbConfigService ovsdbTable = (OvsdbConfigService)ServiceHelper.getGlobalInstance(OvsdbConfigService.class, this);
         try {
-            Map<String, Table<?>> bridges = ovsdbTable.getRows(node, Bridge.NAME.getName());
+            Map<String, Row> bridges = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Bridge.class));
             if (bridges == null) return null;
             for (String bridgeUUID : bridges.keySet()) {
-                Bridge bridge = (Bridge)bridges.get(bridgeUUID);
-                Set<UUID> portUUIDs = bridge.getPorts();
+                Bridge bridge = ovsdbTable.getTypedRow(node, Bridge.class, bridges.get(bridgeUUID));
+                Set<UUID> portUUIDs = bridge.getPortsColumn().getData();
                 logger.trace("Scanning Bridge {} to identify Port : {} ",bridge, uuid);
                 for (UUID portUUID : portUUIDs) {
                     if (portUUID.toString().equalsIgnoreCase(uuid)) {
@@ -289,4 +408,19 @@ public class TenantNetworkManager {
         return null;
     }
 
+    @Override
+    public void networkDeleted(String id) {
+        if (!enableContainer) return;
+
+        IContainerManager containerManager = (IContainerManager)ServiceHelper.getGlobalInstance(IContainerManager.class, this);
+        if (containerManager == null) {
+            logger.error("ContainerManager is not accessible");
+            return;
+        }
+
+        String networkID = BaseHandler.convertNeutronIDToKey(id);
+        ContainerConfig config = new ContainerConfig();
+        config.setContainer(networkID);
+        containerManager.removeContainer(config);
+    }
 }