</parent>
<artifactId>features-adsal</artifactId>
<version>${sal.version}</version>
- <packaging>pom</packaging>
+ <packaging>jar</packaging>
<name>Features :: AD-SAL Features</name>
<description>AD-SAL Features POM</description>
<properties>
<dependencies>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>base-features</artifactId>
- <version>${project.parent.version}</version>
+ <artifactId>features-base</artifactId>
<classifier>features</classifier>
<type>xml</type>
- <scope>runtime</scope>
+ </dependency>
+ <!-- test to validate features.xml -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>features-test</artifactId>
+ </dependency>
+ <!-- dependency for opendaylight-karaf-empty for use by testing -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-empty</artifactId>
+ <version>1.4.2-SNAPSHOT</version>
+ <type>zip</type>
+ </dependency>
+ <!-- Bundle dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>dummy-console</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.connection</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.connection.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.networkconfiguration</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.networkconfiguration.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services-implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.stub</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>logging.bridge</artifactId>
</dependency>
</dependencies>
<build>
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+ <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+ <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
+ </systemPropertyVariables>
+ <dependenciesToScan>
+ <dependency>org.opendaylight.yangtools:features-test</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features name="adsal-${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.controller/features-base/${commons.opendaylight.version}/xml/features</repository>
<feature name="odl-adsal-all" description="OpenDaylight AD-SAL All Features" version="${sal.version}">
<feature version="${sal.version}">odl-adsal-core</feature>
<feature version="${sal.networkconfiguration.version}">odl-adsal-networkconfiguration</feature>
<feature version="${configuration.version}">odl-adsal-configuration</feature>
</feature>
<feature name="odl-adsal-core" description="OpenDaylight :: AD-SAL :: Core" version="${sal.version}">
- <feature>base-felix-dm</feature>
- <feature>base-dummy-console</feature>
+ <feature>odl-base-felix-dm</feature>
+ <feature>odl-base-dummy-console</feature>
<feature version="${project.version}">odl-adsal-thirdparty</feature>
- <bundle start="true" start-level="35">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
+ <bundle start="true">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
<!-- <bundle>mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version}</bundle> -->
<bundle>mvn:org.opendaylight.controller/sal/${sal.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal.implementation/${sal.implementation.version}</bundle>
</feature>
<feature name="odl-adsal-networkconfiguration" description="OpenDaylight :: AD-SAL :: Network Configuration" version="${sal.networkconfiguration.version}">
+ <feature>odl-adsal-core</feature>
<bundle>mvn:org.opendaylight.controller/sal.networkconfiguration/${sal.networkconfiguration.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal.networkconfiguration.implementation/${sal.networkconfiguration.version}</bundle>
</feature>
</feature>
<feature name="odl-adsal-clustering" description="OpenDaylight :: AD-SAL :: Clustering" version="${clustering.services.version}">
<feature>transaction</feature>
- <feature>base-felix-dm</feature>
- <feature>base-eclipselink-persistence</feature>
+ <feature>odl-base-felix-dm</feature>
+ <feature>odl-base-eclipselink-persistence</feature>
<feature version="${sal.version}">odl-adsal-core</feature>
<bundle>mvn:org.opendaylight.controller/clustering.services/${clustering.services.version}</bundle>
<bundle>mvn:org.opendaylight.controller/clustering.services-implementation/${clustering.services_implementation.version}</bundle>
<version>1.4.2-SNAPSHOT</version>
<relativePath>../../opendaylight/commons/opendaylight</relativePath>
</parent>
- <artifactId>base-features</artifactId>
- <packaging>pom</packaging>
+ <artifactId>features-base</artifactId>
+ <packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>Base Features POM</description>
<properties>
<features.file>features.xml</features.file>
</properties>
+ <dependencies>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>dummy-console</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>karaf-tomcat-security</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>ganymed</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-json-org</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-base</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-jaxb-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ </dependency>
+ <!-- Jersey for JAXRS -->
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-net</groupId>
+ <artifactId>commons-net</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>eclipselink</groupId>
+ <artifactId>javax.persistence</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>eclipselink</groupId>
+ <artifactId>javax.resource</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>javax.servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>javax.servlet.jsp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.command</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.shell</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.cm</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.console</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.ds</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.launcher</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi.services</artifactId>
+ </dependency>
+ <!-- Gemini Web -->
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.gemini.web.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.gemini.web.extender</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.gemini.web.tomcat</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.kernel.equinox.extensions</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.math</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.osgi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.osgi.manifest</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.parser.manifest</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-buffer</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-codec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-codec-http</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-common</artifactId>
+ </dependency>
+
+ <!--Netty-->
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-handler</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-transport</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.activation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.annotation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.ejb</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.el</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.mail.glassfish</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.servlet.jsp.jstl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.servlet.jsp.jstl.impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.xml.rpc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.catalina</artifactId>
+ <version>7.0.53.v201406061610</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.catalina.ha</artifactId>
+ <version>7.0.53.v201406070630</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.catalina.tribes</artifactId>
+ <version>7.0.53.v201406070630</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.coyote</artifactId>
+ <version>7.0.53.v201406070630</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.el</artifactId>
+ <version>7.0.53.v201406060720</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.jasper</artifactId>
+ <version>7.0.53.v201406070630</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.juli.extras</artifactId>
+ <version>7.0.53.v201406060720</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.tomcat.api</artifactId>
+ <version>7.0.53.v201406060720</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.tomcat.util</artifactId>
+ <version>7.0.53.v201406070630</version>
+ </dependency>
+ <dependency>
+ <groupId>org.aopalliance</groupId>
+ <artifactId>com.springsource.org.aopalliance</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.dependencymanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.fileinstall</artifactId>
+ </dependency>
+ <!-- felix webconsole -->
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.webconsole</artifactId>
+ <classifier>all</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.jettison</groupId>
+ <artifactId>jettison</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.equinox.http</groupId>
+ <artifactId>servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>org.eclipse.persistence.antlr</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>org.eclipse.persistence.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>org.eclipse.persistence.moxy</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.spec.javax.transaction</groupId>
+ <artifactId>jboss-transaction-api_1.1_spec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jolokia</groupId>
+ <artifactId>jolokia-osgi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-all</artifactId>
+ </dependency>
+ <!-- Visual VM hook -->
+ <dependency>
+ <groupId>org.ow2.chameleon.management</groupId>
+ <artifactId>chameleon-mbeans</artifactId>
+ </dependency>
+
+ <!-- Third party depedencies -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.aop</artifactId>
+ </dependency>
+ <!-- Add Pax Exam -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.asm</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.beans</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.context</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.context.support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.expression</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.transaction</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.web.servlet</artifactId>
+ </dependency>
+ <!-- Spring security -->
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-taglibs</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>virgomirror</groupId>
+ <artifactId>org.eclipse.jdt.core.compiler.batch</artifactId>
+ </dependency>
+
+ <!-- test to validate features.xml -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>features-test</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ </dependency>
+ <!-- dependency for opendaylight-karaf-empty for use by testing -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-empty</artifactId>
+ <version>1.4.2-SNAPSHOT</version>
+ <type>zip</type>
+ </dependency>
+ </dependencies>
<build>
<resources>
<resource>
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+ <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+ <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
+ </systemPropertyVariables>
+ <dependenciesToScan>
+ <dependency>org.opendaylight.yangtools:features-test</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<features name="base-${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">
+<features name="odl-base-${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">
- <feature name="base-all" description="OpenDaylight Controller" version="${project.version}">
+ <feature name="odl-base-all" description="OpenDaylight Controller" version="${project.version}">
<feature>http</feature>
<feature>transaction</feature>
- <feature>base-felix-dm</feature>
- <feature>base-aries-spi-fly</feature>
- <feature>base-dummy-console</feature>
- <feature>base-apache-commons</feature>
- <feature>base-eclipselink-persistence</feature>
- <feature>base-gemini-web</feature>
- <feature>base-tomcat</feature>
- <feature>base-netty</feature>
- <feature>base-jersey</feature>
- <feature>base-jackson</feature>
- <feature>base-spring-security</feature>
+ <feature>odl-base-felix-dm</feature>
+ <feature>odl-base-aries-spi-fly</feature>
+ <feature>odl-base-dummy-console</feature>
+ <feature>odl-base-apache-commons</feature>
+ <feature>odl-base-eclipselink-persistence</feature>
+ <feature>odl-base-gemini-web</feature>
+ <feature>odl-base-tomcat</feature>
+ <feature>odl-base-netty</feature>
+ <feature>odl-base-jersey</feature>
+ <feature>odl-base-jackson</feature>
+ <feature>odl-base-spring-security</feature>
</feature>
- <feature name="base-dummy-console" description="Temporary Dummy Console" version="1.1.0-SNAPSHOT">
+ <feature name="odl-base-dummy-console" description="Temporary Dummy Console" version="1.1.0-SNAPSHOT">
<bundle>mvn:org.opendaylight.controller/dummy-console/1.1.0-SNAPSHOT</bundle>
</feature>
- <feature name="base-felix-dm" description="Felix Dependency Manager" version="${felix.dependencymanager.version}">
- <bundle start-level="35">mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version}</bundle>
- <bundle start-level="35">mvn:org.apache.felix/org.apache.felix.dependencymanager/${felix.dependencymanager.version}</bundle>
- <bundle start-level="35">mvn:org.apache.felix/org.apache.felix.dependencymanager.shell/${felix.dependencymanager.shell.version}</bundle>
+ <feature name="odl-base-felix-dm" description="Felix Dependency Manager" version="${felix.dependencymanager.version}">
+ <bundle>mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version}</bundle>
+ <bundle>mvn:org.apache.felix/org.apache.felix.dependencymanager/${felix.dependencymanager.version}</bundle>
+ <bundle>mvn:org.apache.felix/org.apache.felix.dependencymanager.shell/${felix.dependencymanager.shell.version}</bundle>
</feature>
- <feature name="base-aries-spi-fly" description="Aries SPI Fly" version="${spifly.version}">
- <bundle start-level="35">mvn:org.apache.aries/org.apache.aries.util/1.1.0</bundle>
- <bundle start-level="35">mvn:org.apache.aries.spifly/org.apache.aries.spifly.dynamic.bundle/${spifly.version}</bundle>
- <bundle start-level="35">mvn:org.ow2.asm/asm-all/4.0</bundle>
+ <feature name="odl-base-aries-spi-fly" description="Aries SPI Fly" version="${spifly.version}">
+ <bundle>mvn:org.apache.aries/org.apache.aries.util/1.1.0</bundle>
+ <bundle>mvn:org.apache.aries.spifly/org.apache.aries.spifly.dynamic.bundle/${spifly.version}</bundle>
+ <bundle>mvn:org.ow2.asm/asm-all/4.0</bundle>
</feature>
- <feature name='base-netty' version='${netty.version}'>
+ <feature name='odl-base-netty' version='${netty.version}'>
<bundle>wrap:mvn:io.netty/netty-buffer/${netty.version}</bundle>
<bundle>wrap:mvn:io.netty/netty-codec/${netty.version}</bundle>
<bundle>wrap:mvn:io.netty/netty-transport/${netty.version}</bundle>
<bundle>wrap:mvn:io.netty/netty-codec-http/${netty.version}</bundle>
<bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/1.1-SNAPSHOT</bundle>
</feature>
- <feature name="base-jersey" description="Jersey" version="${jersey.version}">
- <feature>base-gemini-web</feature>
- <bundle>mvn:org.opendaylight.controller.thirdparty/com.sun.jersey.jersey-servlet/${jersey.version}</bundle>
+ <feature name="odl-base-jersey" description="Jersey" version="${jersey.version}">
+ <feature>odl-base-gemini-web</feature>
<bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-client/${jersey.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-servlet/${jersey.version}</bundle>
</feature>
- <feature name="base-jersey2-osgi" description="OSGi friendly Jersey" version="${jersey2.publisher.version}">
+ <feature name="odl-base-jersey2-osgi" description="OSGi friendly Jersey" version="${jersey2.publisher.version}">
<feature>http</feature>
<bundle>mvn:com.eclipsesource.jaxrs/jersey-all/${jersey2.version}</bundle>
<bundle>mvn:com.eclipsesource.jaxrs/publisher/${jersey2.publisher.version}</bundle>
- <bundle start="true" start-level="35">mvn:javax.ws.rs/javax.ws.rs-api/${jsr311.v2.api.version}</bundle>
+ <bundle start="true">mvn:javax.ws.rs/javax.ws.rs-api/${jsr311.v2.api.version}</bundle>
<bundle>mvn:javax.annotation/javax.annotation-api/${javax.annotation.version}</bundle>
</feature>
- <feature name="base-jackson" description="Jackson JAX-RS" version="${jackson.version}">
- <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
- <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
- <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
- <bundle start="true" start-level="35">mvn:org.codehaus.jettison/jettison/${jettison.version}</bundle>
- <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${jackson.version}</bundle>
- <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${jackson.version}</bundle>
- <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${jackson.version}</bundle>
+ <feature name="odl-base-jackson" description="Jackson JAX-RS" version="${jackson.version}">
+ <bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-client/${jersey.version}</bundle>
+ <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
+ <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
+ <bundle start="true">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
+ <bundle start="true">mvn:org.codehaus.jettison/jettison/${jettison.version}</bundle>
+ <bundle start="true">mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${jackson.version}</bundle>
+ <bundle start="true">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${jackson.version}</bundle>
+ <bundle start="true">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${jackson.version}</bundle>
</feature>
- <feature name="base-slf4j" description="SLF4J Logging" version="${slf4j.version}">
- <bundle start-level="35">mvn:org.slf4j/slf4j-jdk14/1.7.2</bundle>
- <bundle start-level="35">mvn:org.slf4j/slf4j-nop/1.7.2</bundle>
- <bundle start-level="35">mvn:org.slf4j/slf4j-simple/1.7.2</bundle>
- <bundle start="true" start-level="35">mvn:org.slf4j/slf4j-api/1.7.2</bundle>
+ <feature name="odl-base-slf4j" description="SLF4J Logging" version="${slf4j.version}">
+ <bundle>mvn:org.slf4j/slf4j-jdk14/1.7.2</bundle>
+ <bundle>mvn:org.slf4j/slf4j-nop/1.7.2</bundle>
+ <bundle>mvn:org.slf4j/slf4j-simple/1.7.2</bundle>
+ <bundle start="true">mvn:org.slf4j/slf4j-api/1.7.2</bundle>
</feature>
- <feature name="base-apache-commons" description="Apache Commons Libraries" version="${project.version}">
- <bundle start="true" start-level="35">mvn:com.google.guava/guava/${guava.version}</bundle>
- <bundle start="true" start-level="35">mvn:org.javassist/javassist/${javassist.version}</bundle>
- <bundle start="true" start-level="35">mvn:commons-io/commons-io/${commons.io.version}</bundle>
- <bundle start="true" start-level="35">mvn:commons-codec/commons-codec/${commons.codec.version}</bundle>
- <bundle start="true" start-level="35">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
- <bundle start="true" start-level="35">mvn:commons-net/commons-net/${commons.net.version}</bundle>
+ <feature name="odl-base-apache-commons" description="Apache Commons Libraries" version="${project.version}">
+ <bundle start="true">mvn:com.google.guava/guava/${guava.version}</bundle>
+ <bundle start="true">mvn:org.javassist/javassist/${javassist.version}</bundle>
+ <bundle start="true">mvn:commons-io/commons-io/${commons.io.version}</bundle>
+ <bundle start="true">mvn:commons-codec/commons-codec/${commons.codec.version}</bundle>
+ <bundle start="true">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
+ <bundle start="true">mvn:commons-net/commons-net/${commons.net.version}</bundle>
</feature>
- <feature name="base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
- <bundle start="true" start-level="35">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
- <bundle start="true" start-level="35">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
- <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/2.5.0</bundle>
- <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0</bundle>
+ <feature name="odl-base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
+ <bundle start="true">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
+ <bundle start="true">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
+ <bundle start="true">mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/2.5.0</bundle>
+ <bundle start="true">mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0</bundle>
</feature>
- <feature name="base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
+ <feature name="odl-base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
<feature>http</feature>
<feature>transaction</feature>
- <feature>base-slf4j</feature>
- <feature>base-felix-dm</feature>
- <feature>base-jackson</feature>
- <feature>base-apache-commons</feature>
- <bundle start="true" start-level="35">mvn:com.google.code.gson/gson/${gson.version}</bundle>
- <bundle start="true" start-level="35">mvn:commons-fileupload/commons-fileupload/${commons.fileupload.version}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.core/${geminiweb.version}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.extender/${geminiweb.version}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.common/${virgo.version}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.io/${virgo.version}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.math/${virgo.version}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.osgi/${virgo.version}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.osgi.manifest/${virgo.version}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.parser.manifest/${virgo.version}</bundle>
- <bundle start="true" start-level="35">mvn:org.apache.felix/org.apache.felix.fileinstall/3.1.6</bundle>
- <bundle start="true" start-level="35">mvn:orbit/javax.activation/1.1.0.v201211130549</bundle>
- <bundle start="true" start-level="35">mvn:orbit/javax.annotation/1.1.0.v201209060031</bundle>
- <bundle start="true" start-level="35">mvn:orbit/javax.ejb/3.1.1.v201204261316</bundle>
- <bundle start="true" start-level="35">mvn:orbit/javax.el/2.2.0.v201108011116</bundle>
- <bundle start="true" start-level="35">mvn:orbit/javax.mail.glassfish/1.4.1.v201108011116</bundle>
- <bundle start="true" start-level="35">mvn:orbit/javax.xml.rpc/1.1.0.v201005080400</bundle>
- <bundle start="true" start-level="35">mvn:org.eclipse.jetty.orbit/javax.servlet.jsp/2.2.0.v201112011158</bundle>
- <bundle start="true" start-level="35">mvn:orbit/javax.servlet.jsp.jstl/1.2.0.v201105211821</bundle>
- <bundle start="true" start-level="35">mvn:orbit/javax.servlet.jsp.jstl.impl/1.2.0.v201210211230</bundle>
+ <feature>odl-base-slf4j</feature>
+ <feature>odl-base-felix-dm</feature>
+ <feature>odl-base-jackson</feature>
+ <feature>odl-base-apache-commons</feature>
+ <bundle start="true">mvn:com.google.code.gson/gson/${gson.version}</bundle>
+ <bundle start="true">mvn:commons-fileupload/commons-fileupload/${commons.fileupload.version}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.gemini.web.core/${geminiweb.version}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.gemini.web.extender/${geminiweb.version}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.common/${virgo.version}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.io/${virgo.version}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.math/${virgo.version}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.osgi/${virgo.version}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.osgi.manifest/${virgo.version}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.virgo.util.parser.manifest/${virgo.version}</bundle>
+ <bundle start="true">mvn:org.apache.felix/org.apache.felix.fileinstall/3.1.6</bundle>
+ <bundle start="true">mvn:orbit/javax.activation/1.1.0.v201211130549</bundle>
+ <bundle start="true">mvn:orbit/javax.annotation/1.1.0.v201209060031</bundle>
+ <bundle start="true">mvn:orbit/javax.ejb/3.1.1.v201204261316</bundle>
+ <bundle start="true">mvn:orbit/javax.el/2.2.0.v201108011116</bundle>
+ <bundle start="true">mvn:orbit/javax.mail.glassfish/1.4.1.v201108011116</bundle>
+ <bundle start="true">mvn:orbit/javax.xml.rpc/1.1.0.v201005080400</bundle>
+ <bundle start="true">mvn:org.eclipse.jetty.orbit/javax.servlet.jsp/2.2.0.v201112011158</bundle>
+ <bundle start="true">mvn:orbit/javax.servlet.jsp.jstl/1.2.0.v201105211821</bundle>
+ <bundle start="true">mvn:orbit/javax.servlet.jsp.jstl.impl/1.2.0.v201210211230</bundle>
</feature>
- <feature name="base-tomcat" description="OpenDaylight Tomcat" version="7.0.53">
- <feature>base-gemini-web</feature>
- <feature>base-eclipselink-persistence</feature>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina/${commons.karaf.catalina}</bundle>
- <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.tomcat/${geminiweb.version}</bundle>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina.ha/${commons.karaf.catalina.ha}</bundle>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina.tribes/${commons.karaf.catalina.tribes}</bundle>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.coyote/${commons.karaf.coyote}</bundle>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.el/${commons.karaf.el}</bundle>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.jasper/${commons.karaf.jasper}</bundle>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.juli.extras/${commons.karaf.juli.version}</bundle>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.tomcat.api/${commons.karaf.tomcat.api}</bundle>
- <bundle start="true" start-level="35">mvn:orbit/org.apache.tomcat.util/${commons.karaf.tomcat.util}</bundle>
+ <feature name="odl-base-tomcat" description="OpenDaylight Tomcat" version="7.0.53">
+ <feature>odl-base-gemini-web</feature>
+ <feature>odl-base-eclipselink-persistence</feature>
+ <bundle start="true">mvn:orbit/org.apache.catalina/${commons.karaf.catalina}</bundle>
+ <bundle start="true">mvn:geminiweb/org.eclipse.gemini.web.tomcat/${geminiweb.version}</bundle>
+ <bundle start="true">mvn:orbit/org.apache.catalina.ha/${commons.karaf.catalina.ha}</bundle>
+ <bundle start="true">mvn:orbit/org.apache.catalina.tribes/${commons.karaf.catalina.tribes}</bundle>
+ <bundle start="true">mvn:orbit/org.apache.coyote/${commons.karaf.coyote}</bundle>
+ <bundle start="true">mvn:orbit/org.apache.el/${commons.karaf.el}</bundle>
+ <bundle start="true">mvn:orbit/org.apache.jasper/${commons.karaf.jasper}</bundle>
+ <bundle start="true">mvn:orbit/org.apache.juli.extras/${commons.karaf.juli.version}</bundle>
+ <bundle start="true">mvn:orbit/org.apache.tomcat.api/${commons.karaf.tomcat.api}</bundle>
+ <bundle start="true">mvn:orbit/org.apache.tomcat.util/${commons.karaf.tomcat.util}</bundle>
<bundle start="true" >mvn:org.opendaylight.controller/karaf-tomcat-security/${karaf.security.version}</bundle>
- <bundle start="true" start-level="35">wrap:mvn:virgomirror/org.eclipse.jdt.core.compiler.batch/${eclipse.jdt.core.compiler.batch.version}</bundle>
+ <bundle start="true">wrap:mvn:virgomirror/org.eclipse.jdt.core.compiler.batch/${eclipse.jdt.core.compiler.batch.version}</bundle>
</feature>
- <feature name="base-spring" description="Opendaylight Spring Support" version="${spring.version}">
+ <feature name="odl-base-spring" description="Opendaylight Spring Support" version="${spring.version}">
<bundle>mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
<bundle>mvn:org.aopalliance/com.springsource.org.aopalliance/${aopalliance.version}</bundle>
<bundle>mvn:org.springframework/org.springframework.aop/${spring.version}</bundle>
<bundle>mvn:org.springframework/org.springframework.expression/${spring.version}</bundle>
<bundle>mvn:org.springframework/org.springframework.transaction/${spring.version}</bundle>
</feature>
- <feature name="base-spring-web" description="OpenDaylight Spring Web" version="${spring.version}">
- <feature>base-spring</feature>
- <feature>base-gemini-web</feature>
+ <feature name="odl-base-spring-web" description="OpenDaylight Spring Web" version="${spring.version}">
+ <feature>odl-base-spring</feature>
+ <feature>odl-base-gemini-web</feature>
<bundle>mvn:org.springframework/org.springframework.web/${spring.version}</bundle>
<bundle>mvn:org.springframework/org.springframework.web.servlet/${spring.version}</bundle>
</feature>
- <feature name="base-spring-security" description="OpenDaylight Spring Security" version="${spring-security.version}">
- <feature>base-spring-web</feature>
+ <feature name="odl-base-spring-security" description="OpenDaylight Spring Security" version="${spring-security.version}">
+ <feature>odl-base-spring-web</feature>
<bundle>mvn:org.springframework.security/spring-security-config/${spring-security.version}</bundle>
<bundle>mvn:org.springframework.security/spring-security-core/${spring-security.version}</bundle>
<bundle>mvn:org.springframework.security/spring-security-taglibs/${spring-security.version}</bundle>
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.controller/features-config-persister/${config.version}/xml/features</repository>
- <feature name='odl-config-netty' version='${project.version}'>
+ <feature name='odl-config-netty' version='${project.version}' description="OpenDaylight :: Config-Netty">
<feature version='${project.version}'>odl-config-netty-config-api</feature>
<bundle>mvn:org.opendaylight.controller/netty-event-executor-config/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/netty-threadgroup-config/${project.version}</bundle>
<repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
<repository>mvn:org.opendaylight.controller/features-netconf/${netconf.version}/xml/features</repository>
<repository>mvn:org.opendaylight.controller/features-config/${config.version}/xml/features</repository>
- <feature name='odl-config-all' version='${project.version}'>
+ <feature name='odl-config-persister-all' version='${project.version}' description="OpenDaylight :: Config Persister:: All">
<feature version='${project.version}'>odl-config-persister</feature>
<feature version='${project.version}'>odl-config-startup</feature>
</feature>
- <feature name='odl-config-persister' version='${project.version}'>
+ <feature name='odl-config-persister' version='${project.version}' description="OpenDaylight :: Config Persister ">
<feature version='${netconf.version}'>odl-netconf-api</feature>
<feature version='${project.version}'>odl-config-api</feature>
<feature version='${yangtools.version}'>odl-yangtools-binding-generator</feature>
<bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.core/${eclipse.persistence.version}</bundle>
<bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/${eclipse.persistence.version}</bundle>
</feature>
- <feature name='odl-config-startup' version='${project.version}'>
+ <feature name='odl-config-startup' version='${project.version}' description="OpenDaylight :: Config Persister:: Config Startup">
<feature version='${project.version}'>odl-config-netconf-connector</feature>
<feature version='${project.version}'>odl-config-persister</feature>
<feature version='${project.version}'>odl-netconf-impl</feature>
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>
- <feature name='odl-config-all' version='${project.version}'>
+ <feature name='odl-config-all' version='${project.version}' description="OpenDaylight :: Config :: All">
<feature version='${mdsal.version}'>odl-mdsal-common</feature>
<feature version='${project.version}'>odl-config-api</feature>
<feature version='${project.version}'>odl-config-netty-config-api</feature>
<feature version='${project.version}'>odl-config-manager</feature>
</feature>
- <feature name='odl-mdsal-common' version='${mdsal.version}'>
+ <feature name='odl-mdsal-common' version='${mdsal.version}' description="OpenDaylight :: Config :: All">
<feature version='${yangtools.version}'>odl-yangtools-data-binding</feature>
<bundle>mvn:org.opendaylight.controller/sal-common/${mdsal.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-common-api/${mdsal.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-common-util/${mdsal.version}</bundle>
</feature>
- <feature name='odl-config-api' version='${project.version}'>
+ <feature name='odl-config-api' version='${project.version}' description="OpenDaylight :: Config :: API">
<bundle>mvn:org.opendaylight.controller/config-api/${project.version}</bundle>
<feature version='${yangtools.version}'>odl-yangtools-common</feature>
<feature version='${yangtools.version}'>odl-yangtools-binding</feature>
</feature>
- <feature name='odl-config-netty-config-api' version='${project.version}'>
+ <feature name='odl-config-netty-config-api' version='${project.version}' description="OpenDaylight :: Config :: Netty Config API">
<feature version='${project.version}'>odl-config-api</feature>
<bundle>mvn:org.opendaylight.controller/netty-config-api/${project.version}</bundle>
<bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
<bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
</feature>
- <feature name='odl-config-core' version='${project.version}'>
+ <feature name='odl-config-core' version='${project.version}' description="OpenDaylight :: Config :: Core">
<feature version='${yangtools.version}'>odl-yangtools-common</feature>
<feature version='${yangtools.version}'>odl-yangtools-binding</feature>
<feature version='${yangtools.version}'>odl-yangtools-binding-generator</feature>
<bundle>mvn:com.google.guava/guava/${guava.version}</bundle>
<bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
</feature>
- <feature name='odl-config-manager' version='${project.version}'>
+ <feature name='odl-config-manager' version='${project.version}' description="OpenDaylight :: Config :: Manager">
<feature version='${project.version}'>odl-config-core</feature>
<bundle>mvn:org.opendaylight.controller/config-manager/${project.version}</bundle>
</feature>
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.controller/features-mdsal/${mdsal.version}/xml/features</repository>
- <feature name='odl-flow-model' version='${project.version}'>
+ <feature name='odl-flow-model' version='${project.version}' description="OpenDaylight :: Flow :: Model">
<feature version='${yangtools.version}'>odl-yangtools-models</feature>
<bundle>mvn:org.opendaylight.controller.model/model-flow-base/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller.model/model-flow-service/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller.model/model-inventory/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller.model/model-topology/${project.version}</bundle>
</feature>
- <feature name='odl-flow-services' version='${project.version}'>
+ <feature name='odl-flow-services' version='${project.version}' description="OpenDaylight :: Flow :: Services">
<feature version='${project.version}'>odl-mdsal-broker</feature>
<feature version='${project.version}'>odl-flow-model</feature>
<bundle>mvn:org.opendaylight.controller.md/topology-manager/${project.version}</bundle>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-broker-impl</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-dom-xsql</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-api</artifactId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
- <groupId>org.opendaylight.controller.thirdparty</groupId>
- <artifactId>com.sun.jersey.jersey-servlet</artifactId>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-servlet</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<repository>mvn:org.opendaylight.controller/features-config/${config.version}/xml/features</repository>
<repository>mvn:org.opendaylight.controller/features-config-persister/${config.version}/xml/features</repository>
<repository>mvn:org.opendaylight.controller/features-config-netty/${config.version}/xml/features</repository>
- <feature name='odl-mdsal-all' version='${project.version}'>
+ <feature name='odl-mdsal-all' version='${project.version}' description="OpenDaylight :: MDSAL :: All">
<feature version='${project.version}'>odl-mdsal-broker</feature>
<feature version='${project.version}'>odl-mdsal-netconf-connector</feature>
<feature version='${project.version}'>odl-restconf</feature>
+ <feature version='${project.version}'>odl-mdsal-xsql</feature>
<feature version='${project.version}'>odl-toaster</feature>
</feature>
- <feature name='odl-mdsal-broker' version='${project.version}'>
+ <feature name='odl-mdsal-broker' version='${project.version}' description="OpenDaylight :: MDSAL :: Broker">
<feature version='${yangtools.version}'>odl-yangtools-common</feature>
<feature version='${yangtools.version}'>odl-yangtools-binding</feature>
<feature version='${mdsal.version}'>odl-mdsal-common</feature>
<bundle>mvn:org.opendaylight.controller/sal-inmemory-datastore/${project.version}</bundle>
<configfile finalname="${config.configfile.directory}/${config.mdsal.configfile}">mvn:org.opendaylight.controller/md-sal-config/${mdsal.version}/xml/config</configfile>
</feature>
- <feature name='odl-mdsal-netconf-connector' version='${project.version}'>
+ <feature name='odl-mdsal-netconf-connector' version='${project.version}' description="OpenDaylight :: MDSAL :: Netconf Connector">
<feature version='${project.version}'>odl-mdsal-broker</feature>
<feature version='${netconf.version}'>odl-netconf-client</feature>
<feature version='${yangtools.version}'>odl-yangtools-models</feature>
<bundle>mvn:org.opendaylight.controller/netconf-config-dispatcher/${config.version}</bundle>
<configfile finalname="${config.configfile.directory}/${config.netconf.connector.configfile}">mvn:org.opendaylight.controller/netconf-connector-config/${netconf.version}/xml/config</configfile>
</feature>
- <feature name='odl-restconf' version='${project.version}'>
+ <feature name='odl-restconf' version='${project.version}' description="OpenDaylight :: Restconf">
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
<feature>war</feature>
<bundle>mvn:org.opendaylight.controller/sal-rest-connector/${project.version}</bundle>
<bundle>mvn:com.google.code.gson/gson/${gson.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
- <bundle>mvn:org.opendaylight.controller.thirdparty/com.sun.jersey.jersey-servlet/${jersey.version}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-servlet/${jersey.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:org.opendaylight.controller/sal-remote/${project.version}</bundle>
<configfile finalname="${config.configfile.directory}/${config.restconf.configfile}">mvn:org.opendaylight.controller/sal-rest-connector-config/${mdsal.version}/xml/config</configfile>
</feature>
- <feature name='odl-toaster' version='${project.version}'>
+ <feature name='odl-toaster' version='${project.version}' description="OpenDaylight :: Toaster">
<feature version='${yangtools.version}'>odl-yangtools-common</feature>
<feature version='${yangtools.version}'>odl-yangtools-binding</feature>
<feature version='${project.version}'>odl-mdsal-broker</feature>
<bundle>mvn:org.opendaylight.controller.samples/sample-toaster-provider/${project.version}</bundle>
<configfile finalname="${config.configfile.directory}/${config.toaster.configfile}">mvn:org.opendaylight.controller.samples/toaster-config/${project.version}/xml/config</configfile>
</feature>
+ <feature name ='odl-mdsal-xsql' version='${project.version}'>
+ <feature version='${project.version}'>odl-mdsal-broker</feature>
+ <bundle>mvn:org.opendaylight.controller/sal-dom-xsql/${project.version}</bundle>
+ <configfile finalname="${config.configfile.directory}/${config.xsql.configfile}">mvn:org.opendaylight.controller/sal-dom-xsql-config/${project.version}/xml/config</configfile>
+ </feature>
</features>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>ganymed</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ </dependency>
<dependency>
<groupId>org.openexi</groupId>
<artifactId>nagasena</artifactId>
xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
<repository>mvn:org.opendaylight.controller/features-protocol-framework/${protocol-framework.version}/xml/features</repository>
<repository>mvn:org.opendaylight.controller/features-config/${config.version}/xml/features</repository>
- <feature name='odl-netconf-all' version='${project.version}'>
+ <feature name='odl-netconf-all' version='${project.version}' description="OpenDaylight :: Netconf :: All">
<feature version='${project.version}'>odl-netconf-api</feature>
<feature version='${project.version}'>odl-netconf-mapping-api</feature>
<feature version='${project.version}'>odl-netconf-util</feature>
<feature version='${project.version}'>odl-netconf-monitoring</feature>
</feature>
- <feature name='odl-netconf-api' version='${project.version}'>
+ <feature name='odl-netconf-api' version='${project.version}' description="OpenDaylight :: Netconf :: API">
<feature version='${protocol-framework.version}'>odl-protocol-framework</feature>
<bundle>mvn:org.opendaylight.controller/netconf-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf-inet-types.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf-yang-types.version}</bundle>
</feature>
- <feature name='odl-netconf-mapping-api' version='${project.version}'>
+ <feature name='odl-netconf-mapping-api' version='${project.version}' description="OpenDaylight :: Netconf :: Mapping API">
<feature version='${project.version}'>odl-netconf-api</feature>
<bundle>mvn:org.opendaylight.controller/netconf-mapping-api/${project.version}</bundle>
</feature>
<feature version='${project.version}'>odl-netconf-mapping-api</feature>
<bundle>mvn:org.opendaylight.controller/netconf-util/${project.version}</bundle>
</feature>
- <feature name='odl-netconf-impl' version='${project.version}'>
+ <feature name='odl-netconf-impl' version='${project.version}' description="OpenDaylight :: Netconf :: Impl">
<feature version='${project.version}'>odl-netconf-api</feature>
<feature version='${project.version}'>odl-netconf-mapping-api</feature>
<feature version='${project.version}'>odl-netconf-util</feature>
<feature version='${project.version}'>odl-netconf-netty-util</feature>
<bundle>mvn:org.opendaylight.controller/netconf-impl/${project.version}</bundle>
</feature>
- <feature name='odl-config-netconf-connector' version='${project.version}'>
+ <feature name='odl-config-netconf-connector' version='${project.version}' description="OpenDaylight :: Netconf :: Connector">
<feature version='${config.version}'>odl-config-manager</feature>
<feature version='${project.version}'>odl-netconf-api</feature>
<feature version='${project.version}'>odl-netconf-mapping-api</feature>
<feature version='${project.version}'>odl-netconf-util</feature>
<bundle>mvn:org.opendaylight.controller/config-netconf-connector/${project.version}</bundle>
</feature>
- <feature name='odl-netconf-netty-util' version='${project.version}'>
+ <feature name='odl-netconf-netty-util' version='${project.version}' description="OpenDaylight :: Netconf :: Netty Util">
<feature version='${project.version}'>odl-netconf-api</feature>
<feature version='${project.version}'>odl-netconf-mapping-api</feature>
<feature version='${project.version}'>odl-netconf-util</feature>
<bundle>mvn:org.opendaylight.controller/netconf-netty-util/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/${ganymed.version}</bundle>
+ <bundle>mvn:org.apache.sshd/sshd-core/${sshd-core.version}</bundle>
<bundle>mvn:org.openexi/nagasena/${exi.nagasena.version}</bundle>
<bundle>mvn:io.netty/netty-codec/${netty.version}</bundle>
<bundle>mvn:io.netty/netty-handler/${netty.version}</bundle>
<bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
<bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
</feature>
- <feature name='odl-netconf-client' version="${project.version}">
+ <feature name='odl-netconf-client' version='${project.version}' description="OpenDaylight :: Netconf :: Client">
<feature version='${project.version}'>odl-netconf-netty-util</feature>
<bundle>mvn:org.opendaylight.controller/netconf-client/${project.version}</bundle>
- <configfile finalname="${config.configfile.directory}/${config.netconf.client.configfile}">mvn:org.opendaylight.controller/netconf-config/${netconf.version}/xml/config</configfile>
+ <configfile finalname='${config.configfile.directory}/${config.netconf.client.configfile}'>mvn:org.opendaylight.controller/netconf-config/${netconf.version}/xml/config</configfile>
</feature>
- <feature name='odl-netconf-monitoring' version='${project.version}'>
+ <feature name='odl-netconf-monitoring' version='${project.version}' description="OpenDaylight :: Netconf :: Monitoring">
<feature version='${project.version}'>odl-netconf-util</feature>
<bundle>mvn:org.opendaylight.controller/netconf-monitoring/${project.version}</bundle>
</feature>
-</features>
\ No newline at end of file
+</features>
<relativePath>../../opendaylight/commons/opendaylight</relativePath>
</parent>
<artifactId>features-nsf</artifactId>
- <packaging>pom</packaging>
+ <version>${nsf.version}</version>
+ <packaging>jar</packaging>
<name>OpenDaylight :: Features :: Network Service Functions</name>
<description>Feature for Network Service Functions</description>
<properties>
<features.file>features.xml</features.file>
</properties>
+ <dependencies>
+ <!-- test to validate features.xml -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>features-test</artifactId>
+ </dependency>
+ <!-- dependency for opendaylight-karaf-empty for use by testing -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-empty</artifactId>
+ <version>1.4.2-SNAPSHOT</version>
+ <type>zip</type>
+ </dependency>
+ <!-- Bundle Dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>appauth</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>arphandler</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>bundlescanner</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>bundlescanner.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>connectionmanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>connectionmanager.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>connectionmanager.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager.shell</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>controllermanager.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>devices.web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>flowprogrammer.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>flows.web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>routing.dijkstra_implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>forwarding.staticrouting</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>forwarding.staticrouting.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>forwardingrulesmanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>forwardingrulesmanager.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker.shell</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>httpservice-bridge</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>jolokia-bridge</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>logging.bridge</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.bridgedomain.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.neutron</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.neutron.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.neutron.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>osgi-brandfragment.web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>samples.loadbalancer</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>samples.loadbalancer.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>samples.simpleforwarding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>security</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>statistics.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>statisticsmanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>statisticsmanager.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>subnets.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topology.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topology.web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topologymanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topologymanager.shell</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>troubleshoot.web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>usermanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>usermanager.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>usermanager.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>net.sf.jung2</artifactId>
+ </dependency>
+ </dependencies>
<build>
<resources>
<resource>
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+ <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+ <karaf.distro.version>${commons.opendaylight.version}</karaf.distro.version>
+ </systemPropertyVariables>
+ <dependenciesToScan>
+ <dependency>org.opendaylight.yangtools:features-test</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features name="nsf-${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.controller/features-base/${commons.opendaylight.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/features-adsal/${sal.version}/xml/features</repository>
<feature name="odl-nsf-all" description="OpenDaylight :: NSF :: All Network Service Functions" version="${project.version}">
<feature version="${sal.version}">odl-adsal-all</feature>
<feature version="${project.version}">odl-nsf-managers</feature>
</feature>
<feature name="odl-nsf-managers" description="OpenDaylight :: AD-SAL :: Network Service Functions" version="${project.version}">
- <feature version="${project.version}">base-all</feature>
+ <feature version="${commons.opendaylight.version}">odl-base-all</feature>
<feature version="${sal.version}">odl-adsal-all</feature>
<bundle>mvn:org.opendaylight.controller/usermanager/${usermanager.version}</bundle>
<bundle>mvn:org.opendaylight.controller/usermanager.implementation/${usermanager.version}</bundle>
<bundle>mvn:org.opendaylight.controller/hosttracker.implementation/${hosttracker.implementation.version}</bundle>
<bundle>mvn:org.opendaylight.controller/hosttracker.shell/${hosttracker.shell.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/forwarding.staticrouting</bundle>
+ <bundle>mvn:org.opendaylight.controller/forwarding.staticrouting/${forwarding.staticrouting}</bundle>
<bundle>mvn:org.opendaylight.controller.thirdparty/net.sf.jung2/2.0.1</bundle>
- <bundle>mvn:org.opendaylight.controller/routing.dijkstra_implementation</bundle>
+ <bundle>mvn:org.opendaylight.controller/routing.dijkstra_implementation/${routing.dijkstra_implementation.version}</bundle>
</feature>
<feature name="odl-adsal-northbound" description="OpenDaylight :: AD-SAL :: Northbound APIs" version="${project.version}">
- <feature version="${project.version}">base-all</feature>
+ <feature version="${commons.opendaylight.version}">odl-base-all</feature>
<feature version="${project.version}">odl-nsf-managers</feature>
- <bundle start-level="35">mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
+ <bundle>mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
<!--
TODO : Resolve these in a follow-up commit
<bundle>mvn:org.opendaylight.controller/httpservice-bridge/${httpservice-bridge.northbound.version}</bundle>
<bundle>mvn:org.opendaylight.controller/bundlescanner/${bundlescanner.api.version}</bundle>
<bundle>mvn:org.opendaylight.controller/bundlescanner.implementation/${bundlescanner.implementation.version}</bundle>
<bundle>mvn:org.opendaylight.controller/commons.northbound/${northbound.commons.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/connectionmanager.northbound/${connectionmanager.version}</bundle>
<bundle>mvn:org.opendaylight.controller/flowprogrammer.northbound/${flowprogrammer.northbound.version}</bundle>
<bundle>mvn:org.opendaylight.controller/hosttracker.northbound/${hosttracker.northbound.version}</bundle>
<bundle>mvn:org.opendaylight.controller/networkconfig.bridgedomain.northbound/${networkconfig.bridgedomain.northbound.version}</bundle>
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.controller/features-config/${config.version}/xml/features</repository>
- <feature name='odl-protocol-framework' version='${project.version}'>
+ <feature name='odl-protocol-framework' version='${project.version}' description="OpenDaylight :: Protocol Framework">
<feature version='${config.version}'>odl-config-api</feature>
<feature version='${config.version}'>odl-config-netty-config-api</feature>
<bundle>mvn:org.opendaylight.controller/protocol-framework/${protocol-framework.version}</bundle>
--- /dev/null
+<?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>
+
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-configfile-archetype</artifactId>
+ <version>1.1-SNAPSHOT</version>
+ <packaging>maven-archetype</packaging>
+
+
+ <build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.archetype</groupId>
+ <artifactId>archetype-packaging</artifactId>
+ <version>2.2</version>
+ </extension>
+ </extensions>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-archetype-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <description>Configuration files for md-sal</description>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git/md-sal-config</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git/md-sal-config</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL/md-sal-config</url>
+ </scm>
+
+ <distributionManagement>
+ <repository>
+ <id>opendaylight-release</id>
+ <url>http://nexus.opendaylight.org/content/repositories/opendaylight.release/</url>
+ </repository>
+ <snapshotRepository>
+ <id>opendaylight-snapshot</id>
+ <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
+ </snapshotRepository>
+ <site>
+ <id>website</id>
+ <url>dav:http://nexus.opendaylight.org/content/sites/site/sal-parent</url>
+ </site>
+ </distributionManagement>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="md-sal-config"
+ xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <requiredProperties>
+ <requiredProperty key="repoName"/>
+ </requiredProperties>
+ <fileSets>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</archetype-descriptor>
--- /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>
+ <!--
+ Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+ maven repos etc. If you run this archetype in a subdirectory of your project, it
+ will pick the pom.xml from the parent directory as the parent pom, which may or may
+ not be correct.
+ -->
+ <artifactId>${artifactId}</artifactId>
+ <groupId>${groupId}</groupId>
+ <description>Configuration files for md-sal</description>
+ <!-- Optional TODO: Uncomment version if you are not using a parent pom.xml
+ <version>${version}</version>
+ -->
+ <packaging>jar</packaging>
+ <properties>
+ <!-- Optional TODO: Rename your configfile to taste -->
+ <configfile>80-configfile.xml</configfile>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${configfile}</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=${repoName}.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2013 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>
+ <!-- Necessary TODO put your required capabilities here
+
+ Examples:
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&revision=2013-11-19</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup?module=threadgroup&revision=2013-11-07</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:netty:timer?module=netty-timer&revision=2013-11-19</capability>
+ -->
+ </required-capabilities>
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <!-- Optional TODO: Add your modules definitions here
+ Examples:
+ <module>
+ <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">netty:netty-threadgroup-fixed</type>
+ <name>global-boss-group</name>
+ </module>
+ <module>
+ <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">netty:netty-threadgroup-fixed</type>
+ <name>global-worker-group</name>
+ </module>
+ <module>
+ <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:timer">netty:netty-hashed-wheel-timer</type>
+ <name>global-timer</name>
+ </module>
+ <module>
+ <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor">netty:netty-global-event-executor</type>
+ <name>singleton</name>
+ </module>
+ -->
+ </modules>
+
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <!-- Optional TODO: Put your service instance definitions here
+ Examples:
+ <service>
+ <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-threadgroup</type>
+ <instance>
+ <name>global-boss-group</name>
+ <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-boss-group']</provider>
+ </instance>
+ <instance>
+ <name>global-worker-group</name>
+ <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-worker-group']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-event-executor</type>
+ <instance>
+ <name>global-event-executor</name>
+ <provider>/modules/module[type='netty-global-event-executor'][name='singleton']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-timer</type>
+ <instance>
+ <name>global-timer</name>
+ <provider>/modules/module[type='netty-hashed-wheel-timer'][name='global-timer']</provider>
+ </instance>
+ </service>
+ -->
+ </services>
+ </data>
+
+ </configuration>
+</snapshot>
--- /dev/null
+#Mon Aug 25 05:45:18 CDT 2014
+package=it.pkg
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
+repoName=foo
--- /dev/null
+<?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>
+
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-distro-archetype</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>maven-archetype</packaging>
+
+ <name>distribution-karaf-archetype</name>
+
+ <build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.archetype</groupId>
+ <artifactId>archetype-packaging</artifactId>
+ <version>2.2</version>
+ </extension>
+ </extensions>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-archetype-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <url>https://wiki.opendaylight.org/view/CrossProject:Integration_Group/distribution-karaf</url>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
+ xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <requiredProperties>
+ <requiredProperty key="repoName"/>
+ </requiredProperties>
+</archetype-descriptor>
--- /dev/null
+<?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>
+ <!--
+ Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+ maven repos etc. If you run this archetype in a subdirectory of your project, it
+ will pick the pom.xml from the parent directory as the parent pom, which may or may
+ not be correct.
+ -->
+ <artifactId>${artifactId}</artifactId>
+ <groupId>${groupId}</groupId>
+ <!-- Optional TODO: Uncomment version if you are not using a parent pom.xml
+ <version>${version}</version>
+ -->
+ <packaging>pom</packaging>
+ <prerequisites>
+ <maven>3.0</maven>
+ </prerequisites>
+ <properties>
+ <!-- Optional TODO: Move these properties to your parent pom and possibly
+ DependencyManagement section of your parent pom -->
+ <branding.version>1.0.0-SNAPSHOT</branding.version>
+ <karaf.resources.version>1.4.2-SNAPSHOT</karaf.resources.version>
+ <karaf.version>3.0.1</karaf.version>
+ </properties>
+
+ <dependencies>
+ <!-- Basic Karaf dependencies -->
+ <dependency>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>framework</artifactId>
+ <version>${karaf.version}</version>
+ <type>kar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>standard</artifactId>
+ <version>${karaf.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+
+ <!-- ODL Branding -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>karaf.branding</artifactId>
+ <version>${branding.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <!-- ODL Resources needed for karaf -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-resources</artifactId>
+ <version>${karaf.resources.version}</version>
+ </dependency>
+
+ <!-- Project local feautures -->
+ <!--
+ Necessary TODO put your features here.
+
+ Note: they will need to be <type>xml</xml>
+ and <classifier>features</classifier>.
+
+ Note: they must be <scope>runtime</scope>
+
+ Note: usually you would only need to depend
+ on your own feature file here for your local distro,
+ and possible the features-mdsal for odl-restconf
+ (although, strange situations do exist :) )
+
+ Example:
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-mdsal</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin</artifactId>
+ <version>0.0.3-SNAPSHOT</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ -->
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>cleanVersions</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>copy</goal>
+ <goal>unpack</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>commands-generate-help</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.fusesource.scalate</groupId>
+ <artifactId>maven-scalate-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>sitegen</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.servicemix.tooling</groupId>
+ <artifactId>depends-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>generate-depends-file</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <version>${karaf.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <bootFeatures>
+ <feature>standard</feature>
+ <!--
+ Optional TODO: Add entries here for the features you want in your local distro
+ Note: odl-restconf is a separate feature from odl-mdsal-broker. If you want
+ restconf, you need to list it here explicitely.
+ Examples:
+ <feature>odl-openflowplugin-flow-services</feature>
+ <feature>odl-restconf</feature>
+ -->
+ <!-- Final TODO: Remove TODO Comments ;) -->
+ </bootFeatures>
+ </configuration>
+ <executions>
+ <execution>
+ <id>process-resources</id>
+ <goals>
+ <goal>install-kars</goal>
+ </goals>
+ <phase>process-resources</phase>
+ </execution>
+ <execution>
+ <id>package</id>
+ <goals>
+ <goal>instance-create-archive</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>karaf.branding</artifactId>
+ <version>${karaf.branding.version}</version>
+ <outputDirectory>target/assembly/lib</outputDirectory>
+ <destFileName>karaf.branding-${branding.version}.jar</destFileName>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-karaf-resources</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <outputDirectory>${project.build.directory}/assembly</outputDirectory>
+ <groupId>org.opendaylight.controller</groupId>
+ <includeArtifactIds>opendaylight-karaf-resources</includeArtifactIds>
+ <excludes>META-INF\/**</excludes>
+ <excludeTransitive>true</excludeTransitive>
+ <ignorePermissions>false</ignorePermissions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <chmod perm="755">
+ <fileset dir="${project.build.directory}/assembly/bin">
+ <include name="karaf" />
+ <include name="instance" />
+ <include name="start"/>
+ <include name="stop"/>
+ <include name="status"/>
+ <include name="client"/>
+ <include name="shell"/>
+ </fileset>
+ </chmod>
+ </tasks>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=${repoName}.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+#Thu Aug 21 14:44:29 CDT 2014
+package=it.pkg
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
+repoName=foo
--- /dev/null
+<?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>
+
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-features-archetype</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>maven-archetype</packaging>
+
+ <name>opendaylight-karaf-features-archetype</name>
+
+ <build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.archetype</groupId>
+ <artifactId>archetype-packaging</artifactId>
+ <version>2.2</version>
+ </extension>
+ </extensions>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-archetype-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git/</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git/</developerConnection>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="features-integration"
+ xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <requiredProperties>
+ <requiredProperty key="repoName"/>
+ </requiredProperties>
+ <fileSets>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>src/main/resources</directory>
+ <include>**/*.xml</include>
+ </fileSet>
+ </fileSets>
+</archetype-descriptor>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Necessary TODO: Put your copyright 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
+-->
+<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>
+ <!--
+ Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+ maven repos etc. If you run this archetype in a subdirectory of your project, it
+ will pick the pom.xml from the parent directory as the parent pom, which may or may
+ not be correct.
+ -->
+ <artifactId>features-${repoName}</artifactId>
+ <groupId>${groupId}</groupId>
+ <!-- Optional TODO: Uncomment version if you are not using a parent pom.xml
+ <version>${version}</version>
+ -->
+ <packaging>jar</packaging>
+ <properties>
+ <features.file>features.xml</features.file>
+ <!-- Optional TODO: Move these properties to your parent pom and possibly
+ DependencyManagement section of your parent pom -->
+ <branding.version>1.0.0-SNAPSHOT</branding.version>
+ <karaf.resources.version>1.4.2-SNAPSHOT</karaf.resources.version>
+ <karaf.version>3.0.1</karaf.version>
+ <feature.test.version>0.6.2-SNAPSHOT</feature.test.version>
+ <karaf.empty.version>1.4.2-SNAPSHOT</karaf.empty.version>
+ <surefire.version>2.16</surefire.version>
+ </properties>
+ <dependencies>
+ <!--
+ Necessary TODO: Put dependencies on any feature repos
+ you use in your features.xml file.
+
+ Note: they will need to be <type>xml</xml>
+ and <classifier>features</classifier>.
+ One other thing to watch for is to make sure they are
+ <scope>compile</compile>, which they should be by default,
+ but be cautious lest they be at a different scope in a parent pom.
+
+ Examples:
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>features-yangtools</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-mdsal</artifactId>
+ <version>1.1-SNAPSHOT</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin</artifactId>
+ <version>0.0.3-SNAPSHOT</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ -->
+
+ <!--
+ Necessary TODO: Put dependencies for bundles directly referenced
+ in your features.xml file. For every <bundle> reference in your
+ features.xml file, you need a corresponding dependency here.
+
+ Examples:
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${repoName}-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${repoName}-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ -->
+
+ <!--
+ Necessary TODO: Put dependencies for configfiles directly referenced
+ in your features.xml file. For every <configfile> reference in your
+ features.xml file, you need a corresponding dependency here.
+
+ Example (presuming here version is coming from the parent pom):
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${repoName}-config</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </dependency>
+ -->
+
+ <!--
+ Optional TODO: Remove TODO comments.
+ -->
+ <!-- test to validate features.xml -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>features-test</artifactId>
+ <version>${feature.test.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- dependency for opendaylight-karaf-empty for use by testing -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-empty</artifactId>
+ <version>${karaf.empty.version}</version>
+ <type>zip</type>
+ </dependency>
+ <!-- Uncomment this if you get an error : java.lang.NoSuchMethodError: org.slf4j.helpers.MessageFormatter.format(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Lorg/slf4j/helpers/FormattingTuple;
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ -->
+
+ </dependencies>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>filter</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>resources</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${features.file}</file>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <systemPropertyVariables>
+ <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+ <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+ <karaf.distro.version>${karaf.empty.version}</karaf.distro.version>
+ </systemPropertyVariables>
+ <dependenciesToScan>
+ <dependency>org.opendaylight.yangtools:features-test</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/${repoName}.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=${repoName}.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?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-${repoName}-${symbol_dollar}{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">
+ <!--
+ Necessary TODO: Please read the features guidelines:
+ https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Feature_Best_Practices
+ -->
+ <!--
+ Necessary TODO: Add repo entries for the repositories of features you refer to
+ in this feature file but do not define here.
+ Examples:
+ <repository>mvn:org.opendaylight.yangtools/features-yangtools/0.6.2-SNAPSHOT/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/features-mdsal/1.1-SNAPSHOT/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/0.0.3-SNAPSHOT/xml/features</repository>
+ -->
+ <feature name='odl-${repoName}-all' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: All'>
+ <!--
+ Necessary TODO:
+ List all of the user consumable features you define in this feature file here.
+ Generally you would *not* list individual bundles here, but only features defined in *this* file.
+ It is useful to list them in the same order they occur in the file.
+
+ Examples:
+ <feature version='${symbol_dollar}{project.version}'>odl-${repoName}-provider</feature>
+ <feature version='${symbol_dollar}{project.version}'>odl-${repoName}-model</feature>
+ -->
+ </feature>
+ <!--
+ Necessary TODO: Define your features. It is useful to list then in order of dependency. So if A depends on B, list A first.
+ When naming your features please be mindful of the guidelines:
+ https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines
+ Particularly:
+ a) Prefixing names with 'odl-': https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Feature_Naming
+ b) Descriptions: https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Description
+ c) Avoid start-levels: https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Avoid_start-levels
+
+ It's also nice to list inside a feature, first the features it needs, then the bundles it needs, then the configfiles.
+ Examples:
+
+ * Basic MD-SAL Provider
+ <feature name='odl-${repoName}-provider' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: Provider '>
+ <feature version='1.1-SNAPSHOT'>odl-mdsal-broker</feature>
+ <feature version='${symbol_dollar}{project.version}'>odl-${repoName}-model</feature>
+ <bundle>mvn:${groupId}/${repoName}-provider/${symbol_dollar}{project.version}</bundle>
+ ... whatever other bundles you need
+ </feature>
+
+ * Basic MD-SAL Model feature
+ <feature name='odl-${repoName}-model' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: Model'>
+ <feature version='0.6.2-SNAPSHOT'>odl-yangtools-binding</feature>
+ <feature version='0.6.2-SNAPSHOT'>odl-yangtools-models</feature>
+ <bundle>mvn:${groupId}/${repoName}-model/${symbol_dollar}{project.version}</bundle>
+ ... whatever other bundles you need
+ </feature>
+
+ * Config Subsystem example - the config file is your config subsystem configuration
+ <feature name='odl-${repoName}-provider' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: Provider'>
+ <feature version='1.1-SNAPSHOT'>odl-mdsal-broker</feature>
+ <bundle>mvn:${groupId}/${repoName}-provider/${symbol_dollar}{project.version}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/80-${repoName}.xml">mvn:${groupId}/${repoName}-config/${symbol_dollar}{project.version}/xml/config</configfile>
+ ... whatever other bundles you need
+ </feature>
+
+ * Basic MD-SAL Provider that uses openflowplugin-flow-services (which brings along odl-mdsal-broker)
+ <feature name='odl-${repoName}-provider' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${repoName} :: Provider'>
+ <feature version='0.0.3-SNAPSHOT'>odl-openflowplugin-flow-services</feature>
+ <bundle>mvn:${groupId}/${repoName}-provider/${symbol_dollar}{project.version}</bundle>
+ ... whatever other bundles you need
+ </feature>
+
+ -->
+ <!-- Optional TODO: Remove TODO Comments -->
+
+</features>
--- /dev/null
+#Thu Aug 21 23:46:25 CDT 2014
+package=it.pkg
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
+repoName=foo
</prerequisites>
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.parent</artifactId>
- <version>1.0.1-SNAPSHOT</version>
- <relativePath>../commons/parent</relativePath>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.2-SNAPSHOT</version>
+ <relativePath>../commons/opendaylight</relativePath>
</parent>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
</distributionManagement>
<modules>
<module>odl-model-project</module>
+ <module>opendaylight-configfile-archetype</module>
+ <module>opendaylight-karaf-distro-archetype</module>
+ <module>opendaylight-karaf-features</module>
</modules>
</project>
<config.configfile.directory>etc/opendaylight/karaf</config.configfile.directory>
<config.netty.configfile>00-netty.xml</config.netty.configfile>
<config.mdsal.configfile>01-mdsal.xml</config.mdsal.configfile>
+ <config.xsql.configfile>04-xsql.xml</config.xsql.configfile>
<config.netconf.client.configfile>01-netconf.xml</config.netconf.client.configfile>
<config.toaster.configfile>03-toaster-sample.xml</config.toaster.configfile>
<config.restconf.configfile>10-rest-connector.xml</config.restconf.configfile>
<usermanager.implementation.version>0.4.2-SNAPSHOT</usermanager.implementation.version>
<usermanager.northbound.version>0.0.2-SNAPSHOT</usermanager.northbound.version>
<usermanager.version>0.4.2-SNAPSHOT</usermanager.version>
+ <nsf.version>0.4.2-SNAPSHOT</nsf.version>
<web.version>0.4.2-SNAPSHOT</web.version>
<xtend.dstdir>src/main/xtend-gen</xtend.dstdir>
<yang-ext.version>2013.09.07.4-SNAPSHOT</yang-ext.version>
<yang-jmx-generator.version>1.0.0-SNAPSHOT</yang-jmx-generator.version>
<yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
+ <sshd-core.version>0.12.0</sshd-core.version>
</properties>
<dependencyManagement>
<artifactId>netconf-netty-util</artifactId>
<version>${netconf.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ <version>${sshd-core.version}</version>
+ </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<artifactId>jersey-core</artifactId>
<version>${jersey.version}</version>
</dependency>
-
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-servlet</artifactId>
+ <version>${jersey-servlet.version}</version>
+ </dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>hosttracker.northbound</artifactId>
<version>${hosttracker.northbound.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker.shell</artifactId>
+ <version>${hosttracker.shell.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker_new</artifactId>
<artifactId>logging.bridge</artifactId>
<version>${logging.bridge.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>dummy-console</artifactId>
+ <version>${dummy-console.version}</version>
+ </dependency>
<!-- Netconf -->
<dependency>
<artifactId>sal-connector-api</artifactId>
<version>${mdsal.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-dom-xsql</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-core-api</artifactId>
<artifactId>security</artifactId>
<version>${security.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>karaf-tomcat-security</artifactId>
+ <version>${karaf.security.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>topologymanager</artifactId>
<version>${topologymanager.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topologymanager.shell</artifactId>
+ <version>${topologymanager.shell.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>troubleshoot.web</artifactId>
<type>xml</type>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-base</artifactId>
+ <version>${commons.opendaylight.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>features-adsal</artifactId>
<type>xml</type>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-nsf</artifactId>
+ <version>${nsf.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>features-mdsal</artifactId>
*
*/
-public class ConfigurationService implements IConfigurationService, ICacheUpdateAware<ConfigurationEvent, String> {
+public class ConfigurationService implements IConfigurationService, ICacheUpdateAware<String, String> {
private static final Logger logger = LoggerFactory
.getLogger(ConfigurationService.class);
public static final String SAVE_EVENT_CACHE = "config.event.save";
private static final String ROOT = GlobalConstants.STARTUPHOME.toString();
private IClusterGlobalServices clusterServices;
- private ConcurrentMap <ConfigurationEvent, String> configEvent;
+ private ConcurrentMap<String, String> configEvent;
private Set<IConfigurationAware> configurationAwareList = Collections
.synchronizedSet(new HashSet<IConfigurationAware>());
private ObjectReader objReader;
@Override
public Status saveConfigurations() {
if (configEvent != null) {
- configEvent.put(ConfigurationEvent.SAVE, "");
+ configEvent.put(ConfigurationEvent.SAVE.toString(), "");
}
return saveConfigurationsInternal();
}
}
@Override
- public void entryCreated(ConfigurationEvent key, String cacheName,
+ public void entryCreated(String key, String cacheName,
boolean originLocal) {
if (originLocal) {
return;
}
@Override
- public void entryUpdated(ConfigurationEvent key, String new_value,
+ public void entryUpdated(String key, String new_value,
String cacheName, boolean originLocal) {
if (originLocal) {
return;
}
- if (key == ConfigurationEvent.SAVE) {
+ if (key.equals(ConfigurationEvent.SAVE.toString())) {
saveConfigurationsInternal();
}
}
@Override
- public void entryDeleted(ConfigurationEvent key, String cacheName,
+ public void entryDeleted(String key, String cacheName,
boolean originLocal) {
if (originLocal) {
return;
logger.error("uninitialized clusterServices, can't retrieve cache");
return;
}
- configEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(SAVE_EVENT_CACHE);
+ configEvent = (ConcurrentMap<String, String>) this.clusterServices.getCache(SAVE_EVENT_CACHE);
if (configEvent == null) {
logger.error("Failed to retrieve configuration Cache");
}
*/
public class ContainerConfigurationService implements IConfigurationContainerService,
- IConfigurationAware, ICacheUpdateAware<ConfigurationEvent, String> {
+ IConfigurationAware,
+ ICacheUpdateAware<String, String> {
public static final String CONTAINER_SAVE_EVENT_CACHE = "config.container.event.save";
private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class);
private IClusterContainerServices clusterServices;
- private ConcurrentMap <ConfigurationEvent, String> containerConfigEvent;
+ private ConcurrentMap<String, String> containerConfigEvent;
// Directory which contains the startup files for this container
private String root;
private Set<IConfigurationContainerAware> configurationAwareList = Collections
@Override
public Status saveConfigurations() {
- containerConfigEvent.put(ConfigurationEvent.SAVE, "");
+ containerConfigEvent.put(ConfigurationEvent.SAVE.toString(), "");
return saveConfiguration();
}
@Override
- public void entryCreated(ConfigurationEvent key, String cacheName,
+ public void entryCreated(String key, String cacheName,
boolean originLocal) {
if (originLocal) {
return;
}
@Override
- public void entryUpdated(ConfigurationEvent key, String new_value,
+ public void entryUpdated(String key, String new_value,
String cacheName, boolean originLocal) {
if (originLocal) {
return;
}
logger.debug("Processing {} event", key);
- if (key == ConfigurationEvent.SAVE) {
+ if (key.equals(ConfigurationEvent.SAVE.toString())) {
saveConfiguration();
}
}
@Override
- public void entryDeleted(ConfigurationEvent key, String cacheName,
+ public void entryDeleted(String key, String cacheName,
boolean originLocal) {
if (originLocal) {
return;
logger.error("uninitialized clusterServices, can't retrieve cache");
return;
}
- containerConfigEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
+ containerConfigEvent =
+ (ConcurrentMap<String, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
if (containerConfigEvent == null) {
logger.error("Failed to retrieve configuration Cache");
}
<Host name="localhost" appBase=""
unpackWARs="false" autoDeploy="false"
deployOnStartup="false" createDirs="false">
- <Realm className="org.opendaylight.controller.karafsecurity.ControllerCustomRealm />
+ <Realm className="org.opendaylight.controller.karafsecurity.ControllerCustomRealm" />
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="web_access_log_" suffix=".txt" resolveHosts="false"
# Extra packages to import from the boot class loader
org.osgi.framework.system.packages.extra=org.apache.karaf.branding,sun.reflect,sun.reflect.misc,sun.misc,sun.nio.ch
+# Override the config.properties to remove
+# ${services-${karaf.framework}}
+# This is to work around:
+# https://issues.apache.org/jira/browse/KARAF-3092
+# Which should be fixed in karaf 3.0.2
+# Which is not as of today (2014-08-24) released.
+# Since it is biting folks, we need to fix it here
+# Please remove this when we shift to karaf 3.0.2
+org.osgi.framework.system.capabilities= \
+ ${eecap-${java.specification.version}}, \
+ service-reference;effective:=active;objectClass=org.osgi.service.packageadmin.PackageAdmin, \
+ service-reference;effective:=active;objectClass=org.osgi.service.startlevel.StartLevel, \
+ service-reference;effective:=active;objectClass=org.osgi.service.url.URLHandlers
+
# https://bugs.eclipse.org/bugs/show_bug.cgi?id=325578
# Extend the framework to avoid the resources to be presented with
# a URL of type bundleresource: but to be presented as file:
#Hosttracker hostsdb key scheme setting
hosttracker.keyscheme=IP
+
down with testing... ie, no broken feature repos
-->
+ <!-- AD-SAL Related Features -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-base</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-adsal</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-nsf</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
<!-- MD-SAL Related Features -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<fileset dir="${project.build.directory}/assembly/bin">
<include name="karaf"/>
<include name="instance"/>
+ <include name="start"/>
+ <include name="stop"/>
+ <include name="status"/>
+ <include name="client"/>
+ <include name="shell"/>
</fileset>
</chmod>
</tasks>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>ganymed</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-api</artifactId>
uses meter:meter;
}
}
-
-
- grouping flow-node {
+ grouping ip-address-grouping {
+ leaf ip-address {
+ description "IP address of a flow capable node.";
+ type inet:ip-address;
+ }
+ }
+
+ grouping flow-node {
leaf manufacturer {
type string;
}
uses tables;
uses group:groups;
uses meters;
+ uses ip-address-grouping;
// TODO: ports
container supported-match-types {
}
}
-
+
+ rpc get-node-ip-address {
+ input {
+ uses "inv:node-context-ref";
+ }
+ output {
+ uses ip-address-grouping;
+ }
+ }
+
grouping flow-node-connector {
uses port:flow-capable-port;
<!-- Clustering -->
<module>sal-remoterpc-connector</module>
+ <module>sal-dom-xsql-config</module>
</modules>
<build>
</goals>
</pluginExecutionFilter>
<action>
- <ignore></ignore>
+ <ignore/>
</action>
</pluginExecution>
<pluginExecution>
</goals>
</pluginExecutionFilter>
<action>
- <ignore></ignore>
+ <ignore/>
</action>
</pluginExecution>
</pluginExecutions>
</modules>
</profile>
</profiles>
-</project>
+</project>
\ No newline at end of file
<artifactId>scala-library</artifactId>
</dependency>
- <!-- Test Dependencies -->
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-slf4j_${scala.version}</artifactId>
+ </dependency>
+
+
+ <!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<includes>
- <include>org.opendaylight.controller.*</include>
+ <include>org/opendaylight/controller/cluster/**/*</include>
</includes>
+ <excludes>
+ <exclude>org/opendaylight/controller/cluster/raft/protobuff/**/*</exclude>
+ <exclude>org/opendaylight/controller/cluster/example/**/*</exclude>
+ </excludes>
<check>false</check>
</configuration>
<executions>
} else if (message instanceof FindLeader) {
getSender().tell(
- new FindLeaderReply(
- context.getPeerAddress(currentBehavior.getLeaderId())),
+ new FindLeaderReply(getLeaderAddress()),
getSelf()
);
// TODO: Handle failure in saving the snapshot
- } else if (message instanceof FindLeader){
-
- getSender().tell(new FindLeaderReply(
- context.getPeerAddress(currentBehavior.getLeaderId())),
- getSelf());
-
} else if (message instanceof AddRaftPeer){
// FIXME : Do not add raft peers like this.
* @return A reference to the leader if known, null otherwise
*/
protected ActorSelection getLeader(){
- String leaderId = currentBehavior.getLeaderId();
- if (leaderId == null) {
- return null;
- }
- String peerAddress = context.getPeerAddress(leaderId);
- LOG.debug("getLeader leaderId = " + leaderId + " peerAddress = "
- + peerAddress);
+ String leaderAddress = getLeaderAddress();
- if(peerAddress == null){
- return null;
- }
- return context.actorSelection(peerAddress);
+ return context.actorSelection(leaderAddress);
}
/**
deleteMessages(sequenceNumber);
}
+ private String getLeaderAddress(){
+ if(isLeader()){
+ return getSelf().path().toString();
+ }
+ String leaderId = currentBehavior.getLeaderId();
+ if (leaderId == null) {
+ return null;
+ }
+ String peerAddress = context.getPeerAddress(leaderId);
+ LOG.debug("getLeaderAddress leaderId = " + leaderId + " peerAddress = "
+ + peerAddress);
+
+ return peerAddress;
+ }
+
private class ReplicatedLogImpl extends AbstractReplicatedLogImpl {
package org.opendaylight.controller.cluster.raft.client.messages;
-public class FindLeader {
+import java.io.Serializable;
+
+public class FindLeader implements Serializable{
}
package org.opendaylight.controller.cluster.raft.client.messages;
-public class FindLeaderReply {
+import java.io.Serializable;
+
+public class FindLeaderReply implements Serializable {
private final String leaderActor;
public FindLeaderReply(String leaderActor) {
import akka.actor.ActorSystem;
import akka.testkit.JavaTestKit;
+import org.apache.commons.io.FileUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
+import java.io.File;
+import java.io.IOException;
+
public abstract class AbstractActorTest {
private static ActorSystem system;
@BeforeClass
- public static void setUpClass() {
+ public static void setUpClass() throws Exception{
+ deleteJournal();
System.setProperty("shard.persistent", "false");
system = ActorSystem.create("test");
}
@AfterClass
- public static void tearDownClass() {
+ public static void tearDownClass() throws Exception{
+ deleteJournal();
JavaTestKit.shutdownActorSystem(system);
system = null;
}
return system;
}
+ protected static void deleteJournal() throws IOException {
+ File journal = new File("journal");
+
+ if(journal.exists()) {
+ FileUtils.deleteDirectory(journal);
+ }
+ }
+
}
--- /dev/null
+package org.opendaylight.controller.cluster.raft;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.event.Logging;
+import akka.japi.Creator;
+import akka.testkit.JavaTestKit;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.client.messages.FindLeader;
+import org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class RaftActorTest extends AbstractActorTest {
+
+
+ public static class MockRaftActor extends RaftActor {
+
+ public MockRaftActor(String id,
+ Map<String, String> peerAddresses) {
+ super(id, peerAddresses);
+ }
+
+ public static Props props(final String id, final Map<String, String> peerAddresses){
+ return Props.create(new Creator<MockRaftActor>(){
+
+ @Override public MockRaftActor create() throws Exception {
+ return new MockRaftActor(id, peerAddresses);
+ }
+ });
+ }
+
+ @Override protected void applyState(ActorRef clientActor,
+ String identifier,
+ Object data) {
+ }
+
+ @Override protected Object createSnapshot() {
+ throw new UnsupportedOperationException("createSnapshot");
+ }
+
+ @Override protected void applySnapshot(Object snapshot) {
+ throw new UnsupportedOperationException("applySnapshot");
+ }
+
+ @Override protected void onStateChanged() {
+ }
+
+ @Override public String persistenceId() {
+ return this.getId();
+ }
+
+ }
+
+
+ private static class RaftActorTestKit extends JavaTestKit {
+ private final ActorRef raftActor;
+
+ public RaftActorTestKit(ActorSystem actorSystem, String actorName) {
+ super(actorSystem);
+
+ raftActor = this.getSystem()
+ .actorOf(MockRaftActor.props(actorName,
+ Collections.EMPTY_MAP), actorName);
+
+ }
+
+
+ public boolean waitForStartup(){
+ // Wait for a specific log message to show up
+ return
+ new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+ ) {
+ protected Boolean run() {
+ return true;
+ }
+ }.from(raftActor.path().toString())
+ .message("Switching from state Candidate to Leader")
+ .occurrences(1).exec();
+
+
+ }
+
+ public void findLeader(final String expectedLeader){
+
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ raftActor.tell(new FindLeader(), getRef());
+
+ String s = new ExpectMsg<String>(duration("1 seconds"),
+ "findLeader") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof FindLeaderReply) {
+ return ((FindLeaderReply) in).getLeaderActor();
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get();// this extracts the received message
+
+ assertEquals(expectedLeader, s);
+
+ }
+
+
+ };
+ }
+
+ public ActorRef getRaftActor() {
+ return raftActor;
+ }
+
+ }
+
+
+ @Test
+ public void testConstruction() {
+ boolean started = new RaftActorTestKit(getSystem(), "testConstruction").waitForStartup();
+ assertEquals(true, started);
+ }
+
+ @Test
+ public void testFindLeaderWhenLeaderIsSelf(){
+ RaftActorTestKit kit = new RaftActorTestKit(getSystem(), "testFindLeader");
+ kit.waitForStartup();
+ kit.findLeader(kit.getRaftActor().path().toString());
+ }
+
+
+}
akka {
-
loglevel = "DEBUG"
+ loggers = ["akka.testkit.TestEventListener", "akka.event.slf4j.Slf4jLogger"]
actor {
# enable to test serialization only.
}
serialization-bindings {
+ "org.opendaylight.controller.cluster.raft.client.messages.FindLeader" = java
"org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry" = java
"com.google.protobuf.Message" = proto
"com.google.protobuf.GeneratedMessage" = proto
+/*
+ * 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.controller.md.sal.binding.api;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * A chain of transactions.
+ * <p>
+ * For more information about transaction chaining and transaction chains
+ * see {@link TransactionChain}.
+ *
+ * @see TransactionChain
+ *
+ */
public interface BindingTransactionChain extends TransactionFactory, TransactionChain<InstanceIdentifier<?>, DataObject> {
-
+ /**
+ * {@inheritDoc}
+ */
@Override
ReadOnlyTransaction newReadOnlyTransaction();
+ /**
+ * {@inheritDoc}
+ */
@Override
ReadWriteTransaction newReadWriteTransaction();
+ /**
+ * {@inheritDoc}
+ */
@Override
WriteTransaction newWriteOnlyTransaction();
-
}
* subscribe for changes to data under a given branch of the tree.
* <p>
* For more information on usage, please see the documentation in {@link AsyncDataBroker}.
+ *
+ * @see AsyncDataBroker
+ * @see TransactionChainFactory
*/
public interface DataBroker extends TransactionFactory, AsyncDataBroker<InstanceIdentifier<?>, DataObject, DataChangeListener>, BindingService, TransactionChainFactory<InstanceIdentifier<?>, DataObject> {
-
+ /**
+ * {@inheritDoc}
+ */
@Override
ReadOnlyTransaction newReadOnlyTransaction();
+ /**
+ * {@inheritDoc}
+ */
@Override
ReadWriteTransaction newReadWriteTransaction();
+ /**
+ * {@inheritDoc}
+ */
@Override
WriteTransaction newWriteOnlyTransaction();
+ /**
+ * {@inheritDoc}
+ */
@Override
ListenerRegistration<DataChangeListener> registerDataChangeListener(LogicalDatastoreType store,
InstanceIdentifier<?> path, DataChangeListener listener, DataChangeScope triggeringScope);
+ /**
+ * {@inheritDoc}
+ */
@Override
BindingTransactionChain createTransactionChain(TransactionChainListener listener);
}
import com.google.common.base.Objects;
import com.google.common.base.Optional;
-import java.util.ArrayList;
+
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+
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;
final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
- for (Map.Entry<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : sortedEntries(normalized)) {
+ for (Map.Entry<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : normalized.entrySet()) {
try {
Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(entry);
if (potential.isPresent()) {
return newMap;
}
- private static final Comparator<Entry<YangInstanceIdentifier, ?>> MAP_ENTRY_COMPARATOR = new Comparator<Entry<YangInstanceIdentifier, ?>>() {
- @Override
- public int compare(final Entry<YangInstanceIdentifier, ?> left, final Entry<YangInstanceIdentifier, ?> right) {
- final Iterator<?> li = left.getKey().getPathArguments().iterator();
- final Iterator<?> ri = right.getKey().getPathArguments().iterator();
-
- // Iterate until left is exhausted...
- while (li.hasNext()) {
- if (!ri.hasNext()) {
- // Left is deeper
- return 1;
- }
-
- li.next();
- ri.next();
- }
-
- // Check if right is exhausted
- return ri.hasNext() ? -1 : 0;
- }
- };
-
- private static <T> Iterable<Entry<YangInstanceIdentifier, T>> sortedEntries(final Map<YangInstanceIdentifier, T> map) {
- if (!map.isEmpty()) {
- ArrayList<Entry<YangInstanceIdentifier, T>> entries = new ArrayList<>(map.entrySet());
- Collections.sort(entries, MAP_ENTRY_COMPARATOR);
- return entries;
- } else {
- return Collections.emptySet();
- }
- }
-
protected Set<InstanceIdentifier<?>> toBinding(final InstanceIdentifier<?> path,
final Set<YangInstanceIdentifier> normalized) {
Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), //
mavenBundle(CONTROLLER, "netconf-util").versionAsInProject(), //
mavenBundle(CONTROLLER, "netconf-netty-util").versionAsInProject(), //
+ mavenBundle("org.apache.sshd", "sshd-core").versionAsInProject(), //
mavenBundle("org.openexi", "nagasena").versionAsInProject(), //
mavenBundle("org.openexi", "nagasena-rta").versionAsInProject(), //
mavenBundle(CONTROLLER + ".thirdparty", "ganymed").versionAsInProject(), //
String parentPath = "";
if(id != null){
- parentPath = PathUtils.getParentPath(id.toString());
+ parentPath = PathUtils.getParentPath(PathUtils.toString(id));
}
@Override
public void visitNode(int level, String parentPath, NormalizedNode normalizedNode) {
- String nodePath = parentPath + "/"+ normalizedNode.getIdentifier().toString();
+ String nodePath = parentPath + "/"+ PathUtils.toString(normalizedNode.getIdentifier());
if(nodePath.toString().equals(path)){
output = normalizedNode;
package org.opendaylight.controller.cluster.datastore.node.utils;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
public class PathUtils {
+
public static String getParentPath(String currentElementPath){
StringBuilder parentPath = new StringBuilder();
}
return parentPath.toString();
}
+
+ /**
+ * Given a YangInstanceIdentifier return a serialized version of the same
+ * as a String
+ *
+ * @param path
+ * @return
+ */
+ public static String toString(YangInstanceIdentifier path){
+ StringBuilder sb = new StringBuilder();
+ Iterator<YangInstanceIdentifier.PathArgument> iterator =
+ path.getPathArguments().iterator();
+
+ while(iterator.hasNext()){
+ sb.append(toString(iterator.next()));
+ if(iterator.hasNext()){
+ sb.append("/");
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Given a YangInstanceIdentifier.PathArgument return a serialized version
+ * of the same as a String
+ *
+ * @param pathArgument
+ * @return
+ */
+ public static String toString(YangInstanceIdentifier.PathArgument pathArgument){
+ if(pathArgument instanceof YangInstanceIdentifier.NodeIdentifier){
+ return toString((YangInstanceIdentifier.NodeIdentifier) pathArgument);
+ } else if(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier){
+ return toString((YangInstanceIdentifier.AugmentationIdentifier) pathArgument);
+ } else if(pathArgument instanceof YangInstanceIdentifier.NodeWithValue){
+ return toString((YangInstanceIdentifier.NodeWithValue) pathArgument);
+ } else if(pathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates){
+ return toString((YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument);
+ }
+
+ return pathArgument.toString();
+ }
+
+ /**
+ * Given a serialized string version of a YangInstanceIdentifier convert
+ * to a YangInstanceIdentifier
+ *
+ * @param path
+ * @return
+ */
+ public static YangInstanceIdentifier toYangInstanceIdentifier(String path){
+ String[] segments = path.split("/");
+
+ List<YangInstanceIdentifier.PathArgument> pathArguments = new ArrayList<>();
+ for (String segment : segments) {
+ if (!"".equals(segment)) {
+ pathArguments.add(NodeIdentifierFactory.getArgument(segment));
+ }
+ }
+ return YangInstanceIdentifier.create(pathArguments);
+ }
+
+ private static String toString(YangInstanceIdentifier.NodeIdentifier pathArgument){
+ return pathArgument.getNodeType().toString();
+ }
+
+ private static String toString(YangInstanceIdentifier.AugmentationIdentifier pathArgument){
+ Set<QName> childNames = pathArgument.getPossibleChildNames();
+ final StringBuilder sb = new StringBuilder("AugmentationIdentifier{");
+ sb.append("childNames=").append(childNames).append('}');
+ return sb.toString();
+
+ }
+
+ private static String toString(YangInstanceIdentifier.NodeWithValue pathArgument){
+ return pathArgument.getNodeType().toString() + "[" + pathArgument.getValue() + "]";
+ }
+
+ private static String toString(YangInstanceIdentifier.NodeIdentifierWithPredicates pathArgument){
+ return pathArgument.getNodeType().toString() + '[' + pathArgument.getKeyValues() + ']';
+ }
+
}
package org.opendaylight.controller.cluster.datastore.node.utils;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import org.opendaylight.yangtools.yang.common.QName;
-import java.util.HashMap;
-import java.util.Map;
-
public class QNameFactory {
- private static final Map<String, QName> cache = new HashMap<>();
- public static QName create(String name){
- QName value = cache.get(name);
- if(value == null){
- synchronized (cache){
- value = cache.get(name);
- if(value == null) {
- value = QName.create(name);
- cache.put(name, value);
+ private static final int MAX_QNAME_CACHE_SIZE = 10000;
+
+ private static LoadingCache<String, QName> cache = CacheBuilder.newBuilder()
+ .maximumSize(MAX_QNAME_CACHE_SIZE)
+ .softValues()
+ .build(
+ new CacheLoader<String, QName>() {
+ public QName load(String key) {
+ return QName.create(key);
}
}
- }
- return value;
+ );
+
+
+ public static QName create(String name){
+ return cache.getUnchecked(name);
}
}
package org.opendaylight.controller.cluster.datastore.util;
import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
+import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
YangInstanceIdentifier.NodeWithValue nodeWithValue =
new YangInstanceIdentifier.NodeWithValue(
- QName.create(pathArgument.getNodeType().getValue()),
+ QNameFactory.create(pathArgument.getNodeType().getValue()),
parseAttribute(pathArgument.getAttributes(0)));
return nodeWithValue;
YangInstanceIdentifier.NodeIdentifierWithPredicates
nodeIdentifierWithPredicates =
new YangInstanceIdentifier.NodeIdentifierWithPredicates(
- QName.create(pathArgument.getNodeType().getValue()), toAttributesMap(pathArgument.getAttributesList()));
+ QNameFactory.create(pathArgument.getNodeType().getValue()), toAttributesMap(pathArgument.getAttributesList()));
return nodeIdentifierWithPredicates;
Set<QName> qNameSet = new HashSet<>();
for(NormalizedNodeMessages.Attribute attribute : pathArgument.getAttributesList()){
- qNameSet.add(QName.create(attribute.getValue()));
+ qNameSet.add(QNameFactory.create(attribute.getValue()));
}
return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
String name = attribute.getName();
Object value = parseAttribute(attribute);
- map.put(QName.create(name), value);
+ map.put(QNameFactory.create(name), value);
}
return map;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeGetter;
import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
+import org.opendaylight.controller.cluster.datastore.node.utils.PathUtils;
import org.opendaylight.controller.cluster.datastore.util.TestModel;
import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Container;
import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import java.util.ArrayList;
import java.util.List;
import static junit.framework.Assert.assertEquals;
}
private YangInstanceIdentifier instanceIdentifierFromString(String s) {
-
- String[] ids = s.split("/");
-
- List<YangInstanceIdentifier.PathArgument> pathArguments = new ArrayList<>();
- for (String nodeId : ids) {
- if (!"".equals(nodeId)) {
- pathArguments.add(NodeIdentifierFactory.getArgument(nodeId));
- }
- }
- final YangInstanceIdentifier instanceIdentifier =
- YangInstanceIdentifier.create(pathArguments);
- return instanceIdentifier;
+ return PathUtils.toYangInstanceIdentifier(s);
}
-
@Test
public void testNormalizeNodeAttributesToProtoBuffNode() {
final NormalizedNode<?, ?> documentOne = TestModel.createTestContainer();
NormalizedNodeGetter normalizedNodeGetter = new NormalizedNodeGetter(id);
new NormalizedNodeNavigator(normalizedNodeGetter).navigate(
- YangInstanceIdentifier.builder().build().toString(), documentOne);
+ PathUtils.toString(YangInstanceIdentifier.builder().build()), documentOne);
// Validate the value of id can be retrieved from the normalized node
NormalizedNode output = normalizedNodeGetter.getOutput();
--- /dev/null
+package org.opendaylight.controller.cluster.datastore.node.utils;
+
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class PathUtilsTest {
+
+ @Test
+ public void getParentPath(){
+ assertEquals("", PathUtils.getParentPath("foobar"));
+ assertEquals("", PathUtils.getParentPath("/a"));
+ assertEquals("/a", PathUtils.getParentPath("/a/b"));
+ assertEquals("/a/b", PathUtils.getParentPath("/a/b/c"));
+ assertEquals("/a/b", PathUtils.getParentPath("a/b/c"));
+ }
+
+ @Test
+ public void toStringNodeIdentifier(){
+ YangInstanceIdentifier.PathArgument pathArgument = nodeIdentifier();
+
+ String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test";
+
+ assertEquals(expected , PathUtils.toString(pathArgument));
+ }
+
+ @Test
+ public void toStringAugmentationIdentifier(){
+ String expected = "AugmentationIdentifier{childNames=[(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics]}";
+
+ YangInstanceIdentifier.PathArgument pathArgument = augmentationIdentifier();
+
+ assertEquals(expected, PathUtils.toString(pathArgument));
+ }
+
+ @Test
+ public void toStringNodeWithValue(){
+
+ YangInstanceIdentifier.PathArgument pathArgument = nodeWithValue();
+
+ String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[100]";
+
+ assertEquals(expected, PathUtils.toString(pathArgument));
+ }
+
+
+ @Test
+ public void toStringNodeIdentifierWithPredicates(){
+
+ YangInstanceIdentifier.PathArgument pathArgument = nodeIdentifierWithPredicates();
+
+ String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=100}]";
+
+ assertEquals(expected, PathUtils.toString(pathArgument));
+ }
+
+ @Test
+ public void toStringYangInstanceIdentifier(){
+
+ YangInstanceIdentifier path =
+ YangInstanceIdentifier.create(nodeIdentifier())
+ .node(nodeIdentifierWithPredicates())
+ .node(augmentationIdentifier()).node(nodeWithValue());
+
+
+ String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test/" +
+ "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=100}]/" +
+ "AugmentationIdentifier{childNames=[(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics]}/" +
+ "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[100]";
+
+ assertEquals(expected, PathUtils.toString(path));
+
+ }
+
+ @Test
+ public void toYangInstanceIdentifier(){
+ String expected = "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test/" +
+ "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[{(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)id=100}]/" +
+ "AugmentationIdentifier{childNames=[(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics]}/" +
+ "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test[100]";
+
+ YangInstanceIdentifier yangInstanceIdentifier =
+ PathUtils.toYangInstanceIdentifier(expected);
+
+ String actual = PathUtils.toString(yangInstanceIdentifier);
+
+ assertEquals(expected, actual);
+
+ }
+
+ private YangInstanceIdentifier.NodeIdentifier nodeIdentifier(){
+ return new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME);
+ }
+
+ private YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier(){
+ Set<QName> childNames = new HashSet();
+ childNames.add(QNameFactory.create("(urn:opendaylight:flow:table:statistics?revision=2013-12-15)flow-table-statistics"));
+
+ return new YangInstanceIdentifier.AugmentationIdentifier(childNames);
+ }
+
+ private YangInstanceIdentifier.NodeWithValue nodeWithValue(){
+ return new YangInstanceIdentifier.NodeWithValue(TestModel.TEST_QNAME, Integer.valueOf(100));
+ }
+
+ private YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates(){
+ Map<QName, Object> keys = new HashMap<>();
+
+ keys.put(TestModel.ID_QNAME, Integer.valueOf(100));
+
+ return new YangInstanceIdentifier.NodeIdentifierWithPredicates(TestModel.TEST_QNAME, keys);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.cluster.datastore.node.utils;
+
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.util.TestModel;
+import org.opendaylight.yangtools.yang.common.QName;
+
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+public class QNameFactoryTest {
+
+ @Test
+ public void testBasic(){
+ QName expected = TestModel.AUG_NAME_QNAME;
+ QName created = QNameFactory.create(expected.toString());
+
+ assertFalse( expected == created);
+
+ assertEquals(expected, created);
+
+ QName cached = QNameFactory.create(expected.toString());
+
+ assertEquals(expected, cached);
+
+ assertTrue( cached == created );
+ }
+
+}
<description>Configuration files for md-sal clustering</description>
<packaging>jar</packaging>
<build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/05-clustering.xml.conf</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
</build>
</project>
}
cluster {
- seed-nodes = ["akka.tcp://opendaylight-cluster-data@<CHANGE_ME>:2550"]
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@<CHANGE_SEED_IP>:2550"]
auto-down-unreachable-after = 10s
}
}
cluster {
- seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@<CHANGE_ME>:2551"]
+ seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@<CHANGE_SEED_IP>:2551"]
auto-down-unreachable-after = 10s
}
import org.opendaylight.yangtools.concepts.Path;
/**
- * A chain of transactions. Transactions in a chain need to be committed in sequence and each
- * transaction should see the effects of previous transactions as if they happened. A chain
- * makes no guarantees of atomicity, in fact transactions are committed as soon as possible.
+ * A chain of transactions. Transactions in a chain need to be committed in
+ * sequence and each transaction should see the effects of previous committed transactions
+ * as they occurred. A chain makes no guarantees of atomicity across the chained transactions -
+ * the transactions are committed as soon as possible in the order that they were submitted.
*
+ * This behaviour is different from the default AsyncDataBroker, where a
+ * transaction is always created from the current global state, not taking into
+ * account any transactions previously committed by the calling thread. Due to
+ * the asynchronous nature of transaction submission this can lead to surprising
+ * results. If a thread executes the following sequence sufficiently quickly:
+ *
+ * AsyncWriteTransaction t1 = broker.newWriteOnlyTransaction();
+ * t1.put(id, data);
+ * t1.submit();
+ *
+ * AsyncReadTransaction t2 = broker.newReadOnlyTransaction();
+ * Optional<?> maybeData = t2.read(id).get();
+ *
+ * it may happen, that it sees maybeData.isPresent() == false, simply because
+ * t1 has not completed the processes of being applied and t2 is actually
+ * allocated from the previous state. This is obviously bad for users who create
+ * incremental state in the datastore and actually read what they write in
+ * subsequent transactions.
+ *
+ * Using a TransactionChain instead of a broker solves this particular problem,
+ * and leads to expected behavior: t2 will always see the data written in t1
+ * present.
*/
-public interface TransactionChain<P extends Path<P>, D> extends AutoCloseable, AsyncDataTransactionFactory<P, D> {
+public interface TransactionChain<P extends Path<P>, D> extends AutoCloseable,
+ AsyncDataTransactionFactory<P, D> {
/**
* Create a new read only transaction which will continue the chain.
- * The previous read-write transaction has to be either COMMITED or CANCELLED.
+ *
+ * <p>
+ * The previous write transaction has to be either SUBMITTED
+ * ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
+ * ({@link #close close} was invoked).
+ * <p>
+ * The returned read-only transaction presents an isolated view of the data if the previous
+ * write transaction was successful - in other words, this read-only transaction will see the
+ * state changes made by the previous write transaction in the chain. However, state which
+ * was introduced by other transactions outside this transaction chain after creation of
+ * the previous transaction is not visible.
*
* @return New transaction in the chain.
- * @throws IllegalStateException if the previous transaction was not COMMITED
- * or CANCELLED.
- * @throws TransactionChainClosedException if the chain has been closed.
+ * @throws IllegalStateException
+ * if the previous transaction was not SUBMITTED or CANCELLED.
+ * @throws TransactionChainClosedException
+ * if the chain has been closed.
*/
@Override
public AsyncReadOnlyTransaction<P, D> newReadOnlyTransaction();
-
/**
- * Create a new read write transaction which will continue the chain.
- * The previous read-write transaction has to be either COMMITED or CANCELLED.
+ * Create a new read-write transaction which will continue the chain.
+ *
+ * <p>
+ * The previous write transaction has to be either SUBMITTED
+ * ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
+ * ({@link #close close} was invoked).
+ * <p>
+ * The returned read-write transaction presents an isolated view of the data if the previous
+ * write transaction was successful - in other words, this read-write transaction will see the
+ * state changes made by the previous write transaction in the chain. However, state which
+ * was introduced by other transactions outside this transaction chain after creation of
+ * the previous transaction is not visible.
+ * <p>
+ * Committing this read-write transaction using {@link AsyncWriteTransaction#submit submit}
+ * will submit the state changes in this transaction to be visible to any subsequent
+ * transaction in this chain and also to any transaction outside this chain.
*
* @return New transaction in the chain.
- * @throws IllegalStateException if the previous transaction was not COMMITTED
- * or CANCELLED.
- * @throws TransactionChainClosedException if the chain has been closed.
+ * @throws IllegalStateException
+ * if the previous transaction was not SUBMITTED or CANCELLED.
+ * @throws TransactionChainClosedException
+ * if the chain has been closed.
*/
@Override
public AsyncReadWriteTransaction<P, D> newReadWriteTransaction();
+ /**
+ * Create a new write-only transaction which will continue the chain.
+ *
+ * <p>
+ * The previous write transaction has to be either SUBMITTED
+ * ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
+ * ({@link #close close} was invoked).
+ * <p>
+ * The returned write-only transaction presents an isolated view of the data if the previous
+ * write transaction was successful - in other words, this write-only transaction will see the
+ * state changes made by the previous write transaction in the chain. However, state which
+ * was introduced by other transactions outside this transaction chain after creation of
+ * the previous transaction is not visible.
+ * <p>
+ * Committing this write-only transaction using {@link AsyncWriteTransaction#submit submit}
+ * will submit the state changes in this transaction to be visible to any subsequent
+ * transaction in this chain and also to any transaction outside this chain.
+ *
+ * @return New transaction in the chain.
+ * @throws IllegalStateException
+ * if the previous transaction was not SUBMITTED or CANCELLED.
+ * @throws TransactionChainClosedException
+ * if the chain has been closed.
+ */
+ @Override
+ public AsyncWriteTransaction<P, D> newWriteOnlyTransaction();
+
@Override
void close();
}
-
* Interface for creating transaction chains.
*/
public interface TransactionChainFactory<P extends Path<P>, D> {
+
/**
* Create a new transaction chain. The chain will be initialized to read
* from its backing datastore, with no outstanding transaction. Listener
@Override
public DOMStoreReadWriteTransaction newReadWriteTransaction() {
return new TransactionProxy(actorContext,
- TransactionProxy.TransactionType.WRITE_ONLY, schemaContext);
+ TransactionProxy.TransactionType.READ_WRITE, schemaContext);
}
@Override
public DOMStoreWriteTransaction newWriteOnlyTransaction() {
return new TransactionProxy(actorContext,
- TransactionProxy.TransactionType.READ_WRITE, schemaContext);
+ TransactionProxy.TransactionType.WRITE_ONLY, schemaContext);
}
@Override
this.identifier = TransactionIdentifier.builder().memberName(memberName).counter(
counter.getAndIncrement()).build();
- LOG.debug("Created txn {}", identifier);
+ LOG.debug("Created txn {} of type {}", identifier, transactionType);
}
package org.opendaylight.controller.cluster.datastore.messages;
import com.google.common.base.Preconditions;
-import org.opendaylight.controller.protobuff.messages.shard.ShardManagerMessages;
/**
* The FindPrimary message is used to locate the primary of any given shard
*
*/
public class FindPrimary implements SerializableMessage{
- public static final Class SERIALIZABLE_CLASS = ShardManagerMessages.FindPrimary.class;
+ public static final Class SERIALIZABLE_CLASS = FindPrimary.class;
private final String shardName;
public FindPrimary(String shardName){
@Override
public Object toSerializable() {
- return ShardManagerMessages.FindPrimary.newBuilder().setShardName(shardName).build();
+ return this;
}
public static FindPrimary fromSerializable(Object message){
- return new FindPrimary(((ShardManagerMessages.FindPrimary)message).getShardName());
+ return (FindPrimary) message;
}
}
package org.opendaylight.controller.cluster.datastore.messages;
-import org.opendaylight.controller.protobuff.messages.shard.ShardManagerMessages;
public class PrimaryFound implements SerializableMessage {
- public static final Class SERIALIZABLE_CLASS = ShardManagerMessages.PrimaryFound.class;
+ public static final Class SERIALIZABLE_CLASS = PrimaryFound.class;
private final String primaryPath;
public PrimaryFound(String primaryPath) {
@Override
public Object toSerializable() {
- return ShardManagerMessages.PrimaryFound.newBuilder().setPrimaryPath(primaryPath).build();
+ return this;
}
public static PrimaryFound fromSerializable(Object message){
- return new PrimaryFound(((ShardManagerMessages.PrimaryFound)message).getPrimaryPath());
+ return (PrimaryFound) message;
}
}
package org.opendaylight.controller.cluster.datastore.messages;
import com.google.common.base.Preconditions;
-import org.opendaylight.controller.protobuff.messages.shard.ShardManagerMessages;
public class PrimaryNotFound implements SerializableMessage {
- public static final Class SERIALIZABLE_CLASS = ShardManagerMessages.PrimaryNotFound.class;
+ public static final Class SERIALIZABLE_CLASS = PrimaryNotFound.class;
private final String shardName;
@Override
public Object toSerializable() {
- return ShardManagerMessages.PrimaryNotFound.newBuilder().setShardName(shardName).build();
+ return this;
}
public static PrimaryNotFound fromSerializable(Object message){
- return new PrimaryNotFound(((ShardManagerMessages.PrimaryNotFound)message).getShardName());
+ return (PrimaryNotFound) message;
}
}
--- /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.controller.cluster.datastore;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class TransactionChainProxyTest {
+ ActorContext actorContext = Mockito.mock(ActorContext.class);
+ SchemaContext schemaContext = Mockito.mock(SchemaContext.class);
+ @Test
+ public void testNewReadOnlyTransaction() throws Exception {
+
+ DOMStoreTransaction dst = new TransactionChainProxy(actorContext, schemaContext).newReadOnlyTransaction();
+ Assert.assertTrue(dst instanceof DOMStoreReadTransaction);
+
+ }
+
+ @Test
+ public void testNewReadWriteTransaction() throws Exception {
+ DOMStoreTransaction dst = new TransactionChainProxy(actorContext, schemaContext).newReadWriteTransaction();
+ Assert.assertTrue(dst instanceof DOMStoreReadWriteTransaction);
+
+ }
+
+ @Test
+ public void testNewWriteOnlyTransaction() throws Exception {
+ DOMStoreTransaction dst = new TransactionChainProxy(actorContext, schemaContext).newWriteOnlyTransaction();
+ Assert.assertTrue(dst instanceof DOMStoreWriteTransaction);
+
+ }
+
+ @Test(expected=UnsupportedOperationException.class)
+ public void testClose() throws Exception {
+ new TransactionChainProxy(actorContext, schemaContext).close();
+ }
+}
* sequence and each transaction must see the effects of previous transactions
* as if they happened. A chain makes no guarantees of atomicity, in fact
* transactions are committed as soon as possible.
- *
- *
*/
public interface DOMStoreTransactionChain extends DOMStoreTransactionFactory, AutoCloseable {
* if the chain has been closed.
*/
@Override
- public DOMStoreReadTransaction newReadOnlyTransaction();
+ DOMStoreReadTransaction newReadOnlyTransaction();
/**
* Create a new read write transaction which will continue the chain. The
* if the chain has been closed.
*/
@Override
- public DOMStoreReadWriteTransaction newReadWriteTransaction();
+ DOMStoreReadWriteTransaction newReadWriteTransaction();
/**
- * Create a new read write transaction which will continue the chain. The
+ * Create a new write-only transaction which will continue the chain. The
* previous read-write transaction has to be either READY or CANCELLED.
*
*
* if the chain has been closed.
*/
@Override
- public DOMStoreWriteTransaction newWriteOnlyTransaction();
-
+ DOMStoreWriteTransaction newWriteOnlyTransaction();
/**
* Closes Transaction Chain.
* @throws IllegalStateException If any of the outstanding created transactions was not canceled or ready.
*/
@Override
- public void close();
-
+ void close();
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+ Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.\r
+\r
+ This program and the accompanying materials are made available under the\r
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ and is available at http://www.eclipse.org/legal/epl-v10.html\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
+\r
+ <modelVersion>4.0.0</modelVersion>\r
+\r
+ <parent>\r
+ <artifactId>sal-parent</artifactId>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <version>1.1-SNAPSHOT</version>\r
+ </parent>\r
+ <artifactId>sal-dom-xsql-config</artifactId>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <description>Configuration files for md-sal</description>\r
+ <packaging>jar</packaging>\r
+ <properties>\r
+ <!-- Optional TODO: Rename your configfile to taste -->\r
+ <configfile>04-xsql.xml</configfile>\r
+ </properties>\r
+ <build>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.codehaus.mojo</groupId>\r
+ <artifactId>build-helper-maven-plugin</artifactId>\r
+ <executions>\r
+ <execution>\r
+ <id>attach-artifacts</id>\r
+ <goals>\r
+ <goal>attach-artifact</goal>\r
+ </goals>\r
+ <phase>package</phase>\r
+ <configuration>\r
+ <artifacts>\r
+ <artifact>\r
+ <file>${project.build.directory}/classes/${configfile}</file>\r
+ <type>xml</type>\r
+ <classifier>config</classifier>\r
+ </artifact>\r
+ </artifacts>\r
+ </configuration>\r
+ </execution>\r
+ </executions>\r
+ </plugin>\r
+ </plugins>\r
+ </build>\r
+ <scm>\r
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
+ <tag>HEAD</tag>\r
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary</url>\r
+ </scm>\r
+</project>\r
--- /dev/null
+<snapshot>
+ <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:XSQL="http://netconfcentral.org/ns/XSQL">
+ XSQL:XSQL
+ </type>
+ <name>XSQL</name>
+ <data-broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <name>binding-data-broker</name>
+ </data-broker>
+ <async-data-broker>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+ <name>inmemory-data-broker</name>
+ </async-data-broker>
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+ <required-capabilities>
+ <capability>http://netconfcentral.org/ns/XSQL?module=XSQL&revision=2014-06-26</capability>
+ </required-capabilities>
+</snapshot>
}
@Override
- public synchronized DOMStoreThreePhaseCommitCohort ready(final SnapshotBackedWriteTransaction writeTx) {
+ public DOMStoreThreePhaseCommitCohort ready(final SnapshotBackedWriteTransaction writeTx) {
LOG.debug("Tx: {} is submitted. Modifications: {}", writeTx.getIdentifier(), writeTx.getMutatedView());
return new ThreePhaseCommitImpl(writeTx);
}
implements DOMStoreReadTransaction {
private static final Logger LOG = LoggerFactory.getLogger(SnapshotBackedReadTransaction.class);
- private DataTreeSnapshot stableSnapshot;
+ private volatile DataTreeSnapshot stableSnapshot;
public SnapshotBackedReadTransaction(final Object identifier, final DataTreeSnapshot snapshot) {
super(identifier);
LOG.debug("Tx: {} Read: {}", getIdentifier(), path);
checkNotNull(path, "Path must not be null.");
- if(stableSnapshot == null) {
+ final DataTreeSnapshot snapshot = stableSnapshot;
+ if (snapshot == null) {
return Futures.immediateFailedCheckedFuture(new ReadFailedException("Transaction is closed"));
}
try {
- return Futures.immediateCheckedFuture(stableSnapshot.readNode(path));
+ return Futures.immediateCheckedFuture(snapshot.readNode(path));
} catch (Exception e) {
LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read failed",e));
}
}
- @Override public CheckedFuture<Boolean, ReadFailedException> exists(YangInstanceIdentifier path) {
+ @Override
+ public CheckedFuture<Boolean, ReadFailedException> exists(YangInstanceIdentifier path) {
LOG.debug("Tx: {} Exists: {}", getIdentifier(), path);
checkNotNull(path, "Path must not be null.");
final CompositeNode schemasNode =
(CompositeNode) NetconfMessageTransformUtil.findNode(schemasNodeResult.getResult(), DATA_STATE_SCHEMAS_IDENTIFIER);
+ if(schemasNode == null) {
+ logger.warn("{}: Unable to detect available schemas, get to {} was empty", id, STATE_SCHEMAS_IDENTIFIER);
+ return EMPTY;
+ }
+
return create(id, schemasNode);
}
import static org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.toTopologyNode;
import static org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.toTopologyNodeId;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import java.util.List;
+
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
class FlowCapableTopologyExporter implements FlowTopologyDiscoveryListener, OpendaylightInventoryListener {
private final Logger LOG = LoggerFactory.getLogger(FlowCapableTopologyExporter.class);
@Override
public void onSuccess(Optional<Topology> topologyOptional) {
if (topologyOptional.isPresent()) {
- Topology topologyData = topologyOptional.get();
- for (Link link : topologyData.getLink()) {
+ List<Link> linkList = topologyOptional.get().getLink() != null
+ ? topologyOptional.get().getLink() : Collections.<Link> emptyList();
+ for (Link link : linkList) {
if (id.equals(link.getSource().getSourceNode()) || id.equals(link.getDestination().getDestNode())) {
transaction.delete(LogicalDatastoreType.OPERATIONAL, linkPath(link));
}
@Override
public void onSuccess(Optional<Topology> topologyOptional) {
if (topologyOptional.isPresent()) {
- Topology topologyData = topologyOptional.get();
- for (Link link : topologyData.getLink()) {
+ List<Link> linkList = topologyOptional.get().getLink() != null
+ ? topologyOptional.get().getLink() : Collections.<Link> emptyList();
+ for (Link link : linkList) {
if (id.equals(link.getSource().getSourceTp()) || id.equals(link.getDestination().getDestTp())) {
transaction.delete(LogicalDatastoreType.OPERATIONAL, linkPath(link));
}
if(configs != null && !configs.isEmpty()) {
configPusher.pushConfigs(configs);
}
- registration = context.registerService(ConfigPusher.class.getName(), configPusher, null);
- configPusher.process(autoCloseables, platformMBeanServer, persisterAggregator);
+ if(context != null) {
+ registration = context.registerService(ConfigPusher.class.getName(), configPusher, null);
+ configPusher.process(autoCloseables, platformMBeanServer, persisterAggregator);
+ } else {
+ logger.warn("Unable to process configs as BundleContext is null");
+ }
} catch (InterruptedException e) {
logger.info("ConfigPusher thread stopped",e);
}
import java.io.IOException;
import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandler;
import org.opendaylight.protocol.framework.SessionListenerFactory;
final class SshClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
@Override
public void initialize(final Channel ch, final Promise<NetconfClientSession> promise) {
try {
- ch.pipeline().addFirst(SshHandler.createForNetconfSubsystem(authenticationHandler));
+ ch.pipeline().addFirst(AsyncSshHandler.createForNetconfSubsystem(authenticationHandler));
super.initialize(ch,promise);
} catch (final IOException e) {
throw new RuntimeException(e);
package org.opendaylight.controller.netconf.it;
import static java.util.Arrays.asList;
-import static org.mockito.Matchers.any;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import ch.ethz.ssh2.Connection;
-import io.netty.channel.ChannelFuture;
+import com.google.common.collect.Lists;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.GlobalEventExecutor;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
import junit.framework.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProviderImpl;
super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, getModuleFactories().toArray(
new ModuleFactory[0])));
- NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+ final NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
final NetconfServerDispatcher dispatchS = createDispatcher(factoriesListener);
- ChannelFuture s = dispatchS.createLocalServer(NetconfConfigUtil.getNetconfLocalAddress());
- s.await();
- EventLoopGroup bossGroup = new NioEventLoopGroup();
+ dispatchS.createLocalServer(NetconfConfigUtil.getNetconfLocalAddress()).await();
+ final EventLoopGroup bossGroup = new NioEventLoopGroup();
sshServer = NetconfSSHServer.start(tlsAddress.getPort(), NetconfConfigUtil.getNetconfLocalAddress(), getAuthProvider(), bossGroup);
}
- private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+ private NetconfServerDispatcher createDispatcher(final NetconfOperationServiceFactoryListenerImpl factoriesListener) {
return super.createDispatcher(factoriesListener, NetconfITTest.getNetconfMonitoringListenerService(), commitNot);
}
@After
public void tearDown() throws Exception {
- sshServer.stop();
+ sshServer.close();
commitNot.close();
+ sshServer.join();
}
private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
@Test
public void testSecure() throws Exception {
- NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
+ final NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
try (TestingNetconfClient netconfClient = new TestingNetconfClient("testing-ssh-client", dispatch, getClientConfiguration())) {
NetconfMessage response = netconfClient.sendMessage(getConfig);
Assert.assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()),
NetconfMessageUtil.isErrorMessage(response));
- NetconfMessage gs = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc message-id=\"2\"\n" +
+ final NetconfMessage gs = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc message-id=\"2\"\n" +
" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
" <get-schema xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n" +
" <identifier>config</identifier>\n" +
}
}
+ /**
+ * Test all requests are handled properly and no mismatch occurs in listener
+ */
+ @Test(timeout = 3*60*1000)
+ public void testSecureStress() throws Exception {
+ final NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
+ try (TestingNetconfClient netconfClient = new TestingNetconfClient("testing-ssh-client", dispatch, getClientConfiguration())) {
+
+ final AtomicInteger responseCounter = new AtomicInteger(0);
+ final List<Future<?>> futures = Lists.newArrayList();
+
+ final int requests = 1000;
+ for (int i = 0; i < requests; i++) {
+ final Future<NetconfMessage> netconfMessageFuture = netconfClient.sendRequest(getConfig);
+ futures.add(netconfMessageFuture);
+ netconfMessageFuture.addListener(new GenericFutureListener<Future<? super NetconfMessage>>() {
+ @Override
+ public void operationComplete(final Future<? super NetconfMessage> future) throws Exception {
+ assertTrue("Request unsuccessful " + future.cause(), future.isSuccess());
+ responseCounter.incrementAndGet();
+ }
+ });
+ }
+
+ for (final Future<?> future : futures) {
+ future.await();
+ }
+
+ // Give future listeners some time to finish counter incrementation
+ Thread.sleep(5000);
+
+ org.junit.Assert.assertEquals(requests, responseCounter.get());
+ }
+ }
+
public NetconfClientConfiguration getClientConfiguration() throws IOException {
final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
b.withAddress(tlsAddress);
}
public AuthProvider getAuthProvider() throws Exception {
- AuthProvider mock = mock(AuthProviderImpl.class);
+ final AuthProvider mock = mock(AuthProviderImpl.class);
doReturn(true).when(mock).authenticated(anyString(), anyString());
doReturn(PEMGenerator.generate().toCharArray()).when(mock).getPEMAsCharArray();
return mock;
}
public AuthenticationHandler getAuthHandler() throws IOException {
- final AuthenticationHandler authHandler = mock(AuthenticationHandler.class);
- doAnswer(new Answer() {
- @Override
- public Object answer(final InvocationOnMock invocation) throws Throwable {
- Connection conn = (Connection) invocation.getArguments()[0];
- conn.authenticateWithPassword("user", "pwd");
- return null;
- }
- }).when(authHandler).authenticate(any(Connection.class));
- doReturn("auth handler").when(authHandler).toString();
- return authHandler;
+ return new LoginPassword("user", "pwd");
}
}
*/
package org.opendaylight.controller.netconf.monitoring;
-import com.google.common.collect.Maps;
-
+import java.util.Collections;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import java.util.Map;
-
public class Get extends AbstractNetconfOperation {
private static final Logger logger = LoggerFactory.getLogger(Get.class);
private final NetconfMonitoringService netconfMonitor;
- public Get(NetconfMonitoringService netconfMonitor) {
+ public Get(final NetconfMonitoringService netconfMonitor) {
super(MonitoringConstants.MODULE_NAME);
this.netconfMonitor = netconfMonitor;
}
- private Element getPlaceholder(Document innerResult) throws NetconfDocumentedException {
- try {
- XmlElement rootElement = null;
- rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(),
- XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE);
- return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement();
- } catch (RuntimeException e) {
- throw new IllegalArgumentException(String.format(
- "Input xml in wrong format, Expecting root element %s with child element %s, but was %s",
- XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.DATA_KEY,
- XmlUtil.toString(innerResult.getDocumentElement())), e);
- }
+ private Element getPlaceholder(final Document innerResult)
+ throws NetconfDocumentedException {
+ final XmlElement rootElement = XmlElement.fromDomElementWithExpected(
+ innerResult.getDocumentElement(), XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE);
+ return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement();
}
@Override
}
@Override
- public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
+ public Document handle(final Document requestMessage, final NetconfOperationChainedExecution subsequentOperation)
throws NetconfDocumentedException {
if (subsequentOperation.isExecutionTermination()){
throw new NetconfDocumentedException(String.format("Subsequent netconf operation expected by %s", this),
}
try {
- Document innerResult = subsequentOperation.execute(requestMessage);
+ final Document innerResult = subsequentOperation.execute(requestMessage);
- NetconfState netconfMonitoring = new NetconfState(netconfMonitor);
+ final NetconfState netconfMonitoring = new NetconfState(netconfMonitor);
Element monitoringXmlElement = new JaxBSerializer().toXml(netconfMonitoring);
monitoringXmlElement = (Element) innerResult.importNode(monitoringXmlElement, true);
- Element monitoringXmlElementPlaceholder = getPlaceholder(innerResult);
+ final Element monitoringXmlElementPlaceholder = getPlaceholder(innerResult);
monitoringXmlElementPlaceholder.appendChild(monitoringXmlElement);
return innerResult;
- } catch (RuntimeException e) {
- String errorMessage = "Get operation for netconf-state subtree failed";
+ } catch (final RuntimeException e) {
+ final String errorMessage = "Get operation for netconf-state subtree failed";
logger.warn(errorMessage, e);
- Map<String, String> info = Maps.newHashMap();
- info.put(NetconfDocumentedException.ErrorSeverity.error.toString(), e.getMessage());
+
throw new NetconfDocumentedException(errorMessage, NetconfDocumentedException.ErrorType.application,
NetconfDocumentedException.ErrorTag.operation_failed,
- NetconfDocumentedException.ErrorSeverity.error, info);
+ NetconfDocumentedException.ErrorSeverity.error,
+ Collections.singletonMap(NetconfDocumentedException.ErrorSeverity.error.toString(), e.getMessage()));
}
}
@Override
- protected Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation)
+ protected Element handle(final Document document, final XmlElement message, final NetconfOperationChainedExecution subsequentOperation)
throws NetconfDocumentedException {
throw new UnsupportedOperationException("Never gets called");
}
public void start(final BundleContext context) {
monitor = new NetconfMonitoringServiceTracker(context);
monitor.open();
-
}
@Override
package org.opendaylight.controller.netconf.monitoring.osgi;
import com.google.common.base.Preconditions;
+import java.util.Hashtable;
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
public class NetconfMonitoringServiceTracker extends ServiceTracker<NetconfMonitoringService, NetconfMonitoringService> {
private static final Logger logger = LoggerFactory.getLogger(NetconfMonitoringServiceTracker.class);
private ServiceRegistration<NetconfOperationServiceFactory> reg;
- NetconfMonitoringServiceTracker(BundleContext context) {
+ NetconfMonitoringServiceTracker(final BundleContext context) {
super(context, NetconfMonitoringService.class, null);
}
@Override
- public NetconfMonitoringService addingService(ServiceReference<NetconfMonitoringService> reference) {
+ public NetconfMonitoringService addingService(final ServiceReference<NetconfMonitoringService> reference) {
Preconditions.checkState(reg == null, "Monitoring service was already added");
- NetconfMonitoringService netconfMonitoringService = super.addingService(reference);
+ final NetconfMonitoringService netconfMonitoringService = super.addingService(reference);
final NetconfMonitoringOperationService operationService = new NetconfMonitoringOperationService(
netconfMonitoringService);
- NetconfOperationServiceFactory factory = new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
+ final NetconfOperationServiceFactory factory = new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
operationService);
- Dictionary<String, ?> props = new Hashtable<>();
- reg = context.registerService(NetconfOperationServiceFactory.class, factory, props);
+ reg = context.registerService(NetconfOperationServiceFactory.class, factory, new Hashtable<String, Object>());
return netconfMonitoringService;
}
@Override
- public void removedService(ServiceReference<NetconfMonitoringService> reference,
- NetconfMonitoringService netconfMonitoringService) {
+ public void removedService(final ServiceReference<NetconfMonitoringService> reference,
+ final NetconfMonitoringService netconfMonitoringService) {
if(reg!=null) {
try {
reg.unregister();
- } catch (Exception e) {
+ } catch (final Exception e) {
logger.warn("Ignoring exception while unregistering {}", reg, e);
}
}
public class JaxBSerializer {
- public Element toXml(NetconfState monitoringModel) {
- DOMResult res = null;
+ public Element toXml(final NetconfState monitoringModel) {
+ final DOMResult res;
try {
- JAXBContext jaxbContext = JAXBContext.newInstance(NetconfState.class);
- Marshaller marshaller = jaxbContext.createMarshaller();
+ final JAXBContext jaxbContext = JAXBContext.newInstance(NetconfState.class);
+ final Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
res = new DOMResult();
marshaller.marshal(monitoringModel, res);
- } catch (JAXBException e) {
+ } catch (final JAXBException e) {
throw new RuntimeException("Unable to serialize netconf state " + monitoringModel, e);
}
return ((Document)res.getNode()).getDocumentElement();
private Schemas schemas;
private Sessions sessions;
- public NetconfState(NetconfMonitoringService monitoringService) {
+ public NetconfState(final NetconfMonitoringService monitoringService) {
this.sessions = monitoringService.getSessions();
this.schemas = monitoringService.getSchemas();
}
- public NetconfState() {
- }
-
-
+ public NetconfState() {}
@XmlElementWrapper(name="schemas")
@XmlElement(name="schema")
return Collections2.transform(schemas.getSchema(), new Function<Schema, MonitoringSchema>() {
@Nullable
@Override
- public MonitoringSchema apply(@Nullable Schema input) {
+ public MonitoringSchema apply(@Nullable final Schema input) {
return new MonitoringSchema(input);
}
});
return Collections2.transform(sessions.getSession(), new Function<Session, MonitoringSession>() {
@Nullable
@Override
- public MonitoringSession apply(@Nullable Session input) {
+ public MonitoringSession apply(@Nullable final Session input) {
return new MonitoringSession(input);
}
});
--- /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.controller.netconf.monitoring;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.TestCase.fail;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+
+import java.util.Collections;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SchemasBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SessionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
+import org.w3c.dom.Document;
+
+public class GetTest {
+
+ @Mock
+ private NetconfMonitoringService monitor;
+ @Mock
+ private Document request;
+ @Mock
+ private NetconfOperationChainedExecution subsequentOperation;
+ private Document incorrectSubsequentResult;
+ private Document correctSubsequentResult;
+
+ private Get get;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ incorrectSubsequentResult = XmlUtil.readXmlToDocument("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>");
+ correctSubsequentResult = XmlUtil.readXmlToDocument("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><data></data></rpc-reply>");
+
+ doReturn(new SessionsBuilder().setSession(Collections.<Session>emptyList()).build()).when(monitor).getSessions();
+ doReturn(new SchemasBuilder().setSchema(Collections.<Schema>emptyList()).build()).when(monitor).getSchemas();
+ doReturn(false).when(subsequentOperation).isExecutionTermination();
+
+ get = new Get(monitor);
+ }
+
+ @Test
+ public void testHandleNoSubsequent() throws Exception {
+ try {
+ get.handle(null, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
+ } catch (final NetconfDocumentedException e) {
+ assertNetconfDocumentedEx(e, NetconfDocumentedException.ErrorSeverity.error, NetconfDocumentedException.ErrorTag.operation_failed, NetconfDocumentedException.ErrorType.application);
+ return;
+ }
+
+ fail("Get should fail without subsequent operation");
+ }
+
+ @Test
+ public void testHandleWrongPlaceholder() throws Exception {
+ doReturn(incorrectSubsequentResult).when(subsequentOperation).execute(request);
+ try {
+ get.handle(request, subsequentOperation);
+ } catch (final NetconfDocumentedException e) {
+ assertNetconfDocumentedEx(e, NetconfDocumentedException.ErrorSeverity.error, NetconfDocumentedException.ErrorTag.invalid_value, NetconfDocumentedException.ErrorType.application);
+ return;
+ }
+
+ fail("Get should fail with wrong xml");
+ }
+
+ @Test
+ public void testHandleRuntimeEx() throws Exception {
+ doThrow(RuntimeException.class).when(subsequentOperation).execute(request);
+ try {
+ get.handle(request, subsequentOperation);
+ } catch (final NetconfDocumentedException e) {
+ assertNetconfDocumentedEx(e, NetconfDocumentedException.ErrorSeverity.error, NetconfDocumentedException.ErrorTag.operation_failed, NetconfDocumentedException.ErrorType.application);
+ assertEquals(1, e.getErrorInfo().size());
+ return;
+ }
+
+ fail("Get should fail with wrong xml");
+ }
+
+ @Test
+ public void testSuccessHandle() throws Exception {
+ doReturn(correctSubsequentResult).when(subsequentOperation).execute(request);
+ assertTrue(get.getHandlingPriority().getPriority().get() > HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.getPriority().get());
+ final Document result = get.handle(request, subsequentOperation);
+ assertThat(XmlUtil.toString(result), CoreMatchers.containsString("sessions"));
+ assertThat(XmlUtil.toString(result), CoreMatchers.containsString("schemas"));
+
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testHandle() throws Exception {
+ get.handle(null, null, null);
+
+ }
+
+ private void assertNetconfDocumentedEx(final NetconfDocumentedException e, final NetconfDocumentedException.ErrorSeverity severity, final NetconfDocumentedException.ErrorTag errorTag, final NetconfDocumentedException.ErrorType type) {
+ assertEquals(severity, e.getErrorSeverity());
+ assertEquals(errorTag, e.getErrorTag());
+ assertEquals(type, e.getErrorType());
+ }
+}
*/
package org.opendaylight.controller.netconf.monitoring.xml;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
import com.google.common.collect.Lists;
+import org.hamcrest.CoreMatchers;
import org.junit.Test;
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.NetconfTcp;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Transport;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SchemasBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SessionsBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.SchemaKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.DateAndTime;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.ZeroBasedCounter32;
-import org.w3c.dom.Element;
-
-import java.util.Date;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
public class JaxBSerializerTest {
@Test
public void testName() throws Exception {
- NetconfMonitoringService service = new NetconfMonitoringService() {
+ final NetconfMonitoringService service = new NetconfMonitoringService() {
@Override
public Sessions getSessions() {
@Override
public Schemas getSchemas() {
- return new SchemasBuilder().setSchema(Lists.<Schema>newArrayList()).build();
+ return new SchemasBuilder().setSchema(Lists.newArrayList(getMockSchema("id", "v1", Yang.class), getMockSchema("id2", "", Yang.class))).build();
}
};
- NetconfState model = new NetconfState(service);
- Element xml = new JaxBSerializer().toXml(model);
+ final NetconfState model = new NetconfState(service);
+ final String xml = XmlUtil.toString(new JaxBSerializer().toXml(model));
+
+ assertThat(xml, CoreMatchers.containsString(
+ "<schema>\n" +
+ "<format>yang</format>\n" +
+ "<identifier>id</identifier>\n" +
+ "<location>NETCONF</location>\n" +
+ "<namespace>localhost</namespace>\n" +
+ "<version>v1</version>\n" +
+ "</schema>\n"));
+
+ assertThat(xml, CoreMatchers.containsString(
+ "<session>\n" +
+ "<session-id>1</session-id>\n" +
+ "<in-bad-rpcs>0</in-bad-rpcs>\n" +
+ "<in-rpcs>0</in-rpcs>\n" +
+ "<login-time>loginTime</login-time>\n" +
+ "<out-notifications>0</out-notifications>\n" +
+ "<out-rpc-errors>0</out-rpc-errors>\n" +
+ "<ncme:session-identifier>client</ncme:session-identifier>\n" +
+ "<source-host>address/port</source-host>\n" +
+ "<transport>ncme:netconf-tcp</transport>\n" +
+ "<username>username</username>\n" +
+ "</session>"));
+ }
+
+ private Schema getMockSchema(final String id, final String version, final Class<Yang> format) {
+ final Schema mock = mock(Schema.class);
+
+ doReturn(format).when(mock).getFormat();
+ doReturn(id).when(mock).getIdentifier();
+ doReturn(new Uri("localhost")).when(mock).getNamespace();
+ doReturn(version).when(mock).getVersion();
+ doReturn(Lists.newArrayList(new Schema.Location(Schema.Location.Enumeration.NETCONF))).when(mock).getLocation();
+ doReturn(new SchemaKey(format, id, version)).when(mock).getKey();
+ return mock;
}
- private Session getMockSession(Class<? extends Transport> transportType) {
- Session mocked = mock(Session.class);
- Session1 mockedSession1 = mock(Session1.class);
+ private Session getMockSession(final Class<? extends Transport> transportType) {
+ final Session mocked = mock(Session.class);
+ final Session1 mockedSession1 = mock(Session1.class);
doReturn("client").when(mockedSession1).getSessionIdentifier();
doReturn(1L).when(mocked).getSessionId();
- doReturn(new DateAndTime(new Date().toString())).when(mocked).getLoginTime();
+ doReturn(new DateAndTime("loginTime")).when(mocked).getLoginTime();
doReturn(new Host(new DomainName("address/port"))).when(mocked).getSourceHost();
doReturn(new ZeroBasedCounter32(0L)).when(mocked).getInBadRpcs();
doReturn(new ZeroBasedCounter32(0L)).when(mocked).getInRpcs();
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>ganymed</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ </dependency>
<dependency>
<groupId>org.openexi</groupId>
<artifactId>nagasena</artifactId>
<groupId>org.openexi</groupId>
<artifactId>nagasena-rta</artifactId>
</dependency>
-
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ </dependency>
</dependencies>
<build>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>ch.ethz.ssh2, com.google.common.base, com.google.common.collect, io.netty.buffer,
+ <Import-Package>org.apache.sshd.*, ch.ethz.ssh2, com.google.common.base, com.google.common.collect, io.netty.buffer,
io.netty.channel, io.netty.channel.socket, io.netty.handler.codec, io.netty.handler.ssl, io.netty.util,
io.netty.util.concurrent, javax.xml.transform, javax.xml.transform.dom, javax.xml.transform.sax,
javax.xml.transform.stream, org.opendaylight.controller.netconf.api,
Optional<NetconfHelloMessageAdditionalHeader> headerOptional = ((NetconfHelloMessage) msg)
.getAdditionalHeader();
- // If additional header present, serialize it along with netconf hello
- // message
+ // If additional header present, serialize it along with netconf hello message
if (headerOptional.isPresent()) {
out.writeBytes(headerOptional.get().toFormattedString().getBytes(Charsets.UTF_8));
}
*/
package org.opendaylight.controller.netconf.nettyutil.handler;
-import java.util.List;
-
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
+import java.util.List;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public final class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToMessageDecoder.class);
@Override
- @VisibleForTesting
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() != 0) {
package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
-import ch.ethz.ssh2.Connection;
-
import java.io.IOException;
+import org.apache.sshd.ClientSession;
/**
* Class providing authentication facility to SSH handler.
*/
public abstract class AuthenticationHandler {
- public abstract void authenticate(Connection connection) throws IOException;
+
+ public abstract String getUsername();
+
+ public abstract org.apache.sshd.client.future.AuthFuture authenticate(final ClientSession session) throws IOException;
}
package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
-import ch.ethz.ssh2.Connection;
-
import java.io.IOException;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.client.future.AuthFuture;
/**
* Class Providing username/password authentication option to
- * {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshHandler}
+ * {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandler}
*/
public class LoginPassword extends AuthenticationHandler {
private final String username;
}
@Override
- public void authenticate(Connection connection) throws IOException {
- boolean isAuthenticated = connection.authenticateWithPassword(username, password);
+ public String getUsername() {
+ return username;
+ }
- if (!isAuthenticated) {
- throw new IOException("Authentication failed.");
- }
+ @Override
+ public AuthFuture authenticate(final ClientSession session) throws IOException {
+ session.addPasswordIdentity(password);
+ return session.auth();
}
}
--- /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.controller.netconf.nettyutil.handler.ssh.client;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelOutboundHandler;
+import io.netty.channel.ChannelOutboundHandlerAdapter;
+import io.netty.channel.ChannelPromise;
+import java.io.IOException;
+import java.net.SocketAddress;
+import org.apache.sshd.ClientChannel;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.SshClient;
+import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.client.future.ConnectFuture;
+import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.SshFutureListener;
+import org.apache.sshd.common.io.IoInputStream;
+import org.apache.sshd.common.io.IoOutputStream;
+import org.apache.sshd.common.io.IoReadFuture;
+import org.apache.sshd.common.io.IoWriteFuture;
+import org.apache.sshd.common.io.WritePendingException;
+import org.apache.sshd.common.util.Buffer;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Netty SSH handler class. Acts as interface between Netty and SSH library.
+ */
+public class AsyncSshHandler extends ChannelOutboundHandlerAdapter {
+
+ private static final Logger logger = LoggerFactory.getLogger(AsyncSshHandler.class);
+ public static final String SUBSYSTEM = "netconf";
+
+ public static final SshClient DEFAULT_CLIENT = SshClient.setUpDefaultClient();
+
+ public static final int SSH_DEFAULT_NIO_WORKERS = 8;
+
+ static {
+ // TODO make configurable, or somehow reuse netty threadpool
+ DEFAULT_CLIENT.setNioWorkers(SSH_DEFAULT_NIO_WORKERS);
+ DEFAULT_CLIENT.start();
+ }
+
+ private final AuthenticationHandler authenticationHandler;
+ private final SshClient sshClient;
+
+ private SshReadAsyncListener sshReadAsyncListener;
+ private SshWriteAsyncHandler sshWriteAsyncHandler;
+
+ private ClientChannel channel;
+ private ClientSession session;
+ private ChannelPromise connectPromise;
+
+
+ public static AsyncSshHandler createForNetconfSubsystem(final AuthenticationHandler authenticationHandler) throws IOException {
+ return new AsyncSshHandler(authenticationHandler, DEFAULT_CLIENT);
+ }
+
+ /**
+ *
+ * @param authenticationHandler
+ * @param sshClient started SshClient
+ * @throws IOException
+ */
+ public AsyncSshHandler(final AuthenticationHandler authenticationHandler, final SshClient sshClient) throws IOException {
+ this.authenticationHandler = Preconditions.checkNotNull(authenticationHandler);
+ this.sshClient = Preconditions.checkNotNull(sshClient);
+ // Start just in case
+ sshClient.start();
+ }
+
+ private void startSsh(final ChannelHandlerContext ctx, final SocketAddress address) {
+ logger.debug("Starting SSH to {} on channel: {}", address, ctx.channel());
+
+ final ConnectFuture sshConnectionFuture = sshClient.connect(authenticationHandler.getUsername(), address);
+ sshConnectionFuture.addListener(new SshFutureListener<ConnectFuture>() {
+ @Override
+ public void operationComplete(final ConnectFuture future) {
+ if (future.isConnected()) {
+ handleSshSessionCreated(future, ctx);
+ } else {
+ handleSshSetupFailure(ctx, future.getException());
+ }
+ }
+ });
+ }
+
+ private synchronized void handleSshSessionCreated(final ConnectFuture future, final ChannelHandlerContext ctx) {
+ try {
+ logger.trace("SSH session created on channel: {}", ctx.channel());
+
+ session = future.getSession();
+ final AuthFuture authenticateFuture = authenticationHandler.authenticate(session);
+ authenticateFuture.addListener(new SshFutureListener<AuthFuture>() {
+ @Override
+ public void operationComplete(final AuthFuture future) {
+ if (future.isSuccess()) {
+ handleSshAuthenticated(session, ctx);
+ } else {
+ handleSshSetupFailure(ctx, future.getException());
+ }
+ }
+ });
+ } catch (final IOException e) {
+ handleSshSetupFailure(ctx, e);
+ }
+ }
+
+ private synchronized void handleSshAuthenticated(final ClientSession session, final ChannelHandlerContext ctx) {
+ try {
+ logger.debug("SSH session authenticated on channel: {}, server version: {}", ctx.channel(), session.getServerVersion());
+
+ channel = session.createSubsystemChannel(SUBSYSTEM);
+ channel.setStreaming(ClientChannel.Streaming.Async);
+ channel.open().addListener(new SshFutureListener<OpenFuture>() {
+ @Override
+ public void operationComplete(final OpenFuture future) {
+ if(future.isOpened()) {
+ handleSshChanelOpened(ctx);
+ } else {
+ handleSshSetupFailure(ctx, future.getException());
+ }
+ }
+ });
+
+
+ } catch (final IOException e) {
+ handleSshSetupFailure(ctx, e);
+ }
+ }
+
+ private synchronized void handleSshChanelOpened(final ChannelHandlerContext ctx) {
+ logger.trace("SSH subsystem channel opened successfully on channel: {}", ctx.channel());
+
+ connectPromise.setSuccess();
+ connectPromise = null;
+
+ sshReadAsyncListener = new SshReadAsyncListener(ctx, channel.getAsyncOut());
+ sshWriteAsyncHandler = new SshWriteAsyncHandler(this, channel.getAsyncIn());
+
+ ctx.fireChannelActive();
+ }
+
+ private synchronized void handleSshSetupFailure(final ChannelHandlerContext ctx, final Throwable e) {
+ logger.warn("Unable to setup SSH connection on channel: {}", ctx.channel(), e);
+ connectPromise.setFailure(e);
+ connectPromise = null;
+ throw new IllegalStateException("Unable to setup SSH connection on channel: " + ctx.channel(), e);
+ }
+
+ @Override
+ public synchronized void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) {
+ sshWriteAsyncHandler.write(ctx, msg, promise);
+ }
+
+ private static void handleSshSessionClosed(final ChannelHandlerContext ctx) {
+ logger.debug("SSH session closed on channel: {}", ctx.channel());
+ ctx.fireChannelInactive();
+ }
+
+ @Override
+ public synchronized void connect(final ChannelHandlerContext ctx, final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) throws Exception {
+ this.connectPromise = promise;
+ startSsh(ctx, remoteAddress);
+ }
+
+ @Override
+ public void close(final ChannelHandlerContext ctx, final ChannelPromise promise) throws Exception {
+ disconnect(ctx, promise);
+ }
+
+ @Override
+ public synchronized void disconnect(final ChannelHandlerContext ctx, final ChannelPromise promise) {
+ if(sshReadAsyncListener != null) {
+ sshReadAsyncListener.close();
+ }
+
+ if(sshWriteAsyncHandler != null) {
+ sshWriteAsyncHandler.close();
+ }
+
+ if(session!= null && !session.isClosed() && !session.isClosing()) {
+ session.close(false).addListener(new SshFutureListener<CloseFuture>() {
+ @Override
+ public void operationComplete(final CloseFuture future) {
+ if (future.isClosed() == false) {
+ session.close(true);
+ }
+ session = null;
+ }
+ });
+ }
+
+ channel = null;
+ promise.setSuccess();
+
+ handleSshSessionClosed(ctx);
+ }
+
+ /**
+ * Listener over async input stream from SSH session.
+ * This listeners schedules reads in a loop until the session is closed or read fails.
+ */
+ private static class SshReadAsyncListener implements SshFutureListener<IoReadFuture>, AutoCloseable {
+ private static final int BUFFER_SIZE = 8192;
+
+ private final ChannelHandlerContext ctx;
+
+ private IoInputStream asyncOut;
+ private Buffer buf;
+ private IoReadFuture currentReadFuture;
+
+ public SshReadAsyncListener(final ChannelHandlerContext ctx, final IoInputStream asyncOut) {
+ this.ctx = ctx;
+ this.asyncOut = asyncOut;
+ buf = new Buffer(BUFFER_SIZE);
+ asyncOut.read(buf).addListener(this);
+ }
+
+ @Override
+ public synchronized void operationComplete(final IoReadFuture future) {
+ if(future.getException() != null) {
+
+ if(asyncOut.isClosed() || asyncOut.isClosing()) {
+ // We are closing
+ handleSshSessionClosed(ctx);
+ } else {
+ logger.warn("Exception while reading from SSH remote on channel {}", ctx.channel(), future.getException());
+ throw new IllegalStateException("Exception while reading from SSH remote on channel " + ctx.channel(), future.getException());
+ }
+ }
+
+ if (future.getRead() > 0) {
+ ctx.fireChannelRead(Unpooled.wrappedBuffer(buf.array(), 0, future.getRead()));
+
+ // Schedule next read
+ buf = new Buffer(BUFFER_SIZE);
+ currentReadFuture = asyncOut.read(buf);
+ currentReadFuture.addListener(this);
+ }
+ }
+
+ @Override
+ public synchronized void close() {
+ // Remove self as listener on close to prevent reading from closed input
+ if(currentReadFuture != null) {
+ currentReadFuture.removeListener(this);
+ }
+
+ asyncOut = null;
+ }
+ }
+
+ private static final class SshWriteAsyncHandler implements AutoCloseable {
+ public static final int MAX_PENDING_WRITES = 100;
+
+ private final ChannelOutboundHandler channelHandler;
+ private IoOutputStream asyncIn;
+
+ // Counter that holds the amount of pending write messages
+ // Pending write can occur in case remote window is full
+ // In such case, we need to wait for the pending write to finish
+ private int pendingWriteCounter;
+ // Last write future, that can be pending
+ private IoWriteFuture lastWriteFuture;
+
+ public SshWriteAsyncHandler(final ChannelOutboundHandler channelHandler, final IoOutputStream asyncIn) {
+ this.channelHandler = channelHandler;
+ this.asyncIn = asyncIn;
+ }
+
+ public synchronized void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) {
+ try {
+ if(asyncIn.isClosed() || asyncIn.isClosing()) {
+ handleSshSessionClosed(ctx);
+ } else {
+ lastWriteFuture = asyncIn.write(toBuffer(msg));
+ lastWriteFuture.addListener(new SshFutureListener<IoWriteFuture>() {
+
+ @Override
+ public void operationComplete(final IoWriteFuture future) {
+ ((ByteBuf) msg).release();
+
+ // Notify success or failure
+ if (future.isWritten()) {
+ promise.setSuccess();
+ }
+ promise.setFailure(future.getException());
+
+ // Reset last pending future
+ synchronized (SshWriteAsyncHandler.this) {
+ lastWriteFuture = null;
+ }
+ }
+ });
+ }
+ } catch (final WritePendingException e) {
+ // Check limit for pending writes
+ pendingWriteCounter++;
+ if(pendingWriteCounter > MAX_PENDING_WRITES) {
+ handlePendingFailed(ctx, new IllegalStateException("Too much pending writes(" + MAX_PENDING_WRITES + ") on channel: " + ctx.channel() +
+ ", remote window is not getting read or is too small"));
+ }
+
+ logger.debug("Write pending to SSH remote on channel: {}, current pending count: {}", ctx.channel(), pendingWriteCounter);
+
+ // In case of pending, re-invoke write after pending is finished
+ lastWriteFuture.addListener(new SshFutureListener<IoWriteFuture>() {
+ @Override
+ public void operationComplete(final IoWriteFuture future) {
+ if(future.isWritten()) {
+ synchronized (SshWriteAsyncHandler.this) {
+ // Pending done, decrease counter
+ pendingWriteCounter--;
+ }
+ write(ctx, msg, promise);
+ } else {
+ // Cannot reschedule pending, fail
+ handlePendingFailed(ctx, e);
+ }
+ }
+
+ });
+ }
+ }
+
+ private void handlePendingFailed(final ChannelHandlerContext ctx, final Exception e) {
+ logger.warn("Exception while writing to SSH remote on channel {}", ctx.channel(), e);
+ try {
+ channelHandler.disconnect(ctx, ctx.newPromise());
+ } catch (final Exception ex) {
+ // This should not happen
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ @Override
+ public void close() {
+ asyncIn = null;
+ }
+
+ private Buffer toBuffer(final Object msg) {
+ // TODO Buffer vs ByteBuf translate, Can we handle that better ?
+ Preconditions.checkState(msg instanceof ByteBuf);
+ final ByteBuf byteBuf = (ByteBuf) msg;
+ final byte[] temp = new byte[byteBuf.readableBytes()];
+ byteBuf.readBytes(temp, 0, byteBuf.readableBytes());
+ return new Buffer(temp);
+ }
+
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.nettyutil.handler.ssh.client;
-
-import java.io.IOException;
-
-/**
- * Abstract class providing mechanism of invoking various SSH level services.
- * Class is not allowed to be extended, as it provides its own implementations via instance initiators.
- */
-abstract class Invoker {
- private boolean invoked = false;
-
- private Invoker() {
- }
-
- protected boolean isInvoked() {
- return invoked;
- }
-
- public void setInvoked() {
- this.invoked = true;
- }
-
- abstract void invoke(SshSession session) throws IOException;
-
- public static Invoker netconfSubsystem(){
- return subsystem("netconf");
- }
-
- public static Invoker subsystem(final String subsystem) {
- return new Invoker() {
- @Override
- synchronized void invoke(SshSession session) throws IOException {
- if (isInvoked()) {
- throw new IllegalStateException("Already invoked.");
- }
- try {
- session.startSubSystem(subsystem);
- } finally {
- setInvoked();
- }
- }
- };
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.nettyutil.handler.ssh.client;
-
-import ch.ethz.ssh2.Connection;
-import ch.ethz.ssh2.Session;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
-
-/**
- * Wrapper class around GANYMED SSH java library.
- */
-class SshClient {
- private final VirtualSocket socket;
- private final Map<Integer, SshSession> openSessions = new HashMap<>();
- private final AuthenticationHandler authenticationHandler;
- private Connection connection;
-
- public SshClient(VirtualSocket socket, AuthenticationHandler authenticationHandler) throws IOException {
- this.socket = socket;
- this.authenticationHandler = authenticationHandler;
- }
-
- public SshSession openSession() throws IOException {
- if (connection == null) {
- connect();
- }
-
- Session session = connection.openSession();
- SshSession sshSession = new SshSession(session);
- openSessions.put(openSessions.size(), sshSession);
-
- return sshSession;
- }
-
- private void connect() throws IOException {
- connection = new Connection(socket);
-
- connection.connect();
- authenticationHandler.authenticate(connection);
- }
-
-
- public void close() {
- for (SshSession session : openSessions.values()){
- session.close();
- }
-
- openSessions.clear();
-
- if (connection != null) {
- connection.close();
- }
- }
-
- @Override
- public String toString() {
- return "SshClient{" +
- "socket=" + socket +
- '}';
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.nettyutil.handler.ssh.client;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelPromise;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * Worker thread class. Handles all downstream and upstream events in SSH Netty
- * pipeline.
- */
-class SshClientAdapter implements Runnable {
- private static final Logger logger = LoggerFactory.getLogger(SshClientAdapter.class);
-
- private static final int BUFFER_SIZE = 1024;
-
- private final SshClient sshClient;
- private final Invoker invoker;
-
- private OutputStream stdIn;
-
- private final Queue<ByteBuf> postponed = new LinkedList<>();
-
- private ChannelHandlerContext ctx;
- private ChannelPromise disconnectPromise;
-
- private final AtomicBoolean stopRequested = new AtomicBoolean(false);
-
- private final Object lock = new Object();
-
- public SshClientAdapter(final SshClient sshClient, final Invoker invoker) {
- this.sshClient = sshClient;
- this.invoker = invoker;
- }
-
- // TODO ganymed spawns a Thread that receives the data from remote inside TransportManager
- // Get rid of this thread and reuse Ganymed internal thread (not sure if its possible without modifications in ganymed)
- public void run() {
- try {
- final SshSession session = sshClient.openSession();
- invoker.invoke(session);
- final InputStream stdOut = session.getStdout();
-
- synchronized (lock) {
- stdIn = session.getStdin();
- while (postponed.peek() != null) {
- writeImpl(postponed.poll());
- }
- }
-
- while (!stopRequested.get()) {
- final byte[] readBuff = new byte[BUFFER_SIZE];
- final int c = stdOut.read(readBuff);
- if (c == -1) {
- continue;
- }
-
- ctx.fireChannelRead(Unpooled.copiedBuffer(readBuff, 0, c));
- }
- } catch (final Exception e) {
- logger.error("Unexpected exception", e);
- } finally {
- sshClient.close();
-
- synchronized (lock) {
- if (disconnectPromise != null) {
- ctx.disconnect(disconnectPromise);
- }
- }
- }
- }
-
- // TODO: needs rework to match netconf framer API.
- public void write(final ByteBuf message) throws IOException {
- synchronized (lock) {
- if (stdIn == null) {
- postponed.add(message);
- return;
- }
- writeImpl(message);
- }
- }
-
- private void writeImpl(final ByteBuf message) throws IOException {
- message.getBytes(0, stdIn, message.readableBytes());
- message.release();
- stdIn.flush();
- }
-
- public void stop(final ChannelPromise promise) {
- synchronized (lock) {
- stopRequested.set(true);
- disconnectPromise = promise;
- }
- }
-
- public Thread start(final ChannelHandlerContext ctx, final ChannelFuture channelFuture) {
- checkArgument(channelFuture.isSuccess());
- checkNotNull(ctx.channel().remoteAddress());
- synchronized (this) {
- checkState(this.ctx == null);
- this.ctx = ctx;
- }
- final String threadName = toString();
- final Thread thread = new Thread(this, threadName);
- thread.start();
- return thread;
- }
-
- @Override
- public String toString() {
- return "SshClientAdapter{" +
- "sshClient=" + sshClient +
- '}';
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.nettyutil.handler.ssh.client;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelFutureListener;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelOutboundHandlerAdapter;
-import io.netty.channel.ChannelPromise;
-import java.io.IOException;
-import java.net.SocketAddress;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Netty SSH handler class. Acts as interface between Netty and SSH library. All standard Netty message handling
- * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter};
- */
-public class SshHandler extends ChannelOutboundHandlerAdapter {
- private static final Logger logger = LoggerFactory.getLogger(SshHandler.class);
- private static final String SOCKET = "socket";
-
- private final VirtualSocket virtualSocket = new VirtualSocket();
- private final SshClientAdapter sshClientAdapter;
-
-
- public static SshHandler createForNetconfSubsystem(AuthenticationHandler authenticationHandler) throws IOException {
- return new SshHandler(authenticationHandler, Invoker.netconfSubsystem());
- }
-
-
- public SshHandler(AuthenticationHandler authenticationHandler, Invoker invoker) throws IOException {
- SshClient sshClient = new SshClient(virtualSocket, authenticationHandler);
- this.sshClientAdapter = new SshClientAdapter(sshClient, invoker);
- }
-
- @Override
- public void handlerAdded(ChannelHandlerContext ctx){
- if (ctx.channel().pipeline().get(SOCKET) == null) {
- ctx.channel().pipeline().addFirst(SOCKET, virtualSocket);
- }
- }
-
- @Override
- public void handlerRemoved(ChannelHandlerContext ctx) {
- if (ctx.channel().pipeline().get(SOCKET) != null) {
- ctx.channel().pipeline().remove(SOCKET);
- }
- }
-
- @Override
- public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws IOException {
- this.sshClientAdapter.write((ByteBuf) msg);
- }
-
- @Override
- public void connect(final ChannelHandlerContext ctx,
- SocketAddress remoteAddress,
- SocketAddress localAddress,
- ChannelPromise promise) {
- ctx.connect(remoteAddress, localAddress, promise);
-
- promise.addListener(new ChannelFutureListener() {
- public void operationComplete(ChannelFuture channelFuture) {
- if (channelFuture.isSuccess()) {
- sshClientAdapter.start(ctx, channelFuture);
- } else {
- logger.debug("Failed to connect to remote host");
- }
- }}
- );
- }
-
- @Override
- public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
- sshClientAdapter.stop(promise);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.nettyutil.handler.ssh.client;
-
-import ch.ethz.ssh2.Session;
-import ch.ethz.ssh2.channel.Channel;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Wrapper class for proprietary SSH sessions implementations
- */
-class SshSession implements Closeable {
- private final Session session;
-
- public SshSession(final Session session) {
- this.session = session;
- }
-
- public void startSubSystem(final String name) throws IOException {
- session.startSubSystem(name);
- }
-
- public InputStream getStdout() {
- return session.getStdout();
- }
-
- // FIXME according to http://www.ganymed.ethz.ch/ssh2/FAQ.html#blocking you should read data from both stdout and stderr to prevent window filling up (since stdout and stderr share a window)
- // FIXME stdErr is not used anywhere
- public InputStream getStderr() {
- return session.getStderr();
- }
-
- public OutputStream getStdin() {
- return session.getStdin();
- }
-
- @Override
- public void close() {
- if (session.getState() == Channel.STATE_OPEN || session.getState() == Channel.STATE_OPENING) {
- session.close();
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.nettyutil.handler.ssh.virtualsocket;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandler;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Class provides {@link InputStream} functionality to users of virtual socket.
- */
-public class ChannelInputStream extends InputStream implements ChannelInboundHandler {
- private final Object lock = new Object();
- private final ByteBuf bb = Unpooled.buffer();
-
- @Override
- public int read(byte b[], int off, int len) throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if (off < 0 || len < 0 || len > b.length - off) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
-
- int bytesRead = 1;
- synchronized (lock) {
- int c = read();
-
- b[off] = (byte)c;
-
- if(this.bb.readableBytes() == 0) {
- return bytesRead;
- }
-
- int ltr = len-1;
- ltr = (ltr <= bb.readableBytes()) ? ltr : bb.readableBytes();
-
- bb.readBytes(b, 1, ltr);
- bytesRead += ltr;
- }
- return bytesRead;
- }
-
- @Override
- public int read() throws IOException {
- synchronized (lock) {
- while (this.bb.readableBytes() == 0) {
- try {
- lock.wait();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new IllegalStateException(e);
- }
- }
- return this.bb.readByte() & 0xFF;
- }
- }
-
- @Override
- public int available() throws IOException {
- synchronized (lock) {
- return this.bb.readableBytes();
- }
- }
-
- public void channelRegistered(ChannelHandlerContext ctx) {
- ctx.fireChannelRegistered();
- }
-
- public void channelUnregistered(ChannelHandlerContext ctx) {
- ctx.fireChannelUnregistered();
- }
-
- public void channelActive(ChannelHandlerContext ctx) {
- ctx.fireChannelActive();
- }
-
- public void channelInactive(ChannelHandlerContext ctx) {
- ctx.fireChannelInactive();
- }
-
- public void channelRead(ChannelHandlerContext ctx, Object o) {
- synchronized(lock) {
- this.bb.discardReadBytes();
- this.bb.writeBytes((ByteBuf) o);
- ((ByteBuf) o).release();
- lock.notifyAll();
- }
- }
-
- public void channelReadComplete(ChannelHandlerContext ctx) {
- ctx.fireChannelReadComplete();
- }
-
- public void userEventTriggered(ChannelHandlerContext ctx, Object o) {
- ctx.fireUserEventTriggered(o);
- }
-
- public void channelWritabilityChanged(ChannelHandlerContext ctx) {
- ctx.fireChannelWritabilityChanged();
- }
-
- public void handlerAdded(ChannelHandlerContext ctx) {
- }
-
- public void handlerRemoved(ChannelHandlerContext ctx) {
- }
-
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
- ctx.fireExceptionCaught(throwable);
- }
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.nettyutil.handler.ssh.virtualsocket;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelOutboundHandler;
-import io.netty.channel.ChannelPromise;
-
-import java.io.OutputStream;
-import java.net.SocketAddress;
-
-/**
- * Class provides {@link OutputStream) functionality to users of virtual socket.
- */
-public class ChannelOutputStream extends OutputStream implements ChannelOutboundHandler {
- private final Object lock = new Object();
- private ByteBuf buff = Unpooled.buffer();
- private ChannelHandlerContext ctx;
-
- @Override
- public void flush() {
- synchronized(lock) {
- ctx.writeAndFlush(buff).awaitUninterruptibly();
- buff = Unpooled.buffer();
- }
- }
-
- @Override
- public void write(int b) {
- synchronized(lock) {
- buff.writeByte(b);
- }
- }
-
- public void bind(ChannelHandlerContext ctx, SocketAddress localAddress,
- ChannelPromise promise) {
- ctx.bind(localAddress, promise);
- }
-
- public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
- SocketAddress localAddress, ChannelPromise promise) {
- this.ctx = ctx;
- ctx.connect(remoteAddress, localAddress, promise);
- }
-
- public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
- ctx.disconnect(promise);
- }
-
- public void close(ChannelHandlerContext ctx, ChannelPromise promise) {
- ctx.close(promise);
- }
-
- public void deregister(ChannelHandlerContext ctx, ChannelPromise channelPromise) {
- ctx.deregister(channelPromise);
- }
-
- public void read(ChannelHandlerContext ctx) {
- ctx.read();
- }
-
- public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
- // pass
- }
-
- public void flush(ChannelHandlerContext ctx) {
- // pass
- }
-
- public void handlerAdded(ChannelHandlerContext ctx)
- throws Exception {
- }
-
- public void handlerRemoved(ChannelHandlerContext ctx)
- throws Exception {
- }
-
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
- ctx.fireExceptionCaught(cause);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.nettyutil.handler.ssh.virtualsocket;
-
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.nio.channels.SocketChannel;
-
-/**
- * Handler class providing Socket functionality to OIO client application. By using VirtualSocket user can
- * use OIO application in asynchronous environment and NIO EventLoop. Using VirtualSocket OIO applications
- * are able to use full potential of NIO environment.
- */
-//TODO: refactor - socket should be created when connection is established
-public class VirtualSocket extends Socket implements ChannelHandler {
- private static final String INPUT_STREAM = "inputStream";
- private static final String OUTPUT_STREAM = "outputStream";
-
- private final ChannelInputStream chais = new ChannelInputStream();
- private final ChannelOutputStream chaos = new ChannelOutputStream();
- private ChannelHandlerContext ctx;
-
-
- public InputStream getInputStream() {
- return this.chais;
- }
-
- public OutputStream getOutputStream() {
- return this.chaos;
- }
-
- public void handlerAdded(ChannelHandlerContext ctx) {
- this.ctx = ctx;
-
- if (ctx.channel().pipeline().get(OUTPUT_STREAM) == null) {
- ctx.channel().pipeline().addFirst(OUTPUT_STREAM, chaos);
- }
-
- if (ctx.channel().pipeline().get(INPUT_STREAM) == null) {
- ctx.channel().pipeline().addFirst(INPUT_STREAM, chais);
- }
- }
-
- public void handlerRemoved(ChannelHandlerContext ctx) {
- if (ctx.channel().pipeline().get(OUTPUT_STREAM) != null) {
- ctx.channel().pipeline().remove(OUTPUT_STREAM);
- }
-
- if (ctx.channel().pipeline().get(INPUT_STREAM) != null) {
- ctx.channel().pipeline().remove(INPUT_STREAM);
- }
- }
-
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
- // TODO exceptionCaught is deprecated transform this handler
- ctx.fireExceptionCaught(throwable);
- }
-
-
- @Override
- public void connect(SocketAddress endpoint) throws IOException {}
-
- @Override
- public void connect(SocketAddress endpoint, int timeout) throws IOException {}
-
- @Override
- public void bind(SocketAddress bindpoint) throws IOException {}
-
- @Override
- public InetAddress getInetAddress() {
- InetSocketAddress isa = getInetSocketAddress();
- return isa.getAddress();
- }
-
- @Override
- public InetAddress getLocalAddress() {return null;}
-
- @Override
- public int getPort() {
- return getInetSocketAddress().getPort();
- }
-
- private InetSocketAddress getInetSocketAddress() {
- return (InetSocketAddress)getRemoteSocketAddress();
- }
-
- @Override
- public int getLocalPort() {return -1;}
-
- @Override
- public SocketAddress getRemoteSocketAddress() {
- return this.ctx.channel().remoteAddress();
- }
-
- @Override
- public SocketAddress getLocalSocketAddress() {
- return this.ctx.channel().localAddress();
- }
-
- @Override
- public SocketChannel getChannel() {return null;}
-
- @Override
- public void setTcpNoDelay(boolean on) throws SocketException {}
-
- @Override
- public boolean getTcpNoDelay() throws SocketException {return false;}
-
- @Override
- public void setSoLinger(boolean on, int linger) throws SocketException {}
-
- @Override
- public int getSoLinger() throws SocketException {return -1;}
-
- @Override
- public void sendUrgentData(int data) throws IOException {}
-
- @Override
- public void setOOBInline(boolean on) throws SocketException {}
-
- @Override
- public boolean getOOBInline() throws SocketException {return false;}
-
- @Override
- public synchronized void setSoTimeout(int timeout) throws SocketException {}
-
- @Override
- public synchronized int getSoTimeout() throws SocketException {return -1;}
-
- @Override
- public synchronized void setSendBufferSize(int size) throws SocketException {}
-
- @Override
- public synchronized int getSendBufferSize() throws SocketException {return -1;}
-
- @Override
- public synchronized void setReceiveBufferSize(int size) throws SocketException {}
-
- @Override
- public synchronized int getReceiveBufferSize() throws SocketException {return -1;}
-
- @Override
- public void setKeepAlive(boolean on) throws SocketException {}
-
- @Override
- public boolean getKeepAlive() throws SocketException {return false;}
-
- @Override
- public void setTrafficClass(int tc) throws SocketException {}
-
- @Override
- public int getTrafficClass() throws SocketException {return -1;}
-
- @Override
- public void setReuseAddress(boolean on) throws SocketException {}
-
- @Override
- public boolean getReuseAddress() throws SocketException {return false;}
-
- @Override
- public synchronized void close() throws IOException {}
-
- @Override
- public void shutdownInput() throws IOException {}
-
- @Override
- public void shutdownOutput() throws IOException {}
-
- @Override
- public String toString() {
- return "VirtualSocket{" + getInetAddress() + ":" + getPort() + "}";
- }
-
- @Override
- public boolean isConnected() {return false;}
-
- @Override
- public boolean isBound() {return false;}
-
- @Override
- public boolean isClosed() {return false;}
-
- @Override
- public boolean isInputShutdown() {return false;}
-
- @Override
- public boolean isOutputShutdown() {return false;}
-
- @Override
- public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {}
-}
--- /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.controller.netconf.nettyutil.handler;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.doAnswer;
+
+import com.google.common.collect.Lists;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
+
+public class ChunkedFramingMechanismEncoderTest {
+
+ private int chunkSize;
+ @Mock
+ private ChannelHandlerContext ctx;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ chunkSize = 256;
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testIllegalSize() throws Exception {
+ new ChunkedFramingMechanismEncoder(10);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testIllegalSizeMax() throws Exception {
+ new ChunkedFramingMechanismEncoder(Integer.MAX_VALUE);
+ }
+
+ @Test
+ public void testEncode() throws Exception {
+ final List<ByteBuf> chunks = Lists.newArrayList();
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ chunks.add((ByteBuf) invocation.getArguments()[0]);
+ return null;
+ }
+ }).when(ctx).write(anyObject());
+
+ final ChunkedFramingMechanismEncoder encoder = new ChunkedFramingMechanismEncoder(chunkSize);
+ final int lastChunkSize = 20;
+ final ByteBuf src = Unpooled.wrappedBuffer(getByteArray(chunkSize * 4 + lastChunkSize));
+ final ByteBuf destination = Unpooled.buffer();
+ encoder.encode(ctx, src, destination);
+ assertEquals(4, chunks.size());
+
+ final int framingSize = "#256\n".getBytes().length + 1/* new line at end */;
+
+ for (final ByteBuf chunk : chunks) {
+ assertEquals(chunkSize + framingSize, chunk.readableBytes());
+ }
+
+ final int lastFramingSize = "#20\n".length() + NetconfMessageConstants.END_OF_CHUNK.length + 1/* new line at end */;
+ assertEquals(lastChunkSize + lastFramingSize, destination.readableBytes());
+ }
+
+ private byte[] getByteArray(final int size) {
+ final byte[] bytes = new byte[size];
+ for (int i = 0; i < size; i++) {
+ bytes[i] = 'a';
+ }
+ return bytes;
+ }
+}
--- /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.controller.netconf.nettyutil.handler;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
+
+public class EOMFramingMechanismEncoderTest {
+
+ @Test
+ public void testEncode() throws Exception {
+ final byte[] content = new byte[50];
+ final ByteBuf source = Unpooled.wrappedBuffer(content);
+ final ByteBuf destination = Unpooled.buffer();
+ new EOMFramingMechanismEncoder().encode(null, source, destination);
+
+ assertEquals(Unpooled.wrappedBuffer(source.array(), NetconfMessageConstants.END_OF_MESSAGE), destination);
+ }
+}
\ No newline at end of file
--- /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.controller.netconf.nettyutil.handler;
+
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.MatcherAssert;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
+
+public class FramingMechanismHandlerFactoryTest {
+
+ @Test
+ public void testCreate() throws Exception {
+ MatcherAssert.assertThat(FramingMechanismHandlerFactory
+ .createHandler(FramingMechanism.CHUNK), CoreMatchers
+ .instanceOf(ChunkedFramingMechanismEncoder.class));
+ MatcherAssert.assertThat(FramingMechanismHandlerFactory
+ .createHandler(FramingMechanism.EOM), CoreMatchers
+ .instanceOf(EOMFramingMechanismEncoder.class));
+ }
+}
\ No newline at end of file
*/
package org.opendaylight.controller.netconf.nettyutil.handler;
+import static org.junit.Assert.assertEquals;
+
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
-import junit.framework.Assert;
+import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
-import java.util.List;
-
public class NetconfChunkAggregatorTest {
private static final String CHUNKED_MESSAGE = "\n#4\n" +
@Test
public void testMultipleChunks() throws Exception {
- List<Object> output = Lists.newArrayList();
- ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE.getBytes(Charsets.UTF_8));
+ final List<Object> output = Lists.newArrayList();
+ final ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE.getBytes(Charsets.UTF_8));
agr.decode(null, input, output);
- Assert.assertEquals(1, output.size());
- ByteBuf chunk = (ByteBuf) output.get(0);
+ assertEquals(1, output.size());
+ final ByteBuf chunk = (ByteBuf) output.get(0);
- Assert.assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
+ assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
}
@Test
public void testOneChunks() throws Exception {
- List<Object> output = Lists.newArrayList();
- ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE_ONE.getBytes(Charsets.UTF_8));
+ final List<Object> output = Lists.newArrayList();
+ final ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE_ONE.getBytes(Charsets.UTF_8));
agr.decode(null, input, output);
- Assert.assertEquals(1, output.size());
- ByteBuf chunk = (ByteBuf) output.get(0);
+ assertEquals(1, output.size());
+ final ByteBuf chunk = (ByteBuf) output.get(0);
- Assert.assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
+ assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
}
--- /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.controller.netconf.nettyutil.handler;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+
+public class NetconfHelloMessageToXMLEncoderTest {
+
+ @Mock
+ private ChannelHandlerContext ctx;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testEncode() throws Exception {
+ final NetconfMessage msg = new NetconfHelloMessage(XmlUtil.readXmlToDocument("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"),
+ NetconfHelloMessageAdditionalHeader.fromString("[tomas;10.0.0.0:10000;tcp;client;]"));
+ final ByteBuf destination = Unpooled.buffer();
+ new NetconfHelloMessageToXMLEncoder().encode(ctx, msg, destination);
+
+ final String encoded = new String(destination.array());
+ assertThat(encoded, containsString("[tomas;10.0.0.0:10000;tcp;client;]"));
+ assertThat(encoded, containsString("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
+ }
+
+ @Test
+ public void testEncodeNoHeader() throws Exception {
+ final NetconfMessage msg = new NetconfHelloMessage(XmlUtil.readXmlToDocument("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
+ final ByteBuf destination = Unpooled.buffer();
+ new NetconfHelloMessageToXMLEncoder().encode(ctx, msg, destination);
+
+ final String encoded = new String(destination.array());
+ assertThat(encoded, not(containsString("[tomas;10.0.0.0:10000;tcp;client;]")));
+ assertThat(encoded, containsString("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testEncodeNotHello() throws Exception {
+ final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
+ new NetconfHelloMessageToXMLEncoder().encode(ctx, msg, null);
+ }
+}
\ No newline at end of file
--- /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.controller.netconf.nettyutil.handler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.List;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+
+public class NetconfXMLToHelloMessageDecoderTest {
+
+ @Test
+ public void testDecodeWithHeader() throws Exception {
+ final ByteBuf src = Unpooled.wrappedBuffer(String.format("%s\n%s",
+ "[tomas;10.0.0.0:10000;tcp;client;]", "<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>").getBytes());
+ final List<Object> out = Lists.newArrayList();
+ new NetconfXMLToHelloMessageDecoder().decode(null, src, out);
+
+ assertEquals(1, out.size());
+ assertThat(out.get(0), CoreMatchers.instanceOf(NetconfHelloMessage.class));
+ final NetconfHelloMessage hello = (NetconfHelloMessage) out.get(0);
+ assertTrue(hello.getAdditionalHeader().isPresent());
+ assertEquals("[tomas;10.0.0.0:10000;tcp;client;]\n", hello.getAdditionalHeader().get().toFormattedString());
+ assertThat(XmlUtil.toString(hello.getDocument()), CoreMatchers.containsString("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\""));
+ }
+
+ @Test
+ public void testDecodeNoHeader() throws Exception {
+ final ByteBuf src = Unpooled.wrappedBuffer("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+ final List<Object> out = Lists.newArrayList();
+ new NetconfXMLToHelloMessageDecoder().decode(null, src, out);
+
+ assertEquals(1, out.size());
+ assertThat(out.get(0), CoreMatchers.instanceOf(NetconfHelloMessage.class));
+ final NetconfHelloMessage hello = (NetconfHelloMessage) out.get(0);
+ assertFalse(hello.getAdditionalHeader().isPresent());
+ }
+
+ @Test
+ public void testDecodeCaching() throws Exception {
+ final ByteBuf msg1 = Unpooled.wrappedBuffer("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+ final ByteBuf msg2 = Unpooled.wrappedBuffer("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+ final ByteBuf src = Unpooled.wrappedBuffer("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+ final List<Object> out = Lists.newArrayList();
+ final NetconfXMLToHelloMessageDecoder decoder = new NetconfXMLToHelloMessageDecoder();
+ decoder.decode(null, src, out);
+ decoder.decode(null, msg1, out);
+ decoder.decode(null, msg2, out);
+
+ assertEquals(1, out.size());
+
+ assertEquals(2, Iterables.size(decoder.getPostHelloNetconfMessages()));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testDecodeNotHelloReceived() throws Exception {
+ final ByteBuf msg1 = Unpooled.wrappedBuffer("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>".getBytes());
+ final List<Object> out = Lists.newArrayList();
+ NetconfXMLToHelloMessageDecoder decoder = new NetconfXMLToHelloMessageDecoder();
+ decoder.decode(null, msg1, out);
+ }
+}
\ No newline at end of file
--- /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.controller.netconf.nettyutil.handler;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.Lists;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import org.junit.Test;
+
+public class NetconfXMLToMessageDecoderTest {
+
+ @Test
+ public void testDecodeNoMoreContent() throws Exception {
+ final ArrayList<Object> out = Lists.newArrayList();
+ new NetconfXMLToMessageDecoder().decode(null, Unpooled.buffer(), out);
+ assertEquals(0, out.size());
+ }
+
+ @Test
+ public void testDecode() throws Exception {
+ final ArrayList<Object> out = Lists.newArrayList();
+ new NetconfXMLToMessageDecoder().decode(null, Unpooled.wrappedBuffer("<msg/>".getBytes()), out);
+ assertEquals(1, out.size());
+ }
+}
\ No newline at end of file
--- /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.controller.netconf.nettyutil.handler.ssh.authentication;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.client.future.AuthFuture;
+import org.junit.Test;
+
+public class LoginPasswordTest {
+
+ @Test
+ public void testLoginPassword() throws Exception {
+ final LoginPassword loginPassword = new LoginPassword("user", "pwd");
+ assertEquals("user", loginPassword.getUsername());
+
+ final ClientSession session = mock(ClientSession.class);
+ doNothing().when(session).addPasswordIdentity("pwd");
+ doReturn(mock(AuthFuture.class)).when(session).auth();
+ loginPassword.authenticate(session);
+
+ verify(session).addPasswordIdentity("pwd");
+ verify(session).auth();
+ }
+}
\ No newline at end of file
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>ganymed</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
import org.junit.Test;
import org.opendaylight.controller.netconf.netty.EchoClientHandler.State;
import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandler;
import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProviderImpl;
ChannelInitializer<NioSocketChannel> channelInitializer = new ChannelInitializer<NioSocketChannel>() {
@Override
public void initChannel(NioSocketChannel ch) throws Exception {
- ch.pipeline().addFirst(SshHandler.createForNetconfSubsystem(new LoginPassword("a", "a")));
+ ch.pipeline().addFirst(AsyncSshHandler.createForNetconfSubsystem(new LoginPassword("a", "a")));
ch.pipeline().addLast(echoClientHandler);
}
};
Thread.sleep(100);
}
assertFalse(echoClientHandler.isConnected());
- assertEquals(State.FAILED_TO_CONNECT, echoClientHandler.getState());
+ assertEquals(State.CONNECTION_CLOSED, echoClientHandler.getState());
}
}
* instance of deleted LoadBalancerPool object
* @return void
*/
- public void NeutronLoadBalancerPoolMemberDeleted(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
+ public void neutronLoadBalancerPoolMemberDeleted(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
}
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-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,
protected static final Logger logger = LoggerFactory
.getLogger(Activator.class);
+ /**
+ * Priority to determine whether to override existing protocol service.
+ */
+ private static final int PLUGIN_PRIORITY = 10;
/**
* Function that is used to communicate to dependency manager the list of
// Set the protocolPluginType property which will be used
// by SAL
props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
+ props.put(GlobalConstants.PROTOCOLPLUGINPRIORITY.toString(),
+ Integer.valueOf(PLUGIN_PRIORITY));
c.setInterface(IPluginInDataPacketService.class.getName(), props);
// Hook the services coming in from SAL, as optional in
// case SAL is not yet there, could happen
// Set the protocolPluginType property which will be used
// by SAL
props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
+ props.put(GlobalConstants.PROTOCOLPLUGINPRIORITY.toString(),
+ Integer.valueOf(PLUGIN_PRIORITY));
c.setInterface(new String[] {
IReadFilterInternalListener.class.getName(),
IPluginInReadService.class.getName() }, props);
// Set the protocolPluginType property which will be used
// by SAL
props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
+ props.put(GlobalConstants.PROTOCOLPLUGINPRIORITY.toString(),
+ Integer.valueOf(PLUGIN_PRIORITY));
c.setInterface(
new String[] { IPluginInFlowProgrammerService.class.getName(), IMessageListener.class.getName(),
IContainerListener.class.getName(), IInventoryShimExternalListener.class.getName(),
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-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.controller.sal.action;
/**
SET_NW_SRC("setNwSrc", 0, 0),
SET_NW_DST("setNwDst", 0, 0),
SET_NW_TOS("setNwTos", 0, 0x3f),
- SET_TP_SRC("setTpSrc", 1, 0xffff),
- SET_TP_DST("setTpDst", 1, 0xffff),
+ SET_TP_SRC("setTpSrc", 0, 0xffff), // Set transport source port
+ SET_TP_DST("setTpDst", 0, 0xffff), // Set transport destination port
SET_NEXT_HOP("setNextHop", 0, 0);
private String id;
-
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-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,
STATICVLAN("staticvlan"),
CLUSTERINGSERVICES("clusteringservices"),
STARTUPHOME("configuration/startup/"),
- PROTOCOLPLUGINTYPE("protocolPluginType");
+ PROTOCOLPLUGINTYPE("protocolPluginType"),
+ PROTOCOLPLUGINPRIORITY("protocolPluginPriority");
private GlobalConstants(String name) {
this.name = name;
public String toString() {
return name;
}
-}
\ No newline at end of file
+}
-
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-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.controller.sal.action;
import org.opendaylight.controller.sal.core.ConstructionException;
action = new SetTpDst(65535);
Assert.assertTrue(action.isValid());
+ action = new SetTpSrc(0);
+ Assert.assertTrue(action.isValid());
+
action = new SetTpDst(0);
- Assert.assertFalse(action.isValid());
+ Assert.assertTrue(action.isValid());
action = new SetTpSrc(-1);
Assert.assertFalse(action.isValid());
-
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-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,
import org.opendaylight.controller.sal.packet.Packet;
import org.opendaylight.controller.sal.packet.PacketResult;
import org.opendaylight.controller.sal.packet.RawPacket;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.NetUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* adding a new service, removing a service, going through all of
* them maybe different.
*/
- private ConcurrentHashMap<String, IPluginInDataPacketService>
+ private ConcurrentHashMap<String, ProtocolService<IPluginInDataPacketService>>
pluginInDataService =
- new ConcurrentHashMap<String, IPluginInDataPacketService>();
+ new ConcurrentHashMap<String, ProtocolService<IPluginInDataPacketService>>();
private Map<String, AtomicInteger> statistics = new HashMap<String, AtomicInteger>();
/**
String t = p.getNode()
.getType();
// Now locate the TX dispatcher
- IPluginInDataPacketService s = pluginInDataService
- .get(t);
- if (s != null) {
+ ProtocolService<IPluginInDataPacketService> service =
+ pluginInDataService.get(t);
+ if (service != null) {
try {
- s.transmitDataPacket(pkt);
+ service.getService().transmitDataPacket(pkt);
increaseStat("TXPacketSuccess");
} catch (Exception e) {
increaseStat("TXPacketFailedForException");
}
void setPluginInDataService(Map props, IPluginInDataPacketService s) {
- if (this.pluginInDataService == null) {
- logger.error("pluginInDataService store null");
- return;
- }
- String type = null;
- logger.trace("Received setPluginInDataService request");
- for (Object e : props.entrySet()) {
- Map.Entry entry = (Map.Entry) e;
- logger.trace("Prop key:({}) value:({})",entry.getKey(), entry.getValue());
- }
-
- Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
- if (value instanceof String) {
- type = (String) value;
- }
- if (type == null) {
- logger.error("Received a PluginInDataService without any "
- + "protocolPluginType provided");
- } else {
- this.pluginInDataService.put(type, s);
- logger.debug("Stored the PluginInDataService for type: {}", type);
- }
+ ProtocolService.set(this.pluginInDataService, props, s, logger);
}
void unsetPluginInDataService(Map props, IPluginInDataPacketService s) {
- if (this.pluginInDataService == null) {
- logger.error("pluginInDataService store null");
- return;
- }
-
- String type = null;
- logger.trace("Received unsetPluginInDataService request");
- for (Object e : props.entrySet()) {
- Map.Entry entry = (Map.Entry) e;
- logger.trace("Prop key:({}) value:({})",entry.getKey(), entry.getValue());
- }
-
- Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
- if (value instanceof String) {
- type = (String) value;
- }
- if (type == null) {
- logger.error("Received a PluginInDataService without any "
- + "protocolPluginType provided");
- } else if (this.pluginInDataService.get(type).equals(s)) {
- this.pluginInDataService.remove(type);
- logger.debug("Removed the PluginInDataService for type: {}", type);
- }
+ ProtocolService.unset(this.pluginInDataService, props, s, logger);
}
void setListenDataPacket(Map props, IListenDataPacket s) {
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-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,
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.controller.sal.utils.EtherTypes;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.Status;
protected static final Logger logger = LoggerFactory
.getLogger(FlowProgrammerService.class);
- private ConcurrentHashMap<String, IPluginInFlowProgrammerService> pluginFlowProgrammer;
+ private ConcurrentHashMap<String, ProtocolService<IPluginInFlowProgrammerService>> pluginFlowProgrammer;
private Set<IFlowProgrammerListener> listener;
private AtomicLong seq;
public FlowProgrammerService() {
- pluginFlowProgrammer = new ConcurrentHashMap<String, IPluginInFlowProgrammerService>();
+ pluginFlowProgrammer = new ConcurrentHashMap<String, ProtocolService<IPluginInFlowProgrammerService>>();
listener = new HashSet<IFlowProgrammerListener>();
seq = new AtomicLong();
/*
// Set the reference to the plugin flow programmer
public void setService(Map<String, Object> props, IPluginInFlowProgrammerService s) {
- if (this.pluginFlowProgrammer == null) {
- logger.error("pluginFlowProgrammer store null");
- return;
- }
-
- if (logger.isTraceEnabled()) {
- logger.trace("Got a service set request {}", s);
- for (Map.Entry<String, Object> entry : props.entrySet()) {
- logger.trace("Prop key:({}) value:({})", entry.getKey(), entry.getValue());
- }
- }
-
- String type = null;
- Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
- if (value instanceof String) {
- type = (String) value;
- }
- if (type == null) {
- logger.error("Received a pluginFlowProgrammer without any "
- + "protocolPluginType provided");
- } else {
- this.pluginFlowProgrammer.put(type, s);
- logger.debug("Stored the pluginFlowProgrammer for type: {}", type);
- }
+ ProtocolService.set(this.pluginFlowProgrammer, props, s, logger);
}
public void unsetService(Map<String, Object> props, IPluginInFlowProgrammerService s) {
- if (this.pluginFlowProgrammer == null) {
- logger.error("pluginFlowProgrammer store null");
- return;
- }
-
- logger.debug("Received unsetpluginFlowProgrammer request");
- if (logger.isTraceEnabled()) {
- logger.trace("Got a service set request {}", s);
- for (Map.Entry<String, Object> entry : props.entrySet()) {
- logger.trace("Prop key:({}) value:({})", entry.getKey(), entry.getValue());
- }
- }
-
- String type = null;
- Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
- if (value instanceof String) {
- type = (String) value;
- }
- if (type == null) {
- logger.error("Received a pluginFlowProgrammer without any "
- + "protocolPluginType provided");
- } else if (this.pluginFlowProgrammer.get(type).equals(s)) {
- this.pluginFlowProgrammer.remove(type);
- logger.debug("Removed the pluginFlowProgrammer for type: {}", type);
- }
+ ProtocolService.unset(this.pluginFlowProgrammer, props, s, logger);
}
public void setListener(IFlowProgrammerListener s) {
@Override
public Status addFlow(Node node, Flow flow) {
if (pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType()).addFlow(
- node, flow);
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().addFlow(node, flow);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@Override
public Status removeFlow(Node node, Flow flow) {
if (pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType())
- .removeFlow(node, flow);
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().removeFlow(node, flow);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@Override
public Status removeAllFlows(Node node) {
if (pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType())
- .removeAllFlows(node);
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().removeAllFlows(node);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@Override
public Status modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
if (pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType())
- .modifyFlow(node, oldFlow, newFlow);
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().modifyFlow(node, oldFlow, newFlow);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@Override
public Status addFlowAsync(Node node, Flow flow) {
if (pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType()).addFlowAsync(
- node, flow, getNextRid());
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().addFlowAsync(node, flow, getNextRid());
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@Override
public Status removeFlowAsync(Node node, Flow flow) {
if (pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType())
- .removeFlowAsync(node, flow, getNextRid());
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().removeFlowAsync(node, flow, getNextRid());
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@Override
public Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow) {
if (pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType())
- .modifyFlowAsync(node, oldFlow, newFlow, getNextRid());
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().modifyFlowAsync(node, oldFlow, newFlow, getNextRid());
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@Override
public Status syncSendBarrierMessage(Node node) {
if (this.pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType())
- .syncSendBarrierMessage(node);
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().syncSendBarrierMessage(node);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
@Override
public Status asyncSendBarrierMessage(Node node) {
if (this.pluginFlowProgrammer != null) {
- if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType())
- .asyncSendBarrierMessage(node);
+ ProtocolService<IPluginInFlowProgrammerService> service =
+ this.pluginFlowProgrammer.get(node.getType());
+ if (service != null) {
+ return service.getService().asyncSendBarrierMessage(node);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
--- /dev/null
+/*
+ * Copyright (c) 2014 NEC Corporation 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.controller.sal.implementation.internal;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+import org.slf4j.Logger;
+
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+
+/**
+ * An instance of this class keeps a protocol plugin service handler.
+ *
+ * @param <T> Type of protocol plugin service.
+ */
+public final class ProtocolService<T> {
+ /**
+ * Default priority value.
+ */
+ private static final int DEFAULT_PRIORITY = 0;
+
+ /**
+ * A protocol plugin service handler.
+ */
+ private final T service;
+
+ /**
+ * A priority value assigned to this protocol plugin.
+ */
+ private final int priority;
+
+ /**
+ * Set protocol plugin service.
+ *
+ * @param map A map that keeps protocol plugin services.
+ * @param props Service properties.
+ * @param s Protocol plugin service.
+ * @param logger A logger instance.
+ * @param <S> Type of protocol plugin service.
+ */
+ public static <S> void set(ConcurrentMap<String, ProtocolService<S>> map,
+ Map<?, ?> props, S s, Logger logger) {
+ if (map == null) {
+ logger.error("Protocol plugin service store is null.");
+ return;
+ }
+ if (s == null) {
+ logger.error("Protocol plugin service is null.");
+ return;
+ }
+ if (props == null) {
+ logger.error("Service property is null.");
+ return;
+ }
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("Received set service request: {}", s);
+ for (Map.Entry<?, ?> entry: props.entrySet()) {
+ logger.trace("Prop key:({}) value:({})", entry.getKey(),
+ entry.getValue());
+ }
+ }
+
+ Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
+ if (!(value instanceof String)) {
+ logger.error("Unexpected protocol type: {}", value);
+ return;
+ }
+
+ String type = (String)value;
+ ProtocolService<S> service = new ProtocolService<S>(props, s);
+ ProtocolService<S> old = map.putIfAbsent(type, service);
+ while (old != null) {
+ // Compare priority value.
+ if (old.getPriority() >= service.getPriority()) {
+ logger.trace("Protocol plugin service for {} is already set: " +
+ "current={}, requested={}", type, old, service);
+ return;
+ }
+
+ if (map.replace(type, old, service)) {
+ break;
+ }
+ old = map.putIfAbsent(type, service);
+ }
+
+ logger.debug("Stored protocol plugin service for {}: {}",
+ type, service);
+ }
+
+ /**
+ * Unset protocol plugin service.
+ *
+ * @param map A map that keeps protocol plugin services.
+ * @param props Service properties.
+ * @param s Protocol plugin service.
+ * @param logger A logger instance.
+ * @param <S> Type of protocol plugin service.
+ */
+ public static <S> void unset(ConcurrentMap<String, ProtocolService<S>> map,
+ Map<?, ?> props, S s, Logger logger) {
+ if (map == null) {
+ logger.error("Protocol plugin service store is null.");
+ return;
+ }
+ if (s == null) {
+ logger.error("Protocol plugin service is null.");
+ return;
+ }
+ if (props == null) {
+ logger.error("Service property is null.");
+ return;
+ }
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("Received unset service request: {}", s);
+ for (Map.Entry<?, ?> entry: props.entrySet()) {
+ logger.trace("Prop key:({}) value:({})",
+ entry.getKey(), entry.getValue());
+ }
+ }
+
+ Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
+ if (!(value instanceof String)) {
+ logger.error("Unexpected protocol type {}: service={}", value, s);
+ return;
+ }
+
+ String type = (String)value;
+ ProtocolService<S> plugin = new ProtocolService<S>(props, s);
+ if (map.remove(type, plugin)) {
+ logger.debug("Removed protocol plugin service for {}: {}",
+ type, plugin);
+ } else {
+ logger.trace("Ignore unset service request for {}: {}",
+ type, plugin);
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param props Protocol plugin service properties.
+ * @param s A protocol plugin service handler.
+ */
+ public ProtocolService(Map<?, ?> props, T s) {
+ service = s;
+
+ String key = GlobalConstants.PROTOCOLPLUGINPRIORITY.toString();
+ Object value = props.get(key);
+ if (value instanceof Integer) {
+ priority = ((Integer)value).intValue();
+ } else {
+ priority = DEFAULT_PRIORITY;
+ }
+ }
+
+ /**
+ * Return a protocol plugin service handler.
+ *
+ * @return A protocol plugin service handler.
+ */
+ public T getService() {
+ return service;
+ }
+
+ /**
+ * Return a priority value assigned to this protocol plugin.
+ *
+ * @return A priority value.
+ */
+ public int getPriority() {
+ return priority;
+ }
+
+ /**
+ * Determine whether the given object is identical to this object.
+ *
+ * @param o An object to be compared.
+ * @return {@code true} if identical. Otherwise {@code false}.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o == null || o.getClass() != getClass()) {
+ return false;
+ }
+
+ ProtocolService plugin = (ProtocolService)o;
+ return (service.equals(plugin.service) && priority == plugin.priority);
+ }
+
+ /**
+ * Return the hash code of this object.
+ *
+ * @return The hash code.
+ */
+ @Override
+ public int hashCode() {
+ return service.hashCode() + (priority * 31);
+ }
+
+ /**
+ * Return a string representation of this instance.
+ *
+ * @return A string representation of this instance.
+ */
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("[service=");
+ return builder.append(service).append(", priority=").append(priority).
+ append(']').toString();
+ }
+}
-
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-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,
import org.opendaylight.controller.sal.reader.NodeDescription;
import org.opendaylight.controller.sal.reader.NodeTableStatistics;
import org.opendaylight.controller.sal.utils.EtherTypes;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.NodeCreator;
public class ReadService implements IReadService, CommandProvider, IPluginOutReadService {
protected static final Logger logger = LoggerFactory.getLogger(ReadService.class);
- private ConcurrentHashMap<String, IPluginInReadService> pluginReader =
- new ConcurrentHashMap<String, IPluginInReadService>();
+ private ConcurrentHashMap<String, ProtocolService<IPluginInReadService>> pluginReader =
+ new ConcurrentHashMap<String, ProtocolService<IPluginInReadService>>();
private Set<IReadServiceListener> readerListeners =
new CopyOnWriteArraySet<IReadServiceListener>();
// Set the reference to the plugin flow Reader service
public void setService(Map<?, ?> props, IPluginInReadService s) {
- if (this.pluginReader == null) {
- logger.error("pluginReader store null");
- return;
- }
-
- logger.trace("Got a service set request {}", s);
- String type = null;
- for (Object e : props.entrySet()) {
- Map.Entry<?, ?> entry = (Map.Entry<?, ?>) e;
- logger.trace("Prop key:({}) value:({})", entry.getKey(),
- entry.getValue());
- }
-
- Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
- if (value instanceof String) {
- type = (String) value;
- }
- if (type == null) {
- logger.error("Received a pluginReader without any "
- + "protocolPluginType provided");
- } else {
- this.pluginReader.put(type, s);
- logger.debug("Stored the pluginReader for type: {}", type);
- }
+ ProtocolService.set(this.pluginReader, props, s, logger);
}
public void unsetService(Map<?, ?> props, IPluginInReadService s) {
- if (this.pluginReader == null) {
- logger.error("pluginReader store null");
- return;
- }
-
- String type = null;
- logger.debug("Received unsetpluginReader request");
- for (Object e : props.entrySet()) {
- Map.Entry<?, ?> entry = (Map.Entry<?, ?>) e;
- logger.trace("Prop key:({}) value:({})", entry.getKey(),
- entry.getValue());
- }
-
- Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
- if (value instanceof String) {
- type = (String) value;
- }
- if (type == null) {
- logger.error("Received a pluginReader without any "
- + "protocolPluginType provided");
- } else if (this.pluginReader.get(type).equals(s)) {
- this.pluginReader.remove(type);
- logger.debug("Removed the pluginReader for type: {}", type);
- }
+ ProtocolService.unset(this.pluginReader, props, s, logger);
}
+
public void setReaderListener(IReadServiceListener service) {
logger.trace("Got a listener set request {}", service);
this.readerListeners.add(service);
@Override
public FlowOnNode readFlow(Node node, Flow flow) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readFlow(node, flow, true);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readFlow(node, flow, true);
}
}
logger.warn("Plugin {} unavailable", node.getType());
@Override
public FlowOnNode nonCachedReadFlow(Node node, Flow flow) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readFlow(node, flow, false);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readFlow(node, flow, false);
}
}
logger.warn("Plugin {} unavailable", node.getType());
@Override
public List<FlowOnNode> readAllFlows(Node node) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readAllFlow(node, true);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readAllFlow(node, true);
}
}
logger.warn("Plugin {} unavailable", node.getType());
@Override
public List<FlowOnNode> nonCachedReadAllFlows(Node node) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readAllFlow(node, false);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readAllFlow(node, false);
}
}
logger.warn("Plugin {} unavailable", node.getType());
@Override
public NodeDescription readDescription(Node node) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readDescription(node, true);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readDescription(node, true);
}
}
logger.warn("Plugin {} unavailable", node.getType());
@Override
public NodeDescription nonCachedReadDescription(Node node) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readDescription(node, false);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readDescription(node, false);
}
}
logger.warn("Plugin {} unavailable", node.getType());
public NodeConnectorStatistics readNodeConnector(NodeConnector connector) {
Node node = connector.getNode();
if (pluginReader != null && node != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readNodeConnector(connector, true);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readNodeConnector(connector, true);
}
}
logger.warn("Plugin {} unavailable", node.getType());
NodeConnector connector) {
Node node = connector.getNode();
if (pluginReader != null && node != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readNodeConnector(connector, false);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readNodeConnector(connector, false);
}
}
logger.warn("Plugin {} unavailable", node.getType());
@Override
public List<NodeConnectorStatistics> readNodeConnectors(Node node) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readAllNodeConnector(node, true);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readAllNodeConnector(node, true);
}
}
logger.warn("Plugin {} unavailable", node.getType());
@Override
public List<NodeTableStatistics> readNodeTable(Node node) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readAllNodeTable(node, true);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readAllNodeTable(node, true);
}
}
logger.warn("Plugin {} unavailable", node.getType());
public NodeTableStatistics nonCachedReadNodeTable(NodeTable table) {
Node node = table.getNode();
if (pluginReader != null && node != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readNodeTable(table, false);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readNodeTable(table, false);
}
}
logger.warn("Plugin {} unavailable", node.getType());
public NodeTableStatistics readNodeTable(NodeTable table) {
Node node = table.getNode();
if (pluginReader != null && node != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readNodeTable(table, true);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readNodeTable(table, true);
}
}
logger.warn("Plugin {} unavailable", node.getType());
@Override
public List<NodeConnectorStatistics> nonCachedReadNodeConnectors(Node node) {
if (pluginReader != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .readAllNodeConnector(node, false);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().readAllNodeConnector(node, false);
}
}
logger.warn("Plugin {} unavailable", node.getType());
public long getTransmitRate(NodeConnector connector) {
Node node = connector.getNode();
if (pluginReader != null && node != null) {
- if (this.pluginReader.get(node.getType()) != null) {
- return this.pluginReader.get(node.getType())
- .getTransmitRate(connector);
+ ProtocolService<IPluginInReadService> service =
+ this.pluginReader.get(node.getType());
+ if (service != null) {
+ return service.getService().getTransmitRate(connector);
}
}
logger.warn("Plugin {} unavailable", node.getType());
--- /dev/null
+/*
+ * Copyright (c) 2014 NEC Corporation 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.controller.sal.implementation;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.sal.implementation.internal.ProtocolService;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+
+/**
+ * Unit test for {@link ProtocolService}.
+ */
+public class ProtocolServiceTest {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(ProtocolServiceTest.class);
+
+ @Test
+ public void testInstance() {
+ HashSet<ProtocolService<ITestService>> set = new HashSet<>();
+ TestService sv1 = new TestService();
+ HashMap<String, Object> prop1 = new HashMap<>();
+
+ ProtocolService<ITestService> ps1 =
+ new ProtocolService<ITestService>(prop1, sv1);
+ assertEquals(sv1, ps1.getService());
+ // Default priority is 0.
+ assertEquals(0, ps1.getPriority());
+ assertTrue(set.add(ps1));
+ assertFalse(set.add(ps1));
+
+ // Specify the same service and priority.
+ String priKey = GlobalConstants.PROTOCOLPLUGINPRIORITY.toString();
+ prop1.put(priKey, Integer.valueOf(0));
+ ProtocolService<ITestService> ps2 =
+ new ProtocolService<ITestService>(prop1, sv1);
+ assertEquals(sv1, ps2.getService());
+ assertEquals(0, ps2.getPriority());
+ assertEquals(ps1, ps2);
+ assertFalse(set.add(ps1));
+
+ // Specify different priority.
+ prop1.put(priKey, Integer.valueOf(Integer.MAX_VALUE));
+ ps2 = new ProtocolService<ITestService>(prop1, sv1);
+ assertEquals(sv1, ps2.getService());
+ assertEquals(Integer.MAX_VALUE, ps2.getPriority());
+ assertFalse(ps1.equals(ps2));
+ assertTrue(set.add(ps2));
+ assertFalse(set.add(ps2));
+
+ // Specify another service.
+ TestService sv2 = new TestService();
+ prop1.put(priKey, Integer.valueOf(0));
+ ps2 = new ProtocolService<ITestService>(prop1, sv2);
+ assertEquals(sv2, ps2.getService());
+ assertEquals(0, ps2.getPriority());
+ assertFalse(ps1.equals(ps2));
+ assertTrue(set.add(ps2));
+ assertFalse(set.add(ps2));
+ }
+
+ @Test
+ public void testSetUnsetError() {
+ ConcurrentMap<String, ProtocolService<ITestService>> services =
+ new ConcurrentHashMap<>();
+ TestService sv = new TestService();
+ Map<String, Object> props = new HashMap<>();
+
+ // null service.
+ ProtocolService.set(services, props, null, LOG);
+ assertTrue(services.isEmpty());
+
+ ProtocolService.unset(services, props, null, LOG);
+ assertTrue(services.isEmpty());
+
+ // null service property.
+ ProtocolService.set(services, null, sv, LOG);
+ assertTrue(services.isEmpty());
+
+ ProtocolService.unset(services, null, sv, LOG);
+ assertTrue(services.isEmpty());
+
+ // Type is not specified.
+ ProtocolService.set(services, props, sv, LOG);
+ assertTrue(services.isEmpty());
+
+ ProtocolService.unset(services, props, sv, LOG);
+ assertTrue(services.isEmpty());
+
+ // null service map.
+ final String typeKey = GlobalConstants.PROTOCOLPLUGINTYPE.toString();
+ assertEquals(null, props.put(typeKey, "OF"));
+ ProtocolService.set(null, props, sv, LOG);
+ assertTrue(services.isEmpty());
+
+ ProtocolService.unset(null, props, sv, LOG);
+ assertTrue(services.isEmpty());
+ }
+
+ @Test
+ public void testSetUnset() {
+ ConcurrentMap<String, ProtocolService<ITestService>> serviceMap =
+ new ConcurrentHashMap<>();
+ ConcurrentMap<String, ProtocolService<ITestService>> expected =
+ new ConcurrentHashMap<>();
+
+ final String typeKey = GlobalConstants.PROTOCOLPLUGINTYPE.toString();
+ final String priKey = GlobalConstants.PROTOCOLPLUGINPRIORITY.toString();
+ final String[] protocols = {"OF", "PE", "PK"};
+ final int basePri = 0;
+ final int loop = 5;
+
+ // Should override the service if higher priority is specified.
+ for (String proto: protocols) {
+ for (int pri = basePri - loop + 1; pri <= basePri; pri++) {
+ TestService sv = new TestService();
+ Map<String, Object> props = new HashMap<>();
+ assertEquals(null, props.put(typeKey, proto));
+ assertEquals(null, props.put(priKey, Integer.valueOf(pri)));
+ ProtocolService.set(serviceMap, props, sv, LOG);
+
+ ProtocolService<ITestService> service = serviceMap.get(proto);
+ assertNotNull(service);
+ assertEquals(sv, service.getService());
+ assertEquals(pri, service.getPriority());
+
+ ProtocolService<ITestService> service1 =
+ new ProtocolService<ITestService>(props, sv);
+ expected.put(proto, service1);
+ assertEquals(expected, serviceMap);
+
+ // Unset service request should be ignored if different
+ // parameters are specified.
+ TestService another = new TestService();
+ ProtocolService.unset(serviceMap, props, another, LOG);
+ assertEquals(expected, serviceMap);
+
+ props.put(priKey, Integer.valueOf(Integer.MAX_VALUE));
+ ProtocolService.unset(serviceMap, props, sv, LOG);
+ assertEquals(expected, serviceMap);
+ }
+ }
+
+ // Should reject the set service request if lower priority is specified.
+ for (String proto: protocols) {
+ for (int pri = basePri - loop; pri < basePri; pri++) {
+ TestService sv = new TestService();
+ Map<String, Object> props = new HashMap<>();
+ assertEquals(null, props.put(typeKey, proto));
+ assertEquals(null, props.put(priKey, Integer.valueOf(pri)));
+ ProtocolService.set(serviceMap, props, sv, LOG);
+ assertEquals(expected, serviceMap);
+ }
+ }
+
+ // Unset protocol services.
+ for (String proto: protocols) {
+ ProtocolService<ITestService> service = expected.remove(proto);
+ assertNotNull(service);
+
+ ITestService sv = service.getService();
+ Map<String, Object> props = new HashMap<>();
+ assertEquals(null, props.put(typeKey, proto));
+ assertEquals(null, props.put(priKey, Integer.valueOf(basePri)));
+ ProtocolService.unset(serviceMap, props, sv, LOG);
+ assertEquals(expected, serviceMap);
+
+ // Should be ignored if the specified service does not exist.
+ ProtocolService.unset(serviceMap, props, sv, LOG);
+ assertEquals(expected, serviceMap);
+ }
+
+ assertTrue(serviceMap.isEmpty());
+ }
+}
+
+interface ITestService {
+}
+
+class TestService implements ITestService {
+}
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-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,
var h3 = "Set Transport Source Port";
var placeholder = "Transport Source Port";
var id = one.f.flows.id.modal.action.modifyTransportSourcePort;
- var help = "Range: 1 - 65535";
+ var help = "Range: 0 - 65535";
var action = 'SET_TP_SRC';
var name = "Source Port";
var body = function() {
var h3 = "Set Transport Destination Port";
var placeholder = "Transport Destination Port";
var id = one.f.flows.id.modal.action.modifyTransportDestinationPort;
- var help = "Range: 1 - 65535";
+ var help = "Range: 0 - 65535";
var action = 'SET_TP_DST';
var name = "Destination Port";
var body = function() {
<module>opendaylight/forwardingrulesmanager/implementation</module>
<module>opendaylight/hosttracker/api</module>
<module>opendaylight/hosttracker/implementation</module>
+ <module>opendaylight/hosttracker/shell</module>
<module>opendaylight/hosttracker_new/api</module>
<module>opendaylight/hosttracker_new/implementation</module>
<module>opendaylight/containermanager/api</module>
<module>opendaylight/distribution/opendaylight-karaf</module>
<module>opendaylight/distribution/opendaylight-karaf-resources</module>
<module>features</module>
+
+ <!-- archetypes -->
+ <module>opendaylight/archetypes</module>
</modules>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>