Neutron bundle migration to the new redesigned schema independent Library and Plugin.
[ovsdb.git] / neutron / src / main / java / org / opendaylight / ovsdb / neutron / TenantNetworkManager.java
index 10f8e24847c2d4f16abab15d5312ba87c7531d2d..689143606baaf98f372fe845745a1175682dd4f6 100644 (file)
@@ -1,22 +1,21 @@
 /*
- * Copyright (C) 2013 Red Hat, Inc.
+ * 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
+ * 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;
@@ -31,60 +30,129 @@ 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.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.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<>();
+
+    // The implementation for each of these services is resolved by the OSGi Service Manager
+    private volatile IProviderNetworkManager providerNetworkManager;
 
-    private static final int MAX_VLAN = 4096;
-    public static final String EXTERNAL_ID_VM_ID = "vm-id";
-    public static final String EXTERNAL_ID_INTERFACE_ID = "iface-id";
-    public 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 boolean enableContainer = false;
-    private TenantNetworkManager() {
-        for (int i = 1; i < MAX_VLAN ; i++) {
-            internalVlans.add(i);
-        }
+    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) {
-        int internalVlan = this.assignInternalVlan(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;
+        }
+
+        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) {
@@ -110,28 +178,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);
         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)) {
@@ -142,18 +228,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();
+            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;
                     }
@@ -171,6 +257,7 @@ public class TenantNetworkManager {
         return false;
     }
 
+    @Override
     public String getNetworkIdForSegmentationId (String segmentationId) {
         INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
         List <NeutronNetwork> networks = neutronNetworkService.getAllNetworks();
@@ -187,10 +274,11 @@ public class TenantNetworkManager {
         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);
@@ -205,19 +293,36 @@ 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();
+        Port port = ovsdbTable.createTypedRow(node, Port.class);
         OvsDBSet<BigInteger> tags = new OvsDBSet<BigInteger>();
         tags.add(BigInteger.valueOf(vlan));
         port.setTag(tags);
-        ovsdbTable.updateRow(node, Port.NAME.getName(), null, portUUID, port);
+        ovsdbTable.updateRow(node, port.getSchema().getName(), null, portUUID, port.getRow());
         if (enableContainer) this.addPortToTenantNetworkContainer(node, portUUID, network);
     }
 
@@ -229,12 +334,13 @@ public class TenantNetworkManager {
         }
         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;
@@ -244,16 +350,16 @@ 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<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
                 if (of_ports == null) continue;
-                for (BigInteger of_port : of_ports) {
+                for (Integer of_port : of_ports) {
                     ContainerConfig config = new ContainerConfig();
                     config.setContainer(BaseHandler.convertNeutronIDToKey(network.getID()));
                     logger.debug("Adding Port {} to Container : {}", port.toString(), config.getContainer());
@@ -284,11 +390,11 @@ public class TenantNetworkManager {
     private Bridge getBridgeIdForPort (Node node, String uuid) {
         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)) {
@@ -303,6 +409,7 @@ public class TenantNetworkManager {
         return null;
     }
 
+    @Override
     public void networkDeleted(String id) {
         if (!enableContainer) return;
 
@@ -317,5 +424,4 @@ public class TenantNetworkManager {
         config.setContainer(networkID);
         containerManager.removeContainer(config);
     }
-
 }