Merge "Bug 7848: Allow neutron port create with security disabled."
authorIsaku Yamahata <isaku.yamahata@gmail.com>
Sat, 4 Mar 2017 00:17:32 +0000 (00:17 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sat, 4 Mar 2017 00:17:32 +0000 (00:17 +0000)
27 files changed:
features/production/pom.xml
features/production/src/main/features/features.xml
features/test/pom.xml
integration/test/pom.xml
karaf/pom.xml
model/pom.xml
model/src/main/yang/neutron-extensions.yang
model/src/main/yang/neutron.yang
neutron-hostconfig/ovs/pom.xml
neutron-hostconfig/ovs/src/main/java/org/opendaylight/neutron/hostconfig/ovs/NeutronHostconfigOvsListener.java
neutron-hostconfig/pom.xml
neutron-hostconfig/utils/pom.xml
neutron-hostconfig/utils/src/main/java/org/opendaylight/neutron/hostconfig/utils/NeutronHostconfigUtils.java
neutron-hostconfig/vpp/pom.xml [new file with mode: 0644]
neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/HostconfigUtil.java [new file with mode: 0644]
neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/NeutronHostconfigVppListener.java [new file with mode: 0644]
neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/SocketInfo.java [new file with mode: 0644]
neutron-hostconfig/vpp/src/main/resources/config/org.opendaylight.neutron.hostconfig.vpp [new file with mode: 0644]
neutron-hostconfig/vpp/src/main/resources/org/opendaylight/blueprint/neutron-hostconfig-vpp.xml [new file with mode: 0644]
neutron-hostconfig/vpp/src/test/java/org/opendaylight/neutron/hostconfig/vpp/HostconfigsDataBrokerTest.java [new file with mode: 0644]
neutron-hostconfig/vpp/src/test/java/org/opendaylight/neutron/hostconfig/vpp/NeutronHostconfigVppListenerTest.java [new file with mode: 0644]
neutron-logger/pom.xml
neutron-spi/pom.xml
northbound-api/pom.xml
northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/AbstractNeutronNorthbound.java
parent/pom.xml
transcriber/pom.xml

index 77cac88262232c012c7c755a874146d6ed8ae118..0252c3b0ef61306e411f09d21bdabed23a48e0e0 100644 (file)
@@ -11,6 +11,9 @@
   <artifactId>features-neutron</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>jar</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
       <aaa.version>0.5.0-SNAPSHOT</aaa.version>
       <yangtools.version>1.1.0-SNAPSHOT</yangtools.version>
@@ -18,6 +21,7 @@
       <mdsal.model.version>0.10.0-SNAPSHOT</mdsal.model.version>
       <restconf.version>1.5.0-SNAPSHOT</restconf.version>
       <ovsdb.version>1.4.0-SNAPSHOT</ovsdb.version>
+      <netconf.version>1.2.0-SNAPSHOT</netconf.version>
   </properties>
   <dependencyManagement>
     <dependencies>
@@ -38,8 +42,8 @@
       </dependency>
       <dependency>
         <groupId>org.opendaylight.netconf</groupId>
-        <artifactId>restconf-artifacts</artifactId>
-        <version>${restconf.version}</version>
+        <artifactId>netconf-artifacts</artifactId>
+        <version>${netconf.version}</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
       <type>xml</type>
       <classifier>features</classifier>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.netconf</groupId>
-      <artifactId>features-restconf</artifactId>
-      <version>${restconf.version}</version>
-      <type>xml</type>
-      <classifier>features</classifier>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.aaa</groupId>
       <artifactId>features-aaa-shiro</artifactId>
       <artifactId>utils.mdsal-utils</artifactId>
       <version>${ovsdb.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.netconf</groupId>
+      <artifactId>features-netconf-connector</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>neutron-hostconfig-utils</artifactId>
       <artifactId>neutron-hostconfig-ovs</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>neutron-hostconfig-vpp</artifactId>
+      <version>${project.version}</version>
+    </dependency>
   </dependencies>
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/neutron.git</connection>
index b5a171e3c66ca01da202c8dffb1aee53d89a8328..6a07b733095a986077b608b1a64b9c9e21e87f86 100644 (file)
@@ -9,6 +9,7 @@
    <repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
    <repository>mvn:org.opendaylight.ovsdb/southbound-features/{{VERSION}}/xml/features</repository>
    <repository>mvn:org.opendaylight.netconf/features-restconf/{{VERSION}}/xml/features</repository>
+   <repository>mvn:org.opendaylight.netconf/features-netconf-connector/{{VERSION}}/xml/features</repository>
    <feature name='odl-neutron-service' version='${project.version}' description="OpenDaylight :: Neutron :: API">
     <feature version='${project.version}'>odl-neutron-spi</feature>
     <feature version='${project.version}'>odl-neutron-northbound-api</feature>
     <bundle>mvn:org.opendaylight.neutron/neutron-hostconfig-ovs/{{VERSION}}</bundle>
     <bundle>mvn:org.osgi/org.osgi.core/{{VERSION}}</bundle>
   </feature>
+  <feature name='odl-neutron-hostconfig-vpp' version='${project.version}' description="OpenDaylight :: Neutron :: HostconfigVpp">
+    <feature version='${controller.mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version="${netconf.version}">odl-netconf-clustered-topology</feature>
+    <bundle>mvn:org.opendaylight.neutron/model/{{VERSION}}</bundle>
+    <bundle>mvn:org.opendaylight.neutron/neutron-hostconfig-utils/{{VERSION}}</bundle>
+    <bundle>mvn:org.opendaylight.neutron/neutron-hostconfig-vpp/{{VERSION}}</bundle>
+    <bundle>mvn:org.osgi/org.osgi.core/{{VERSION}}</bundle>
+  </feature>
 </features>
index ca3e7e5da464ce165dc932a34fe3e773b166bf61..9b5defe86aadf023ba220958f408247f26dc1df2 100644 (file)
@@ -11,7 +11,9 @@
   <artifactId>features-neutron-test</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>jar</packaging>
-
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <dependencies>
     <dependency>
       <groupId>org.opendaylight.neutron</groupId>
index f3f26482c6ea58e07d1c4cdff148729d04bd463e..1b44aca805b99116deded73e977699c6cbe08dd1 100644 (file)
@@ -12,7 +12,9 @@
   <artifactId>integration-test</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>jar</packaging>
-
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
     <checkstyle.location>${project.parent.basedir}/src/main/resources</checkstyle.location>
     <sonar.jacoco.itReportPath>target/jacoco-it.exec</sonar.jacoco.itReportPath>
index ad6ef3bd0b69221a222d2fa34f63f2c678ad562c..9085f240a43269b361c8f3f98b4bbaa2180bd4ee 100644 (file)
@@ -16,7 +16,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
   <groupId>org.opendaylight.neutron</groupId>
   <artifactId>neutron-karaf</artifactId>
   <version>0.8.0-SNAPSHOT</version>
-  <name>${project.artifactId}</name>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <prerequisites>
     <maven>3.1.1</maven>
   </prerequisites>
index db7601609535b55e5e12ec6a8234bf0103c9d8b9..08385d55e08aa524f17013f44af9951fef9ef316 100644 (file)
@@ -21,7 +21,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <artifactId>model</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
-
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
     <sonar.jacoco.itReportPath>../target/jacoco-it.exec</sonar.jacoco.itReportPath>
   </properties>
index 2d0b3a0b88106fc6e9908e9a77b16143f022f038..9fea24f9709397145252c9be672f2a7802923aac 100644 (file)
@@ -50,4 +50,48 @@ module neutron-extensions {
             }
         }
     }
+
+    identity service-provider-feature-type-base {
+        description "Base identity for Feature that openstack service provider
+                    supports.";
+    }
+
+    // The list of openstack service provider features.
+    // Maintain the list of features as they are introduced
+    // identity extension-report {
+    //     description "extensions-attributes is populated";
+    //     base service-provider-feature-type-base;
+    // }
+    // identity port-status {
+    //     description "port status is updated";
+    //     base service-provider-feature-type-base;
+    // }
+
+    grouping service-provider-feature-attributes {
+        leaf service-provider-feature {
+            type identityref {
+                base service-provider-feature-type-base;
+            }
+            description "supported features by openstack service provider";
+        }
+        leaf configuration {
+            type string;
+            description "The configuration of this feature";
+        }
+    }
+
+    grouping service-provider-features-attributes {
+        description "List of features that openstack service provider supports.
+                    networking-odl will retrieve this list and configures itself
+                    to use what features.
+                    This is for networking-odl to support multiple versions
+                    ODL and multiple openstack service providers";
+        container features {
+            config false;
+            list feature {
+                key "service-provider-feature";
+                uses service-provider-feature-attributes;
+            }
+        }
+    }
 }
index 2663ab22c98316088d192129376235e2ce4baa8e..1fc44bbbcc06090d4ff75003e0adfac2a4c6f293 100644 (file)
@@ -45,6 +45,7 @@ module neutron {
 
     container neutron {
         uses extensions:extensions-attributes;
+        uses extensions:service-provider-features-attributes;
         uses networks:networks-attributes;
         uses subnets:subnets-attributes;
         uses ports:ports-attributes;
index c8ae8161161980ef6964ebfbf35e3601277393c4..1966ad9be00637e49d656857dc69c67fe5629a86 100644 (file)
@@ -12,6 +12,9 @@
   <artifactId>neutron-hostconfig-ovs</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
     <checkstyle.location>${project.parent.basedir}/src/main/resources</checkstyle.location>
   </properties>
   </dependencies>
   <build>
     <plugins>
+      <plugin>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <configuration>
+          <excludes>org/opendaylight/yang/gen/**,**/yang/**</excludes>
+          <consoleOutput>true</consoleOutput>
+          <propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>check</goal>
+            </goals>
+            <phase>process-sources</phase>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
index c09e88b82d86d242997c5d4a4d407994d22d1d48..f3cbf1b197517ff7d8856edc20884d35f6665b33 100644 (file)
@@ -14,9 +14,9 @@ import com.google.common.collect.Maps;
 import java.util.Collection;
 import java.util.Map;
 import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
-import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
index c1f5009d93dc9c904aa6c86ce5f74ddca07c89b6..4765a80ff731a4de2123d037249c200268a9a8d9 100644 (file)
   <artifactId>neutron-hostconfig</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>pom</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <modules>
     <module>utils</module>
     <module>ovs</module>
+    <module>vpp</module>
   </modules>
   <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
   <build>
@@ -53,4 +57,3 @@
     </site>
   </distributionManagement>
 </project>
-
index 013d4ce67f07b5df5d07450248ae03b7c0d71412..f99bdb6356cdf275be08d7265fff456173cd34e3 100644 (file)
@@ -12,6 +12,9 @@
   <artifactId>neutron-hostconfig-utils</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
     <checkstyle.location>${project.parent.basedir}/src/main/resources</checkstyle.location>
   </properties>
   </dependencies>
   <build>
     <plugins>
+      <plugin>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <configuration>
+          <excludes>org/opendaylight/yang/gen/**,**/yang/**</excludes>
+          <consoleOutput>true</consoleOutput>
+          <propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>check</goal>
+            </goals>
+            <phase>process-sources</phase>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
   -->
   <url>${odl.site.url}/${project.groupId}/${stream}/${project.artifactId}/</url>
 </project>
-
index 44cee4e5958c24d6e3645b00a1359449d2b15b13..fcab6e31ce3d06f26d7302e62a171e7e2827f5b6 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.neutron.hostconfig.utils;
 
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.ExecutionException;
+
 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;
@@ -46,17 +51,19 @@ public class NeutronHostconfigUtils {
                     hostConfigId = createInstanceIdentifier(hostConfig);
                     writeTx.put(LogicalDatastoreType.OPERATIONAL, hostConfigId, hostConfig, true);
                     writeTx.submit().get();
+                    LOG.trace("Hostconfig updated for node {}", hostConfig.getHostId());
                     break;
                 case DELETE:
                     final WriteTransaction delTx = dataBroker.newWriteOnlyTransaction();
                     hostConfigId = createInstanceIdentifier(hostConfig);
                     delTx.delete(LogicalDatastoreType.OPERATIONAL, hostConfigId);
+                    LOG.trace("Hostconfig deleted for node {}", hostConfig.getHostId());
                     delTx.submit().get();
                     break;
                 default:
                     break;
             }
-        } catch (Exception e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.warn("Hostconfig transaction commit failed to DS.", e);
         }
     }
@@ -73,4 +80,16 @@ public class NeutronHostconfigUtils {
         return InstanceIdentifier.create(Neutron.class).child(Hostconfigs.class)
                 .child(Hostconfig.class, hostconfig.getKey());
     }
+
+    /**
+     * Used for parsing model revisions.
+     */
+    public static Date parseDate(final String strDate) {
+        final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            return formatter.parse(strDate);
+        } catch (final ParseException e) {
+            throw new IllegalArgumentException("Date " + strDate + " not valid.", e);
+        }
+    }
 }
diff --git a/neutron-hostconfig/vpp/pom.xml b/neutron-hostconfig/vpp/pom.xml
new file mode 100644 (file)
index 0000000..ed9b6e2
--- /dev/null
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.6.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <groupId>org.opendaylight.neutron</groupId>
+  <artifactId>neutron-hostconfig-vpp</artifactId>
+  <version>0.8.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <properties>
+    <netconf.version>1.2.0-SNAPSHOT</netconf.version>
+    <checkstyle.location>${project.parent.basedir}/src/main/resources</checkstyle.location>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.opendaylight.mdsal.model</groupId>
+        <artifactId>mdsal-model-artifacts</artifactId>
+        <version>0.10.0-SNAPSHOT</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.netconf</groupId>
+        <artifactId>netconf-artifacts</artifactId>
+        <version>${netconf.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.neutron</groupId>
+      <artifactId>neutron-spi</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.neutron</groupId>
+      <artifactId>model</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.neutron</groupId>
+      <artifactId>neutron-hostconfig-utils</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-api</artifactId>
+      <version>0.6.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.netconf</groupId>
+      <artifactId>sal-netconf-connector</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <inherited>true</inherited>
+        <configuration>
+          <compilerArgs>
+            <arg>-Xlint:unchecked</arg>
+            <arg>-Xlint:deprecation</arg>
+          </compilerArgs>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <configuration>
+          <excludes>org/opendaylight/yang/gen/**,**/yang/**</excludes>
+          <consoleOutput>true</consoleOutput>
+          <propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>check</goal>
+            </goals>
+            <phase>process-sources</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+            <Import-Package>*</Import-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/neutron.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/neutron.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/NeutronNorthBound:Main</url>
+  </scm>
+  <distributionManagement>
+    <!-- Site deployment -->
+    <site>
+      <id>opendaylight-site</id>
+      <url>${nexus.site.url}/${project.artifactId}/</url>
+    </site>
+  </distributionManagement>
+
+  <!--
+      Maven Site Configuration
+
+      The following configuration is necessary for maven-site-plugin to
+      correctly identify the correct deployment path for OpenDaylight Maven
+      sites.
+  -->
+  <url>${odl.site.url}/${project.groupId}/${stream}/${project.artifactId}/</url>
+</project>
diff --git a/neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/HostconfigUtil.java b/neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/HostconfigUtil.java
new file mode 100644 (file)
index 0000000..72e0a93
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 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.neutron.hostconfig.vpp;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+
+public class HostconfigUtil {
+
+    static final String L2_HOST_TYPE = "ODL L2";
+    private static final String VHOST_USER = "vhostuser";
+    private static final String VNIC_TYPE = "normal";
+    private static final String HAS_DATAPATH_TYPE_NETDEV = "False";
+    private static final String SUPPORT_VHOST_USER = "True";
+    private static final List<String> SUPPORTED_NET_TYPES = Lists.newArrayList("local", "vlan", "vxlan", "gre");
+
+    public static Map<String, String> createHostconfigsDataFor(NodeId nodeId, SocketInfo socketInfo) {
+        Preconditions.checkNotNull(nodeId);
+        Preconditions.checkNotNull(socketInfo);
+        JsonObject odlL2 = new JsonObject();
+        odlL2.add("allowed_network_types", buildSupportedNetworkTypes());
+        odlL2.add("supported_vnic_types", buildSupportedVnicTypes(socketInfo));
+        Map<String, String> hostConfigs = new HashMap<>();
+        hostConfigs.put(L2_HOST_TYPE, odlL2.toString());
+        return hostConfigs;
+    }
+
+    private static JsonArray buildSupportedNetworkTypes() {
+        JsonArray networkTypes = new JsonArray();
+        SUPPORTED_NET_TYPES.forEach(networkTypes::add);
+        return networkTypes;
+    }
+
+    private static JsonArray buildSupportedVnicTypes(SocketInfo socketInfo) {
+        JsonObject supportedVnicType = new JsonObject();
+        supportedVnicType.addProperty("vnic_type", VNIC_TYPE);
+        supportedVnicType.addProperty("vif_type", VHOST_USER);
+        supportedVnicType.add("vif_details", buildVifDetails(socketInfo));
+        JsonArray supportedVnicTypes = new JsonArray();
+        supportedVnicTypes.add(supportedVnicType);
+        return supportedVnicTypes;
+    }
+
+    private static JsonObject buildVifDetails(SocketInfo socketInfo) {
+        JsonObject vifDetails = new JsonObject();
+        vifDetails.addProperty("has_datapath_type_netdev", HAS_DATAPATH_TYPE_NETDEV);
+        vifDetails.addProperty("support_vhost_user", SUPPORT_VHOST_USER);
+        vifDetails.addProperty("port_prefix", socketInfo.getSocketPrefix());
+        vifDetails.addProperty("vhostuser_socket_dir", socketInfo.getSocketPath());
+        vifDetails.addProperty("vhostuser_mode", socketInfo.getVhostuserMode());
+        vifDetails.addProperty("vhostuser_socket", socketInfo.getVhostUserSocket());
+        return vifDetails;
+    }
+}
diff --git a/neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/NeutronHostconfigVppListener.java b/neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/NeutronHostconfigVppListener.java
new file mode 100644 (file)
index 0000000..42e34a9
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2017 Intel Corporation. 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.neutron.hostconfig.vpp;
+
+import com.google.common.base.Preconditions;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.neutron.hostconfig.utils.NeutronHostconfigUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+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.TopologyId;
+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.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronHostconfigVppListener implements ClusteredDataTreeChangeListener<Node> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NeutronHostconfigVppListener.class);
+    private final DataBroker dataBroker;
+    private final NeutronHostconfigUtils neutronHostconfig;
+    private ListenerRegistration<DataTreeChangeListener<Node>> listenerRegistration;
+    private final ExecutorService executorService = Executors.newFixedThreadPool(1);
+
+    private static final TopologyId TOPOLOGY_NETCONF = new TopologyId("topology-netconf");
+    private static final QName V3PO_CAPABILITY = QName.create(URI.create("urn:opendaylight:params:xml:ns:yang:v3po"),
+            NeutronHostconfigUtils.parseDate("2016-12-14"), "v3po");
+    private static final QName INTERFACES_CAPABILITY =
+            QName.create(URI.create("urn:ietf:params:xml:ns:yang:ietf-interfaces"),
+                    NeutronHostconfigUtils.parseDate("2014-05-08"), "ietf-interfaces");
+    private static final List<QName> REQUIRED_CAPABILITIES = new ArrayList<>();
+    private SocketInfo socketInfo;
+
+    public NeutronHostconfigVppListener(final DataBroker dataBroker, String spath, String sname, String vhostMode) {
+        LOG.info("Initializing Neutron-Hostconfig-Vpp-Listener");
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
+        vhostMode = Preconditions.checkNotNull(vhostMode).toLowerCase();
+        Preconditions.checkArgument(vhostMode.equals("server") || vhostMode.equals("client"),
+                "Supported values for vhostuser-mode are client and server.");
+        this.socketInfo =
+                new SocketInfo(Preconditions.checkNotNull(spath), Preconditions.checkNotNull(sname), vhostMode);
+        this.neutronHostconfig = new NeutronHostconfigUtils(dataBroker);
+        REQUIRED_CAPABILITIES.add(V3PO_CAPABILITY);
+        REQUIRED_CAPABILITIES.add(INTERFACES_CAPABILITY);
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> changes) {
+        LOG.info("onDataTreeChanged: Received Data Tree Changed ...", changes);
+        executorService.submit(() -> {
+            for (DataTreeModification<Node> change : Preconditions.checkNotNull(changes, "Changes may not be null!")) {
+                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+                final DataObjectModification<Node> mod = change.getRootNode();
+                LOG.info("onDataTreeChanged: Received Data Tree Changed Update of Type={} for Key={}",
+                        mod.getModificationType(), key);
+                switch (mod.getModificationType()) {
+                    case SUBTREE_MODIFIED:
+                        if (validateVppNode(mod.getDataAfter())) {
+                            updateHostConfig(mod.getDataAfter(), NeutronHostconfigUtils.Action.UPDATE);
+                        } else {
+                            updateHostConfig(mod.getDataBefore(), NeutronHostconfigUtils.Action.DELETE);
+                        }
+                        break;
+                    case DELETE:
+                        updateHostConfig(mod.getDataBefore(), NeutronHostconfigUtils.Action.DELETE);
+                        break;
+                    case WRITE:
+                        if (validateVppNode(mod.getDataAfter())) {
+                            updateHostConfig(mod.getDataAfter(), NeutronHostconfigUtils.Action.ADD);
+                        }
+                        break;
+                    default:
+                }
+            }
+        });
+    }
+
+    public void init() {
+        LOG.info("Initializing {}", getClass().getSimpleName());
+        DataTreeIdentifier<Node> dataTreeIdentifier = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(NetworkTopology.class)
+                    .child(Topology.class, new TopologyKey(TOPOLOGY_NETCONF))
+                    .child(Node.class)
+                    .build());
+        listenerRegistration =
+                dataBroker.registerDataTreeChangeListener(dataTreeIdentifier, NeutronHostconfigVppListener.this);
+        LOG.info("Registered listener to netconf nodes {}.", dataTreeIdentifier.getRootIdentifier());
+    }
+
+    private void updateHostConfig(Node node, NeutronHostconfigUtils.Action action) {
+        for (Map.Entry<String, String> entry : HostconfigUtil.createHostconfigsDataFor(node.getNodeId(), socketInfo)
+            .entrySet()) {
+            LOG.info("Updating hostconfig for node {}. Action: {}.", node.getKey(), action);
+            neutronHostconfig.updateMdsal(neutronHostconfig.buildHostConfigInfo(node.getNodeId().getValue(),
+                    entry.getKey(), entry.getValue()), action);
+        }
+    }
+
+    private boolean validateVppNode(Node node) {
+        LOG.info("Registering new node {}", node.getNodeId().getValue());
+        NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
+        if (netconfNode == null) {
+            LOG.warn("Node {} is not a netconf device", node.getNodeId().getValue());
+            return false;
+        }
+        NetconfNodeConnectionStatus.ConnectionStatus connectionStatus = netconfNode.getConnectionStatus();
+        switch (connectionStatus) {
+            case Connecting:
+                LOG.info("Connecting device {} ...", node.getNodeId().getValue());
+                break;
+            case Connected:
+                if (netconfNode.getAvailableCapabilities() == null
+                        || netconfNode.getAvailableCapabilities().getAvailableCapability() == null
+                        || netconfNode.getAvailableCapabilities().getAvailableCapability().isEmpty()) {
+                    LOG.warn("Node {} does not contain any capabilities", node.getNodeId().getValue());
+                    break;
+                }
+                if (!capabilityCheck(netconfNode.getAvailableCapabilities().getAvailableCapability())) {
+                    LOG.warn("Node {} does not contain all capabilities required by vpp-renderer",
+                            node.getNodeId().getValue());
+                    break;
+                }
+                LOG.info("VPP node connected {}", node.getNodeId().getValue());
+                return true;
+            case UnableToConnect:
+                LOG.warn("Unable to connect to node {}.", node.getNodeId().getValue());
+                break;
+            default:
+        }
+        return false;
+    }
+
+    private boolean capabilityCheck(final List<AvailableCapability> capabilities) {
+        final List<String> availableCapabilities =
+                capabilities.stream().map(AvailableCapability::getCapability).collect(Collectors.toList());
+        return REQUIRED_CAPABILITIES.stream().map(QName::toString).allMatch(availableCapabilities::contains);
+    }
+
+    public void close() throws Exception {
+        if (listenerRegistration != null) {
+            listenerRegistration.close();
+            LOG.info("HostConfig listener Closed");
+        }
+    }
+}
diff --git a/neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/SocketInfo.java b/neutron-hostconfig/vpp/src/main/java/org/opendaylight/neutron/hostconfig/vpp/SocketInfo.java
new file mode 100644 (file)
index 0000000..5c07fef
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017 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.neutron.hostconfig.vpp;
+
+import com.google.common.base.Preconditions;
+
+public class SocketInfo {
+
+    private final String socketPath;
+    private final String socketPrefix;
+    private final String vhostuserMode;
+    private static final String PORT_ID = "$PORT_ID";
+
+    public SocketInfo(String socketPath, String socketPrefix, String vhostuserMode) {
+        this.socketPath = Preconditions.checkNotNull(socketPath);
+        this.socketPrefix = Preconditions.checkNotNull(socketPrefix);
+        this.vhostuserMode = Preconditions.checkNotNull(vhostuserMode);
+    }
+
+    public String getSocketPath() {
+        return socketPath;
+    }
+
+    public String getSocketPrefix() {
+        return socketPrefix;
+    }
+
+    public String getVhostuserMode() {
+        return vhostuserMode;
+    }
+
+    public String getVhostUserSocket() {
+        return new StringBuilder().append(socketPath).append(socketPrefix).append(PORT_ID).toString();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((socketPath == null) ? 0 : socketPath.hashCode());
+        result = prime * result + ((socketPrefix == null) ? 0 : socketPrefix.hashCode());
+        result = prime * result + ((vhostuserMode == null) ? 0 : vhostuserMode.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;
+        }
+        SocketInfo other = (SocketInfo) obj;
+        if (socketPath == null) {
+            if (other.socketPath != null) {
+                return false;
+            }
+        } else if (!socketPath.equals(other.socketPath)) {
+            return false;
+        }
+        if (socketPrefix == null) {
+            if (other.socketPrefix != null) {
+                return false;
+            }
+        } else if (!socketPrefix.equals(other.socketPrefix)) {
+            return false;
+        }
+        if (vhostuserMode == null) {
+            if (other.vhostuserMode != null) {
+                return false;
+            }
+        } else if (!vhostuserMode.equals(other.vhostuserMode)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/neutron-hostconfig/vpp/src/main/resources/config/org.opendaylight.neutron.hostconfig.vpp b/neutron-hostconfig/vpp/src/main/resources/config/org.opendaylight.neutron.hostconfig.vpp
new file mode 100644 (file)
index 0000000..58ce0c2
--- /dev/null
@@ -0,0 +1,19 @@
+# INITIAL VPP HOSTCONFIG CONFIGURATION
+#
+# Uncomment lines on the bottom of this file to change
+# default values of neutron-hostconfig-vpp bundle config.
+# The file should be placed to karaf_root_dir/etc
+# vhostuser-mode can be set to client or server
+#   server - VPP owns the connection creates a socket
+#            file on hosting machine
+#   client - VPP accepts the connection and looks for
+#            a socket file on hosting machine
+#
+# socket-dir - directory where socket files should be
+#              created or searched
+# socket-prefix - name prefix of created socket files,
+#                 e.g. socket_<port-uuid>
+#
+#vhostuser-mode=server
+#socket-dir=/tmp/
+#socket-prefix = socket_
diff --git a/neutron-hostconfig/vpp/src/main/resources/org/opendaylight/blueprint/neutron-hostconfig-vpp.xml b/neutron-hostconfig/vpp/src/main/resources/org/opendaylight/blueprint/neutron-hostconfig-vpp.xml
new file mode 100644 (file)
index 0000000..e2205fe
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+    xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+    xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
+    odl:use-default-for-reference-types="true">
+
+  <reference id="dataBroker"
+      interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+      odl:type="default" />
+
+  <cm:property-placeholder persistent-id="org.opendaylight.neutron.hostconfig.vpp" update-strategy="none">
+    <cm:default-properties>
+      <cm:property name="vhostuser-mode" value="server"/>
+      <cm:property name="socket-dir" value="/tmp/"/>
+      <cm:property name="socket-prefix" value="socket_"/>
+    </cm:default-properties>
+  </cm:property-placeholder>
+
+  <bean id="neutronHostconfigVpp"
+     class="org.opendaylight.neutron.hostconfig.vpp.NeutronHostconfigVppListener"
+     init-method="init"
+     destroy-method="close">
+    <argument ref="dataBroker"/>
+    <argument value="${socket-dir}"/>
+    <argument value="${socket-prefix}"/>
+    <argument value="${vhostuser-mode}"/>
+  </bean>
+
+</blueprint>
\ No newline at end of file
diff --git a/neutron-hostconfig/vpp/src/test/java/org/opendaylight/neutron/hostconfig/vpp/HostconfigsDataBrokerTest.java b/neutron-hostconfig/vpp/src/test/java/org/opendaylight/neutron/hostconfig/vpp/HostconfigsDataBrokerTest.java
new file mode 100644 (file)
index 0000000..20040f7
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 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.neutron.hostconfig.vpp;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+
+public class HostconfigsDataBrokerTest extends AbstractDataChangeListenerTest {
+
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        Builder<YangModuleInfo> moduleInfoSet = ImmutableSet.<YangModuleInfo>builder();
+        for (Class<?> moduleClass : ImmutableList.<Class<?>>of(
+            NetworkTopology.class, Neutron.class, NetconfNode.class)) {
+            YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(moduleClass);
+            Preconditions.checkNotNull(moduleInfo, "Module Info for %s is not available.", moduleClass);
+            collectYangModuleInfo(moduleInfo, moduleInfoSet);
+        }
+        return moduleInfoSet.build();
+    }
+
+    private static void collectYangModuleInfo(final YangModuleInfo moduleInfo,
+            final Builder<YangModuleInfo> moduleInfoSet) {
+        moduleInfoSet.add(moduleInfo);
+        for (YangModuleInfo dependency : moduleInfo.getImportedModules()) {
+            collectYangModuleInfo(dependency, moduleInfoSet);
+        }
+    }
+}
diff --git a/neutron-hostconfig/vpp/src/test/java/org/opendaylight/neutron/hostconfig/vpp/NeutronHostconfigVppListenerTest.java b/neutron-hostconfig/vpp/src/test/java/org/opendaylight/neutron/hostconfig/vpp/NeutronHostconfigVppListenerTest.java
new file mode 100644 (file)
index 0000000..883d91e
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2017 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.neutron.hostconfig.vpp;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.Hostconfigs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.Hostconfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.HostconfigKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+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.TopologyId;
+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.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NeutronHostconfigVppListenerTest extends HostconfigsDataBrokerTest
+        implements ClusteredDataTreeChangeListener<Hostconfig> {
+
+    private static final String V3PO = "(urn:opendaylight:params:xml:ns:yang:v3po?revision=2016-12-14)v3po";
+    private static final String INTERFACES =
+            "(urn:ietf:params:xml:ns:yang:ietf-interfaces?revision=2014-05-08)ietf-interfaces";
+    private static final NodeId NODE_ID = new NodeId("node1");
+    private static final String SOCKET_PATH = "/tmp";
+    private static final String SOCKET_PREFIX = "socket_";
+    private static final String VHOSTUSER_MODE = "server";
+    private SettableFuture<Integer> sf;
+    private ListenerRegistration<DataTreeChangeListener<Hostconfig>> listenerRegistration;
+    private NeutronHostconfigVppListener neutronHostconfigVppListener;
+
+    @Before
+    public void init() throws InterruptedException, ExecutionException {
+        DataTreeIdentifier<Hostconfig> dataTreeIdentifier = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                hostConfigIid(NODE_ID).firstIdentifierOf(Hostconfigs.class).builder().child(Hostconfig.class).build());
+        listenerRegistration = getDataBroker().registerDataTreeChangeListener(dataTreeIdentifier,
+                NeutronHostconfigVppListenerTest.this);
+        neutronHostconfigVppListener =
+                new NeutronHostconfigVppListener(getDataBroker(), SOCKET_PATH, SOCKET_PREFIX, VHOSTUSER_MODE);
+        neutronHostconfigVppListener.init();
+        sf = SettableFuture.create();
+    }
+
+    @Test
+    public void testPutCreateParentsSuccess() throws Exception {
+        InstanceIdentifier<Node> iid = InstanceIdentifier.builder(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(new TopologyId("topology-netconf")))
+            .child(Node.class, new NodeKey(new NodeId(NODE_ID)))
+            .build();
+        Node node1 = createNetconfNode(NODE_ID, V3PO, INTERFACES);
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.OPERATIONAL, iid, node1, true);
+        writeTx.submit().get();
+        Assert.assertEquals(sf.get(), Integer.valueOf(1));
+        sf = SettableFuture.create();
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+        writeTx.submit().get();
+        Assert.assertEquals(sf.get(), Integer.valueOf(2));
+    }
+
+    private InstanceIdentifier<Hostconfig> hostConfigIid(@Nonnull NodeId nodeId) {
+        return InstanceIdentifier.builder(Neutron.class)
+            .child(Hostconfigs.class)
+            .child(Hostconfig.class, new HostconfigKey(nodeId.getValue(), HostconfigUtil.L2_HOST_TYPE))
+            .build();
+    }
+
+    private Node createNetconfNode(NodeId nodeId, String... capabilities) {
+        List<AvailableCapability> caps = Arrays.asList(capabilities)
+            .stream()
+            .map(name -> new AvailableCapabilityBuilder().setCapability(name).build())
+            .collect(Collectors.toList());
+        NetconfNode netconfNode = new NetconfNodeBuilder().setConnectionStatus(ConnectionStatus.Connected)
+            .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(caps).build())
+            .build();
+        return new NodeBuilder().setNodeId(nodeId).addAugmentation(NetconfNode.class, netconfNode).build();
+    }
+
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<Hostconfig>> hostConfigDtm) {
+        for (DataTreeModification<Hostconfig> dtm : hostConfigDtm) {
+            ModificationType mod = dtm.getRootNode().getModificationType();
+            switch (mod) {
+                case WRITE: {
+                    sf.set(1);
+                    break;
+                }
+                case DELETE: {
+                    sf.set(2);
+                    break;
+                }
+                default:
+            }
+        }
+    }
+
+    @After
+    public void close() throws Exception {
+        if (listenerRegistration != null) {
+            listenerRegistration = null;
+        }
+        if (neutronHostconfigVppListener != null) {
+            neutronHostconfigVppListener.close();
+        }
+    }
+}
index 553b36df77bf3f8870176f233b2dbedced7fe763..bddd5ac4fcc77a45f7c883494e0e529fae4834d7 100644 (file)
@@ -12,6 +12,9 @@
   <artifactId>neutron-logger</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
     <checkstyle.location>${project.parent.basedir}/src/main/resources</checkstyle.location>
   </properties>
index 465e7b9f1b78c5681526e58a1e1ba2d54794669d..53a9812f723dcf613adb6cefe63c425fbbc37726 100644 (file)
@@ -12,6 +12,9 @@
   <artifactId>neutron-spi</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
     <checkstyle.location>${project.parent.basedir}/src/main/resources</checkstyle.location>
   </properties>
index 39bf10e2f080de3726e612afe8aade82255f610c..b8e6c54b8f9f0b004334175209714d3fba722dd8 100644 (file)
@@ -12,6 +12,9 @@
   <artifactId>northbound-api</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
     <checkstyle.location>${project.parent.basedir}/src/main/resources</checkstyle.location>
   </properties>
index 6382b9b23586b0cd1709ad4eba3d66a66113c5a9..cad9f32bff528145225684678e54d441346c59f3 100644 (file)
@@ -73,7 +73,6 @@ public abstract class AbstractNeutronNorthbound<T extends INeutronObject<T>, R e
     }
 
     protected I getNeutronCRUD() {
-        ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
         // cls = I.class
         Class<I> cls = getActualTypeArgument(NEUTRON_CRUD_TYPE_INDEX);
         I neutronCrud = NeutronCRUDInterfaces.fetchINeutronCRUD(cls, (Object) this);
index 265673108a913791e1c420d409d3de8be68597a2..7aabf6797a96e7ebe8380db95b482d34f7eca6c9 100644 (file)
@@ -16,6 +16,9 @@
   <artifactId>project-neutron-parent</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>pom</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
 
   <properties>
     <aaa.version>0.4.0-SNAPSHOT</aaa.version>
index f7a713d614459b6fde1686fcc09691d6f524fb01..311280df3a97199c69c705cd7a082a353bb56e3d 100644 (file)
@@ -11,6 +11,9 @@
   <artifactId>transcriber</artifactId>
   <version>0.8.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
+  <!-- <name> formatting is used by autorelease to parse and notify projects on
+       build failure. Please do not modify this unless you have a good reason. -->
+  <name>ODL :: neutron :: ${project.artifactId}</name>
   <properties>
     <checkstyle.location>${project.parent.basedir}/src/main/resources</checkstyle.location>
     <sonar.jacoco.itReportPath>../target/jacoco-it.exec</sonar.jacoco.itReportPath>