.vagrant
.DS_Store
.checkstyle
+yang-gen-config
+yang-gen-sal
+maven-metadata-local.xml
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,
*
* 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;
<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 -->
--- /dev/null
+<?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
--- /dev/null
+<?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>
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+ }
+
+
+}
--- /dev/null
+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();
+ }
+
+}
--- /dev/null
+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;
+}
--- /dev/null
+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");
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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 {
+
+}
--- /dev/null
+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;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<?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>