Skeleton Event handlers for the Neutron integration with OVSDB. 25/3025/1
authorMadhu Venugopal <mavenugo@gmail.com>
Fri, 22 Nov 2013 06:34:45 +0000 (22:34 -0800)
committerMadhu Venugopal <mavenugo@gmail.com>
Fri, 22 Nov 2013 06:34:45 +0000 (22:34 -0800)
As per the design, the ovsdb.neutron plugin will be a bunch of event handlers which
converts the events into corresponding OVSDB/OF programming. The 5 events of interests are
1. NeutronNetwork events
2. NeutronPort events
3. NeutronSubnet events
4. Southbound Node Connectivity events
5. Southbound Port table update events
This push just brings in the barebones of these event handlers.

Change-Id: Ic94429672303bee29de0c245558669e9462c0a01
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
neutron/pom.xml [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/Activator.java [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/BaseHandler.java [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/NetworkHandler.java [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/PortHandler.java [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/SouthboundHandler.java [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/SubnetHandler.java [new file with mode: 0644]
ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/InventoryService.java
ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/OVSDBInventoryListener.java [new file with mode: 0644]

diff --git a/neutron/pom.xml b/neutron/pom.xml
new file mode 100644 (file)
index 0000000..0712010
--- /dev/null
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.ovsdb</groupId>
+        <artifactId>commons.ovsdb</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../commons/parent/</relativePath>
+    </parent>
+
+    <artifactId>ovsdb.neutron</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <scm>
+      <connection>scm:git:ssh://git.opendaylight.org:29418/ovsdb.git</connection>
+      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/ovsdt.git</developerConnection>
+      <url>https://wiki.opendaylight.org/view/OVSDB_Integration:Main</url>
+      <tag>HEAD</tag>
+    </scm>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>
+              org.opendaylight.controller.networkconfig.neutron,
+              org.opendaylight.controller.containermanager,
+              org.opendaylight.controller.sal.core,
+              org.opendaylight.controller.sal.utils,
+              org.opendaylight.ovsdb.plugin,
+              org.opendaylight.ovsdb.lib.table.internal,
+              org.apache.felix.dm,
+              org.slf4j,
+              org.osgi.framework
+            </Import-Package>
+            <Bundle-Activator>
+              org.opendaylight.ovsdb.neutron.Activator
+            </Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <version>0.4.1-SNAPSHOT</version>
+      <artifactId>networkconfig.neutron</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.ovsdb</groupId>
+      <artifactId>ovsdb</artifactId>
+      <version>0.5.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/Activator.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/Activator.java
new file mode 100644 (file)
index 0000000..147257c
--- /dev/null
@@ -0,0 +1,111 @@
+
+package org.opendaylight.ovsdb.neutron;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.containermanager.IContainerManager;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
+import org.opendaylight.ovsdb.plugin.OVSDBInventoryListener;
+
+/**
+ * OSGi bundle activator for the OVSDB Neutron Interface.
+ */
+public class Activator extends ComponentActivatorAbstractBase {
+    /**
+     * Function called when the activator starts just after some
+     * initializations are done by the
+     * ComponentActivatorAbstractBase.
+     */
+    @Override
+    public void init() {
+    }
+
+    /**
+     * Function called when the activator stops just before the
+     * cleanup done by ComponentActivatorAbstractBase.
+     *
+     */
+    @Override
+    public void destroy() {
+    }
+
+    /**
+     * Function that is used to communicate to dependency manager the
+     * list of known implementations for services inside a container.
+     *
+     * @return An array containing all the CLASS objects that will be
+     * instantiated in order to get an fully working implementation
+     * Object
+     */
+    @Override
+    public Object[] getImplementations() {
+        Object[] res = {NetworkHandler.class,
+                        SubnetHandler.class,
+                        PortHandler.class,
+                        SouthboundHandler.class};
+        return res;
+    }
+
+    /**
+     * Function that is called when configuration of the dependencies
+     * is required.
+     *
+     * @param c dependency manager Component object, used for
+     * configuring the dependencies exported and imported
+     * @param imp Implementation class that is being configured,
+     * needed as long as the same routine can configure multiple
+     * implementations
+     * @param containerName The containerName being configured, this allow
+     * also optional per-container different behavior if needed, usually
+     * should not be the case though.
+     */
+    @Override
+    public void configureInstance(Component c, Object imp,
+                                  String containerName) {
+        if (imp.equals(NetworkHandler.class)) {
+            c.setInterface(INeutronNetworkAware.class.getName(), null);
+        }
+
+        if (imp.equals(SubnetHandler.class)) {
+            c.setInterface(INeutronSubnetAware.class.getName(), null);
+        }
+
+        if (imp.equals(PortHandler.class)) {
+            c.setInterface(INeutronPortAware.class.getName(), null);
+        }
+
+        if (imp.equals(SouthboundHandler.class)) {
+            c.setInterface(OVSDBInventoryListener.class.getName(), null);
+        }
+
+        c.add(createServiceDependency().
+                setService(OVSDBConfigService.class).
+                setCallbacks("setOVSDBConfigService", "unsetOVSDBConfigService").
+                setRequired(true));
+
+        // Create service dependencies.
+        c.add(createServiceDependency().
+              setService(IContainerManager.class).
+              setCallbacks("setContainerManager", "unsetContainerManager").
+              setRequired(true));
+
+        c.add(createServiceDependency().
+                setService(INeutronNetworkCRUD.class).
+                setCallbacks("setNeutronNetworkCRUD", "unsetNeutronNetworkCRUD").
+                setRequired(true));
+        c.add(createServiceDependency().
+                setService(INeutronSubnetCRUD.class).
+                setCallbacks("setNeutronSubnetCRUD", "unsetNeutronSubnetCRUD").
+                setRequired(true));
+        c.add(createServiceDependency().
+                setService(INeutronPortCRUD.class).
+                setCallbacks("setNeutronPortCRUD", "unsetNeutronPortCRUD").
+                setRequired(true));
+    }
+}
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/BaseHandler.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/BaseHandler.java
new file mode 100644 (file)
index 0000000..c9eb771
--- /dev/null
@@ -0,0 +1,334 @@
+package org.opendaylight.ovsdb.neutron;
+
+import java.net.HttpURLConnection;
+import java.util.UUID;
+
+import org.opendaylight.controller.containermanager.IContainerManager;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base utility functions used by neutron handlers.
+ */
+public class BaseHandler {
+
+    /**
+     * Logger instance.
+     */
+    static final Logger logger = LoggerFactory.getLogger(BaseHandler.class);
+
+    /**
+     * Neutron UUID identifier length.
+     */
+    private static final int UUID_LEN = 36;
+
+    /**
+     * Tenant id length when keystone identifier is used in neutron.
+     */
+    private static final int KEYSTONE_ID_LEN = 32;
+
+    /**
+     * UUID version number position.
+     */
+    private static final int UUID_VERSION_POS = 12;
+
+    /**
+     * UUID time-low field byte length in hex.
+     */
+    private static final int UUID_TIME_LOW = 8;
+
+    /**
+     * UUID time-mid field byte length in hex.
+     */
+    private static final int UUID_TIME_MID = 4;
+
+    /**
+     * UUID time-high and version field byte length in hex.
+     */
+    private static final int UUID_TIME_HIGH_VERSION = 4;
+
+    /**
+     * UUID clock sequence field byte length in hex.
+     */
+    private static final int UUID_CLOCK_SEQ = 4;
+
+    /**
+     * UUID node field byte length in hex.
+     */
+    private static final int UUID_NODE = 12;
+
+    /**
+     * UUID time field byte length in hex.
+     */
+    private static final int UUID_TIME_LEN = (UUID_TIME_LOW +
+            UUID_TIME_MID + UUID_TIME_HIGH_VERSION);
+
+    /**
+     * Convert failure status returned by the  manager into
+     * neutron API service errors.
+     *
+     * @param status  manager status
+     * @return  An error to be returned to neutron API service.
+     */
+    protected static final int getException(Status status) {
+        int result = HttpURLConnection.HTTP_INTERNAL_ERROR;
+
+        assert !status.isSuccess();
+
+        StatusCode code = status.getCode();
+        logger.debug(" Execption code - {}, description - {}",
+                code, status.getDescription());
+
+        if (code == StatusCode.BADREQUEST) {
+            result = HttpURLConnection.HTTP_BAD_REQUEST;
+        } else if (code == StatusCode.CONFLICT) {
+            result = HttpURLConnection.HTTP_CONFLICT;
+        } else if (code == StatusCode.NOTACCEPTABLE) {
+            result = HttpURLConnection.HTTP_NOT_ACCEPTABLE;
+        } else if (code == StatusCode.NOTFOUND) {
+            result = HttpURLConnection.HTTP_NOT_FOUND;
+        } else {
+            result = HttpURLConnection.HTTP_INTERNAL_ERROR;
+        }
+
+        return result;
+    }
+
+    /**
+     * Verify the validity of neutron object identifiers.
+     *
+     * @param id neutron object id.
+     * @return {@code true} neutron identifier is valid.
+     *         {@code false} neutron identifier is invalid.
+     */
+    protected static final boolean isValidNeutronID(String id) {
+        if (id == null) {
+            return false;
+        }
+        boolean isValid = false;
+        logger.trace("id - {}, length - {} ", id, id.length());
+        /**
+         * check the string length
+         * if length is 36 its a uuid do uuid validation
+         * if length is 32 it can be tenant id form keystone
+         * if its less than 32  can be valid  ID
+         */
+        if (id.length() == UUID_LEN) {
+            try {
+                UUID fromUUID = UUID.fromString(id);
+                String toUUID = fromUUID.toString();
+                isValid = toUUID.equalsIgnoreCase(id);
+            } catch(IllegalArgumentException e) {
+                logger.error(" IllegalArgumentExecption for id - {} ", id);
+                isValid = false;
+            }
+        } else if ((id.length() > 0) && (id.length() <= KEYSTONE_ID_LEN)) {
+            isValid = true;
+        } else {
+            isValid = false;
+        }
+        return isValid;
+    }
+
+    /**
+     * Convert UUID to  key syntax.
+     *
+     * @param id neutron object UUID.
+     * @return key in compliance to  object key.
+     */
+    private static String convertUUIDToKey(String id) {
+
+        String key = null;
+        if (id == null) {
+            return key;
+        }
+        logger.trace("id - {}, length - {} ", id, id.length());
+        /**
+         *  ID must be less than 32 bytes,
+         * Shorten UUID string length from 36 to 31 as follows:
+         * delete UUID Version and hyphen (see RFC4122) field in the UUID
+         */
+        try {
+            StringBuilder tKey = new StringBuilder();
+            // remove all the '-'
+            for (String retkey: id.split("-")) {
+                tKey.append(retkey);
+            }
+            // remove the version byte
+            tKey.deleteCharAt(UUID_VERSION_POS);
+            key = tKey.toString();
+        } catch(IllegalArgumentException ile) {
+            logger.error(" Invalid UUID - {} ", id);
+            key = null;
+        }
+        return key;
+    }
+
+    /**
+     * Convert string id to  key syntax.
+     *
+     * @param id neutron object id.
+     * @return key in compliance to  object key.
+     */
+    private static String convertKeystoneIDToKey(String id) {
+        String key = null;
+        if (id == null) {
+            return key;
+        }
+
+        /**
+         * tenant ID if given from openstack keystone does not follow the
+         * generic UUID syntax, convert the ID to UUID format for validation
+         * and reconvert it to  key
+         */
+
+        logger.trace(" id - {}, length - {} ", id, id.length());
+        try {
+            StringBuilder tKey = new StringBuilder();
+            String tmpStr = id.substring(0, UUID_TIME_LOW);
+            tKey.append(tmpStr);
+            tKey.append("-");
+            tmpStr = id.substring(UUID_TIME_LOW,
+                    (UUID_TIME_LOW + UUID_TIME_MID));
+            tKey.append(tmpStr);
+            tKey.append("-");
+            tmpStr = id.substring((UUID_TIME_LOW + UUID_TIME_MID),
+                    UUID_TIME_LEN);
+            tKey.append(tmpStr);
+            tKey.append("-");
+            tmpStr = id.substring(UUID_TIME_LEN,
+                    (UUID_TIME_LEN + UUID_CLOCK_SEQ));
+            tKey.append(tmpStr);
+            tKey.append("-");
+            tmpStr = id.substring((UUID_TIME_LEN + UUID_CLOCK_SEQ),
+                    (UUID_TIME_LEN + UUID_CLOCK_SEQ + UUID_NODE));
+            tKey.append(tmpStr);
+
+            tmpStr = tKey.toString();
+            UUID fromUUID = UUID.fromString(tmpStr);
+            String toUUID = fromUUID.toString();
+            if (toUUID.equalsIgnoreCase(tmpStr)) {
+                key = convertUUIDToKey(tmpStr);
+            }
+        } catch(IndexOutOfBoundsException ibe) {
+            logger.error(" Execption! Invalid UUID - {} ", id);
+            key = null;
+        } catch (IllegalArgumentException iae) {
+            logger.error(" Execption! Invalid object ID - {} ", id);
+            key = null;
+        }
+        return key;
+    }
+
+    /**
+     * Convert neutron object id to  key syntax.
+     *
+     * @param neutronID neutron object id.
+     * @return key in compliance to  object key.
+     */
+    protected static final String convertNeutronIDToKey(String neutronID) {
+        String key = null;
+        if (neutronID == null) {
+            return key;
+        }
+
+        logger.trace(" neutronID - {}, length - {} ",
+                neutronID, neutronID.length());
+        if (!isValidNeutronID(neutronID)) {
+            return key;
+        }
+
+        if (neutronID.length() == UUID_LEN) {
+            key = convertUUIDToKey(neutronID);
+        } else if (neutronID.length() == KEYSTONE_ID_LEN) {
+            key = convertKeystoneIDToKey(neutronID);
+        } else {
+            key = neutronID;
+        }
+        return key;
+    }
+
+    protected IContainerManager containerManager;
+
+    public IContainerManager getContainerManager() {
+        return containerManager;
+    }
+
+    public void unsetContainerManager(IContainerManager s) {
+        if (s == this.containerManager) {
+            this.containerManager = null;
+        }
+    }
+
+    public void setContainerManager(IContainerManager s) {
+        this.containerManager = s;
+    }
+
+    protected OVSDBConfigService ovsdbConfigService;
+
+    public OVSDBConfigService getOVSDBConfigService() {
+        return ovsdbConfigService;
+    }
+
+    public void unsetOVSDBConfigService(OVSDBConfigService s) {
+        if (s == this.ovsdbConfigService) {
+            this.ovsdbConfigService = null;
+        }
+    }
+
+    public void setOVSDBConfigService(OVSDBConfigService s) {
+        this.ovsdbConfigService = s;
+    }
+
+
+    protected INeutronPortCRUD neutronPortCache;
+    public INeutronPortCRUD getNeutronPortCRUD() {
+        return neutronPortCache;
+    }
+
+    public void unsetNeutronPortCRUD(INeutronPortCRUD s) {
+        if (s == this.neutronPortCache) {
+            this.neutronPortCache = null;
+        }
+    }
+
+    public void setNeutronPortCRUD(INeutronPortCRUD s) {
+        this.neutronPortCache = s;
+    }
+
+    protected INeutronSubnetCRUD neutronSubnetCache;
+    public INeutronSubnetCRUD getNeutronSubnetCRUD() {
+        return neutronSubnetCache;
+    }
+
+    public void unsetNeutronSubnetCRUD(INeutronSubnetCRUD s) {
+        if (s == this.neutronSubnetCache) {
+            this.neutronSubnetCache = null;
+        }
+    }
+
+    public void setNeutronSubnetCRUD(INeutronSubnetCRUD s) {
+        this.neutronSubnetCache = s;
+    }
+
+    protected INeutronNetworkCRUD neutronNetworkCache;
+    public INeutronNetworkCRUD getNeutronNetworkCRUD() {
+        return neutronNetworkCache;
+    }
+
+    public void unsetNeutronNetworkCRUD(INeutronNetworkCRUD s) {
+        if (s == this.neutronNetworkCache) {
+            this.neutronNetworkCache = null;
+        }
+    }
+
+    public void setNeutronNetworkCRUD(INeutronNetworkCRUD s) {
+        this.neutronNetworkCache = s;
+    }
+}
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/NetworkHandler.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/NetworkHandler.java
new file mode 100644 (file)
index 0000000..efd9397
--- /dev/null
@@ -0,0 +1,130 @@
+package org.opendaylight.ovsdb.neutron;
+
+import java.net.HttpURLConnection;
+import java.util.List;
+
+import org.opendaylight.controller.containermanager.ContainerConfig;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Handle requests for Neutron Network.
+ */
+public class NetworkHandler extends BaseHandler
+                            implements INeutronNetworkAware {
+    /**
+     * Logger instance.
+     */
+    static final Logger logger = LoggerFactory.getLogger(NetworkHandler.class);
+
+    /**
+     * Invoked when a network creation is requested
+     * to indicate if the specified network can be created.
+     *
+     * @param network  An instance of proposed new Neutron Network object.
+     * @return A HTTP status code to the creation request.
+     */
+    @Override
+    public int canCreateNetwork(NeutronNetwork network) {
+        if (network.isShared()) {
+            logger.error(" Network shared attribute not supported ");
+            return HttpURLConnection.HTTP_NOT_ACCEPTABLE;
+        }
+
+        String networkID = convertNeutronIDToKey(network.getID());
+
+        List<String> containers = containerManager.getContainerNames();
+        if (containers.contains(networkID)) {
+            logger.debug("Container with name {} exists", networkID);
+            return HttpURLConnection.HTTP_CONFLICT;
+        }
+
+        return HttpURLConnection.HTTP_CREATED;
+    }
+
+    /**
+     * Invoked to take action after a network has been created.
+     *
+     * @param network  An instance of new Neutron Network object.
+     */
+    @Override
+    public void neutronNetworkCreated(NeutronNetwork network) {
+        int result = HttpURLConnection.HTTP_BAD_REQUEST;
+
+        result = canCreateNetwork(network);
+        if (result != HttpURLConnection.HTTP_CREATED) {
+            logger.debug("Network creation failed {} ", result);
+            return;
+        }
+
+        logger.debug("Neutron Network Creation : {}", network.toString());
+        String networkID = convertNeutronIDToKey(network.getID());
+
+        ContainerConfig config = new ContainerConfig();
+        config.setContainer(networkID);
+        Status status = containerManager.addContainer(config);
+        logger.debug("Network Creation Status : {}", status.toString());
+    }
+
+    /**
+     * Invoked when a network update is requested
+     * to indicate if the specified network can be changed
+     * using the specified delta.
+     *
+     * @param delta     Updates to the network object using patch semantics.
+     * @param original  An instance of the Neutron Network object
+     *                  to be updated.
+     * @return A HTTP status code to the update request.
+     */
+    @Override
+    public int canUpdateNetwork(NeutronNetwork delta,
+                                NeutronNetwork original) {
+        return HttpURLConnection.HTTP_OK;
+    }
+
+    /**
+     * Invoked to take action after a network has been updated.
+     *
+     * @param network An instance of modified Neutron Network object.
+     */
+    @Override
+    public void neutronNetworkUpdated(NeutronNetwork network) {
+        return;
+    }
+
+    /**
+     * Invoked when a network deletion is requested
+     * to indicate if the specified network can be deleted.
+     *
+     * @param network  An instance of the Neutron Network object to be deleted.
+     * @return A HTTP status code to the deletion request.
+     */
+    @Override
+    public int canDeleteNetwork(NeutronNetwork network) {
+        return HttpURLConnection.HTTP_OK;
+    }
+
+    /**
+     * Invoked to take action after a network has been deleted.
+     *
+     * @param network  An instance of deleted Neutron Network object.
+     */
+    @Override
+    public void neutronNetworkDeleted(NeutronNetwork network) {
+
+        int result = canDeleteNetwork(network);
+        if  (result != HttpURLConnection.HTTP_OK) {
+            logger.error(" deleteNetwork validation failed for result - {} ",
+                    result);
+            return;
+        }
+        String networkID = convertNeutronIDToKey(network.getID());
+
+        ContainerConfig config = new ContainerConfig();
+        config.setContainer(networkID);
+        containerManager.removeContainer(config);
+    }
+}
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/PortHandler.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/PortHandler.java
new file mode 100644 (file)
index 0000000..3724368
--- /dev/null
@@ -0,0 +1,165 @@
+package org.opendaylight.ovsdb.neutron;
+
+import java.net.HttpURLConnection;
+
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Handle requests for Neutron Port.
+ */
+public class PortHandler extends BaseHandler
+                         implements INeutronPortAware {
+
+    /**
+     * Logger instance.
+     */
+    static final Logger logger = LoggerFactory.getLogger(PortHandler.class);
+
+    /**
+     * Invoked when a port creation is requested
+     * to indicate if the specified port can be created.
+     *
+     * @param port     An instance of proposed new Port Port object.
+     * @return A HTTP status code to the creation request.
+     */
+    @Override
+    public int canCreatePort(NeutronPort port) {
+        return HttpURLConnection.HTTP_CREATED;
+    }
+
+    /**
+     * Invoked to take action after a port has been created.
+     *
+     * @param port An instance of new Neutron Port object.
+     */
+    @Override
+    public void neutronPortCreated(NeutronPort port) {
+
+        int result = canCreatePort(port);
+        if (result != HttpURLConnection.HTTP_CREATED) {
+            logger.error(" Port create validation failed result - {} ", result);
+            return;
+        }
+
+        String tenantID = convertNeutronIDToKey(port.getTenantID());
+        String networkID = convertNeutronIDToKey(port.getNetworkUUID());
+        String portID = convertNeutronIDToKey(port.getID());
+        String portDesc = port.getName();
+        Boolean portAdminState = port.getAdminStateUp();
+/*
+ * Add the Corresponding OF NodeConnector to the Container
+ *
+        ContainerConfig config = new ContainerConfig();
+        config.setContainer(networkID);
+        logger.debug("Adding Port {} to Container : {}", port.toString(), config.getContainer());
+        List<String> ncList = new ArrayList<String>();
+        ncList.add("OVS|"+ portID +"@OVS|"+networkID);
+        config.addNodeConnectors(ncList);
+        Status status = containerManager.addContainerEntry(networkID, ncList);
+
+        if (!status.isSuccess()) {
+            logger.error(" Port-ADD failed for tenant-id - {}," +
+                    " bridge-id - {}, port-id - {}, result - {} ",
+                    tenantID, networkID, portID, result);
+        } else {
+            logger.debug(" Port-ADD successful for tenant-id - {}," +
+                    " bridge-id - {}, port-id - {}, result - {} ",
+                    tenantID, networkID, portID, result);
+        }
+*/
+        logger.debug(" Port-ADD successful for tenant-id - {}," +
+                " network-id - {}, port-id - {}, result - {} ",
+                tenantID, networkID, portID, result);
+    }
+
+    /**
+     * Invoked when a port update is requested
+     * to indicate if the specified port can be changed
+     * using the specified delta.
+     *
+     * @param delta    Updates to the port object using patch semantics.
+     * @param original An instance of the Neutron Port object
+     *                  to be updated.
+     * @return A HTTP status code to the update request.
+     */
+    @Override
+    public int canUpdatePort(NeutronPort delta,
+                             NeutronPort original) {
+        int result = HttpURLConnection.HTTP_OK;
+        /**
+         * To basic validation of the request
+         */
+
+        if ((original == null) || (delta == null)) {
+            logger.error("port object not specified");
+            return HttpURLConnection.HTTP_BAD_REQUEST;
+        }
+        return result;
+    }
+
+    /**
+     * Invoked to take action after a port has been updated.
+     *
+     * @param port An instance of modified Neutron Port object.
+     */
+    @Override
+    public void neutronPortUpdated(NeutronPort port) {
+    }
+
+    /**
+     * Invoked when a port deletion is requested
+     * to indicate if the specified port can be deleted.
+     *
+     * @param port     An instance of the Neutron Port object to be deleted.
+     * @return A HTTP status code to the deletion request.
+     */
+    @Override
+    public int canDeletePort(NeutronPort port) {
+        int result = HttpURLConnection.HTTP_OK;
+        return result;
+    }
+
+    /**
+     * Invoked to take action after a port has been deleted.
+     *
+     * @param port  An instance of deleted Neutron Port object.
+     */
+    @Override
+    public void neutronPortDeleted(NeutronPort port) {
+
+        int result = canDeletePort(port);
+        if  (result != HttpURLConnection.HTTP_OK) {
+            logger.error(" deletePort validation failed - result {} ", result);
+            return;
+        }
+
+        String tenantID = convertNeutronIDToKey(port.getTenantID());
+        String networkID = convertNeutronIDToKey(port.getNetworkUUID());
+        String portID = convertNeutronIDToKey(port.getID());
+/*
+ * Delete the Corresponding OF NodeConnector from the Container
+ *
+        ContainerConfig config = new ContainerConfig();
+        config.setContainer(networkID);
+        List<String> ncList = new ArrayList<String>();
+        ncList.add("OVS|"+ portID +"@OVS|"+networkID);
+        config.addNodeConnectors(ncList);
+        Status status = containerManager.removeContainerEntry(networkID, ncList);
+        if (!status.isSuccess()) {
+            logger.error(" PORT delete failed for tenant-id - {}, " +
+                    " bridge-id - {}, port-id - {}, result - {} ",
+                    tenantID, networkID, portID, status);
+        } else {
+            logger.error(" PORT delete successful for tenant-id - {}, " +
+                    " bridge-id - {}, port-id - {}, result - {} ",
+                    tenantID, networkID, portID, status);
+        }
+*/
+        logger.debug(" PORT delete successful for tenant-id - {}, " +
+                     " network-id - {}, port-id - {}", tenantID, networkID, portID);
+
+    }
+}
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/SouthboundHandler.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/SouthboundHandler.java
new file mode 100644 (file)
index 0000000..e7543f7
--- /dev/null
@@ -0,0 +1,31 @@
+package org.opendaylight.ovsdb.neutron;
+
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.ovsdb.lib.table.internal.Table;
+import org.opendaylight.ovsdb.plugin.OVSDBInventoryListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SouthboundHandler extends BaseHandler implements OVSDBInventoryListener {
+    static final Logger logger = LoggerFactory.getLogger(SouthboundHandler.class);
+    @Override
+    public void nodeAdded(Node node) {
+        logger.debug("NODE ADDED {}", node);
+    }
+
+    @Override
+    public void nodeRemoved(Node node) {
+        logger.debug("NODE REMOVED {}", node);
+    }
+
+    @Override
+    public void rowAdded(Node node, String tableName, Table<?> row) {
+        logger.debug("ROW ADDED {} , {}", node, row);
+
+    }
+
+    @Override
+    public void rowRemoved(Node node, String tableName, Table<?> row) {
+        logger.debug("ROW REMOVED {} , {}", node, row);
+    }
+}
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/SubnetHandler.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/SubnetHandler.java
new file mode 100644 (file)
index 0000000..ec5c850
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.ovsdb.neutron;
+
+import java.net.HttpURLConnection;
+
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SubnetHandler extends BaseHandler implements INeutronSubnetAware {
+    static final Logger logger = LoggerFactory.getLogger(SubnetHandler.class);
+    @Override
+    public int canCreateSubnet(NeutronSubnet subnet) {
+        return HttpURLConnection.HTTP_CREATED;
+    }
+
+    @Override
+    public void neutronSubnetCreated(NeutronSubnet subnet) {
+        logger.debug("Neutron Subnet Creation : {}", subnet.toString());
+    }
+
+    @Override
+    public int canUpdateSubnet(NeutronSubnet delta, NeutronSubnet original) {
+        return HttpURLConnection.HTTP_CREATED;
+    }
+
+    @Override
+    public void neutronSubnetUpdated(NeutronSubnet subnet) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public int canDeleteSubnet(NeutronSubnet subnet) {
+        // TODO Auto-generated method stub
+        return HttpURLConnection.HTTP_CREATED;
+    }
+
+    @Override
+    public void neutronSubnetDeleted(NeutronSubnet subnet) {
+        // TODO Auto-generated method stub
+
+    }
+}
index f92eeed5225deb815eb8fdbe20f01596ee014eaa..37dbd5a756e5213040c24be7512c3cc5ce86a337 100755 (executable)
@@ -167,6 +167,7 @@ public class InventoryService implements IPluginInInventoryService, InventorySer
             dbCache.put(n, db);
         }
 
+        OVSDBInventoryListener inventoryListener = (OVSDBInventoryListener)ServiceHelper.getGlobalInstance(OVSDBInventoryListener.class, this);
         Set<Table.Name> available = tableUpdates.availableUpdates();
         for (Table.Name name : available) {
             TableUpdate tableUpdate = tableUpdates.getUpdate(name);
@@ -185,7 +186,13 @@ public class InventoryService implements IPluginInInventoryService, InventorySer
                         // Updating the Openflow bridge name via the SAL Description update.
                         updateOFBridgeName(n, (Bridge)newRow);
                     }
+                    if ((oldRow == null) && (inventoryListener != null)) {
+                        inventoryListener.rowAdded(n, name.getName(), newRow);
+                    }
                 } else if (oldRow != null) {
+                    if (inventoryListener != null) {
+                        inventoryListener.rowRemoved(n, name.getName(), oldRow);
+                    }
                     db.removeRow(name.getName(), uuid);
                 }
             }
@@ -237,6 +244,10 @@ public class InventoryService implements IPluginInInventoryService, InventorySer
     @Override
     public void addNode(Node node, Set<Property> props) {
         addNodeProperty(node, UpdateType.ADDED, props);
+        OVSDBInventoryListener inventoryListener = (OVSDBInventoryListener)ServiceHelper.getGlobalInstance(OVSDBInventoryListener.class, this);
+        if (inventoryListener != null) {
+            inventoryListener.nodeAdded(node);
+        }
     }
 
     @Override
@@ -271,6 +282,11 @@ public class InventoryService implements IPluginInInventoryService, InventorySer
 
     @Override
     public void removeNode(Node node) {
+        OVSDBInventoryListener inventoryListener = (OVSDBInventoryListener)ServiceHelper.getGlobalInstance(OVSDBInventoryListener.class, this);
+        if (inventoryListener != null) {
+            inventoryListener.nodeRemoved(node);
+        }
+
         for (IPluginOutInventoryService service : pluginOutInventoryServices) {
             service.updateNode(node, UpdateType.REMOVED, null);
         }
diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/OVSDBInventoryListener.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/OVSDBInventoryListener.java
new file mode 100644 (file)
index 0000000..c0d964e
--- /dev/null
@@ -0,0 +1,11 @@
+package org.opendaylight.ovsdb.plugin;
+
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.ovsdb.lib.table.internal.Table;
+
+public interface OVSDBInventoryListener {
+    public void nodeAdded(Node node);
+    public void nodeRemoved(Node node);
+    public void rowAdded(Node node, String tableName, Table<?> row);
+    public void rowRemoved(Node node, String tableName, Table<?> row);
+}