Rough musings towards an MD-SAL OVSDB SB 61/14261/20
authorEd Warnicke <eaw@cisco.com>
Mon, 19 Jan 2015 20:17:53 +0000 (13:17 -0700)
committerEd Warnicke <eaw@cisco.com>
Wed, 4 Feb 2015 02:28:43 +0000 (02:28 +0000)
This patch is incomplete, it only manages to accept
ovsdb connections and log them, but its a start.

PatchSet2: Added a simple starting model around tunneling
PatchSet3: Added additional tunnel info
PatchSet4: Added ovsdb.yang model.  Separated tunnel into tunnel.yang
PatchSet5: Renamed tunnel.yang to overlay.yang.  Added topology-type info.
PatchSet6: Added in dummy DataChangeListener for OvsdbNodes.
           Moved mapping functions into a mapping class.
           Handled tracking of OvsdbClients
PatchSet7:  Responded to comments:
            Fixed whitespace
            Fixed parent for aggregator
            Fixed features from odl-southbound- to odl-ovsdb-southbound-
PatchSet10: Added DataChangeListner to listen for new ovsdb-nodes in topology
            and connect to them.
PatchSet15: Response to Colin's comments
PatchSet18: Fixed feature dependencies.  Depends on patch
            https://git.opendaylight.org/gerrit/#/c/14791/ in controller
PatchSet19: Fixed small error in startup order

Change-Id: I13179ec4a1c338ae239f79c0812adf4bc4d6e76d
Signed-off-by: Ed Warnicke <eaw@cisco.com>
23 files changed:
.gitignore
library/pom.xml
library/src/main/java/org/opendaylight/ovsdb/lib/osgi/Activator.java [moved from library/src/main/java/org/opendaylight/ovsdb/lib/Activator.java with 90% similarity]
pom.xml
southbound/pom.xml [new file with mode: 0644]
southbound/southbound-api/pom.xml [new file with mode: 0644]
southbound/southbound-api/src/main/yang/overlay.yang [new file with mode: 0644]
southbound/southbound-api/src/main/yang/ovsdb.yang [new file with mode: 0644]
southbound/southbound-artifacts/pom.xml [new file with mode: 0644]
southbound/southbound-features/pom.xml [new file with mode: 0644]
southbound/southbound-features/src/main/features/features.xml [new file with mode: 0644]
southbound/southbound-impl/pom.xml [new file with mode: 0644]
southbound/southbound-impl/src/main/config/default-config.xml [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OVSDBClientKey.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbNodeDataChangeListener.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundMapper.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/southbound/impl/rev141210/SouthboundImplModule.java [new file with mode: 0644]
southbound/southbound-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/southbound/impl/rev141210/SouthboundImplModuleFactory.java [new file with mode: 0644]
southbound/southbound-impl/src/main/yang/southbound-impl.yang [new file with mode: 0644]
southbound/southbound-karaf/pom.xml [new file with mode: 0644]

index 7326a4a5281fa86c98904f1174133a4fc695a96b..6576f6243cb3b4a5a016470b063553fa9dbe32de 100755 (executable)
@@ -27,3 +27,6 @@ target-ide/
 .vagrant
 .DS_Store
 .checkstyle
+yang-gen-config
+yang-gen-sal
+maven-metadata-local.xml
index 17e7acf92f6224e1595ecbf284ee6f1fc97284fa..97cc63065c57c3a878218aecfb83292806aaf8bf 100755 (executable)
                 javax.net.ssl,
                 *</Import-Package>
             <Embed-Transitive>true</Embed-Transitive>
-            <Bundle-Activator>org.opendaylight.ovsdb.lib.Activator</Bundle-Activator>
+            <Bundle-Activator>org.opendaylight.ovsdb.lib.osgi.Activator</Bundle-Activator>
             <Export-Package>
                 org.opendaylight.ovsdb.lib,
+                org.opendaylight.ovsdb.lib.impl,
                 org.opendaylight.ovsdb.lib.error,
                 org.opendaylight.ovsdb.lib.jsonrpc,
                 org.opendaylight.ovsdb.lib.notation,
similarity index 90%
rename from library/src/main/java/org/opendaylight/ovsdb/lib/Activator.java
rename to library/src/main/java/org/opendaylight/ovsdb/lib/osgi/Activator.java
index 09866068324692f4f406d1eff0d4a3ec93568925..9730bc5f68609d84359fcd9b67e0df22fb79dc23 100644 (file)
@@ -7,10 +7,12 @@
  *
  * Authors : Madhu Venugopal, Brent Salisbury
  */
-package org.opendaylight.ovsdb.lib;
+package org.opendaylight.ovsdb.lib.osgi;
 
 import org.apache.felix.dm.DependencyActivatorBase;
 import org.apache.felix.dm.DependencyManager;
+import org.opendaylight.ovsdb.lib.OvsdbConnection;
+import org.opendaylight.ovsdb.lib.OvsdbConnectionListener;
 import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
diff --git a/pom.xml b/pom.xml
index 4fe29d7b94af67301770b6993d3421be7134c912..468633cd6fb8f244dde27f8a33a7b38316b1a529 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,7 @@
     <module>openstack/net-virt</module>
     <module>openstack/net-virt-providers</module>
     <module>ovs-sfc</module>
+    <module>southbound</module>
     <!-- Integration Tests -->
     <module>integrationtest</module>
     <!-- Config Files -->
diff --git a/southbound/pom.xml b/southbound/pom.xml
new file mode 100644 (file)
index 0000000..ad2247f
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+Copyright (c) 2014 Cisco Systems 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 INTERNAL
+-->\r
+<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">\r
+  <groupId>org.opendaylight.ovsdb</groupId>\r
+  <parent>\r
+    <artifactId>commons</artifactId>\r
+    <groupId>org.opendaylight.ovsdb</groupId>\r
+    <version>1.1.0-SNAPSHOT</version>\r
+    <relativePath>../commons/parent</relativePath>\r
+  </parent>\r
+  <artifactId>southbound-aggregator</artifactId>\r
+  <version>1.1.0-SNAPSHOT</version>\r
+  <name>${project.artifactId}</name>\r
+  <packaging>pom</packaging>\r
+  <modelVersion>4.0.0</modelVersion>\r
+  <prerequisites>\r
+    <maven>3.1.1</maven>\r
+  </prerequisites>\r
+  <modules>\r
+    <module>southbound-api</module>\r
+    <module>southbound-impl</module>\r
+    <module>southbound-karaf</module>\r
+    <module>southbound-features</module>\r
+    <module>southbound-artifacts</module>\r
+  </modules>\r
+</project>\r
diff --git a/southbound/southbound-api/pom.xml b/southbound/southbound-api/pom.xml
new file mode 100644 (file)
index 0000000..08574cb
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2014 Cisco Systems, Inc. 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
+-->
+<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">
+  <parent>
+    <groupId>org.opendaylight.yangtools</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>0.7.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.ovsdb</groupId>
+  <artifactId>southbound-api</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-topology</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>yang-ext</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-inet-types</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-yang-types-20130715</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/southbound/southbound-api/src/main/yang/overlay.yang b/southbound/southbound-api/src/main/yang/overlay.yang
new file mode 100644 (file)
index 0000000..5c32a55
--- /dev/null
@@ -0,0 +1,128 @@
+module overlay {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:overlay";
+    prefix "southbound";
+
+    import network-topology {prefix "topo"; revision-date "2013-10-21"; }
+    import yang-ext { prefix "ext"; }
+    import ietf-inet-types { prefix inet; }
+
+    revision "2015-01-05" {
+        description "Initial revision of overlay model";
+    }
+
+
+    identity tunnel-type-base {
+        description "Base identity for all tunnel-types";
+    }
+
+    identity tunnel-type-vxlan {
+        description "Tunnel type for vxlan tunnels";
+        base tunnel-type-base;
+    }
+
+    identity tunnel-type-vxlan-gpe {
+        description "Tunnel type for vxlan tunnels";
+        base tunnel-type-base;
+    }
+
+    identity tunnel-type-gre {
+        description "Tunnel type for gre tunnels";
+        base tunnel-type-base;
+    }
+
+    grouping ip-port-locator {
+      description
+        "Data plane-locator: IP address and L4 port";
+      leaf ip {
+        type inet:ip-address;
+        description "Data-plane IP address";
+      }
+      leaf port {
+        type inet:port-number;
+        description "Data-plane port number";
+      }
+    }
+
+    grouping tunnel-type-attributes {
+        description "Common leaf for expressing tunnel-type";
+        leaf tunnel-type {
+            type identityref {
+                base tunnel-type-base;
+            }
+        }
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:node" {
+        description "Augment topology node with a list of supported-tunnel-entries";
+        ext:augment-identifier "supported-tunnels";
+        list supported-tunnel-entry {
+            uses tunnel-type-attributes;
+        }
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:node/supported-tunnel-entry" {
+        description "Augment additional tunnel-parameters into the supported-tunnel-entry list";
+        ext:augment-identifier "supported-tunnels-parameters";
+        when "./tunnel-type = 'tunnel-type-gre' or
+            ./tunnel-type = 'tunnel-type-vxlan' or 
+            ./tunnel-type = 'tunnel-type-vxlan-gre'" {
+            description "Augment tunnel types that use ip-port as tunnnel parameters";
+        }
+        list ip-port-locator-entry {
+            uses ip-port-locator;
+        }
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:link" {
+        description "Type of link tunnel";
+        ext:augment-identifier "tunnel";
+        uses tunnel-type-attributes;
+    }
+    augment "/topo:network-topology/topo:topology/topo:link/topo:source" {
+        description "ip-port-locator for the source end of a tunnel link";
+        ext:augment-identifier "tunnel-source-parameters";
+        when "../tunnel-type = 'tunnel-type-gre' or
+            ../tunnel-type = 'tunnel-type-vxlan' or 
+            ../tunnel-type = 'tunnel-type-vxlan-gre'" {
+            description "Augment tunnel types that use ip-port as tunnnel parameters";
+        }
+        uses ip-port-locator;
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:link/topo:destination" {
+        description "ip-port-locator for the source end of a tunnel link";
+        ext:augment-identifier "tunnel-dest-parameters";
+        when "../tunnel-type = 'tunnel-type-gre' or
+            ../tunnel-type = 'tunnel-type-vxlan' or 
+            ../tunnel-type = 'tunnel-type-vxlan-gre'" {
+            description "Augment tunnel types that use ip-port as tunnnel parameters";
+        }
+        uses ip-port-locator;
+    }
+
+    identity topology-type-base {
+        description "Base identity for all topology-types";
+    }
+
+    identity topology-type-overlay {
+        description "Marker to indicate a topology is of type overlay";
+        base topology-type-base;
+    }
+
+    grouping topology-type-attributes {
+        description "Attributed to indicate the topology type";
+        leaf topology-type {
+            type identityref {
+                base topology-type-base;
+            }
+        }
+    }
+
+    augment "/topo:network-topology/topo:topology/" {
+        description "Mark type of topology";
+        ext:augment-identifier "topology-type";
+        uses topology-type-attributes; 
+    }
+}
diff --git a/southbound/southbound-api/src/main/yang/ovsdb.yang b/southbound/southbound-api/src/main/yang/ovsdb.yang
new file mode 100644 (file)
index 0000000..0cf664e
--- /dev/null
@@ -0,0 +1,51 @@
+module ovsdb {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:ovsdb";
+    prefix "southbound";
+
+    import network-topology {prefix "topo"; revision-date "2013-10-21"; }
+    import yang-ext { prefix "ext"; }
+    import ietf-inet-types { prefix inet; }
+    import overlay { prefix overlay; }
+    import ietf-yang-types { prefix yang; revision-date "2013-07-15";}
+
+    revision "2015-01-05" {
+        description "Initial revision of southbound model";
+    }
+    grouping ovsdb-bridge-attributes {
+        leaf bridge-uuid {
+            description "The unique identifier of the bridge";
+            type yang:uuid;
+        }
+
+        leaf bridge-name {
+            description "The name of the bridge";
+            type string;
+        }
+
+        leaf managed-by {
+            description "The OVSDB which this bridge belongs to";
+            type topo:node-ref;
+        }
+    }
+
+    grouping ovsdb-node-attributes {
+        uses overlay:ip-port-locator;
+
+        leaf-list managed-node-entry {
+            type topo:node-ref;
+        }
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:node" {
+        description "Augmentation for bridge nodes managed by ovsdb";
+        ext:augment-identifier "ovsdb-managed-node-augmentation";
+        uses ovsdb-bridge-attributes;
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:node" {
+        description "Augment topology node for an ovsdb node";
+        ext:augment-identifier "ovsdb-node-augmentation";
+        uses ovsdb-node-attributes;
+    }
+}
\ No newline at end of file
diff --git a/southbound/southbound-artifacts/pom.xml b/southbound/southbound-artifacts/pom.xml
new file mode 100644 (file)
index 0000000..ed62fc5
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2014 Cisco Systems, Inc. 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
+-->
+
+<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>
+  <groupId>org.opendaylight.ovsdb</groupId>
+  <artifactId>southbound-artifacts</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>southbound-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>southbound-impl</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>southbound-features</artifactId>
+        <version>${project.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+</project>
diff --git a/southbound/southbound-features/pom.xml b/southbound/southbound-features/pom.xml
new file mode 100644 (file)
index 0000000..b2c060e
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2014 Cisco Systems, Inc. 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 INTERNAL
+-->
+<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">
+  <parent>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <artifactId>features-parent</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+  </parent>
+  <groupId>org.opendaylight.ovsdb</groupId>
+  <artifactId>southbound-features</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <mdsal.version>1.2.0-SNAPSHOT</mdsal.version>
+    <yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <!-- project specific dependencies -->
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yangtools-artifacts</artifactId>
+        <version>${yangtools.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-artifacts</artifactId>
+        <version>${mdsal.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-yangtools</artifactId>
+      <type>xml</type>
+      <classifier>features</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-mdsal</artifactId>
+      <type>xml</type>
+      <classifier>features</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-restconf</artifactId>
+      <type>xml</type>
+      <classifier>features</classifier>
+    </dependency>
+    <dependency>
+      <groupId>${groupId}</groupId>
+      <artifactId>southbound-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${groupId}</groupId>
+      <artifactId>southbound-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/southbound/southbound-features/src/main/features/features.xml b/southbound/southbound-features/src/main/features/features.xml
new file mode 100644 (file)
index 0000000..ccb9ee5
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Necessary TODO: Put your copyright statement here
+
+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
+-->
+<features name="odl-ovsdb-southbound-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/features-restconf/${mdsal.version}/xml/features</repository>
+  <feature name='odl-ovsdb-southbound-api' version='${project.version}' description='OpenDaylight :: southbound :: api '>
+    <feature version='${yangtools.version}'>odl-yangtools-models</feature>
+    <bundle>mvn:org.opendaylight.ovsdb/southbound-api/${project.version}</bundle>
+  </feature>
+  <feature name='odl-ovsdb-southbound-impl' version='${project.version}' description='OpenDaylight :: southbound :: impl '>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version='${project.version}'>odl-ovsdb-southbound-api</feature>
+    <bundle>mvn:org.opendaylight.ovsdb/southbound-impl/${project.version}</bundle>
+    <bundle>mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
+    <bundle>mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
+    <bundle>mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
+    <bundle>mvn:com.fasterxml.jackson.datatype/jackson-datatype-json-org/${jackson.version}</bundle>
+    <bundle>wrap:mvn:org.json/json/${org.json.version}</bundle>
+    <bundle>mvn:com.google.code.gson/gson/${gson.version}</bundle>
+    <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-codec/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-codec-http/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-common/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-handler/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
+    <configfile finalname="southbound-impl-default-config.xml">mvn:org.opendaylight.ovsdb/southbound-impl/${project.version}/xml/config</configfile>
+  </feature>
+  <feature name='odl-ovsdb-southbound-impl-rest' version='${project.version}' description='OpenDaylight :: southbound :: impl :: REST '>
+    <feature version="${project.version}">odl-ovsdb-southbound-impl</feature>
+    <feature version="${mdsal.version}">odl-restconf</feature>
+  </feature>
+  <feature name='odl-ovsdb-southbound-impl-ui' version='${project.version}' description='OpenDaylight :: southbound :: impl :: UI'>
+    <feature version="${project.version}">odl-ovsdb-southbound-impl-rest</feature>
+    <feature version="${mdsal.version}">odl-mdsal-apidocs</feature>
+    <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
+  </feature>
+
+</features>
diff --git a/southbound/southbound-impl/pom.xml b/southbound/southbound-impl/pom.xml
new file mode 100644 (file)
index 0000000..545d22c
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2014 Cisco Systems, Inc. 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
+-->
+<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">
+
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.3.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.ovsdb</groupId>
+  <artifactId>southbound-impl</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>southbound-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>library</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Private-Package>!org.opendaylight.ovsdb.lib.osgi,org.opendaylight.ovsdb.lib.*</Private-Package>
+            <Export-Package>org.opendaylight.ovsdb.southbound.*,org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.southbound.impl.rev141210</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/southbound/southbound-impl/src/main/config/default-config.xml b/southbound/southbound-impl/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..f42a56d
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2014 Cisco Systems, Inc. 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
+-->
+<snapshot>
+  <required-capabilities>
+  </required-capabilities>
+  <configuration>
+
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:southbound:impl">prefix:southbound-impl</type>
+          <name>southbound-default</name>
+          <broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <name>binding-osgi-broker</name>
+          </broker>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+</snapshot>
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OVSDBClientKey.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OVSDBClientKey.java
new file mode 100644 (file)
index 0000000..6c5de10
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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
+ */
+package org.opendaylight.ovsdb.southbound;
+
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.IpPortLocator;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class OVSDBClientKey {
+    /*
+     * This class is immutable.  If you are in anyway changing its fields after
+     * creation, your are doing it wrong :)
+     */
+    private IpAddress ipaddress;
+    private PortNumber port;
+
+    OVSDBClientKey(IpPortLocator locator) {
+        ipaddress = locator.getIp();
+        port = locator.getPort();
+    }
+
+    OVSDBClientKey(OvsdbClient client) {
+        ipaddress = SouthboundMapper.createIpAddress(client.getConnectionInfo().getRemoteAddress());
+        port = new PortNumber(client.getConnectionInfo().getRemotePort());
+    }
+
+    public IpAddress getIp() {
+        return ipaddress;
+    }
+
+    public PortNumber getPort() {
+        return port;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result
+                + ((ipaddress == null) ? 0 : ipaddress.hashCode());
+        result = prime * result + ((port == null) ? 0 : port.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        OVSDBClientKey other = (OVSDBClientKey) obj;
+        if (ipaddress == null) {
+            if (other.ipaddress != null)
+                return false;
+        } else if (!ipaddress.equals(other.ipaddress))
+            return false;
+        if (port == null) {
+            if (other.port != null)
+                return false;
+        } else if (!port.equals(other.port))
+            return false;
+        return true;
+    }
+
+    InstanceIdentifier<Node> toInstanceIndentifier() {
+        return SouthboundMapper.createInstanceIdentifier(ipaddress,port);
+    }
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java
new file mode 100644 (file)
index 0000000..6cd8c13
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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
+ */
+package org.opendaylight.ovsdb.southbound;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.OvsdbConnectionListener;
+import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoCloseable {
+    Map<OVSDBClientKey,OvsdbClient> clients = new ConcurrentHashMap<OVSDBClientKey,OvsdbClient>();
+    private static final Logger LOG = LoggerFactory.getLogger(OvsdbConnectionManager.class);
+
+    DataBroker db;
+
+    public OvsdbConnectionManager(DataBroker db) {
+        this.db = db;
+    }
+
+    @Override
+    public void connected(OvsdbClient client) {
+        LOG.info("OVSDB Connection from {}:{}",client.getConnectionInfo().getRemoteAddress(),
+                client.getConnectionInfo().getRemotePort());
+        OVSDBClientKey key = new OVSDBClientKey(client);
+        clients.put(key, client);
+        WriteTransaction transaction = db.newWriteOnlyTransaction();
+        transaction.put(LogicalDatastoreType.OPERATIONAL, key.toInstanceIndentifier(),
+                SouthboundMapper.createNode(client));
+        // TODO - Check the future and retry if needed
+        transaction.submit();
+    }
+
+    @Override
+    public void disconnected(OvsdbClient client) {
+        LOG.info("OVSDB Disconnect from {}:{}",client.getConnectionInfo().getRemoteAddress(),
+                client.getConnectionInfo().getRemotePort());
+        OVSDBClientKey key = new OVSDBClientKey(client);
+        WriteTransaction transaction = db.newWriteOnlyTransaction();
+        transaction.delete(LogicalDatastoreType.OPERATIONAL, key.toInstanceIndentifier());
+        // TODO - Check the future and retry if needed
+        transaction.submit();
+        clients.remove(key);
+    }
+
+    public OvsdbClient connect(OvsdbNodeAugmentation ovsdbNode) throws UnknownHostException {
+        // TODO handle case where we already have a connection
+        // TODO use transaction chains to handle ordering issues between disconnected and connected when writing to the operational store
+        InetAddress ip = SouthboundMapper.createInetAddress(ovsdbNode.getIp());
+        OvsdbClient client = OvsdbConnectionService.getService().connect(ip, ovsdbNode.getPort().getValue().intValue());
+        OVSDBClientKey key = new OVSDBClientKey(client);
+        clients.put(key, client);
+        connected(client); // For connections from the controller to the ovs instance, the library doesn't call this method for us
+        return client;
+    }
+
+    @Override
+    public void close() throws Exception {
+        for(OvsdbClient client: clients.values()) {
+            client.disconnect();
+        }
+    }
+
+
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbNodeDataChangeListener.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbNodeDataChangeListener.java
new file mode 100644 (file)
index 0000000..dd6612c
--- /dev/null
@@ -0,0 +1,64 @@
+package org.opendaylight.ovsdb.southbound;
+
+import java.net.UnknownHostException;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OvsdbNodeDataChangeListener implements DataChangeListener, AutoCloseable {
+
+    private ListenerRegistration<DataChangeListener> registration;
+    private OvsdbConnectionManager cm;
+    private static final Logger LOG = LoggerFactory.getLogger(OvsdbNodeDataChangeListener.class);
+
+    OvsdbNodeDataChangeListener(DataBroker db, OvsdbConnectionManager cm) {
+        LOG.info("Registering OvsdbNodeDataChangeListener");
+        this.cm = cm;
+        InstanceIdentifier<OvsdbNodeAugmentation> path = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class)
+                .augmentation(OvsdbNodeAugmentation.class);
+        registration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, this, DataChangeScope.ONE);
+
+    }
+
+    @Override
+    public void onDataChanged(
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+       LOG.info("Received change to ovsdbNode: {}",changes);
+       for( Entry<InstanceIdentifier<?>, DataObject> created : changes.getCreatedData().entrySet()) {
+           // TODO validate we have the correct kind of InstanceIdentifier
+           if(created.getValue() instanceof OvsdbNodeAugmentation) {
+               try {
+                cm.connect((OvsdbNodeAugmentation)created.getValue());
+            } catch (UnknownHostException e) {
+                LOG.warn("Failed to connect to ovsdbNode", e);
+            }
+           }
+       }
+       // TODO handle case of updates to ovsdb nodes as needed
+
+       // TODO handle case of delete of ovsdb nodes as needed
+    }
+
+    @Override
+    public void close() throws Exception {
+        registration.close();
+    }
+
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundConstants.java
new file mode 100644 (file)
index 0000000..6982c9d
--- /dev/null
@@ -0,0 +1,10 @@
+package org.opendaylight.ovsdb.southbound;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+
+public class SouthboundConstants {
+    public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
+    public static final String OVSDB_URI_PREFIX = "ovsdb";
+    public static final Integer DEFAULT_OVSDB_PORT = 6640;
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundMapper.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundMapper.java
new file mode 100644 (file)
index 0000000..ec272c4
--- /dev/null
@@ -0,0 +1,103 @@
+package org.opendaylight.ovsdb.southbound;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SouthboundMapper {
+    private static final Logger LOG = LoggerFactory.getLogger(SouthboundMapper.class);
+
+    public static Node createNode(OvsdbClient client) {
+        NodeBuilder nodeBuilder = new NodeBuilder();
+        nodeBuilder.setNodeId(createNodeId(client.getConnectionInfo()));
+        nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(client));
+        return nodeBuilder.build();
+    }
+
+    public static OvsdbNodeAugmentation createOvsdbAugmentation(OvsdbClient client) {
+        OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
+        ovsdbNodeBuilder.setIp(createIpAddress(client.getConnectionInfo().getRemoteAddress()));
+        ovsdbNodeBuilder.setPort(new PortNumber(client.getConnectionInfo().getRemotePort()));
+        return ovsdbNodeBuilder.build();
+    }
+
+    public static IpAddress createIpAddress(InetAddress address) {
+        IpAddress ip = null;
+        if(address instanceof Inet4Address) {
+            ip = createIpAddress((Inet4Address)address);
+        } else if (address instanceof Inet6Address) {
+            ip = createIpAddress((Inet6Address)address);
+        }
+        return ip;
+    }
+
+    public static IpAddress createIpAddress(Inet4Address address) {
+        Ipv4Address ipv4 = new Ipv4Address(address.getHostAddress());
+        return new IpAddress(ipv4);
+    }
+
+    public static IpAddress createIpAddress(Inet6Address address) {
+        Ipv6Address ipv6 = new Ipv6Address(address.getHostAddress());
+        return new IpAddress(ipv6);
+    }
+
+    public static InstanceIdentifier<Node> createInstanceIdentifier(OvsdbClient client) {
+        return createInstanceIdentifier(createIpAddress(client.getConnectionInfo().getRemoteAddress()),
+                new PortNumber(client.getConnectionInfo().getRemotePort()));
+    }
+    public static InstanceIdentifier<Node> createInstanceIdentifier(IpAddress ip, PortNumber port) {
+        InstanceIdentifier<Node> path = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class,createNodeKey(ip,port));
+        LOG.info("Created ovsdb path: {}",path);
+        return path;
+    }
+
+    public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
+        return new NodeKey(createNodeId(ip,port));
+    }
+
+    public static NodeId createNodeId(OvsdbConnectionInfo connectionInfo) {
+        return createNodeId(createIpAddress(connectionInfo.getRemoteAddress()),
+                new PortNumber(connectionInfo.getRemotePort()));
+    }
+    public static NodeId createNodeId(IpAddress ip, PortNumber port) {
+        String uriString = SouthboundConstants.OVSDB_URI_PREFIX + ":/" + new String(ip.getValue()) +
+                   ":" + port.getValue();
+        Uri uri = new Uri(uriString);
+        NodeId nodeId = new NodeId(uri);
+        return nodeId;
+    }
+
+    public static InetAddress createInetAddress(IpAddress ip) throws UnknownHostException {
+        if(ip.getIpv4Address() != null) {
+            return InetAddress.getByName(ip.getIpv4Address().getValue());
+        } else if(ip.getIpv6Address() != null) {
+            return InetAddress.getByName(ip.getIpv6Address().getValue());
+        } else {
+            throw new UnknownHostException("IP Address has no value");
+        }
+    }
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java
new file mode 100644 (file)
index 0000000..c6a5579
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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
+ */
+package org.opendaylight.ovsdb.southbound;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.ovsdb.lib.OvsdbConnection;
+import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+
+public class SouthboundProvider implements BindingAwareProvider, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SouthboundProvider.class);
+    private DataBroker db;
+    private OvsdbConnectionManager cm;
+    private OvsdbNodeDataChangeListener ovsdbNodeListener;
+
+
+
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        LOG.info("SouthboundProvider Session Initiated");
+        db = session.getSALService(DataBroker.class);
+        cm = new OvsdbConnectionManager(db);
+        ovsdbNodeListener = new OvsdbNodeDataChangeListener(db, cm);
+        initializeOvsdbTopology(LogicalDatastoreType.OPERATIONAL);
+        initializeOvsdbTopology(LogicalDatastoreType.CONFIGURATION);
+        OvsdbConnection ovsdbConnection = new OvsdbConnectionService();
+        ovsdbConnection.registerConnectionListener(cm);
+        ovsdbConnection.startOvsdbManager(SouthboundConstants.DEFAULT_OVSDB_PORT);
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("SouthboundProvider Closed");
+        cm.close();
+        ovsdbNodeListener.close();
+    }
+
+    private void initializeOvsdbTopology(LogicalDatastoreType type) {
+        InstanceIdentifier<Topology> path = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
+        ReadWriteTransaction transaction = db.newReadWriteTransaction();
+        initializeTopology(transaction,type);
+        CheckedFuture<Optional<Topology>, ReadFailedException> ovsdbTp = transaction.read(type, path);
+        try {
+            if(!ovsdbTp.get().isPresent()) {
+                TopologyBuilder tpb = new TopologyBuilder();
+                tpb.setTopologyId(SouthboundConstants.OVSDB_TOPOLOGY_ID);
+                transaction.put(type, path, tpb.build());
+                transaction.submit();
+            } else {
+                transaction.cancel();
+            }
+        } catch (Exception e) {
+            LOG.error("Error initializing ovsdb topology {}",e);
+        }
+    }
+
+    private void initializeTopology(ReadWriteTransaction t, LogicalDatastoreType type) {
+        InstanceIdentifier<NetworkTopology> path = InstanceIdentifier
+                .create(NetworkTopology.class);
+       CheckedFuture<Optional<NetworkTopology>, ReadFailedException> tp = t.read(type,path);
+       try {
+           if(!tp.get().isPresent()) {
+               NetworkTopologyBuilder ntb = new NetworkTopologyBuilder();
+               t.put(type,path,ntb.build());
+           }
+       } catch (Exception e) {
+           LOG.error("Error initializing ovsdb topology {}",e);
+       }
+    }
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/southbound/impl/rev141210/SouthboundImplModule.java b/southbound/southbound-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/southbound/impl/rev141210/SouthboundImplModule.java
new file mode 100644 (file)
index 0000000..482455d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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
+ */
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.southbound.impl.rev141210;
+
+import org.opendaylight.ovsdb.southbound.SouthboundProvider;
+
+public class SouthboundImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.southbound.impl.rev141210.AbstractSouthboundImplModule {
+    public SouthboundImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public SouthboundImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.southbound.impl.rev141210.SouthboundImplModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        SouthboundProvider provider = new SouthboundProvider();
+        getBrokerDependency().registerProvider(provider);
+        return provider;
+    }
+
+}
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/southbound/impl/rev141210/SouthboundImplModuleFactory.java b/southbound/southbound-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/southbound/impl/rev141210/SouthboundImplModuleFactory.java
new file mode 100644 (file)
index 0000000..1af1601
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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
+ */
+/*
+* Generated file
+*
+* Generated from: yang module name: southbound yang module local name: southbound
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Jan 02 13:49:24 CST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.southbound.impl.rev141210;
+public class SouthboundImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.southbound.impl.rev141210.AbstractSouthboundImplModuleFactory {
+
+}
diff --git a/southbound/southbound-impl/src/main/yang/southbound-impl.yang b/southbound/southbound-impl/src/main/yang/southbound-impl.yang
new file mode 100644 (file)
index 0000000..d1e9c8c
--- /dev/null
@@ -0,0 +1,35 @@
+module southbound-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:southbound:impl";
+    prefix "southbound-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+    description
+        "Service definition for southbound project";
+
+    revision "2014-12-10" {
+        description
+            "Initial revision";
+    }
+
+    identity southbound-impl {
+        base config:module-type;
+        config:java-name-prefix SouthboundImpl;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case southbound-impl {
+            when "/config:modules/config:module/config:type = 'southbound-impl'";
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/southbound/southbound-karaf/pom.xml b/southbound/southbound-karaf/pom.xml
new file mode 100644 (file)
index 0000000..9c260d8
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2014 Cisco Systems 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 INTERNAL
+-->
+<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">
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>karaf-parent</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.ovsdb</groupId>
+  <artifactId>southbound-karaf</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <karaf.localFeature>odl-ovsdb-southbound-impl-ui</karaf.localFeature>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>southbound-artifacts</artifactId>
+        <version>${project.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <!-- scope is compile so all features (there is only one) are installed
+      into startup.properties and the feature repo itself is not installed -->
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>framework</artifactId>
+      <type>kar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>southbound-features</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+</project>