</prerequisites>
<properties>
+ <aopalliance.version>1.0.0</aopalliance.version>
+ <appauth.version>0.4.2-SNAPSHOT</appauth.version>
+ <!-- Controller Modules Versions -->
<arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
+ <!-- Plugin Versions -->
+ <bouncycastle.version>1.50</bouncycastle.version>
<bundle.plugin.version>2.3.7</bundle.plugin.version>
<bundlescanner.version>0.4.2-SNAPSHOT</bundlescanner.version>
<checkstyle.version>2.10</checkstyle.version>
<clustering.services.version>0.5.1-SNAPSHOT</clustering.services.version>
<clustering.services_implementation.version>0.4.3-SNAPSHOT</clustering.services_implementation.version>
<clustering.stub.version>0.4.2-SNAPSHOT</clustering.stub.version>
+ <clustering.test.version>0.4.2-SNAPSHOT</clustering.test.version>
+ <commmons.northbound.version>0.4.2-SNAPSHOT</commmons.northbound.version>
+ <!-- Third Party Versions -->
+ <commons.codec.version>1.7</commons.codec.version>
+ <commons.fileupload.version>1.2.2</commons.fileupload.version>
<commons.httpclient.version>0.1.2-SNAPSHOT</commons.httpclient.version>
<commons.io.version>2.4</commons.io.version>
<commons.lang.version>3.1</commons.lang.version>
+ <commons.net.version>3.0.1</commons.net.version>
<compiler.version>2.3.2</compiler.version>
<concepts.version>0.5.2-SNAPSHOT</concepts.version>
<config.version>0.2.5-SNAPSHOT</config.version>
+ <configuration.implementation.version>0.4.3-SNAPSHOT</configuration.implementation.version>
<configuration.version>0.4.3-SNAPSHOT</configuration.version>
<connectionmanager.version>0.1.2-SNAPSHOT</connectionmanager.version>
<containermanager.it.version>0.5.2-SNAPSHOT</containermanager.it.version>
+ <containermanager.northbound.version>0.4.2-SNAPSHOT</containermanager.northbound.version>
<containermanager.version>0.5.2-SNAPSHOT</containermanager.version>
- <!--versions for bits of the controller -->
+ <controllermanager.northbound.version>0.0.2-SNAPSHOT</controllermanager.northbound.version>
<corsfilter.version>7.0.42</corsfilter.version>
+ <devices.web.version>0.4.2-SNAPSHOT</devices.web.version>
+ <eclipse.persistence.version>2.5.0</eclipse.persistence.version>
<!-- enforcer version -->
<enforcer.version>1.3.1</enforcer.version>
<enunciate.version>1.26.2</enunciate.version>
<!-- OpenEXI third party lib for netconf-->
<exi.nagasena.version>0000.0002.0038.0-SNAPSHOT</exi.nagasena.version>
<failsafe.version>2.15</failsafe.version>
+ <felix.dependencymanager.shell.version>3.0.1</felix.dependencymanager.shell.version>
+ <felix.dependencymanager.version>3.1.0</felix.dependencymanager.version>
+ <felix.fileinstall.version>3.1.6</felix.fileinstall.version>
+ <felix.webconsole.version>4.2.0</felix.webconsole.version>
+ <flowprogrammer.northbound.version>0.4.2-SNAPSHOT</flowprogrammer.northbound.version>
+ <flows.web.version>0.4.2-SNAPSHOT</flows.web.version>
<forwarding.staticrouting>0.5.2-SNAPSHOT</forwarding.staticrouting>
+ <forwarding.staticrouting.northbound.version>0.4.2-SNAPSHOT</forwarding.staticrouting.northbound.version>
+ <forwardingrulesmanager.implementation.version>0.4.2-SNAPSHOT</forwardingrulesmanager.implementation.version>
<forwardingrulesmanager.version>0.6.0-SNAPSHOT</forwardingrulesmanager.version>
<geminiweb.version>2.2.0.RELEASE</geminiweb.version>
+ <gson.version>2.2.4</gson.version>
<guava.version>14.0.1</guava.version>
<hosttracker.api.version>0.5.2-SNAPSHOT</hosttracker.api.version>
<hosttracker.implementation.version>0.5.2-SNAPSHOT</hosttracker.implementation.version>
+ <hosttracker.northbound.version>0.4.2-SNAPSHOT</hosttracker.northbound.version>
<hosttracker_new.api.version>0.4.2-SNAPSHOT</hosttracker_new.api.version>
<ietf-inet-types.version>2010.09.24.4-SNAPSHOT</ietf-inet-types.version>
<ietf-topology.version>2013.10.21.2-SNAPSHOT</ietf-topology.version>
<!-- Third party version -->
<jersey-servlet.version>1.17</jersey-servlet.version>
<jersey.version>1.17</jersey.version>
+ <jettison.version>1.3.3</jettison.version>
<jmxGeneratorPath>src/main/yang-gen-config</jmxGeneratorPath>
<jolokia.version>1.1.4</jolokia.version>
+ <jsr305.api.version>2.0.1</jsr305.api.version>
+ <jsr311.api.version>1.1.1</jsr311.api.version>
<junit.version>4.8.1</junit.version>
<logback.version>1.0.9</logback.version>
<logging.bridge.version>0.4.2-SNAPSHOT</logging.bridge.version>
<netconf.version>0.2.5-SNAPSHOT</netconf.version>
<netty.version>4.0.17.Final</netty.version>
<networkconfig.bridgedomain.northbound.version>0.0.3-SNAPSHOT</networkconfig.bridgedomain.northbound.version>
+ <networkconfig.neutron.implementation.version>0.4.2-SNAPSHOT</networkconfig.neutron.implementation.version>
+ <networkconfig.neutron.northbound.version>0.4.2-SNAPSHOT</networkconfig.neutron.northbound.version>
+ <networkconfig.neutron.version>0.4.2-SNAPSHOT</networkconfig.neutron.version>
<!-- ODL repository / plugin repository -->
<nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
<opendaylight-l2-types.version>2013.08.27.4-SNAPSHOT</opendaylight-l2-types.version>
+ <osgi-brandfragment.web.version>0.0.2-SNAPSHOT</osgi-brandfragment.web.version>
+ <osgi.compendium.version>5.0.0</osgi.compendium.version>
<osgi.core.version>5.0.0</osgi.core.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<projectinfo>2.6</projectinfo>
-
<propertymavenplugin.version>1.0-alpha-2</propertymavenplugin.version>
<protocol-framework.version>0.5.0-SNAPSHOT</protocol-framework.version>
- <protocol_plugin.stub.version>0.4.2-SNAPSHOT</protocol_plugin.stub.version>
+ <protocol_plugins.openflow.version>0.4.2-SNAPSHOT</protocol_plugins.openflow.version>
+ <protocol_plugins.stub.version>0.4.2-SNAPSHOT</protocol_plugins.stub.version>
<releaseplugin.version>2.3.2</releaseplugin.version>
+ <routing.dijkstra_implementation.version>0.4.2-SNAPSHOT</routing.dijkstra_implementation.version>
<sal.connection.version>0.1.2-SNAPSHOT</sal.connection.version>
+ <sal.implementation.version>0.4.2-SNAPSHOT</sal.implementation.version>
<sal.networkconfiguration.version>0.0.3-SNAPSHOT</sal.networkconfiguration.version>
<sal.version>0.8.1-SNAPSHOT</sal.version>
<salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
<samples.loadbalancer>0.5.2-SNAPSHOT</samples.loadbalancer>
+ <samples.loadbalancer.northbound.version>0.4.2-SNAPSHOT</samples.loadbalancer.northbound.version>
+ <samples.simpleforwarding.version>0.4.2-SNAPSHOT</samples.simpleforwarding.version>
<sanitytest.version>0.4.2-SNAPSHOT</sanitytest.version>
+ <security.version>0.4.2-SNAPSHOT</security.version>
<sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
<siteplugin>3.2</siteplugin>
<slf4j.version>1.7.2</slf4j.version>
<spring-osgi.version>1.2.1</spring-osgi.version>
<spring-security.version>3.1.3.RELEASE</spring-security.version>
<spring.version>3.1.3.RELEASE</spring.version>
+ <statistics.northbound.version>0.4.2-SNAPSHOT</statistics.northbound.version>
+ <statisticsmanager.implementation.version>0.4.2-SNAPSHOT</statisticsmanager.implementation.version>
<statisticsmanager.version>0.5.1-SNAPSHOT</statisticsmanager.version>
+ <subnets.northbound.version>0.4.2-SNAPSHOT</subnets.northbound.version>
<surefire.version>2.15</surefire.version>
<switchmanager.api.version>0.7.1-SNAPSHOT</switchmanager.api.version>
+ <switchmanager.implementation.version>0.4.2-SNAPSHOT</switchmanager.implementation.version>
+ <switchmanager.northbound.version>0.4.2-SNAPSHOT</switchmanager.northbound.version>
<testvm.argLine>-Xmx1024m -XX:MaxPermSize=256m</testvm.argLine>
+ <topology.northbound.version>0.4.2-SNAPSHOT</topology.northbound.version>
+ <topology.web.version>0.4.2-SNAPSHOT</topology.web.version>
<topologymanager.version>0.4.2-SNAPSHOT</topologymanager.version>
+ <troubleshoot.web.version>0.4.2-SNAPSHOT</troubleshoot.web.version>
<url.version>1.5.0</url.version>
+ <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>
<virgo.version>3.6.0.RELEASE</virgo.version>
+ <web.version>0.4.2-SNAPSHOT</web.version>
<xtend.dstdir>src/main/xtend-gen</xtend.dstdir>
<xtend.version>2.4.3</xtend.version>
<yang-ext.version>2013.09.07.4-SNAPSHOT</yang-ext.version>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
- <version>2.0.1</version>
+ <version>${jsr305.api.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
- <version>2.2.4</version>
+ <version>${gson.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.7</version>
+ <version>${commons.codec.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
- <version>1.2.2</version>
+ <version>${commons.fileupload.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
- <version>3.0.1</version>
+ <version>${commons.net.version}</version>
</dependency>
<dependency>
<groupId>eclipselink</groupId>
<artifactId>netty-common</artifactId>
<version>${netty.version}</version>
</dependency>
-
- <!--Netty-->
+ <!-- Netty -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
</dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>jsr311-api</artifactId>
+ <version>${jsr311.api.version}</version>
+ </dependency>
<dependency>
<groupId>orbit</groupId>
<artifactId>javax.activation</artifactId>
<dependency>
<groupId>org.aopalliance</groupId>
<artifactId>com.springsource.org.aopalliance</artifactId>
- <version>1.0.0</version>
+ <version>${aopalliance.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.dependencymanager</artifactId>
- <version>3.1.0</version>
+ <version>${felix.dependencymanager.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.dependencymanager.shell</artifactId>
- <version>3.0.1</version>
+ <version>${felix.dependencymanager.shell.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.fileinstall</artifactId>
- <version>3.1.6</version>
+ <version>${felix.fileinstall.version}</version>
</dependency>
<!-- felix webconsole -->
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.webconsole</artifactId>
- <version>4.2.0</version>
+ <version>${felix.webconsole.version}</version>
<!-- the all bundle includes all the necessary plugins -->
<classifier>all</classifier>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
- <version>1.50</version>
+ <version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
- <version>1.50</version>
+ <version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.enunciate</groupId>
<artifactId>enunciate-core-annotations</artifactId>
<version>${enunciate.version}</version>
</dependency>
-
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
- <version>1.3.3</version>
+ <version>${jettison.version}</version>
</dependency>
<!-- equinox http service bridge -->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.antlr</artifactId>
- <version>2.5.0</version>
+ <version>${eclipse.persistence.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
- <version>2.5.0</version>
+ <version>${eclipse.persistence.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
- <version>2.5.0</version>
+ <version>${eclipse.persistence.version}</version>
</dependency>
<!-- md-sal -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>appauth</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${appauth.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.test</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${clustering.test.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${commmons.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>configuration.implementation</artifactId>
- <version>0.4.3-SNAPSHOT</version>
+ <version>${configuration.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>containermanager.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${containermanager.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>controllermanager.northbound</artifactId>
- <version>0.0.2-SNAPSHOT</version>
+ <version>${controllermanager.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>devices.web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${devices.web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>flowprogrammer.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${flowprogrammer.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>flows.web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${flows.web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwarding.staticrouting.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${forwarding.staticrouting.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwardingrulesmanager.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${forwardingrulesmanager.implementation.version}</version>
</dependency>
<dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${hosttracker.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>networkconfig.neutron</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${networkconfig.neutron.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>networkconfig.neutron.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${networkconfig.neutron.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>networkconfig.neutron.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${networkconfig.neutron.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>osgi-brandfragment.web</artifactId>
- <version>0.0.2-SNAPSHOT</version>
+ <version>${osgi-brandfragment.web.version}</version>
</dependency>
<dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>protocol_plugins.openflow</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${protocol_plugins.openflow.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>protocol_plugins.stub</artifactId>
- <version>${protocol_plugin.stub.version}</version>
+ <version>${protocol_plugins.stub.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>routing.dijkstra_implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${routing.dijkstra_implementation.version}</version>
</dependency>
<!-- SAL bundles -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${sal.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>samples.loadbalancer.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${samples.loadbalancer.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>samples.simpleforwarding</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${samples.simpleforwarding.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>security</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${security.version}</version>
</dependency>
<dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>statistics.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${statistics.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>statisticsmanager.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${statisticsmanager.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>subnets.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${subnets.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${switchmanager.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${switchmanager.northbound.version}</version>
</dependency>
<!-- threadpool -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>topology.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${topology.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>topology.web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${topology.web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>troubleshoot.web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${troubleshoot.web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>usermanager.implementation</artifactId>
- <version>${usermanager.version}</version>
+ <version>${usermanager.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>usermanager.northbound</artifactId>
- <version>0.0.2-SNAPSHOT</version>
+ <version>${usermanager.northbound.version}</version>
</dependency>
<!-- Web bundles -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
- <version>${osgi.core.version}</version>
+ <version>${osgi.compendium.version}</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
*/
package org.opendaylight.controller.config.yang.protocol.framework;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
public class NeverReconnectStrategyModuleTest extends AbstractConfigTest {
private static final String INSTANCE_NAME = "never-reconect-strategy-factory-impl";
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new NeverReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
}
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new ReconnectImmediatelyStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
}
*/
package org.opendaylight.controller.config.yang.protocol.framework;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.math.BigDecimal;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+import java.math.BigDecimal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
public class TimedReconnectStrategyModuleTest extends AbstractConfigTest {
private static final String INSTANCE_NAME = "timed-reconect-stategy-facotry-impl";
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TimedReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
}
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+/**
+ * Interface exposing some internal state on top of ServiceReferenceReadableRegistry. This will
+ * not be exposed via JMX.
+ */
public interface CloseableServiceReferenceReadableRegistry extends AutoCloseable, ServiceReferenceReadableRegistry {
-
void close();
}
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
-import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.DestroyedModule;
}
};
- Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = Collections.unmodifiableMap(
+ Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = new HashMap<>(
resolver.getAllFactories());
+ // add all factories that disappeared from SR but are still committed
+ for (ModuleInternalInfo moduleInternalInfo : currentConfig.getEntries()) {
+ String name = moduleInternalInfo.getModuleFactory().getImplementationName();
+ if (allCurrentFactories.containsKey(name) == false) {
+ logger.trace("Factory {} not found in SR, using reference from previous commit", name);
+ allCurrentFactories.put(name,
+ Maps.immutableEntry(moduleInternalInfo.getModuleFactory(), moduleInternalInfo.getBundleContext()));
+ }
+ }
+ allCurrentFactories = Collections.unmodifiableMap(allCurrentFactories);
+
// closed by transaction controller
ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier(
transactionName), factory, allCurrentFactories);
- ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
+ SearchableServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
readableSRRegistry, txLookupRegistry, allCurrentFactories);
ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
// non recoverable from here:
try {
return secondPhaseCommit(configTransactionController, commitInfo, configTransactionControllerEntry.getValue());
- } catch (Throwable t) { // some libs throw Errors: e.g.
+ } catch (Error | RuntimeException t) { // some libs throw Errors: e.g.
// javax.xml.ws.spi.FactoryFinder$ConfigurationError
isHealthy = false;
logger.error("Configuration Transaction failed on 2PC, server is unhealthy", t);
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
- } else if (t instanceof Error) {
- throw (Error) t;
} else {
- throw new RuntimeException(t);
+ throw (Error) t;
}
}
}
// register to JMX
try {
- newModuleJMXRegistrator.registerMBean(newReadableConfigBean,
- primaryReadOnlyON);
+ newModuleJMXRegistrator.registerMBean(newReadableConfigBean, primaryReadOnlyON);
} catch (InstanceAlreadyExistsException e) {
- throw new IllegalStateException(e);
+ throw new IllegalStateException("Possible code error, already registered:" + primaryReadOnlyON,e);
}
- // register to OSGi
+ // register services to OSGi
+ Map<String, ServiceInterfaceAnnotation> annotationMapping = configTransactionController.getWritableRegistry().findServiceInterfaces(moduleIdentifier);
+ BundleContext bc = configTransactionController.getModuleFactoryBundleContext(
+ entry.getModuleFactory().getImplementationName());
if (osgiRegistration == null) {
- ModuleFactory moduleFactory = entry.getModuleFactory();
- if (moduleFactory != null) {
- BundleContext bc = configTransactionController.
- getModuleFactoryBundleContext(moduleFactory.getImplementationName());
- osgiRegistration = beanToOsgiServiceManager.registerToOsgi(realModule.getClass(),
- newReadableConfigBean.getInstance(), entry.getIdentifier(), bc);
- } else {
- throw new NullPointerException(entry.getIdentifier().getFactoryName() + " ModuleFactory not found.");
- }
-
+ osgiRegistration = beanToOsgiServiceManager.registerToOsgi(
+ newReadableConfigBean.getInstance(), moduleIdentifier, bc, annotationMapping);
+ } else {
+ osgiRegistration.updateRegistrations(annotationMapping, bc, instance);
}
RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator = runtimeRegistrators
ModuleInternalInfo newInfo = new ModuleInternalInfo(
entry.getIdentifier(), newReadableConfigBean, osgiRegistration,
runtimeBeanRegistrator, newModuleJMXRegistrator,
- orderingIdx, entry.isDefaultBean());
+ orderingIdx, entry.isDefaultBean(), entry.getModuleFactory(), entry.getBundleContext());
newConfigEntries.put(realModule, newInfo);
orderingIdx++;
*/
package org.opendaylight.controller.config.manager.impl;
+import static java.lang.String.format;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.DynamicMBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.DynamicMBean;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
import static com.google.common.base.Preconditions.checkNotNull;
-import static java.lang.String.format;
-
/**
* This is a JMX bean representing current transaction. It contains
* transaction identifier, unique version and parent version for
private final boolean blankTransaction;
@GuardedBy("this")
- private final ServiceReferenceWritableRegistry writableSRRegistry;
+ private final SearchableServiceReferenceWritableRegistry writableSRRegistry;
public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
long parentVersion, CodecRegistry codecRegistry, long currentVersion,
Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
- boolean blankTransaction, ServiceReferenceWritableRegistry writableSRRegistry) {
+ boolean blankTransaction, SearchableServiceReferenceWritableRegistry writableSRRegistry) {
this.txLookupRegistry = txLookupRegistry;
String transactionName = txLookupRegistry.getTransactionIdentifier().getName();
this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName);
}
// add default modules
for (ModuleFactory moduleFactory : toBeAdded) {
+ BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager,
- getModuleFactoryBundleContext(moduleFactory.getImplementationName()));
+ bundleContext);
for (Module module : defaultModules) {
// ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
try {
boolean defaultBean = true;
- putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver, defaultBean);
+ putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null,
+ dependencyResolver, defaultBean, bundleContext);
} catch (InstanceAlreadyExistsException e) {
throw new IllegalStateException(e);
}
}
- private synchronized void copyExistingModule(
- ModuleInternalInfo oldConfigBeanInfo)
- throws InstanceAlreadyExistsException {
+ private synchronized void copyExistingModule(ModuleInternalInfo oldConfigBeanInfo) throws InstanceAlreadyExistsException {
+
transactionStatus.checkNotCommitStarted();
transactionStatus.checkNotAborted();
ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getIdentifier();
dependencyResolverManager.assertNotExists(moduleIdentifier);
- ModuleFactory moduleFactory = factoriesHolder
- .findByModuleName(moduleIdentifier.getFactoryName());
+ ModuleFactory moduleFactory;
+ BundleContext bc;
+ try {
+ moduleFactory = factoriesHolder.findByModuleName(moduleIdentifier.getFactoryName());
+ bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
+ } catch (InstanceNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
Module module;
DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
try {
- BundleContext bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
+
module = moduleFactory.createModule(
moduleIdentifier.getInstanceName(), dependencyResolver,
oldConfigBeanInfo.getReadableModule(), bc);
oldConfigBeanInfo, moduleFactory), e);
}
putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver,
- oldConfigBeanInfo.isDefaultBean());
+ oldConfigBeanInfo.isDefaultBean(), bc);
}
@Override
dependencyResolverManager.assertNotExists(moduleIdentifier);
// find factory
- ModuleFactory moduleFactory = factoriesHolder.findByModuleName(factoryName);
+ ModuleFactory moduleFactory;
+ try {
+ moduleFactory = factoriesHolder.findByModuleName(factoryName);
+ } catch (InstanceNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ }
DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
+ BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
Module module = moduleFactory.createModule(instanceName, dependencyResolver,
- getModuleFactoryBundleContext(moduleFactory.getImplementationName()));
+ bundleContext);
boolean defaultBean = false;
return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
- moduleFactory, null, dependencyResolver, defaultBean);
+ moduleFactory, null, dependencyResolver, defaultBean, bundleContext);
}
private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
ModuleIdentifier moduleIdentifier, Module module,
ModuleFactory moduleFactory,
- @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver, boolean isDefaultBean)
+ @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver,
+ boolean isDefaultBean, BundleContext bundleContext)
throws InstanceAlreadyExistsException {
logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
dependencyResolverManager.put(
moduleIdentifier, module, moduleFactory,
- maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean);
+ maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean, bundleContext);
return writableON;
}
logger.debug("Destroying module {} in transaction {}", moduleIdentifier, this);
transactionStatus.checkNotAborted();
+ ModuleInternalTransactionalInfo found = dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier);
if (blankTransaction == false) {
- ModuleInternalTransactionalInfo found =
- dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier);
+
if (found.isDefaultBean()) {
logger.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem");
}
}
// first remove refNames, it checks for objectname existence
+
try {
writableSRRegistry.removeServiceReferences(
ObjectNameUtil.createTransactionModuleON(getTransactionName(), moduleIdentifier));
}
@Override
- public ServiceReferenceWritableRegistry getWritableRegistry() {
+ public SearchableServiceReferenceWritableRegistry getWritableRegistry() {
return writableSRRegistry;
}
*/
package org.opendaylight.controller.config.manager.impl;
-import java.util.Collection;
-import java.util.List;
-
-import javax.management.ObjectName;
-
import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.osgi.framework.BundleContext;
+import javax.management.ObjectName;
+import java.util.Collection;
+import java.util.List;
+
/**
* Defines contract between {@link ConfigTransactionControllerImpl} (producer)
* and {@link ConfigRegistryImpl} (consumer).
BundleContext getModuleFactoryBundleContext(String factoryName);
- ServiceReferenceWritableRegistry getWritableRegistry();
+ SearchableServiceReferenceWritableRegistry getWritableRegistry();
TransactionIdentifier getTransactionIdentifier();
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
+import java.util.Deque;
+import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
public class DeadlockMonitor implements AutoCloseable {
private final TransactionIdentifier transactionIdentifier;
private final DeadlockMonitorRunnable thread;
@GuardedBy("this")
- private ModuleIdentifierWithNanos moduleIdentifierWithNanos = new ModuleIdentifierWithNanos();
+ private final Deque<ModuleIdentifierWithNanos> moduleIdentifierWithNanosStack = new LinkedList<>();
+ @GuardedBy("this")
+ private ModuleIdentifierWithNanos top = ModuleIdentifierWithNanos.EMPTY;
public DeadlockMonitor(TransactionIdentifier transactionIdentifier) {
this.transactionIdentifier = transactionIdentifier;
}
public synchronized void setCurrentlyInstantiatedModule(ModuleIdentifier currentlyInstantiatedModule) {
- this.moduleIdentifierWithNanos = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
+
+ boolean popping = currentlyInstantiatedModule == null;
+ if (popping) {
+ moduleIdentifierWithNanosStack.pop();
+ if (moduleIdentifierWithNanosStack.isEmpty()) {
+ top = ModuleIdentifierWithNanos.EMPTY;
+ } else {
+ top = moduleIdentifierWithNanosStack.peekLast();
+ }
+ } else {
+ ModuleIdentifierWithNanos current = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
+ moduleIdentifierWithNanosStack.push(current);
+ top = current;
+ }
+ logger.trace("setCurrentlyInstantiatedModule {}, top {}", currentlyInstantiatedModule, top);
}
public boolean isAlive() {
public void run() {
ModuleIdentifierWithNanos old = new ModuleIdentifierWithNanos(); // null moduleId
while (this.isInterrupted() == false) {
- ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.moduleIdentifierWithNanos);
- if (old.moduleIdentifier == null) {
+ ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.top);
+ if (old.moduleIdentifier == null || old.equals(copy) == false) {
// started
old = copy;
- } else if (old.moduleIdentifier != null && old.equals(copy)) {
+ } else {
// is the getInstance() running longer than WARN_AFTER_MILLIS ?
long runningTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - copy.nanoTime);
if (runningTime > WARN_AFTER_MILLIS) {
}
}
- private class ModuleIdentifierWithNanos {
+
+
+
+ private static class ModuleIdentifierWithNanos {
+ private static ModuleIdentifierWithNanos EMPTY = new ModuleIdentifierWithNanos();
@Nullable
private final ModuleIdentifier moduleIdentifier;
+
private final long nanoTime;
private ModuleIdentifierWithNanos() {
- moduleIdentifier = null;
- nanoTime = System.nanoTime();
+ this((ModuleIdentifier)null);
}
private ModuleIdentifierWithNanos(ModuleIdentifier moduleIdentifier) {
result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
return result;
}
+
+ @Override
+ public String toString() {
+ return "ModuleIdentifierWithNanos{" +
+ moduleIdentifier +
+ '}';
+ }
}
}
import org.opendaylight.controller.config.manager.impl.jmx.ModuleJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.RootRuntimeBeanRegistratorImpl;
import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceManager.OsgiRegistration;
+import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.concepts.Identifiable;
+import org.osgi.framework.BundleContext;
/**
* Provides metadata about Module from controller to registry.
private final ModuleJMXRegistrator moduleJMXRegistrator;
private final int orderingIdx;
private final boolean isDefaultBean;
+ private final ModuleFactory moduleFactory;
+ private final BundleContext bundleContext;
public ModuleInternalInfo(ModuleIdentifier name,
@Nullable DynamicReadableWrapper readableModule,
OsgiRegistration osgiRegistration,
RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator,
ModuleJMXRegistrator moduleJMXRegistrator, int orderingIdx,
- boolean isDefaultBean) {
+ boolean isDefaultBean, ModuleFactory moduleFactory, BundleContext bundleContext) {
if (osgiRegistration == null) {
throw new IllegalArgumentException(
this.moduleJMXRegistrator = moduleJMXRegistrator;
this.orderingIdx = orderingIdx;
this.isDefaultBean = isDefaultBean;
+ this.moduleFactory = moduleFactory;
+ this.bundleContext = bundleContext;
}
public DynamicReadableWrapper getReadableModule() {
public boolean isDefaultBean() {
return isDefaultBean;
}
+
+ public ModuleFactory getModuleFactory() {
+ return moduleFactory;
+ }
+
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
}
--- /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.config.manager.impl;
+
+import java.util.Map;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
+
+public interface SearchableServiceReferenceWritableRegistry extends ServiceReferenceWritableRegistry {
+ /**
+ * Return mapping between service ref names and service interface annotation for given
+ * module.
+ *
+ * @throws java.lang.IllegalArgumentException if any of service qNames is not found
+ * @throws java.lang.NullPointerException if parameter is null
+ */
+ Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier);
+
+}
*/
package org.opendaylight.controller.config.manager.impl;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.LookupRegistry;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
+public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, SearchableServiceReferenceWritableRegistry {
private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class);
private final Map<String, ModuleFactory> factories;
private final ServiceReferenceRegistrator serviceReferenceRegistrator;
// helper method for getting QName of SI from namespace + local name
private final Map<String /* namespace */, Map<String /* local name */, ServiceInterfaceAnnotation>> namespacesToAnnotations;
+ private final Map<String /* service qName */, ServiceInterfaceAnnotation> serviceQNamesToAnnotations;
// all Service Interface qNames for sanity checking
private final Set<String /* qName */> allQNames;
+ Map<ModuleIdentifier, Map<String /* service ref name */, ServiceInterfaceAnnotation >> modulesToServiceRef = new HashMap<>();
+
// actual reference database
private final Map<ServiceReference, ModuleIdentifier> refNames = new HashMap<>();
/**
* Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data.
*/
- public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
+ public static SearchableServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
ConfigTransactionLookupRegistry txLookupRegistry,
Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
Map<String, Set<String /* QName */>> modifiableFactoryNamesToQNames = new HashMap<>();
Set<ServiceInterfaceAnnotation> allAnnotations = new HashSet<>();
Set<String /* qName */> allQNames = new HashSet<>();
+
+
for (Entry<String, ModuleFactory> entry : factories.entrySet()) {
if (entry.getKey().equals(entry.getValue().getImplementationName()) == false) {
logger.error("Possible error in code: Mismatch between supplied and actual name of {}", entry);
throw new IllegalArgumentException("Possible error in code: Mismatch between supplied and actual name of " + entry);
}
Set<ServiceInterfaceAnnotation> siAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(entry.getValue());
- Set<String> qNames = new HashSet<>();
- for (ServiceInterfaceAnnotation sia: siAnnotations) {
- qNames.add(sia.value());
- }
+ Set<String> qNames = InterfacesHelper.getQNames(siAnnotations);
allAnnotations.addAll(siAnnotations);
allQNames.addAll(qNames);
modifiableFactoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames));
// fill namespacesToAnnotations
Map<String /* namespace */, Map<String /* localName */, ServiceInterfaceAnnotation>> modifiableNamespacesToAnnotations =
new HashMap<>();
+ Map<String /* service qName*/, ServiceInterfaceAnnotation> modifiableServiceQNamesToAnnotations = new HashMap<>();
for (ServiceInterfaceAnnotation sia : allAnnotations) {
Map<String, ServiceInterfaceAnnotation> ofNamespace = modifiableNamespacesToAnnotations.get(sia.namespace());
if (ofNamespace == null) {
throw new IllegalArgumentException("Conflict between local names in " + sia.namespace() + " : " + sia.localName());
}
ofNamespace.put(sia.localName(), sia);
+ modifiableServiceQNamesToAnnotations.put(sia.value(), sia);
}
this.namespacesToAnnotations = Collections.unmodifiableMap(modifiableNamespacesToAnnotations);
- // copy refNames
+ this.serviceQNamesToAnnotations = Collections.unmodifiableMap(modifiableServiceQNamesToAnnotations);
logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames);
}
+ @Override
+ public Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier) {
+ Map<String, ServiceInterfaceAnnotation> result = modulesToServiceRef.get(moduleIdentifier);
+ if (result == null) {
+ return Collections.emptyMap();
+ }
+ return Collections.unmodifiableMap(result);
+ }
@Override
public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
public synchronized Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> result = new HashMap<>();
for (Entry<ServiceReference, ModuleIdentifier> entry: refNames.entrySet()) {
- String qName = entry.getKey().getServiceInterfaceName();
+ String qName = entry.getKey().getServiceInterfaceQName();
Map<String /* refName */, ObjectName> innerMap = result.get(qName);
if (innerMap == null) {
innerMap = new HashMap<>();
throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + moduleIdentifier.getFactoryName());
}
// supplied serviceInterfaceName must exist in this collection
- if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
- logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
- throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName() + " within factory " + moduleIdentifier.getFactoryName());
+ if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceQName()) == false) {
+ logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceQName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
+ throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceQName() + " within factory " + moduleIdentifier.getFactoryName());
}
}
// save to refNames
refNames.put(serviceReference, moduleIdentifier);
+ Map<String, ServiceInterfaceAnnotation> refNamesToAnnotations = modulesToServiceRef.get(moduleIdentifier);
+ if (refNamesToAnnotations == null){
+ refNamesToAnnotations = new HashMap<>();
+ modulesToServiceRef.put(moduleIdentifier, refNamesToAnnotations);
+ }
+
+ ServiceInterfaceAnnotation annotation = serviceQNamesToAnnotations.get(serviceReference.getServiceInterfaceQName());
+ checkNotNull(annotation, "Possible error in code, cannot find annotation for " + serviceReference);
+ refNamesToAnnotations.put(serviceReference.getRefName(), annotation);
return result;
}
private ObjectName getServiceON(ServiceReference serviceReference) {
if (writable) {
return ObjectNameUtil.createTransactionServiceON(serviceReferenceRegistrator.getNullableTransactionName(),
- serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
+ serviceReference.getServiceInterfaceQName(), serviceReference.getRefName());
} else {
- return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
+ return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceQName(), serviceReference.getRefName());
}
}
logger.debug("Removing service reference {} from {}", serviceReference, this);
assertWritable();
// is the qName known?
- if (allQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
- logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceName(), allQNames);
- throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName());
+ if (allQNames.contains(serviceReference.getServiceInterfaceQName()) == false) {
+ logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceQName(), allQNames);
+ throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceQName());
}
ModuleIdentifier removed = refNames.remove(serviceReference);
if (removed == null){
- throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceName());
+ throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceQName());
}
Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> entry = mBeans.remove(serviceReference);
if (entry == null) {
@Override
public synchronized boolean removeServiceReferences(ObjectName moduleObjectName) throws InstanceNotFoundException {
+ lookupRegistry.checkConfigBeanExists(moduleObjectName);
+ String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
+ // check that service interface name exist
+ Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
+ return removeServiceReferences(moduleObjectName, serviceInterfaceQNames);
+ }
+
+
+ private boolean removeServiceReferences(ObjectName moduleObjectName, Set<String> qNames) throws InstanceNotFoundException {
+ ObjectNameUtil.checkType(moduleObjectName, ObjectNameUtil.TYPE_MODULE);
assertWritable();
- Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName);
+ Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName, qNames);
for (ServiceReference sr : serviceReferencesLinkingTo) {
removeServiceReference(sr);
}
return serviceReferencesLinkingTo.isEmpty() == false;
}
- private synchronized Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName) throws InstanceNotFoundException {
- lookupRegistry.checkConfigBeanExists(moduleObjectName);
+ private Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName, Set<String> serviceInterfaceQNames) {
String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
- // check that service interface name exist
- Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
if (serviceInterfaceQNames == null) {
- logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
+ logger.warn("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
}
String instanceName = ObjectNameUtil.getInstanceName(moduleObjectName);
return result;
}
-
@Override
public String toString() {
return "ServiceReferenceRegistryImpl{" +
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.reflect.AbstractInvocationHandler;
import com.google.common.reflect.Reflection;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.DependencyResolverFactory;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static com.google.common.base.Preconditions.checkState;
+import org.osgi.framework.BundleContext;
/**
* Holds information about modules being created and destroyed within this
ModuleFactory moduleFactory,
ModuleInternalInfo maybeOldInternalInfo,
TransactionModuleJMXRegistration transactionModuleJMXRegistration,
- boolean isDefaultBean) {
+ boolean isDefaultBean, BundleContext bundleContext) {
transactionStatus.checkNotCommitted();
Class<? extends Module> moduleClass = Module.class;
ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo(
moduleIdentifier, proxiedModule, moduleFactory,
- maybeOldInternalInfo, transactionModuleJMXRegistration, isDefaultBean, module);
+ maybeOldInternalInfo, transactionModuleJMXRegistration, isDefaultBean, module, bundleContext);
modulesHolder.put(moduleInternalTransactionalInfo);
}
import org.opendaylight.yangtools.concepts.Identifiable;
import javax.annotation.Nullable;
+import org.osgi.framework.BundleContext;
public class ModuleInternalTransactionalInfo implements Identifiable<ModuleIdentifier> {
private final ModuleIdentifier name;
private final ModuleInternalInfo maybeOldInternalInfo;
private final TransactionModuleJMXRegistration transactionModuleJMXRegistration;
private final boolean isDefaultBean;
+ private final BundleContext bundleContext;
public ModuleInternalTransactionalInfo(ModuleIdentifier name, Module proxiedModule,
ModuleFactory moduleFactory,
ModuleInternalInfo maybeOldInternalInfo,
TransactionModuleJMXRegistration transactionModuleJMXRegistration,
- boolean isDefaultBean, Module realModule) {
+ boolean isDefaultBean, Module realModule, BundleContext bundleContext) {
this.name = name;
this.proxiedModule = proxiedModule;
this.moduleFactory = moduleFactory;
this.transactionModuleJMXRegistration = transactionModuleJMXRegistration;
this.isDefaultBean = isDefaultBean;
this.realModule = realModule;
+ this.bundleContext = bundleContext;
}
public Module getRealModule() {
return realModule;
}
+
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
}
package org.opendaylight.controller.config.manager.impl.factoriesresolver;
-import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.osgi.framework.BundleContext;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
+import javax.management.InstanceNotFoundException;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.BundleContext;
/**
* Hold sorted ConfigMBeanFactories by their module names. Check that module
* @throws IllegalArgumentException
* if factory is not found
*/
- public ModuleFactory findByModuleName(String moduleName) {
+ public ModuleFactory findByModuleName(String moduleName) throws InstanceNotFoundException {
Map.Entry<ModuleFactory, BundleContext> result = moduleNamesToConfigBeanFactories.get(moduleName);
if (result == null) {
- throw new IllegalArgumentException(
+ throw new InstanceNotFoundException(
"ModuleFactory not found with module name: " + moduleName);
}
return result.getKey();
return moduleFactories;
}
- public Map<String, Entry<ModuleFactory, BundleContext>> getModuleNamesToConfigBeanFactories() {
- return moduleNamesToConfigBeanFactories;
- }
}
this.refName = refName;
}
- public String getServiceInterfaceName() {
+ public String getServiceInterfaceQName() {
return serviceInterfaceName;
}
result = 31 * result + refName.hashCode();
return result;
}
+
+ @Override
+ public String toString() {
+ return "ServiceReference{" +
+ "serviceInterfaceName='" + serviceInterfaceName + '\'' +
+ ", refName='" + refName + '\'' +
+ '}';
+ }
}
*/
package org.opendaylight.controller.config.manager.impl.osgi;
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
-import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
-import org.opendaylight.controller.config.spi.Module;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
+import static com.google.common.base.Preconditions.checkState;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Registers instantiated beans as OSGi services and unregisters these services
* if beans are destroyed.
*/
public class BeanToOsgiServiceManager {
- // name of properties submitted to osgi
- static final String INSTANCE_NAME_OSGI_PROP = "instanceName";
- static final String IMPLEMENTATION_NAME_OSGI_PROP = "implementationName";
+ private static final String SERVICE_NAME_OSGI_PROP = "name";
/**
* To be called for every created, reconfigured and recreated config bean.
* It is expected that before using this method OSGi service registry will
* be cleaned from previous registrations.
*/
- public OsgiRegistration registerToOsgi(
- Class<? extends Module> configBeanClass, AutoCloseable instance,
- ModuleIdentifier moduleIdentifier, BundleContext bundleContext) {
- try {
- final Set<Class<?>> configuresInterfaces = InterfacesHelper
- .getOsgiRegistrationTypes(configBeanClass);
- checkInstanceImplementing(instance, configuresInterfaces);
-
- // bundleContext.registerService blows up with empty 'clazzes'
- if (configuresInterfaces.isEmpty() == false) {
- final Dictionary<String, ?> propertiesForOsgi = getPropertiesForOsgi(moduleIdentifier);
- final ServiceRegistration<?> serviceRegistration = bundleContext
- .registerService(classesToNames(configuresInterfaces), instance, propertiesForOsgi);
- return new OsgiRegistration(serviceRegistration);
- } else {
- return new OsgiRegistration();
- }
- } catch (IllegalStateException e) {
- throw new IllegalStateException(
- "Error while registering instance into OSGi Service Registry: "
- + moduleIdentifier, e);
- }
+ public OsgiRegistration registerToOsgi(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
+ BundleContext bundleContext,
+ Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ return new OsgiRegistration(instance, moduleIdentifier, bundleContext, serviceNamesToAnnotations);
}
- private static String[] classesToNames(Set<Class<?>> cfgs) {
- String[] result = new String[cfgs.size()];
- int i = 0;
- for (Class<?> cfg : cfgs) {
- result[i] = cfg.getName();
- i++;
- }
+ private static Dictionary<String, String> createProps(String serviceName) {
+ Hashtable<String, String> result = new Hashtable<>();
+ result.put(SERVICE_NAME_OSGI_PROP, serviceName);
return result;
}
- private void checkInstanceImplementing(AutoCloseable instance,
- Set<Class<?>> configures) {
- Set<Class<?>> missing = new HashSet<>();
- for (Class<?> requiredIfc : configures) {
- if (requiredIfc.isInstance(instance) == false) {
- missing.add(requiredIfc);
- }
- }
- if (missing.isEmpty() == false) {
- throw new IllegalStateException(
- instance.getClass()
- + " does not implement following interfaces as announced by "
- + ServiceInterfaceAnnotation.class.getName()
- + " annotation :" + missing);
- }
- }
-
- private static Dictionary<String, ?> getPropertiesForOsgi(
- ModuleIdentifier moduleIdentifier) {
- Hashtable<String, String> table = new Hashtable<>();
- table.put(IMPLEMENTATION_NAME_OSGI_PROP,
- moduleIdentifier.getFactoryName());
- table.put(INSTANCE_NAME_OSGI_PROP, moduleIdentifier.getInstanceName());
- return table;
- }
public static class OsgiRegistration implements AutoCloseable {
- private final ServiceRegistration<?> serviceRegistration;
+ private static final Logger logger = LoggerFactory.getLogger(OsgiRegistration.class);
- public OsgiRegistration(ServiceRegistration<?> serviceRegistration) {
- this.serviceRegistration = serviceRegistration;
+ @GuardedBy("this")
+ private AutoCloseable instance;
+ private final ModuleIdentifier moduleIdentifier;
+ @GuardedBy("this")
+ private final Set<ServiceRegistration<?>> serviceRegistrations;
+ @GuardedBy("this")
+ private final Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations;
+
+ public OsgiRegistration(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
+ BundleContext bundleContext,
+ Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ this.instance = instance;
+ this.moduleIdentifier = moduleIdentifier;
+ this.serviceNamesToAnnotations = serviceNamesToAnnotations;
+ this.serviceRegistrations = registerToSR(instance, bundleContext, serviceNamesToAnnotations);
}
- public OsgiRegistration() {
- this.serviceRegistration = null;
+ private static Set<ServiceRegistration<?>> registerToSR(AutoCloseable instance, BundleContext bundleContext,
+ Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ Set<ServiceRegistration<?>> serviceRegistrations = new HashSet<>();
+ for (Entry<String, ServiceInterfaceAnnotation> entry : serviceNamesToAnnotations.entrySet()) {
+ Class<?> requiredInterface = entry.getValue().osgiRegistrationType();
+ checkState(requiredInterface.isInstance(instance), instance.getClass().getName() +
+ " instance should implement " + requiredInterface.getName());
+ Dictionary<String, String> propertiesForOsgi = createProps(entry.getKey());
+ ServiceRegistration<?> serviceRegistration = bundleContext
+ .registerService(requiredInterface.getName(), instance, propertiesForOsgi);
+ serviceRegistrations.add(serviceRegistration);
+ }
+ return serviceRegistrations;
}
@Override
- public void close() {
- if (serviceRegistration != null) {
- serviceRegistration.unregister();
+ public synchronized void close() {
+ for (ServiceRegistration<?> serviceRegistration : serviceRegistrations) {
+ try {
+ serviceRegistration.unregister();
+ } catch(IllegalStateException e) {
+ logger.trace("Cannot unregister {}", serviceRegistration, e);
+ }
}
+ serviceRegistrations.clear();
}
- }
+ public synchronized void updateRegistrations(Map<String, ServiceInterfaceAnnotation> newAnnotationMapping,
+ BundleContext bundleContext, AutoCloseable newInstance) {
+ boolean notEquals = this.instance != newInstance;
+ notEquals |= newAnnotationMapping.equals(serviceNamesToAnnotations) == false;
+ if (notEquals) {
+ // FIXME: changing from old state to new state can be improved by computing the diff
+ logger.debug("Detected change in service registrations for {}: old: {}, new: {}", moduleIdentifier,
+ serviceNamesToAnnotations, newAnnotationMapping);
+ close();
+ this.instance = newInstance;
+ Set<ServiceRegistration<?>> newRegs = registerToSR(instance, bundleContext, newAnnotationMapping);
+ serviceRegistrations.clear();
+ serviceRegistrations.addAll(newRegs);
+ }
+ }
+ }
}
return result;
}
+ public static Set<String> getQNames(Set<ServiceInterfaceAnnotation> siAnnotations) {
+ Set<String> qNames = new HashSet<>();
+ for (ServiceInterfaceAnnotation sia: siAnnotations) {
+ qNames.add(sia.value());
+ }
+ return Collections.unmodifiableSet(qNames);
+ }
public static Set<ServiceInterfaceAnnotation> getServiceInterfaceAnnotations(ModuleFactory factory) {
Set<Class<? extends AbstractServiceInterface>> implementedServiceIntefaces = Collections.unmodifiableSet(factory.getImplementedServiceIntefaces());
result.add(annotation);
}
}
- return result;
+ return Collections.unmodifiableSet(result);
}
static Set<Class<? extends AbstractServiceInterface>> getAllAbstractServiceInterfaceClasses(
*/
package org.opendaylight.controller.config.manager;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-import java.lang.management.ManagementFactory;
-
import org.junit.Test;
import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.lang.management.ManagementFactory;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
public class ConfigRegistryImplTest extends
AbstractLockedPlatformMBeanServerTest {
private static final Logger logger = LoggerFactory
BundleContext context = mock(BundleContext.class);
ConfigRegistryImpl configRegistry = null;
try {
- ModuleFactoriesResolver resolver = new HardcodedModuleFactoriesResolver(
+ ModuleFactoriesResolver resolver = new HardcodedModuleFactoriesResolver(mock(BundleContext.class),
factory, factory);
configRegistry = new ConfigRegistryImpl(resolver,
package org.opendaylight.controller.config.manager.impl;
import com.google.common.base.Preconditions;
-import junit.framework.Assert;
import org.junit.After;
+import org.junit.Before;
import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.RuntimeMBeanException;
-import java.io.Closeable;
-import java.io.InputStream;
import java.lang.management.ManagementFactory;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Dictionary;
+import java.util.LinkedList;
import java.util.List;
import java.util.Set;
protected ConfigRegistryJMXClient configRegistryClient;
protected BaseJMXRegistrator baseJmxRegistrator;
protected InternalJMXRegistrator internalJmxRegistrator;
- protected BundleContext mockedContext = mock(BundleContext.class);
+ @Mock
+ protected BundleContext mockedContext;
+ @Mock
protected ServiceRegistration<?> mockedServiceRegistration;
- private static final Logger logger = LoggerFactory.getLogger(AbstractConfigTest.class);
+ @Before
+ public void setUpMocks() {
+ MockitoAnnotations.initMocks(this);
+ }
+
// Default handler for OSGi service registration
- private static final BundleContextServiceRegistrationHandler noopServiceRegHandler = new BundleContextServiceRegistrationHandler() {
+ protected static class RecordingBundleContextServiceRegistrationHandler implements BundleContextServiceRegistrationHandler {
+ private final List<RegistrationHolder> registrations = new LinkedList<>();
@Override
- public void handleServiceRegistration(Object serviceInstance) {}
- };
+ public void handleServiceRegistration(Class<?> clazz, Object serviceInstance, Dictionary<String, ?> props) {
+
+ registrations.add(new RegistrationHolder(clazz, serviceInstance, props));
+ }
+
+ public List<RegistrationHolder> getRegistrations() {
+ return registrations;
+ }
+
+ protected static class RegistrationHolder {
+ protected final Class<?> clazz;
+ protected final Object instance;
+ protected final Dictionary<String, ?> props;
+
+ public RegistrationHolder(Class<?> clazz, Object instance, Dictionary<String, ?> props) {
+ this.clazz = clazz;
+ this.instance = instance;
+ this.props = props;
+ }
+ }
+
+ }
+
+ protected BundleContextServiceRegistrationHandler currentBundleContextServiceRegistrationHandler;
protected BundleContextServiceRegistrationHandler getBundleContextServiceRegistrationHandler(Class<?> serviceType) {
- return noopServiceRegHandler;
+ return currentBundleContextServiceRegistrationHandler;
}
// this method should be called in @Before
protected void initConfigTransactionManagerImpl(
ModuleFactoriesResolver resolver) {
+
final MBeanServer platformMBeanServer = ManagementFactory
.getPlatformMBeanServer();
- configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(
- platformMBeanServer);
+ configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(platformMBeanServer);
initBundleContext();
internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer);
throw new RuntimeException(e);
}
configRegistryClient = new ConfigRegistryJMXClient(platformMBeanServer);
+ currentBundleContextServiceRegistrationHandler = new RecordingBundleContextServiceRegistrationHandler();
}
private void initBundleContext() {
- this.mockedServiceRegistration = mock(ServiceRegistration.class);
doNothing().when(mockedServiceRegistration).unregister();
-
RegisterServiceAnswer answer = new RegisterServiceAnswer();
-
- doAnswer(answer).when(mockedContext).registerService(Matchers.any(String[].class),
- any(Closeable.class), Matchers.<Dictionary<String, ?>>any());
- doAnswer(answer).when(mockedContext).registerService(Matchers.<Class<Closeable>>any(), any(Closeable.class),
- Matchers.<Dictionary<String, ?>>any());
- }
-
-
- public Collection<InputStream> getFilesAsInputStreams(List<String> paths) {
- final Collection<InputStream> resources = new ArrayList<>();
- List<String> failedToFind = new ArrayList<>();
- for (String path : paths) {
- InputStream resourceAsStream = getClass().getResourceAsStream(path);
- if (resourceAsStream == null) {
- failedToFind.add(path);
- } else {
- resources.add(resourceAsStream);
- }
- }
- Assert.assertEquals("Some files were not found", Collections.<String>emptyList(), failedToFind);
-
- return resources;
+ doAnswer(answer).when(mockedContext).registerService(Matchers.<String>any(), any(), Matchers.<Dictionary<String, ?>>any());
+ doAnswer(answer).when(mockedContext).registerService(Matchers.<Class>any(), any(), Matchers.<Dictionary<String, ?>>any());
}
@After
transaction.commit();
}
- protected void assertSame(ObjectName oN1, ObjectName oN2) {
- assertEquals(oN1.getKeyProperty("instanceName"),
- oN2.getKeyProperty("instanceName"));
- assertEquals(oN1.getKeyProperty("interfaceName"),
- oN2.getKeyProperty("interfaceName"));
- }
-
protected void assertStatus(CommitStatus status, int expectedNewInstances,
int expectedRecreatedInstances, int expectedReusedInstances) {
assertEquals("New instances mismatch in " + status, expectedNewInstances, status.getNewInstances().size());
.size());
}
- protected ObjectName createTestConfigBean(
- ConfigTransactionJMXClient transaction, String implementationName,
- String name) throws InstanceAlreadyExistsException {
- return transaction.createModule(implementationName,
- name);
- }
protected void assertBeanCount(int i, String configMXBeanName) {
assertEquals(i, configRegistry.lookupConfigBeans(configMXBeanName)
.size());
}
- protected void assertBeanExists(int count, String moduleName,
- String instanceName) {
- assertEquals(1,
- configRegistry.lookupConfigBeans(moduleName, instanceName)
- .size());
- }
-
/**
*
* @param configBeanClass
public static interface BundleContextServiceRegistrationHandler {
- void handleServiceRegistration(Object serviceInstance);
+ void handleServiceRegistration(Class<?> clazz, Object serviceInstance, Dictionary<String, ?> props);
}
Object serviceTypeRaw = args[0];
Object serviceInstance = args[1];
+ Dictionary<String, ?> props = (Dictionary) args[2];
if (serviceTypeRaw instanceof Class) {
Class<?> serviceType = (Class<?>) serviceTypeRaw;
- invokeServiceHandler(serviceInstance, serviceType);
+ invokeServiceHandler(serviceInstance, serviceType, props);
} else if(serviceTypeRaw instanceof String[]) {
for (String className : (String[]) serviceTypeRaw) {
- try {
- Class<?> serviceType = Class.forName(className);
- invokeServiceHandler(serviceInstance, serviceType);
- } catch (ClassNotFoundException e) {
- logger.warn("Not handling service registration of type {} ", className, e);
- }
+ invokeServiceHandler(serviceInstance, className, props);
}
+ } else if (serviceTypeRaw instanceof String) {
+ invokeServiceHandler(serviceInstance, (String) serviceTypeRaw, props);
+ } else {
+ throw new IllegalStateException("Not handling service registration of type, Unknown type" + serviceTypeRaw);
+ }
- } else
- logger.debug("Not handling service registration of type {}, Unknown type", serviceTypeRaw);
return mockedServiceRegistration;
}
- private void invokeServiceHandler(Object serviceInstance, Class<?> serviceType) {
+ public void invokeServiceHandler(Object serviceInstance, String className, Dictionary<String, ?> props) {
+ try {
+ Class<?> serviceType = Class.forName(className);
+ invokeServiceHandler(serviceInstance, serviceType, props);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Not handling service registration of type " + className, e);
+ }
+ }
+
+ private void invokeServiceHandler(Object serviceInstance, Class<?> serviceType, Dictionary<String, ?> props) {
BundleContextServiceRegistrationHandler serviceRegistrationHandler = getBundleContextServiceRegistrationHandler(serviceType);
if (serviceRegistrationHandler != null) {
- serviceRegistrationHandler.handleServiceRegistration(serviceType.cast(serviceInstance));
+ serviceRegistrationHandler.handleServiceRegistration(serviceType, serviceInstance, props);
}
}
}
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator;
}
}, currentlyRegisteredFactories);
- ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
+ SearchableServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
ServiceReferenceRegistryImpl.createInitialSRLookupRegistry(), txLookupRegistry, currentlyRegisteredFactories);
@Before
public void setUp() {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver());
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext));
}
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest.RecordingBundleContextServiceRegistrationHandler.RegistrationHolder;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBean;
import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory;
import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import javax.management.Attribute;
import javax.management.MBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
-
+import java.util.List;
import java.util.Map;
import java.util.Set;
@Before
public void setUp() {
super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ mockedContext,
new TestingFixedThreadPoolModuleFactory(),
new TestingParallelAPSPModuleFactory(),
new TestingScheduledThreadPoolModuleFactory()));
// create apsp-parallel
createParallelAPSP(transaction1, serviceReference);
transaction1.commit();
+
// check fixed1 is used
ServiceReferenceMXBean serviceReferenceMXBean = JMX.newMXBeanProxy(platformMBeanServer,
withoutTransactionName(serviceReference), ServiceReferenceMXBean.class);
assertEquals(withoutTransactionName(fixedTPTransactionON), serviceReferenceMXBean.getCurrentImplementation());
checkApspThreadCount(fixedNrOfThreads);
+ // check OSGi SR
+ List<RegistrationHolder> registrations =
+ ((RecordingBundleContextServiceRegistrationHandler) currentBundleContextServiceRegistrationHandler).getRegistrations();
+ assertEquals(1, registrations.size());
+ RegistrationHolder record = registrations.get(0);
+ assertEquals(TestingThreadPoolIfc.class, record.clazz);
+ assertEquals(ImmutableMap.of("name","ref"), (Map<String, String>) record.props);
// switch reference to scheduled
ConfigTransactionJMXClient transaction2 = configRegistryClient.createTransaction();
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
+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.reset;
+
+import java.util.Arrays;
+import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
-
-import java.util.Arrays;
-import java.util.List;
-
-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.reset;
+import org.osgi.framework.BundleContext;
public class DependencyResolverManagerTest {
moduleFactory,
maybeOldInternalInfo,
transactionModuleJMXRegistration,
- isDefaultBean);
+ isDefaultBean, mock(BundleContext.class));
}
private static Module mockedModule() {
}
}
- public HardcodedModuleFactoriesResolver(ModuleFactory... list) {
- this(mockBundleContext(),list);
- }
-
private static BundleContext mockBundleContext() {
BundleContext bundleContext = Mockito.mock(BundleContext.class);
ServiceRegistration<ModuleFactory> serviceRegistration = mock(ServiceRegistration.class);
@Before
public void setUp() {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TestingFixedThreadPoolModuleFactory(),
new TestingParallelAPSPModuleFactory()));
}
*/
package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.concurrent.Executor;
-
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import javax.management.ObjectName;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.Executor;
+
public class MockedDependenciesTest extends AbstractParallelAPSPTest {
private final String threadPoolImplementationName = "mockedthreadpool";
ClassBasedModuleFactory mockedThreadPoolConfigFactory = new ClassBasedModuleFactory(
threadPoolImplementationName, MockedThreadPoolModule.class);
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TestingParallelAPSPModuleFactory(),
mockedThreadPoolConfigFactory));
}
*/
package org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.test;
-import static org.junit.Assert.assertEquals;
-
import org.junit.After;
import org.junit.Before;
import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolImpl;
-import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool
- .TestingScheduledThreadPoolModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
+import static org.junit.Assert.assertEquals;
+
public abstract class AbstractScheduledTest extends AbstractConfigTest {
protected static final String scheduled1 = "scheduled1";
public final void setUp() {
assertEquals(0,
TestingScheduledThreadPoolImpl.getNumberOfCloseMethodCalls());
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TestingScheduledThreadPoolModuleFactory(),
new TestingFixedThreadPoolModuleFactory(),
new TestingParallelAPSPModuleFactory()));
@Override
public void close() throws IOException {
executorService.shutdown();
+ allExecutors.remove(executorService);
}
--- /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.config.manager.testingservices.threadpool.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.osgi.framework.BundleContext;
+
+public class ShutdownTest extends AbstractConfigTest {
+ private final TestingFixedThreadPoolModuleFactory testingFixedThreadPoolModuleFactory = new TestingFixedThreadPoolModuleFactory();
+
+ @Mock
+ ModuleFactoriesResolver mockedResolver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Map<String, Entry<ModuleFactory, BundleContext>> allFactories = ImmutableMap.of(
+ testingFixedThreadPoolModuleFactory.getImplementationName(),
+ Maps.<ModuleFactory, BundleContext>immutableEntry(testingFixedThreadPoolModuleFactory, mockedContext));
+ doReturn(allFactories).when(mockedResolver).getAllFactories();
+ super.initConfigTransactionManagerImpl(mockedResolver);
+ }
+
+
+ @Test
+ public void testCreateAndDestroyBeanInSameTransaction() throws Exception {
+ {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ SimpleConfigurationTest.createFixedThreadPool(transaction);
+ transaction.commit();
+ }
+ assertEquals(1, TestingFixedThreadPool.allExecutors.size());
+ doReturn(Collections.emptyMap()).when(mockedResolver).getAllFactories();
+ {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ transaction.commit();
+ }
+ assertEquals(1, TestingFixedThreadPool.allExecutors.size());
+ }
+}
* dependencies.
*/
public class SimpleConfigurationTest extends AbstractConfigTest {
- private final int numberOfThreads = 5;
+ private static final int numberOfThreads = 5;
private final int numberOfThreads2 = 10;
private static final String fixed1 = "fixed1";
private static final List<ObjectName> emptyONs = Collections
@Before
public void setUp() {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TestingFixedThreadPoolModuleFactory()));
}
return fixed1names;
}
- private ObjectName createFixedThreadPool(
+ static ObjectName createFixedThreadPool(
ConfigTransactionJMXClient transaction)
throws InstanceAlreadyExistsException, InstanceNotFoundException {
transaction.assertVersion(0, 1);
// 4, check
assertEquals(2, configRegistryClient.getVersion());
- assertEquals(1, TestingFixedThreadPool.allExecutors.size());
- assertTrue(TestingFixedThreadPool.allExecutors.get(0).isShutdown());
+ assertEquals(0, TestingFixedThreadPool.allExecutors.size());
// dynamic config should be removed from platform
try {
// commit
transaction.commit();
// check that first threadpool is closed
- checkThreadPools(2, numberOfThreads2);
+ checkThreadPools(1, numberOfThreads2);
}
private void checkThreadPools(int expectedTotalNumberOfExecutors,
// commit
CommitStatus commitStatus = transaction.commit();
// check that new threadpool is created and old one is closed
- checkThreadPools(2, numberOfThreads);
+ checkThreadPools(1, numberOfThreads);
CommitStatus expected = new CommitStatus(emptyONs, emptyONs, fixed1List);
assertEquals(expected, commitStatus);
}
platformMBeanServer.getMBeanInfo(transaction.getObjectName());
fail();
}catch(InstanceNotFoundException e){
+ assertEquals("org.opendaylight.controller:TransactionName=ConfigTransaction-0-1,type=ConfigTransaction", e.getMessage());
}
}
* @return prefix + key as used in getProperty method.
*/
String getFullKeyForReporting(String key);
+
+ String getPrefix();
+ String getPropertyWithoutPrefix(String fullKey);
}
public String getFullKeyForReporting(String key) {
return null;
}
+
+ @Override
+ public String getPrefix() {
+ return null;
+ }
+
+ @Override
+ public String getPropertyWithoutPrefix(String fullKey) {
+ return null;
+ }
}
public void setUp() throws Exception {
factory = new LogbackModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
@Test
public void setUp() throws IOException, ClassNotFoundException {
factory = new LogbackModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
/**
public void setUp() throws JoranException, IOException {
factory = new LogbackModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
lc = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator();
@Before
public void setUp() {
factory = new GlobalEventExecutorModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
@Test
@Before
public void setUp() {
factory = new NettyThreadgroupModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
@Test
class StopSystemBundleThread extends Thread {
private static final Logger logger = LoggerFactory.getLogger(StopSystemBundleThread.class);
- public static final String CONFIG_MANAGER_SYMBOLIC_NAME = "org.opendaylight.controller.config-manager";
private final Bundle systemBundle;
StopSystemBundleThread(Bundle systemBundle) {
try {
// wait so that JMX response is received
Thread.sleep(1000);
- // first try to stop config-manager
- Bundle configManager = findConfigManager();
- if (configManager != null){
- logger.debug("Stopping config-manager");
- configManager.stop();
- Thread.sleep(1000);
- }
logger.debug("Stopping system bundle");
systemBundle.stop();
} catch (BundleException e) {
logger.warn("Shutdown process interrupted", e);
}
}
-
- private Bundle findConfigManager() {
- for(Bundle bundle: systemBundle.getBundleContext().getBundles()){
- if (CONFIG_MANAGER_SYMBOLIC_NAME.equals(bundle.getSymbolicName())) {
- return bundle;
- }
- }
- return null;
- }
-
}
class CallSystemExitThread extends Thread {
*/
package org.opendaylight.controller.config.yang.shutdown.impl;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.opendaylight.controller.config.yang.shutdown.impl.ShutdownModuleFactory.NAME;
+
+import java.util.Collections;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMX;
+import javax.management.ObjectName;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.osgi.framework.Bundle;
-import javax.management.InstanceNotFoundException;
-import javax.management.JMX;
-import javax.management.ObjectName;
-import java.util.Collections;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
-import static org.opendaylight.controller.config.yang.shutdown.impl.ShutdownModuleFactory.NAME;
-
public class ShutdownTest extends AbstractConfigTest {
private final ShutdownModuleFactory factory = new ShutdownModuleFactory();
@Mock
- private Bundle mockedSysBundle, mockedConfigManager;
+ private Bundle mockedSysBundle;
@Before
doReturn(mockedSysBundle).when(mockedContext).getBundle(0);
mockedContext.getBundle(0);
doNothing().when(mockedSysBundle).stop();
- doNothing().when(mockedConfigManager).stop();
doReturn(mockedContext).when(mockedSysBundle).getBundleContext();
- doReturn(new Bundle[]{mockedSysBundle, mockedConfigManager}).when(mockedContext).getBundles();
+ doReturn(new Bundle[]{mockedSysBundle}).when(mockedContext).getBundles();
doReturn("system bundle").when(mockedSysBundle).getSymbolicName();
- doReturn(StopSystemBundleThread.CONFIG_MANAGER_SYMBOLIC_NAME).when(mockedConfigManager).getSymbolicName();
+
ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
private void assertStopped() throws Exception {
Thread.sleep(3000); // happens on another thread
- verify(mockedConfigManager).stop();
verify(mockedSysBundle).stop();
}
}
TestingScheduledThreadPoolModule.class, poolImplName);
factory = new AsyncEventBusModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
scheduledThreadPoolConfigFactory));
}
*/
package org.opendaylight.controller.config.threadpool.eventbus;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.junit.matchers.JUnitMatchers.containsString;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.opendaylight.controller.config.yang.threadpool.impl.EventBusModuleFactory;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
public class SyncEventBusConfigBeanTest extends AbstractConfigTest {
private EventBusModuleFactory factory;
public void setUp() {
factory = new EventBusModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
@Test
@Before
public void setUp() {
factory = new FixedThreadPoolModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
new NamingThreadFactoryModuleFactory()));
}
public void setUp() {
flexibleFactory = new FlexibleThreadPoolModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(flexibleFactory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,flexibleFactory,
new NamingThreadFactoryModuleFactory()));
}
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.ConflictingVersionException;
public void setUp() {
factory = new NamingThreadFactoryModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory));
}
@Test
public void setUp() {
factory = new ScheduledThreadPoolModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory,
new NamingThreadFactoryModuleFactory()));
}
*/
package org.opendaylight.controller.config.yangjmxgenerator.it;
-import static org.junit.Assert.fail;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.TestImplModuleMXBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.fail;
+
@Ignore
// ietf beans are not JMX compliant beans:
// Do not know how to make a
public void setUp() {
factory = new TestImplModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
factory));
}
File[] sourceFiles = sourceDirectory.listFiles();
for (File sourceFile: sourceFiles) {
- if(sourceFile.getName().endsWith("Module.java") || sourceFile.getName().endsWith("ModuleFactory.java")) {
- File stubFile = new File(sourceFile.getPath().replace(".java", "Stub.txt"));
- if (stubFile.exists()) {
- try {
- rewrite(sourceFile, FileUtils.readFileToString(stubFile));
- } catch (IOException e) {
- getLog().error("Error while reading/writing to files.", e);
+ if (sourceFile.getName().endsWith(".java")) {
+ String sourceContent;
+ try {
+ sourceContent = FileUtils.readFileToString(sourceFile);
+ } catch (IOException e) {
+ getLog().error("Cannot read " + sourceFile.getAbsolutePath(), e);
+ continue;
+ }
+ if (sourceFile.getName().endsWith("Module.java") || sourceFile.getName().endsWith("ModuleFactory.java")) {
+ File stubFile = new File(sourceFile.getPath().replace(".java", "Stub.txt"));
+ if (stubFile.exists()) {
+ String stubContent = null;
+ try {
+ stubContent = FileUtils.readFileToString(stubFile);
+ } catch (IOException e) {
+ getLog().error("Cannot read " + stubFile.getAbsolutePath(), e);
+ }
+ if (stubContent != null) {
+ sourceContent = rewriteStub(sourceContent, stubContent);
+ }
}
}
+ // remove copyright headers as they can contain timestamp
+ sourceContent = removeCopyrights(sourceContent);
+
+ // replace the file content
+ try {
+ FileUtils.write(sourceFile, sourceContent);
+ } catch (IOException e) {
+ getLog().error("Cannot write " + sourceFile.getAbsolutePath(), e);
+ }
}
+
}
}
- private static void rewrite(File sourceFile, String replaceTODOWith) throws IOException {
- String source = FileUtils.readFileToString(sourceFile);
- String target = Pattern.compile("^.*TODO.*\n.*throw new java.lang.UnsupportedOperationException.*$", Pattern.MULTILINE).matcher(source).replaceFirst(replaceTODOWith);
- FileUtils.write(sourceFile, target);
+ private static Pattern MULTILINE_COMMENT_PATTERN = Pattern.compile("/\\*.*\\*/", Pattern.MULTILINE | Pattern.DOTALL);
+ private static String removeCopyrights(String source) {
+ String target = MULTILINE_COMMENT_PATTERN.matcher(source).replaceAll("\n");
+ //FileUtils.write(sourceFile, target);
+ return target;
+ }
+
+ private static Pattern UNSUPPORTED_OP_PATTERN = Pattern.compile("^.*TODO.*\n.*throw new java.lang.UnsupportedOperationException.*$", Pattern.MULTILINE);
+
+ private static String rewriteStub(String source, String replaceTODOWith) {
+ String target = UNSUPPORTED_OP_PATTERN.matcher(source).replaceFirst(replaceTODOWith);
+ return target;
}
}
-/*
-* 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.config.yang.test.impl;
public class DepTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule {
public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-/*
-* 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
-*/
-/*
-* Generated file
-*
-* Generated from: yang module name: config-test-impl yang module local name: impl-dep
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Apr 25 09:12:08 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory {
-/*
-* 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.config.yang.test.impl;
public class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule {
public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-/*
-* 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
-*/
-/*
-* Generated file
-*
-* Generated from: yang module name: config-test-impl yang module local name: impl-identity-test
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Apr 25 09:12:08 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory {
-/*
-* 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.config.yang.test.impl;
public class NetconfTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule {
public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-/*
-* 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
-*/
-/*
-* Generated file
-*
-* Generated from: yang module name: config-test-impl yang module local name: impl-netconf
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Apr 25 09:12:08 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory {
-/*
- * 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.config.yang.test.impl;
import com.google.common.collect.Lists;
-/*
-* 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.config.yang.test.impl;
public class TestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule {
public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-/*
-* 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
-*/
-/*
-* Generated file
-*
-* Generated from: yang module name: config-test-impl yang module local name: impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Apr 25 09:12:08 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+
+
package org.opendaylight.controller.config.yang.test.impl;
public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory {
public void setUp() {
factory = new NetconfTestImplModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
new DepTestImplModuleFactory(), new IdentityTestModuleFactory()));
}
netconf.ssh.address=0.0.0.0
netconf.ssh.port=1830
netconf.ssh.pk.path = ./configuration/RSA.pk
+netconf.ssh.default.user = netconf
+netconf.ssh.default.password = netconf
netconf.config.persister.active=1,2
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
<name>yang-schema-service</name>
</module>
- <!-- To enable use of new in-memory datastore and new implementations
- of data brokers, comment out all parts of this
- xml which are marked with DATA-BROKER and uncomment all parts
- of this xml which are marked with NEW-DATA-BROKER
- -->
- <!-- DATA-BROKER start-->
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</type>
- <name>hash-map-data-store</name>
- </module>
- <!-- DATA BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
- <name>async-data-broker</name>
- <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>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
+ <name>runtime-mapping-singleton</name>
</module>
- -->
- <!-- NEW-DATA-BROKER end -->
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
- <name>dom-broker</name>
- <!-- DATA-BROKER start -->
- <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
- <!-- to switch to the clustered data store, comment out the hash-map-data-store <name> and uncomment the cluster-data-store one -->
- <name>hash-map-data-store</name>
- <!-- <name>cluster-data-store</name> -->
- </data-store>
- <!-- DATA-BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
- <async-data-broker>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
- <name>async-data-broker</name>
- </async-data-broker>
- -->
- <!-- NEW-DATA-BROKER end -->
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
+ <name>binding-notification-broker</name>
</module>
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
<name>binding-data-broker</name>
</data-broker>
</module>
+
+ <!--
+ Tree-based in-memory data store. This is the data store which is currently
+ recommended for single-node deployments.
+ -->
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
- <name>runtime-mapping-singleton</name>
- </module>
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
- <name>binding-notification-broker</name>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
+ <name>inmemory-data-broker</name>
+ <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>
- <!-- DATA-BROKER start -->
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</type>
- <name>binding-data-broker</name>
- <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
- <name>dom-broker</name>
- </dom-broker>
- <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
- <name>runtime-mapping-singleton</name>
- </mapping-service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
+ <name>inmemory-dom-broker</name>
+ <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>
</module>
- <!-- DATA-BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-compatible-broker</type>
- <name>binding-data-broker</name>
+ <name>inmemory-binding-data-broker</name>
<dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
<name>dom-broker</name>
<name>runtime-mapping-singleton</name>
</binding-mapping-service>
</module>
- -->
- <!-- NEW-DATA-BROKER end -->
</modules>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
- <instance>
- <name>yang-schema-service</name>
- <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
- <instance>
- <name>binding-notification-broker</name>
- <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
- </instance>
- </service>
- <!-- DATA-BROKER start -->
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
- <instance>
- <name>hash-map-data-store</name>
- <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
- </instance>
- </service>
- <!-- DATA-BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
- <instance>
- <name>async-data-broker</name>
- <provider>/modules/module[type='dom-inmemory-data-broker'][name='async-data-broker']</provider>
- </instance>
- </service>
- -->
- <!-- NEW-DATA-BROKER end -->
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
- <instance>
- <name>binding-osgi-broker</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <instance>
- <name>binding-rpc-broker</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
- <instance>
- <name>runtime-mapping-singleton</name>
- <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
- <instance>
- <name>dom-broker</name>
- <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
- </instance>
- </service>
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <instance>
+ <name>yang-schema-service</name>
+ <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
+ <instance>
+ <name>runtime-mapping-singleton</name>
+ <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+ <instance>
+ <name>binding-notification-broker</name>
+ <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <instance>
+ <name>binding-osgi-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <instance>
+ <name>binding-rpc-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ </instance>
+ </service>
- <service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
- <instance>
- <name>binding-data-broker</name>
- <!-- DATA-BROKER start -->
- <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
- <!-- DATA-BROKER end -->
- <!-- NEW-DATA-BROKER start -->
- <!--
- <provider>/modules/module[type='binding-data-compatible-broker'][name='binding-data-broker']</provider>
- -->
- <!-- NEW-DATA-BROKER end -->
- </instance>
- </service>
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <instance>
+ <name>dom-broker</name>
+ <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <instance>
+ <name>binding-data-broker</name>
+ <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']</provider>
+ </instance>
+ </service>
+
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+ <instance>
+ <name>inmemory-data-broker</name>
+ <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
+ </instance>
+ </service>
</services>
</data>
</configuration>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwardingrulesmanager</artifactId>
</instructions>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
</plugins>
</build>
<scm>
--- /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.md.frm.compatibility;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
+import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.FlowsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ConfigurationReader implements FlowManagementReader {
+
+ private final static Logger LOG = LoggerFactory.getLogger(ConfigurationReader.class);
+
+ private IForwardingRulesManager manager;
+
+ @Override
+ public Flows readAllFlows() {
+ List<FlowConfig> staticFlows = this.manager.getStaticFlows();
+ List<Flow> flowMap = new ArrayList<Flow>(staticFlows.size());
+
+ for (FlowConfig conf : staticFlows) {
+ flowMap.add(FlowConfigMapping.toConfigurationFlow(conf));
+ }
+ final FlowsBuilder flowsBuilder = new FlowsBuilder();
+ return (flowsBuilder.setFlow(flowMap)).build();
+ }
+
+ @Override
+ public Flow readFlow(final FlowKey key) {
+ try {
+ final FlowConfig flowConf =
+ this.manager.getStaticFlow(String.valueOf(key.getId()), NodeMapping.toADNode(key.getNode()));
+ return FlowConfigMapping.toConfigurationFlow(flowConf);
+ } catch (Exception e) {
+ String errMsg = MessageFormat.format("readFlow by key {} fail", key);
+ LOG.error(errMsg, e);
+ throw new RuntimeException(errMsg, e);
+ }
+ }
+
+ public IForwardingRulesManager getManager() {
+ return this.manager;
+ }
+
+ public void setManager(final IForwardingRulesManager manager) {
+ this.manager = manager;
+ }
+}
--- /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.md.frm.compatibility;
+
+import java.util.Collections;
+
+import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
+import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
+import org.opendaylight.controller.sal.common.util.Arguments;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+
+public class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject> {
+
+ private final static InstanceIdentifier<Flows> FLOWS_PATH = InstanceIdentifier.<Flows> builder(Flows.class).toInstance();
+
+ private final FlowManagementReader configuration = new ConfigurationReader();
+ private DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> changeListener;
+ private DataProviderService dataService;
+ private IForwardingRulesManager manager;
+
+ public Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> init() {
+ return this.dataService.registerCommitHandler(FRMRuntimeDataProvider.FLOWS_PATH, this);
+ }
+
+ @Override
+ public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
+ return this.readFrom(this.configuration, path);
+ }
+
+ @Override
+ public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
+ return this.readFrom(this.configuration, path);
+ }
+
+ public DataObject readFrom(final FlowManagementReader store, final InstanceIdentifier<? extends DataObject> path) {
+ if (Objects.equal(FRMRuntimeDataProvider.FLOWS_PATH, path)) {
+ return store.readAllFlows();
+ }
+ if (FRMRuntimeDataProvider.FLOWS_PATH.contains(path)) {
+ return store.readFlow(this.toFlowKey(path));
+ }
+ return null;
+ }
+
+ @Override
+ public FlowCommitTransaction requestCommit(final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ return new FlowCommitTransaction(this, modification);
+ }
+
+ public FlowKey toFlowKey(final InstanceIdentifier<? extends DataObject> identifier) {
+ Preconditions.<InstanceIdentifier<? extends DataObject>> checkNotNull(identifier);
+
+ Iterable<PathArgument> path = identifier.getPathArguments();
+ PathArgument get = path.iterator().next();
+ final Identifier itemKey = Arguments.<IdentifiableItem> checkInstanceOf(get, IdentifiableItem.class).getKey();
+ return Arguments.<FlowKey> checkInstanceOf(itemKey, FlowKey.class);
+ }
+
+ public RpcResult<Void> finish(final FlowCommitTransaction transaction) {
+ Iterable<FlowConfig> toRemove = transaction.getToRemove();
+ for (final FlowConfig flow : toRemove) {
+ this.manager.removeStaticFlow(flow.getName(), flow.getNode());
+ }
+ Iterable<FlowConfig> toUpdate = transaction.getToUpdate();
+ for (final FlowConfig flow : toUpdate) {
+ this.manager.removeStaticFlow(flow.getName(), flow.getNode());
+ this.manager.addStaticFlow(flow);
+ }
+ return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+ }
+
+ public RpcResult<Void> rollback(final FlowCommitTransaction transaction) {
+ return null;
+ }
+
+ public DataProviderService getDataService() {
+ return this.dataService;
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> getChangeListener() {
+ return this.changeListener;
+ }
+
+ public void setChangeListener(final DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> changeListener) {
+ this.changeListener = changeListener;
+ }
+
+ public IForwardingRulesManager getManager() {
+ return this.manager;
+ }
+
+ public void setManager(final IForwardingRulesManager manager) {
+ this.manager = manager;
+ }
+}
+++ /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.md.frm.compatibility
-
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.FlowsBuilder
-import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager
-import static com.google.common.base.Preconditions.*;
-import static extension org.opendaylight.controller.md.frm.compatibility.FlowConfigMapping.*;
-import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*;
-import org.opendaylight.controller.sal.common.util.Arguments
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig
-import java.util.HashSet
-import org.opendaylight.controller.sal.common.util.Rpcs
-import java.util.Collections
-import org.opendaylight.yangtools.yang.common.RpcError
-
-class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- static val FLOWS_PATH = InstanceIdentifier.builder(Flows).toInstance;
-
- @Property
- var DataProviderService dataService;
-
- @Property
- var DataChangeListener changeListener;
-
- @Property
- var IForwardingRulesManager manager;
-
- FlowManagementReader configuration = new ConfigurationReader();
-
- def init() {
- //dataService.registerDataChangeListener(FLOWS_PATH, changeListener);
- dataService.registerCommitHandler(FLOWS_PATH, this);
- }
-
- override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
- return readFrom(configuration, path);
- }
-
- override DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
- return readFrom(configuration, path);
- }
-
- def DataObject readFrom(FlowManagementReader store, InstanceIdentifier<? extends DataObject> path) {
- if (FLOWS_PATH == path) {
- return store.readAllFlows();
- }
- if (FLOWS_PATH.contains(path)) {
- return store.readFlow(path.toFlowKey());
- }
- return null;
- }
-
- override FlowCommitTransaction requestCommit(
- DataModification modification) {
- return new FlowCommitTransaction(this,modification);
- }
-
- def toFlowKey(InstanceIdentifier<? extends DataObject> identifier) {
- checkNotNull(identifier)
- val item = Arguments.checkInstanceOf(identifier.path.get(1),IdentifiableItem);
- val key = Arguments.checkInstanceOf(item.key,FlowKey)
- return key;
- }
-
- def RpcResult<Void> finish(FlowCommitTransaction transaction) {
- for(flw: transaction.toRemove) {
- manager.removeStaticFlow(flw.name,flw.node)
- }
-
- for(flw: transaction.toUpdate) {
- manager.removeStaticFlow(flw.name,flw.node);
- manager.addStaticFlow(flw);
- }
-
- return Rpcs.<Void>getRpcResult(true,null,Collections.<RpcError>emptySet())
- }
-
- def RpcResult<Void> rollback(FlowCommitTransaction transaction) {
- // NOOP: We did not changed any state.
- }
-
-}
-
-class ConfigurationReader implements FlowManagementReader {
-
- @Property
- var IForwardingRulesManager manager;
-
- override Flows readAllFlows() {
- val it = new FlowsBuilder();
- flow = manager.staticFlows.map[
- toConfigurationFlow();
- ]
- return it.build();
- }
-
- override readFlow(FlowKey key) {
- val flowCfg = manager.getStaticFlow(String.valueOf(key.id), key.node.toADNode());
- return flowCfg.toConfigurationFlow;
- }
-}
-
-public static class FlowCommitTransaction implements DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- @Property
- val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-
- @Property
- val FRMRuntimeDataProvider flowManager;
-
- @Property
- val toAdd = new HashSet<FlowConfig>();
-
- @Property
- var Iterable<FlowConfig> toUpdate
-
- @Property
- var Iterable<FlowConfig> toRemove
-
-
- new(FRMRuntimeDataProvider flowManager,DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- super();
- _flowManager = flowManager;
- _modification = modification;
- processModification();
- }
-
- override finish() throws IllegalStateException {
- return flowManager.finish(this);
- }
-
- override rollback() throws IllegalStateException
-{
- return flowManager.rollback(this);
- }
-
- def processModification() {
- val updated = modification.updatedConfigurationData.entrySet;
-
- val _toUpdate = updated.filter[key.isFlowPath].map[
- return (value as Flow).toFlowConfig
- ]
- toUpdate = _toUpdate as Iterable<FlowConfig>
-
-
- val _toRemove = modification.removedConfigurationData.filter[isFlowPath].map[
- toFlowConfig
- ]
- toRemove = _toRemove as Iterable<FlowConfig>
-
- }
-}
--- /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.md.frm.compatibility;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class FlowCommitTransaction implements DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+ private final HashSet<FlowConfig> toAdd = new HashSet<FlowConfig>();
+ private final FRMRuntimeDataProvider flowManager;
+ private Iterable<FlowConfig> toUpdate;
+ private Iterable<FlowConfig> toRemove;
+
+ public FlowCommitTransaction(
+ final FRMRuntimeDataProvider flowManager,
+ final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ this.flowManager = flowManager;
+ this.modification = modification;
+ this.processModification();
+ }
+
+ @Override
+ public RpcResult<Void> finish() throws IllegalStateException {
+ return this.flowManager.finish(this);
+ }
+
+ @Override
+ public RpcResult<Void> rollback() throws IllegalStateException {
+ return this.flowManager.rollback(this);
+ }
+
+ public void processModification() {
+ final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updated =
+ this.modification.getUpdatedConfigurationData().entrySet();
+ final List<FlowConfig> forUpdate = new ArrayList<FlowConfig>(updated.size());
+
+ if (updated != null && !(updated.isEmpty())) {
+ for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : updated) {
+ if (FlowConfigMapping.isFlowPath(entry.getKey())) {
+ forUpdate.add(FlowConfigMapping.toFlowConfig((Flow) entry.getValue()));
+ }
+ }
+ }
+ this.toUpdate = Collections.unmodifiableCollection(forUpdate);
+
+ final Set<InstanceIdentifier<? extends DataObject>> removedConfigurationData =
+ this.modification.getRemovedConfigurationData();
+ final List<FlowConfig> forRemove = new ArrayList<FlowConfig>(removedConfigurationData.size());
+
+ if (removedConfigurationData != null && !(removedConfigurationData.isEmpty())) {
+ for (InstanceIdentifier<? extends DataObject> data : removedConfigurationData) {
+ if (FlowConfigMapping.isFlowPath(data)) {
+ forRemove.add(FlowConfigMapping.toFlowConfig(data));
+ }
+ }
+ }
+ this.toRemove = Collections.unmodifiableCollection(forRemove);
+ }
+
+ @Override
+ public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
+ return this.modification;
+ }
+
+ public FRMRuntimeDataProvider getFlowManager() {
+ return this.flowManager;
+ }
+
+ public HashSet<FlowConfig> getToAdd() {
+ return this.toAdd;
+ }
+
+ public Iterable<FlowConfig> getToUpdate() {
+ return this.toUpdate;
+ }
+
+ public Iterable<FlowConfig> getToRemove() {
+ return this.toRemove;
+ }
+}
--- /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.md.frm.compatibility;
+
+import java.text.MessageFormat;
+import java.util.Iterator;
+
+import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
+import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowConfigMapping {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FlowConfigMapping.class);
+
+ /* nodes/node/flow -> 0 / 1 / 2 */
+ private static final int FLOW_KEY_IDENTIFIER_DEEP = 2;
+
+ public static Flow toConfigurationFlow(final FlowConfig sourceCfg) {
+ final FlowAdded source = MDFlowMapping.flowAdded(sourceCfg.getFlow());
+ final FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setInstructions(source.getInstructions());
+ flowBuilder.setCookie(source.getCookie());
+ flowBuilder.setHardTimeout(source.getHardTimeout());
+ flowBuilder.setIdleTimeout(source.getIdleTimeout());
+ flowBuilder.setMatch(source.getMatch());
+ flowBuilder.setNode(source.getNode());
+
+ FlowKey flowKey =
+ new FlowKey(Long.valueOf(sourceCfg.getName()), flowBuilder.getNode());
+ flowBuilder.setKey(flowKey);
+ return flowBuilder.build();
+ }
+
+ public static FlowConfig toFlowConfig(final Flow sourceCfg) {
+ try {
+ final FlowConfig flowConfig = new FlowConfig();
+ flowConfig.setName(String.valueOf(sourceCfg.getId()));
+ flowConfig.setNode(NodeMapping.toADNode(sourceCfg.getNode()));
+ return flowConfig;
+ } catch (Exception e) {
+ String errMsg = MessageFormat.format("Convert from Flow {} to FlowConfig fail", sourceCfg);
+ LOG.error(errMsg, e);
+ throw new RuntimeException(errMsg, e);
+ }
+ }
+
+ public static FlowConfig toFlowConfig(final InstanceIdentifier<? extends Object> identifier) {
+ try {
+ PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(identifier);
+ if (pathArg != null) {
+ final FlowConfig flowConfig = new FlowConfig();
+ FlowKey key = ((IdentifiableItem<Flow, FlowKey>) pathArg).getKey();
+ flowConfig.setName(String.valueOf(key.getId()));
+ flowConfig.setNode(NodeMapping.toADNode(key.getNode()));
+ return flowConfig;
+ }
+ return null;
+ } catch (Exception e) {
+ String errMsg = MessageFormat.format("Convert from InstanceIdentifier {} to FlowConfig fail", identifier);
+ LOG.error(errMsg, e);
+ throw new RuntimeException(errMsg, e);
+ }
+ }
+
+ public static boolean isFlowPath(final InstanceIdentifier<? extends Object> path) {
+ PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(path);
+ if (pathArg == null) {
+ return false;
+ }
+ if (pathArg instanceof IdentifiableItem<?,?>) {
+ final Identifiable<?> key = ((IdentifiableItem<?, ? extends Identifiable<?>>) pathArg).getKey();
+ if ((key instanceof FlowKey)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static PathArgument getSecondPathArgumentFromPath(final InstanceIdentifier<? extends Object> path) {
+ if (path != null && path.getPathArguments() != null) {
+ Iterator<PathArgument> iterator = path.getPathArguments().iterator();
+ int deep = 0;
+ while (iterator.hasNext()) {
+ PathArgument pathArg = iterator.next();
+ if (deep == FlowConfigMapping.FLOW_KEY_IDENTIFIER_DEEP) {
+ return pathArg;
+ }
+ deep++;
+ }
+ }
+ return null;
+ }
+}
+++ /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.md.frm.compatibility
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder
-
-import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
-import static org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.*
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-import org.opendaylight.yangtools.yang.binding.Identifiable
-
-class FlowConfigMapping {
-
- static def toConfigurationFlow(FlowConfig sourceCfg) {
- val source = flowAdded(sourceCfg.flow);
- val it = new FlowBuilder();
- instructions = source.instructions;
- cookie = source.cookie;
- hardTimeout = source.hardTimeout
- idleTimeout = source.idleTimeout
- match = source.match
- node = source.node
- key = new FlowKey(Long.parseLong(sourceCfg.name),node);
- return it.build();
- }
-
- static def toFlowConfig(Flow sourceCfg) {
- val it = new FlowConfig;
- name = String.valueOf(sourceCfg.id);
- node = sourceCfg.node.toADNode();
-
- return it
- }
-
- static def toFlowConfig(InstanceIdentifier<?> identifier) {
- val it = new FlowConfig()
- val FlowKey key = ((identifier.path.get(2) as IdentifiableItem<Flow,FlowKey>).key)
- name = String.valueOf(key.id);
- node = key.node.toADNode();
-
- return it;
- }
-
- static def boolean isFlowPath(InstanceIdentifier<?> path) {
- if(path.path.size < 2) return false;
- if (path.path.get(2) instanceof IdentifiableItem<?,?>) {
- val IdentifiableItem<?,? extends Identifiable<?>> item = path.path.get(2) as IdentifiableItem<?,? extends Identifiable<?>>;
- val Identifiable<?> key = item.key;
- if (key instanceof FlowKey) {
- return true;
- }
- }
- return false;
- }
-}
-/*
+/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
--- /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.sal.compatibility.topology;
+
+import static org.opendaylight.controller.sal.compatibility.topology.TopologyMapping.toAdEdge;
+import static org.opendaylight.controller.sal.compatibility.topology.TopologyMapping.toTopoEdgeUpdate;
+
+import java.util.Map.Entry;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.UpdateType;
+import org.opendaylight.controller.sal.topology.IPluginOutTopologyService;
+import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TopologyCommitHandler implements DataChangeListener {
+ private static final Logger LOG = LoggerFactory.getLogger(TopologyCommitHandler.class);
+
+ private IPluginOutTopologyService topologyPublisher;
+
+ private final DataProviderService dataService;
+
+ public TopologyCommitHandler(final DataProviderService dataService, final IPluginOutTopologyService topologyPub) {
+ this.topologyPublisher = topologyPub;
+ this.dataService = dataService;
+ }
+
+ @Override
+ public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> modification) {
+ CopyOnWriteArrayList<TopoEdgeUpdate> msg = new CopyOnWriteArrayList<TopoEdgeUpdate>();
+ try {
+ TypeSafeDataReader reader = TypeSafeDataReader.forReader(dataService);
+ InstanceIdentifier<Topology> topologyPath = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId("flow:1"))).build();
+ Topology topology = reader.readOperationalData(topologyPath);
+
+ for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : modification
+ .getCreatedOperationalData().entrySet()) {
+ if (entry.getValue() instanceof Link
+ && modification.getCreatedOperationalData().containsKey(entry.getKey())) {
+ msg.add(toTopoEdgeUpdate(toAdEdge((Link) entry.getValue(), topology), UpdateType.ADDED, reader));
+ }
+ }
+
+ for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : modification
+ .getUpdatedOperationalData().entrySet()) {
+ if (entry.getValue() instanceof Link) {
+ msg.add(toTopoEdgeUpdate(toAdEdge((Link) entry.getValue(), topology), UpdateType.CHANGED, reader));
+ }
+ }
+ for (InstanceIdentifier<? extends DataObject> path : modification.getRemovedOperationalData()) {
+ if (path.getTargetType() == Link.class) {
+ Link link = (Link) modification.getOriginalOperationalData().get(path);
+ msg.add(toTopoEdgeUpdate(toAdEdge(link, topology), UpdateType.CHANGED, reader));
+ }
+
+ }
+
+ if (topologyPublisher != null && msg != null && !msg.isEmpty()) {
+ topologyPublisher.edgeUpdate(msg);
+ }
+
+ } catch (Exception e) {
+ LOG.error("Exception caught", e);
+ }
+ }
+
+ protected IPluginOutTopologyService getTopologyPublisher() {
+ return topologyPublisher;
+ }
+
+ protected void setTopologyPublisher(final IPluginOutTopologyService topologyPublisher) {
+ this.topologyPublisher = topologyPublisher;
+ }
+
+}
+++ /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.sal.compatibility.topology
-
-import com.google.common.collect.FluentIterable
-import java.util.concurrent.CopyOnWriteArrayList
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.core.UpdateType
-import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
-import org.opendaylight.controller.sal.topology.TopoEdgeUpdate
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import static extension org.opendaylight.controller.sal.compatibility.topology.TopologyMapping.*
-import org.slf4j.LoggerFactory
-
-class TopologyCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
- static val LOG = LoggerFactory.getLogger(TopologyCommitHandler);
- @Property
- IPluginOutTopologyService topologyPublisher;
-
- @Property
- DataProviderService dataService;
-
- new(DataProviderService dataService) {
- _topologyPublisher = topologyPublisher
- _dataService = dataService
- }
-
- override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- val msg = new CopyOnWriteArrayList<TopoEdgeUpdate>()
- try {
- val reader = TypeSafeDataReader.forReader(dataService)
- val topologyPath = InstanceIdentifier.builder(NetworkTopology).child(Topology, new TopologyKey(new TopologyId("flow:1"))).toInstance
- val topology = reader.readOperationalData(topologyPath)
- val adds = FluentIterable.from(modification.createdOperationalData.entrySet)
- .filter[value instanceof Link]
- .transform[(value as Link).toAdEdge(topology).toTopoEdgeUpdate(UpdateType.ADDED,reader)]
- .toList
- val updates = FluentIterable.from(modification.updatedOperationalData.entrySet)
- .filter[!modification.createdOperationalData.containsKey(key) && (value instanceof Link)]
- .transform[(value as Link).toAdEdge(topology).toTopoEdgeUpdate(UpdateType.ADDED,reader)] // Evidently the ADSAL does not expect edge 'CHANGED"
- .toList
- val removes = FluentIterable.from(modification.removedOperationalData)
- .transform[reader.readOperationalData(it as InstanceIdentifier<DataObject>)]
- .filter[it instanceof Link]
- .transform[(it as Link).toAdEdge(topology).toTopoEdgeUpdate(UpdateType.REMOVED,reader)]
- .toList
- msg.addAll(adds)
- msg.addAll(updates)
- msg.addAll(removes)
- } catch (Exception e) {
- LOG.error("Exception caught",e)
- }
- return new TopologyTransaction(modification,topologyPublisher,dataService,msg)
- }
-}
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey
import org.opendaylight.yangtools.yang.binding.DataObject
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link
import org.slf4j.LoggerFactory
+import org.opendaylight.yangtools.concepts.ListenerRegistration
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener
class TopologyProvider implements AutoCloseable{
static val LOG = LoggerFactory.getLogger(TopologyProvider);
@Property
DataProviderService dataService;
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
-
+ ListenerRegistration<DataChangeListener> listenerRegistration
+
+
def void start() {
}
LOG.error("dataService not set");
return;
}
- commitHandler = new TopologyCommitHandler(dataService)
- commitHandler.setTopologyPublisher(topologyPublisher)
+ commitHandler = new TopologyCommitHandler(dataService,topologyPublisher);
val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(NetworkTopology)
.child(Topology,new TopologyKey(new TopologyId("flow:1")))
.child(Link)
.toInstance();
- commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
+ listenerRegistration = dataService.registerDataChangeListener(path,commitHandler);
LOG.info("TopologyProvider started")
}
override close() throws Exception {
- commitHandlerRegistration.close
+ listenerRegistration.close
}
def setTopologyPublisher(IPluginOutTopologyService topologyPublisher) {
+++ /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.sal.compatibility.topology
-
-import java.util.Collections
-import java.util.List
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
-import org.opendaylight.controller.sal.topology.TopoEdgeUpdate
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.slf4j.LoggerFactory
-
-class TopologyTransaction implements DataCommitTransaction<InstanceIdentifier<?extends DataObject>, DataObject> {
- static val LOG = LoggerFactory.getLogger(TopologyTransaction);
- @Property
- val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-
- @Property
- IPluginOutTopologyService topologyPublisher;
-
- @Property
- DataProviderService dataService;
- @Property
- List<TopoEdgeUpdate> edgeUpdates;
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,IPluginOutTopologyService topologyPublisher,
- DataProviderService dataService,List<TopoEdgeUpdate> edgeUpdates) {
- _modification = modification;
- _topologyPublisher = topologyPublisher
- _dataService = dataService
- _edgeUpdates = edgeUpdates
- }
- override finish() throws IllegalStateException {
-
- if(topologyPublisher != null && _edgeUpdates != null && !edgeUpdates.empty) {
- topologyPublisher.edgeUpdate(edgeUpdates)
- }
-
- return new RpcResultTo()
- }
-
- override getModification() {
- return _modification;
- }
-
- override rollback() throws IllegalStateException {
- // NOOP
- }
-}
-class RpcResultTo implements RpcResult<Void> {
-
- override getErrors() {
- return Collections.emptySet
- }
-
- override getResult() {
- return null;
- }
-
- override isSuccessful() {
- return true;
- }
-
-}
</instructions>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
</plugins>
</build>
--- /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.frm;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public abstract class AbstractChangeListener implements DataChangeListener {
+
+ private final AtomicLong txNum = new AtomicLong();
+ private String transactionId;
+
+ @Override
+ public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ this.transactionId = this.newTransactionIdentifier().toString();
+
+ final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
+ changeEvent.getCreatedConfigurationData().entrySet();
+ final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries =
+ new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
+
+ Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updateConfigEntrySet =
+ changeEvent.getUpdatedConfigurationData().entrySet();
+ updatedEntries.addAll(updateConfigEntrySet);
+ updatedEntries.removeAll(createdEntries);
+
+ final Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
+ changeEvent.getRemovedConfigurationData();
+
+ for (final Entry<InstanceIdentifier<? extends DataObject>, DataObject> createdEntry : createdEntries) {
+ InstanceIdentifier<? extends DataObject> c_key = createdEntry.getKey();
+ DataObject c_value = createdEntry.getValue();
+ this.add(c_key, c_value);
+ }
+
+ for (final Entry<InstanceIdentifier<?>, DataObject> updatedEntrie : updatedEntries) {
+ Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
+ changeEvent.getOriginalConfigurationData();
+
+ InstanceIdentifier<? extends Object> u_key = updatedEntrie.getKey();
+ final DataObject originalFlow = origConfigData.get(u_key);
+ final DataObject updatedFlow = updatedEntrie.getValue();
+ this.update(u_key, originalFlow, updatedFlow);
+ }
+
+ for (final InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers) {
+ Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
+ changeEvent.getOriginalConfigurationData();
+
+ final DataObject removeValue = origConfigData.get(instanceId);
+ this.remove(instanceId, removeValue);
+ }
+ }
+
+ public String getTransactionId() {
+ return this.transactionId;
+ }
+
+ private Object newTransactionIdentifier() {
+ return "DOM-" + txNum.getAndIncrement();
+ }
+
+ protected abstract void validate() throws IllegalStateException;
+
+ protected abstract void remove(
+ final InstanceIdentifier<? extends DataObject> identifier,
+ final DataObject remove);
+
+ protected abstract void update(
+ final InstanceIdentifier<? extends DataObject> identifier,
+ final DataObject original, final DataObject update);
+
+ protected abstract void add(
+ final InstanceIdentifier<? extends DataObject> identifier,
+ final DataObject add);
+}
+++ /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.frm
-
-import java.util.Collections
-import java.util.HashSet
-import java.util.Map.Entry
-import java.util.Set
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.controller.sal.common.util.Rpcs
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.common.RpcError
-
-abstract class AbstractTransaction implements DataCommitTransaction<InstanceIdentifier<?extends DataObject>, DataObject> {
-
- @Property
- val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- _modification = modification;
- }
-
- def void validate() throws IllegalStateException
-
- override finish() throws IllegalStateException {
- validate()
- callRpcs();
- return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
- }
-
- override getModification() {
- return _modification;
- }
-
- override rollback() throws IllegalStateException {
- rollbackRpcs();
- return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
- }
-
- def private callRpcs() {
- val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet();
-
- /*
- * This little dance is because updatedEntries contains both created and modified entries
- * The reason I created a new HashSet is because the collections we are returned are immutable.
- */
- val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
- updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet());
- updatedEntries.removeAll(createdEntries);
-
- val Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData();
- for (Entry<InstanceIdentifier<? extends DataObject >, DataObject> entry : createdEntries) {
- add(entry.key,entry.value);
- }
- for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
- val originalFlow = _modification.originalConfigurationData.get(entry.key);
- val updatedFlow = entry.value
- update(entry.key, originalFlow ,updatedFlow);
- }
-
- for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
- val removeValue = _modification.getOriginalConfigurationData.get(instanceId);
- remove(instanceId,removeValue);
- }
- }
-
- def void remove(InstanceIdentifier<?> identifier, DataObject remove)
-
- def void update(InstanceIdentifier<?> identifier, DataObject original, DataObject update)
-
- def void add(InstanceIdentifier<?> identifier, DataObject add)
-
- def private rollbackRpcs() {
- val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet();
-
- /*
- * This little dance is because updatedEntries contains both created and modified entries
- * The reason I created a new HashSet is because the collections we are returned are immutable.
- */
- val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
- updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet());
- updatedEntries.removeAll(createdEntries);
-
- val Set<InstanceIdentifier<? >> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData();
- for (Entry<InstanceIdentifier<?>, DataObject> entry : createdEntries) {
- remove(entry.key,entry.value); // because we are rolling back, remove what we would have added.
- }
- for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
- val originalFlow = _modification.originalConfigurationData.get(entry.key);
- val updatedFlow = entry.value
- update(entry.key, updatedFlow ,originalFlow);// because we are rolling back, replace the updated with the original
- }
-
- for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
- val removeValue = _modification.getOriginalConfigurationData.get(instanceId);
- add(instanceId,removeValue);// because we are rolling back, add what we would have removed.
- }
- }
-}
--- /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.frm;
+
+import org.opendaylight.controller.frm.flow.FlowProvider;
+import org.opendaylight.controller.frm.group.GroupProvider;
+import org.opendaylight.controller.frm.meter.MeterProvider;
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FRMActivator extends AbstractBindingAwareProvider {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FRMActivator.class);
+
+ private static FlowProvider flowProvider = new FlowProvider();
+ private static GroupProvider groupProvider = new GroupProvider();
+ private static MeterProvider meterProvider = new MeterProvider();
+
+ @Override
+ public void onSessionInitiated(final ProviderContext session) {
+ DataProviderService flowSalService = session.<DataProviderService>getSALService(DataProviderService.class);
+ FRMActivator.flowProvider.setDataService(flowSalService);
+ SalFlowService rpcFlowSalService = session.<SalFlowService>getRpcService(SalFlowService.class);
+ FRMActivator.flowProvider.setSalFlowService(rpcFlowSalService);
+ FRMActivator.flowProvider.start();
+ DataProviderService groupSalService = session.<DataProviderService>getSALService(DataProviderService.class);
+ FRMActivator.groupProvider.setDataService(groupSalService);
+ SalGroupService rpcGroupSalService = session.<SalGroupService>getRpcService(SalGroupService.class);
+ FRMActivator.groupProvider.setSalGroupService(rpcGroupSalService);
+ FRMActivator.groupProvider.start();
+ DataProviderService meterSalService = session.<DataProviderService>getSALService(DataProviderService.class);
+ FRMActivator.meterProvider.setDataService(meterSalService);
+ SalMeterService rpcMeterSalService = session.<SalMeterService>getRpcService(SalMeterService.class);
+ FRMActivator.meterProvider.setSalMeterService(rpcMeterSalService);
+ FRMActivator.meterProvider.start();
+ }
+
+ @Override
+ protected void stopImpl(final BundleContext context) {
+ try {
+ FRMActivator.flowProvider.close();
+ FRMActivator.groupProvider.close();
+ FRMActivator.meterProvider.close();
+ } catch (Throwable e) {
+ LOG.error("Unexpected error by stopping FRMActivator", e);
+ throw new RuntimeException(e);
+ }
+ }
+ }
\ No newline at end of file
+++ /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.frm
-
-import org.opendaylight.controller.frm.flow.FlowProvider
-import org.opendaylight.controller.frm.group.GroupProvider
-import org.opendaylight.controller.frm.meter.MeterProvider
-import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.osgi.framework.BundleContext
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
-
-class FRMActivator extends AbstractBindingAwareProvider {
-
- static var FlowProvider provider = new FlowProvider();
- static var GroupProvider groupProvider = new GroupProvider();
- static var MeterProvider meterProvider = new MeterProvider();
-
- override onSessionInitiated(ProviderContext session) {
- provider.dataService = session.getSALService(DataProviderService)
- provider.salFlowService = session.getRpcService(SalFlowService);
- provider.start();
-
- groupProvider.dataService = session.getSALService(DataProviderService)
- groupProvider.salGroupService = session.getRpcService(SalGroupService)
- groupProvider.start();
-
- meterProvider.dataService = session.getSALService(DataProviderService)
- meterProvider.salMeterService = session.getRpcService(SalMeterService)
- meterProvider.start();
- }
-
- override protected stopImpl(BundleContext context) {
- provider.close();
- groupProvider.close();
- meterProvider.close();
- }
-
-}
--- /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.frm.flow;
+
+import org.opendaylight.controller.frm.AbstractChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class FlowChangeListener extends AbstractChangeListener {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FlowChangeListener.class);
+
+ private final SalFlowService salFlowService;
+
+ public SalFlowService getSalFlowService() {
+ return this.salFlowService;
+ }
+
+ public FlowChangeListener(final SalFlowService manager) {
+ this.salFlowService = manager;
+ }
+
+ @Override
+ protected void validate() throws IllegalStateException {
+ FlowTransactionValidator.validate(this);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
+ if ((removeDataObj instanceof Flow)) {
+
+ final Flow flow = ((Flow) removeDataObj);
+ final InstanceIdentifier<Table> tableInstanceId = identifier.<Table> firstIdentifierOf(Table.class);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(flow);
+
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowTable(new FlowTableRef(tableInstanceId));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salFlowService.removeFlow((RemoveFlowInput) builder.build());
+ LOG.debug("Transaction {} - Removed Flow has removed flow: {}", new Object[]{uri, removeDataObj});
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
+ if (original instanceof Flow && update instanceof Flow) {
+
+ final Flow originalFlow = ((Flow) original);
+ final Flow updatedFlow = ((Flow) update);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node>firstIdentifierOf(Node.class);
+ final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder();
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowRef(new FlowRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+
+ builder.setUpdatedFlow((UpdatedFlow) (new UpdatedFlowBuilder(updatedFlow)).build());
+ builder.setOriginalFlow((OriginalFlow) (new OriginalFlowBuilder(originalFlow)).build());
+
+ this.salFlowService.updateFlow((UpdateFlowInput) builder.build());
+ LOG.debug("Transaction {} - Update Flow has updated flow {} with {}", new Object[]{uri, original, update});
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
+ if ((addDataObj instanceof Flow)) {
+
+ final Flow flow = ((Flow) addDataObj);
+ final InstanceIdentifier<Table> tableInstanceId = identifier.<Table> firstIdentifierOf(Table.class);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setFlowTable(new FlowTableRef(tableInstanceId));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salFlowService.addFlow((AddFlowInput) builder.build());
+ LOG.debug("Transaction {} - Add Flow has added flow: {}", new Object[]{uri, addDataObj});
+ }
+ }
+}
+++ /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.frm.flow
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-
-class FlowCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- @Property
- val SalFlowService salFlowService;
-
- new(SalFlowService manager) {
- _salFlowService = manager;
- }
-
- override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- return new FlowTransaction(modification,salFlowService);
- }
-
-}
--- /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.frm.flow;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowProvider implements AutoCloseable {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FlowProvider.class);
+
+ private SalFlowService salFlowService;
+ private DataProviderService dataService;
+
+ /* DataChangeListener */
+ private FlowChangeListener flowDataChangeListener;
+ ListenerRegistration<DataChangeListener> flowDataChangeListenerRegistration;
+
+ public void start() {
+ /* Build Path */
+ InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
+ InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
+ InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
+ InstanceIdentifierBuilder<Table> tableChild = augmentFlowCapNode.<Table> child(Table.class);
+ InstanceIdentifierBuilder<Flow> flowChild = tableChild.<Flow> child(Flow.class);
+ final InstanceIdentifier<? extends DataObject> flowDataObjectPath = flowChild.toInstance();
+
+ /* DataChangeListener registration */
+ this.flowDataChangeListener = new FlowChangeListener(this.salFlowService);
+ this.flowDataChangeListenerRegistration = this.dataService.registerDataChangeListener(flowDataObjectPath, flowDataChangeListener);
+ LOG.info("Flow Config Provider started.");
+ }
+
+ protected DataModificationTransaction startChange() {
+ return this.dataService.beginTransaction();
+ }
+
+ @Override
+ public void close() throws Exception {
+ if(flowDataChangeListenerRegistration != null){
+ flowDataChangeListenerRegistration.close();
+ }
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public void setSalFlowService(final SalFlowService salFlowService) {
+ this.salFlowService = salFlowService;
+ }
+}
+++ /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.frm.flow
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.slf4j.LoggerFactory
-
-class FlowProvider implements AutoCloseable {
-
- @Property
- DataProviderService dataService;
-
- @Property
- SalFlowService salFlowService;
-
- FlowCommitHandler commitHandler
-
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
-
- static val LOG = LoggerFactory.getLogger(FlowProvider);
-
- def void start() {
- commitHandler = new FlowCommitHandler(salFlowService)
- val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
- .child(Node)
- .augmentation(FlowCapableNode)
- .child(Table)
- .child(Flow)
- .toInstance();
- commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
- LOG.info("Flow Config Provider started.");
- }
-
- protected def startChange() {
- return dataService.beginTransaction;
- }
-
- override close() throws Exception {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
-}
+++ /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.frm.flow
-
-import org.opendaylight.controller.frm.AbstractTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
-
-class FlowTransaction extends AbstractTransaction {
-
- @Property
- val SalFlowService salFlowService;
-
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalFlowService salFlowService) {
- super(modification)
- _salFlowService = salFlowService;
- }
-
- override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Flow) {
- val flow = (obj as Flow)
- val tableInstanceId = instanceId.firstIdentifierOf(Table);
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new RemoveFlowInputBuilder(flow);
- builder.setFlowRef(new FlowRef(instanceId));
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setFlowTable(new FlowTableRef(tableInstanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- _salFlowService.removeFlow(builder.build());
- }
- }
-
- override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
- if(originalObj instanceof Flow && updatedObj instanceof Flow) {
- val originalFlow = (originalObj as Flow)
- val updatedFlow = (updatedObj as Flow)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new UpdateFlowInputBuilder();
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setFlowRef(new FlowRef(instanceId));
- val ufb = new UpdatedFlowBuilder(updatedFlow);
- builder.setUpdatedFlow((ufb.build()));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- val ofb = new OriginalFlowBuilder(originalFlow);
- builder.setOriginalFlow(ofb.build());
- _salFlowService.updateFlow(builder.build());
-
- }
- }
-
- override add(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Flow) {
- val flow = (obj as Flow)
- val tableInstanceId = instanceId.firstIdentifierOf(Table);
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new AddFlowInputBuilder(flow);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- builder.setFlowRef(new FlowRef(instanceId));
- builder.setFlowTable(new FlowTableRef(tableInstanceId));
- _salFlowService.addFlow(builder.build());
- }
- }
-
- override validate() throws IllegalStateException {
- FlowTransactionValidator.validate(this)
- }
-}
-/*
+/**
* 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
public class FlowTransactionValidator {
- public static void validate(FlowTransaction transaction) throws IllegalStateException {
+ public static void validate(FlowChangeListener transaction) throws IllegalStateException {
// NOOP
}
-
}
--- /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.frm.group;
+
+import org.opendaylight.controller.frm.AbstractChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class GroupChangeListener extends AbstractChangeListener {
+
+ private final static Logger LOG = LoggerFactory.getLogger(GroupChangeListener.class);
+
+ private final SalGroupService salGroupService;
+
+ public SalGroupService getSalGroupService() {
+ return this.salGroupService;
+ }
+
+ public GroupChangeListener(final SalGroupService manager) {
+ this.salGroupService = manager;
+ }
+
+ @Override
+ protected void validate() throws IllegalStateException {
+ GroupTransactionValidator.validate(this);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
+ if ((removeDataObj instanceof Group)) {
+
+ final Group group = ((Group) removeDataObj);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(group);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setGroupRef(new GroupRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salGroupService.removeGroup((RemoveGroupInput) builder.build());
+ LOG.debug("Transaction {} - Remove Group has removed group: {}", new Object[]{uri, removeDataObj});
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
+ if (original instanceof Group && update instanceof Group) {
+
+ final Group originalGroup = ((Group) original);
+ final Group updatedGroup = ((Group) update);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder();
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setGroupRef(new GroupRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+
+ builder.setUpdatedGroup((UpdatedGroup) (new UpdatedGroupBuilder(updatedGroup)).build());
+ builder.setOriginalGroup((OriginalGroup) (new OriginalGroupBuilder(originalGroup)).build());
+
+ this.salGroupService.updateGroup((UpdateGroupInput) builder.build());
+ LOG.debug("Transaction {} - Update Group has updated group {} with group {}", new Object[]{uri, original, update});
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
+ if ((addDataObj instanceof Group)) {
+ final Group group = ((Group) addDataObj);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final AddGroupInputBuilder builder = new AddGroupInputBuilder(group);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setGroupRef(new GroupRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salGroupService.addGroup((AddGroupInput) builder.build());
+ LOG.debug("Transaction {} - Add Group has added group: {}", new Object[]{uri, addDataObj});
+ }
+ }
+}
+++ /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.frm.group
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-
-class GroupCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- @Property
- val SalGroupService groupService;
-
- new(SalGroupService groupService) {
- _groupService = groupService;
- }
-
- override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- return new GroupTransaction(modification,groupService);
- }
-
-}
--- /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.frm.group;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GroupProvider implements AutoCloseable {
+
+ private final static Logger LOG = LoggerFactory.getLogger(GroupProvider.class);
+
+ private SalGroupService salGroupService;
+ private DataProviderService dataService;
+
+ /* DataChangeListener */
+ private GroupChangeListener groupDataChangeListener;
+ ListenerRegistration<DataChangeListener> groupDataChangeListenerRegistration;
+
+ public void start() {
+ /* Build Path */
+ InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
+ InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
+ InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
+ InstanceIdentifierBuilder<Group> groupChild = augmentFlowCapNode.<Group> child(Group.class);
+ final InstanceIdentifier<? extends DataObject> groupDataObjectPath = groupChild.toInstance();
+
+ /* DataChangeListener registration */
+ this.groupDataChangeListener = new GroupChangeListener(this.salGroupService);
+ this.groupDataChangeListenerRegistration = this.dataService.registerDataChangeListener(groupDataObjectPath, groupDataChangeListener);
+ LOG.info("Group Config Provider started.");
+ }
+
+ protected DataModificationTransaction startChange() {
+ return this.dataService.beginTransaction();
+ }
+
+ public void close() throws Exception {
+ if(groupDataChangeListenerRegistration != null){
+ groupDataChangeListenerRegistration.close();
+ }
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public void setSalGroupService(final SalGroupService salGroupService) {
+ this.salGroupService = salGroupService;
+ }
+}
+++ /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.frm.group
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.slf4j.LoggerFactory
-
-class GroupProvider implements AutoCloseable {
-
- @Property
- DataProviderService dataService;
-
- @Property
- SalGroupService salGroupService;
-
- GroupCommitHandler commitHandler
-
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
-
- static val LOG = LoggerFactory.getLogger(GroupProvider);
-
- def void start() {
- commitHandler = new GroupCommitHandler(salGroupService)
- val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
- .child(Node)
- .augmentation(FlowCapableNode)
- .child(Group)
- .toInstance();
- commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
- LOG.info("Group Config Provider started.");
- }
-
- protected def startChange() {
- return dataService.beginTransaction;
- }
-
- override close() throws Exception {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
-}
+++ /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.frm.group
-
-import org.opendaylight.controller.frm.AbstractTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
-
-class GroupTransaction extends AbstractTransaction {
-
- @Property
- val SalGroupService groupService;
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalGroupService groupService) {
- super(modification)
- _groupService = groupService;
- }
-
- override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Group) {
- val group = (obj as Group)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new RemoveGroupInputBuilder(group);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- builder.setGroupRef(new GroupRef(instanceId));
- _groupService.removeGroup(builder.build());
- }
- }
-
- override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
- if(originalObj instanceof Group && updatedObj instanceof Group) {
- val originalGroup = (originalObj as Group)
- val updatedGroup = (updatedObj as Group)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new UpdateGroupInputBuilder();
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setGroupRef(new GroupRef(instanceId));
- val ufb = new UpdatedGroupBuilder(updatedGroup);
- builder.setUpdatedGroup((ufb.build()));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- val ofb = new OriginalGroupBuilder(originalGroup);
- builder.setOriginalGroup(ofb.build());
- _groupService.updateGroup(builder.build());
-
- }
- }
-
- override add(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Group) {
- val group = (obj as Group)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new AddGroupInputBuilder(group);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setGroupRef(new GroupRef(instanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- _groupService.addGroup(builder.build());
- }
- }
-
- override validate() throws IllegalStateException {
- GroupTransactionValidator.validate(this)
- }
-}
-/*
+/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
public class GroupTransactionValidator {
- public static void validate(GroupTransaction transaction) throws IllegalStateException {
+ public static void validate(GroupChangeListener transaction) throws IllegalStateException {
// NOOP
}
-
}
--- /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.frm.meter;
+
+import org.opendaylight.controller.frm.AbstractChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ */
+public class MeterChangeListener extends AbstractChangeListener {
+
+ private final static Logger LOG = LoggerFactory.getLogger(MeterChangeListener.class);
+
+ private final SalMeterService salMeterService;
+
+ public SalMeterService getSalMeterService() {
+ return this.salMeterService;
+ }
+
+ public MeterChangeListener(final SalMeterService manager) {
+ this.salMeterService = manager;
+ }
+
+ @Override
+ protected void validate() throws IllegalStateException {
+ MeterTransactionValidator.validate(this);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<? extends DataObject> identifier, DataObject removeDataObj) {
+ if ((removeDataObj instanceof Meter)) {
+
+ final Meter meter = ((Meter) removeDataObj);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(meter);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setMeterRef(new MeterRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salMeterService.removeMeter((RemoveMeterInput) builder.build());
+ LOG.debug("Transaction {} - Remove Meter has removed meter: {}", new Object[]{uri, removeDataObj});
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<? extends DataObject> identifier, DataObject original, DataObject update) {
+ if (original instanceof Meter && update instanceof Meter) {
+
+ final Meter originalMeter = ((Meter) original);
+ final Meter updatedMeter = ((Meter) update);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder();
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setMeterRef(new MeterRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+
+ builder.setUpdatedMeter((UpdatedMeter) (new UpdatedMeterBuilder(updatedMeter)).build());
+ builder.setOriginalMeter((OriginalMeter) (new OriginalMeterBuilder(originalMeter)).build());
+
+ this.salMeterService.updateMeter((UpdateMeterInput) builder.build());
+ LOG.debug("Transaction {} - Update Meter has updated meter {} with {}", new Object[]{uri, original, update});
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<? extends DataObject> identifier, DataObject addDataObj) {
+ if ((addDataObj instanceof Meter)) {
+
+ final Meter meter = ((Meter) addDataObj);
+ final InstanceIdentifier<Node> nodeInstanceId = identifier.<Node> firstIdentifierOf(Node.class);
+ final AddMeterInputBuilder builder = new AddMeterInputBuilder(meter);
+
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setMeterRef(new MeterRef(identifier));
+
+ Uri uri = new Uri(this.getTransactionId());
+ builder.setTransactionUri(uri);
+ this.salMeterService.addMeter((AddMeterInput) builder.build());
+ LOG.debug("Transaction {} - Add Meter has added meter: {}", new Object[]{uri, addDataObj});
+ }
+ }
+}
\ 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.frm.meter
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-
-class FlowCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- @Property
- val SalMeterService salMeterService;
-
- new(SalMeterService manager) {
- _salMeterService = manager;
- }
-
- override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- return new MeterTransaction(modification,salMeterService);
- }
-
-}
--- /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.frm.meter;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MeterProvider implements AutoCloseable {
+
+ private final static Logger LOG = LoggerFactory.getLogger(MeterProvider.class);
+
+ private DataProviderService dataService;
+ private SalMeterService salMeterService;
+
+ /* DataChangeListener */
+ private MeterChangeListener meterDataChangeListener;
+ ListenerRegistration<DataChangeListener> meterDataChangeListenerRegistration;
+
+ public void start() {
+ /* Build Path */
+ InstanceIdentifierBuilder<Nodes> nodesBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
+ InstanceIdentifierBuilder<Node> nodeChild = nodesBuilder.<Node> child(Node.class);
+ InstanceIdentifierBuilder<FlowCapableNode> augmentFlowCapNode = nodeChild.<FlowCapableNode> augmentation(FlowCapableNode.class);
+ InstanceIdentifierBuilder<Meter> meterChild = augmentFlowCapNode.<Meter> child(Meter.class);
+ final InstanceIdentifier<? extends DataObject> meterDataObjectPath = meterChild.toInstance();
+
+ /* DataChangeListener registration */
+ this.meterDataChangeListener = new MeterChangeListener(this.salMeterService);
+ this.meterDataChangeListenerRegistration = this.dataService.registerDataChangeListener(meterDataObjectPath, meterDataChangeListener);
+ LOG.info("Meter Config Provider started.");
+ }
+
+ protected DataModificationTransaction startChange() {
+ return this.dataService.beginTransaction();
+ }
+
+ public void close() throws Exception {
+ if(meterDataChangeListenerRegistration != null){
+ meterDataChangeListenerRegistration.close();
+ }
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public void setSalMeterService(final SalMeterService salMeterService) {
+ this.salMeterService = salMeterService;
+ }
+}
\ 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.frm.meter
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.slf4j.LoggerFactory
-
-class MeterProvider implements AutoCloseable {
-
- @Property
- DataProviderService dataService;
-
- @Property
- SalMeterService salMeterService;
-
- FlowCommitHandler commitHandler
-
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
-
- static val LOG = LoggerFactory.getLogger(MeterProvider);
-
- def void start() {
- commitHandler = new FlowCommitHandler(salMeterService)
- val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
- .child(Node)
- .augmentation(FlowCapableNode)
- .child(Meter)
- .toInstance();
- commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
- LOG.info("Meter Config Provider started.");
- }
-
- protected def startChange() {
- return dataService.beginTransaction;
- }
-
- override close() throws Exception {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
-}
+++ /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.frm.meter
-
-import org.opendaylight.controller.frm.AbstractTransaction
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri
-
-class MeterTransaction extends AbstractTransaction {
-
- @Property
- val SalMeterService salMeterService;
-
- new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalMeterService salMeterService) {
- super(modification)
- _salMeterService = salMeterService;
- }
-
- override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Meter) {
- val meter = (obj as Meter)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new RemoveMeterInputBuilder(meter);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setMeterRef(new MeterRef(instanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- _salMeterService.removeMeter(builder.build());
- }
- }
-
- override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
- if(originalObj instanceof Meter && updatedObj instanceof Meter) {
- val originalMeter = (originalObj as Meter)
- val updatedMeter = (updatedObj as Meter)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new UpdateMeterInputBuilder();
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setMeterRef(new MeterRef(instanceId));
- val ufb = new UpdatedMeterBuilder(updatedMeter);
- builder.setUpdatedMeter((ufb.build()));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- val ofb = new OriginalMeterBuilder(originalMeter);
- builder.setOriginalMeter(ofb.build());
- _salMeterService.updateMeter(builder.build());
-
- }
- }
-
- override add(InstanceIdentifier<?> instanceId, DataObject obj) {
- if(obj instanceof Meter) {
- val meter = (obj as Meter)
- val nodeInstanceId = instanceId.firstIdentifierOf(Node);
- val builder = new AddMeterInputBuilder(meter);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setMeterRef(new MeterRef(instanceId));
- builder.setTransactionUri(new Uri(modification.getIdentifier() as String));
- _salMeterService.addMeter(builder.build());
- }
- }
-
- override validate() throws IllegalStateException {
- MeterTransactionValidator.validate(this)
- }
-}
-/*
+/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
public class MeterTransactionValidator {
- public static void validate(MeterTransaction transaction) throws IllegalStateException {
+ public static void validate(MeterChangeListener transaction) throws IllegalStateException {
// NOOP
}
-
}
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-api</artifactId>
</instructions>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
</plugins>
</build>
<scm>
--- /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.md.inventory.manager;
+
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowCapableInventoryProvider implements AutoCloseable {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider.class);
+
+ private DataProviderService dataService;
+ private NotificationProviderService notificationService;
+ private Registration<NotificationListener> listenerRegistration;
+ private final NodeChangeCommiter changeCommiter = new NodeChangeCommiter(FlowCapableInventoryProvider.this);
+
+ public void start() {
+ this.listenerRegistration = this.notificationService.registerNotificationListener(this.changeCommiter);
+ LOG.info("Flow Capable Inventory Provider started.");
+ }
+
+ protected DataModificationTransaction startChange() {
+ DataProviderService _dataService = this.dataService;
+ return _dataService.beginTransaction();
+ }
+
+ @Override
+ public void close() {
+ try {
+ LOG.info("Flow Capable Inventory Provider stopped.");
+ if (this.listenerRegistration != null) {
+ this.listenerRegistration.close();
+ }
+ } catch (Exception e) {
+ String errMsg = "Error by stop Flow Capable Inventory Provider.";
+ LOG.error(errMsg, e);
+ throw new RuntimeException(errMsg, e);
+ }
+ }
+
+ public DataProviderService getDataService() {
+ return this.dataService;
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public NotificationProviderService getNotificationService() {
+ return this.notificationService;
+ }
+
+ public void setNotificationService(
+ final NotificationProviderService notificationService) {
+ this.notificationService = notificationService;
+ }
+}
+++ /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.md.inventory.manager
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.NotificationListener
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
-import static extension org.opendaylight.controller.md.inventory.manager.InventoryMapping.*
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
-import org.slf4j.LoggerFactory
-
-class FlowCapableInventoryProvider implements AutoCloseable {
-
-
- static val LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider);
-
- @Property
- DataProviderService dataService;
-
- @Property
- NotificationProviderService notificationService;
- val NodeChangeCommiter changeCommiter = new NodeChangeCommiter(this);
-
- Registration<NotificationListener> listenerRegistration
-
- def void start() {
- listenerRegistration = notificationService.registerNotificationListener(changeCommiter);
- LOG.info("Flow Capable Inventory Provider started.");
-
- }
-
- protected def startChange() {
- return dataService.beginTransaction;
- }
-
- override close() {
- LOG.info("Flow Capable Inventory Provider stopped.");
- listenerRegistration?.close();
- }
-
-}
\ 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.md.inventory.manager;
+
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.osgi.framework.BundleContext;
+
+public class InventoryActivator extends AbstractBindingAwareProvider {
+
+ private static FlowCapableInventoryProvider provider = new FlowCapableInventoryProvider();
+
+ @Override
+ public void onSessionInitiated(final ProviderContext session) {
+ DataProviderService salDataService = session.<DataProviderService> getSALService(DataProviderService.class);
+ NotificationProviderService salNotifiService =
+ session.<NotificationProviderService> getSALService(NotificationProviderService.class);
+ InventoryActivator.provider.setDataService(salDataService);
+ InventoryActivator.provider.setNotificationService(salNotifiService);
+ InventoryActivator.provider.start();
+ }
+
+ @Override
+ protected void stopImpl(final BundleContext context) {
+ InventoryActivator.provider.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.md.inventory.manager
-
-import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
-import org.osgi.framework.BundleContext
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService
-
-class InventoryActivator extends AbstractBindingAwareProvider {
-
- static var FlowCapableInventoryProvider provider = new FlowCapableInventoryProvider();
-
- override onSessionInitiated(ProviderContext session) {
- provider.dataService = session.getSALService(DataProviderService)
- provider.notificationService = session.getSALService(NotificationProviderService)
- provider.start();
- }
-
- override protected stopImpl(BundleContext context) {
- provider.close();
- }
-
-}
--- /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.md.inventory.manager;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNodeConnector;
+
+public class InventoryMapping {
+
+ public static FlowCapableNodeConnector toInventoryAugment(final FlowNodeConnector updated) {
+ if ((updated instanceof FlowCapableNodeConnector)) {
+ return ((FlowCapableNodeConnector) updated);
+ }
+ final FlowCapableNodeConnectorBuilder builder = new FlowCapableNodeConnectorBuilder();
+ builder.setAdvertisedFeatures(updated.getAdvertisedFeatures());
+ builder.setConfiguration(updated.getConfiguration());
+ builder.setCurrentFeature(updated.getCurrentFeature());
+ builder.setCurrentSpeed(updated.getCurrentSpeed());
+ builder.setHardwareAddress(updated.getHardwareAddress());
+ builder.setMaximumSpeed(updated.getMaximumSpeed());
+ builder.setName(updated.getName());
+ builder.setPeerFeatures(updated.getPeerFeatures());
+ builder.setPortNumber(updated.getPortNumber());
+ builder.setState(updated.getState());
+ builder.setSupported(updated.getSupported());
+ return builder.build();
+ }
+
+ public static FlowCapableNode toInventoryAugment(final FlowNode source) {
+ if ((source instanceof FlowCapableNode)) {
+ return ((FlowCapableNode) source);
+ }
+ return (new FlowCapableNodeBuilder(source)).build();
+ }
+}
+++ /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.md.inventory.manager
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder
-
-class InventoryMapping {
-
- static def FlowCapableNodeConnector toInventoryAugment(FlowNodeConnector updated) {
- if (updated instanceof FlowCapableNodeConnector) {
- return updated as FlowCapableNodeConnector;
- }
- val it = new FlowCapableNodeConnectorBuilder();
- advertisedFeatures = updated.advertisedFeatures
- configuration = updated.configuration
- currentFeature = updated.currentFeature
- currentSpeed = updated.currentSpeed
- hardwareAddress = updated.hardwareAddress
- maximumSpeed = updated.maximumSpeed
- name = updated.name
- peerFeatures = updated.peerFeatures
- portNumber = updated.portNumber
- state = updated.state
- supported = updated.supported
- return build();
- }
-
- static def FlowCapableNode toInventoryAugment(FlowNode source) {
- if (source instanceof FlowCapableNode) {
- return source as FlowCapableNode;
- }
- val it = new FlowCapableNodeBuilder(source);
- return build();
- }
-
-}
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
import com.google.common.base.Objects;
-@SuppressWarnings("all")
public class NodeChangeCommiter implements OpendaylightInventoryListener {
+
private final static Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class);
private final FlowCapableInventoryProvider manager;
final NodeConnectorRef ref = connector.getNodeConnectorRef();
final FlowCapableNodeConnectorUpdated flowConnector = connector
.getAugmentation(FlowCapableNodeConnectorUpdated.class);
- final DataModificationTransaction it = this.getManager().startChange();
+ final DataModificationTransaction it = this.manager.startChange();
final NodeConnectorBuilder data = new NodeConnectorBuilder(connector);
NodeConnectorId id = connector.getId();
NodeConnectorKey nodeConnectorKey = new NodeConnectorKey(id);
data.addAugmentation(FlowCapableNodeConnector.class, augment);
}
InstanceIdentifier<? extends Object> value = ref.getValue();
- String string = value.toString();
- String plus = ("updating node connector : " + string);
- NodeChangeCommiter.LOG.debug(plus);
- InstanceIdentifier<? extends Object> value1 = ref.getValue();
+ NodeChangeCommiter.LOG.debug("updating node connector : {}.", value);
NodeConnector build = data.build();
- it.putOperationalData((value1), build);
+ it.putOperationalData((value), build);
Future<RpcResult<TransactionStatus>> commitResult = it.commit();
try {
commitResult.get();
public synchronized void onNodeRemoved(final NodeRemoved node) {
final NodeRef ref = node.getNodeRef();
- FlowCapableInventoryProvider manager = this.getManager();
- final DataModificationTransaction it = manager.startChange();
- InstanceIdentifier<? extends Object> value = ref.getValue();
- String string = value.toString();
- String plus = ("removing node : " + string);
- NodeChangeCommiter.LOG.debug(plus);
- InstanceIdentifier<? extends Object> value1 = ref.getValue();
- it.removeOperationalData((value1));
+ final DataModificationTransaction it = this.manager.startChange();
+ NodeChangeCommiter.LOG.debug("removing node : {}", ref.getValue());
+ it.removeOperationalData((ref.getValue()));
Future<RpcResult<TransactionStatus>> commitResult = it.commit();
try {
commitResult.get();
final NodeRef ref = node.getNodeRef();
final FlowCapableNodeUpdated flowNode = node
.<FlowCapableNodeUpdated> getAugmentation(FlowCapableNodeUpdated.class);
- FlowCapableInventoryProvider manager = this.getManager();
- final DataModificationTransaction it = manager.startChange();
- NodeBuilder nodeBuilder = new NodeBuilder(node);
- final NodeBuilder data = nodeBuilder;
- NodeId id = node.getId();
- NodeKey nodeKey = new NodeKey(id);
- data.setKey(nodeKey);
+ final DataModificationTransaction it = this.manager.startChange();
+ final NodeBuilder nodeBuilder = new NodeBuilder(node);
+ nodeBuilder.setKey(new NodeKey(node.getId()));
boolean equals = Objects.equal(flowNode, null);
if (equals) {
return;
}
final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
- data.addAugmentation(FlowCapableNode.class, augment);
+ nodeBuilder.addAugmentation(FlowCapableNode.class, augment);
InstanceIdentifier<? extends Object> value = ref.getValue();
InstanceIdentifierBuilder<Node> builder = InstanceIdentifier.<Node> builder(((InstanceIdentifier<Node>) value));
InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder
try {
final DataObject dataObject = normalizedNode.isPresent() ? codec.toBinding(path,
normalizedNode.get()) : null;
- if(dataObject != null) {
+ if (dataObject != null) {
updateCache(store, path, dataObject);
}
return Optional.fromNullable(dataObject);
.toNormalizedNode(path, data);
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+ ensureParentsByMerge(writeTransaction, store, normalized.getKey(), path);
+ LOG.debug("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
+ writeTransaction.put(store, normalized.getKey(), normalized.getValue());
+ }
+
+ protected void doMergeWithEnsureParents(final DOMDataReadWriteTransaction writeTransaction,
+ final LogicalDatastoreType store, final InstanceIdentifier<?> path, final DataObject data) {
+ invalidateCache(store, path);
+ final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
+ .toNormalizedNode(path, data);
+
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+ ensureParentsByMerge(writeTransaction, store, normalized.getKey(), path);
+ LOG.debug("Tx: {} : Merge data {}",getDelegate().getIdentifier(),normalized.getKey());
+ writeTransaction.merge(store, normalized.getKey(), normalized.getValue());
+ }
+
+ private void ensureParentsByMerge(final DOMDataReadWriteTransaction writeTransaction,
+ final LogicalDatastoreType store,
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath,
+ final InstanceIdentifier<?> path) {
List<PathArgument> currentArguments = new ArrayList<>();
DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
writeTransaction.merge(store, currentPath, currentOp.createDefault(currentArg));
}
}
- //LOG .info("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
- writeTransaction.put(store, normalized.getKey(), normalized.getValue());
}
protected void doMerge(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
private class ForwardedBackwardsCompatibleTransacion extends
AbstractForwardedTransaction<DOMDataReadWriteTransaction> implements DataModificationTransaction {
+ private final ListenerRegistry<DataTransactionListener> listeners = ListenerRegistry.create();
private final Map<InstanceIdentifier<? extends DataObject>, DataObject> updated = new HashMap<>();
private final Map<InstanceIdentifier<? extends DataObject>, DataObject> created = new HashMap<>();
private final Set<InstanceIdentifier<? extends DataObject>> removed = new HashSet<>();
@Override
public void putOperationalData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
- posponedRemovedOperational.remove(path);
- doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+ boolean previouslyRemoved = posponedRemovedOperational.remove(path);
+ if(previouslyRemoved) {
+ doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+ } else {
+ doMergeWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data);
+ }
}
@Override
public void putConfigurationData(final InstanceIdentifier<? extends DataObject> path, final DataObject data) {
- posponedRemovedConfiguration.remove(path);
+ boolean previouslyRemoved = posponedRemovedConfiguration.remove(path);
DataObject originalObj = readConfigurationData(path);
if (originalObj != null) {
original.put(path, originalObj);
created.put(path, data);
}
updated.put(path, data);
- doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+ if(previouslyRemoved) {
+ doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+ } else {
+ doMergeWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data);
+ }
}
@Override
private void changeStatus(final TransactionStatus status) {
LOG.trace("Transaction {} changed status to {}", getIdentifier(), status);
this.status = status;
+
+ for(ListenerRegistration<DataTransactionListener> listener : listeners) {
+ try {
+ listener.getInstance().onStatusUpdated(this, status);
+ } catch (Exception e) {
+ LOG.error("Error during invoking transaction listener {}",listener.getInstance(),e);
+ }
+ }
}
@Override
doDelete(getDelegate(), LogicalDatastoreType.OPERATIONAL, path);
}
- final ListenableFuture<RpcResult<TransactionStatus>> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this);
-
changeStatus(TransactionStatus.SUBMITED);
+ final ListenableFuture<RpcResult<TransactionStatus>> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this);
+
Futures.addCallback(f, new FutureCallback<RpcResult<TransactionStatus>>() {
@Override
public void onSuccess(final RpcResult<TransactionStatus> result) {
@Override
public ListenerRegistration<DataTransactionListener> registerListener(final DataTransactionListener listener) {
- throw new UnsupportedOperationException();
+ return listeners.register(listener);
}
}
public static final int CORE_NOTIFICATION_THREADS = 4;
public static final int MAX_NOTIFICATION_THREADS = 32;
+ // block caller thread after MAX_NOTIFICATION_THREADS + MAX_NOTIFICATION_QUEUE_SIZE pending notifications
+ public static final int MAX_NOTIFICATION_QUEUE_SIZE = 10;
public static final int NOTIFICATION_THREAD_LIFE = 15;
private static ListeningExecutorService NOTIFICATION_EXECUTOR = null;
public static synchronized final ListeningExecutorService getDefaultNotificationExecutor() {
if (NOTIFICATION_EXECUTOR == null) {
- // Overriding the queue since we need an unbounded queue
- // and threadpoolexecutor would not create new threads if the queue is not full
- BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>() {
+ // Overriding the queue:
+ // ThreadPoolExecutor would not create new threads if the queue is not full, thus adding
+ // occurs in RejectedExecutionHandler.
+ // This impl saturates threadpool first, then queue. When both are full caller will get blocked.
+ BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(MAX_NOTIFICATION_QUEUE_SIZE) {
@Override
public boolean offer(Runnable r) {
- if (size() <= 1) {
- // if the queue is empty (or has just 1), no need to rampup the threads
- return super.offer(r);
- } else {
- // if the queue is not empty, force the queue to return false.
- // threadpoolexecutor will spawn a new thread if the queue.offer returns false.
- return false;
- }
+ // ThreadPoolExecutor will spawn a new thread after core size is reached only if the queue.offer returns false.
+ return false;
}
};
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
- e.printStackTrace();
+ Thread.currentThread().interrupt();// set interrupt flag after clearing
+ throw new IllegalStateException(e);
}
}
});
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.binding.codegen.impl;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import java.lang.reflect.Field;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Ignore
+public class SingletonHolderTest {
+ private static final Logger logger = LoggerFactory.getLogger(SingletonHolderTest.class);
+
+ @Test
+ public void testNotificationExecutor() throws Exception {
+ ListeningExecutorService executor = SingletonHolder.getDefaultNotificationExecutor();
+ ThreadPoolExecutor tpExecutor = (ThreadPoolExecutor) setAccessible(executor.getClass().getDeclaredField("delegate")).get(executor);
+ BlockingQueue<Runnable> queue = tpExecutor.getQueue();
+
+ for (int idx = 0; idx < 100; idx++) {
+ final int idx2 = idx;
+ logger.info("Adding {}\t{}\t{}", idx, queue.size(), tpExecutor.getActiveCount());
+ executor.execute(new Runnable() {
+
+ @Override
+ public void run() {
+ logger.info("in {}", idx2);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ logger.info("out {}", idx2);
+ }
+ });
+ }
+ executor.shutdown();
+ executor.awaitTermination(10, TimeUnit.SECONDS);
+ }
+
+ private static Field setAccessible(Field field) {
+ field.setAccessible(true);
+ return field;
+ }
+}
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-broker-impl</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-management</artifactId>
</dependencies>
<build>
<plugins>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- <configuration>
- <codeGenerators>
- <generator>
- <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>${salGeneratorPath}</outputBaseDir>
- </generator>
- </codeGenerators>
- <inspectDependencies>true</inspectDependencies>
- </configuration>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
<scm>
import java.util.List;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.yangtools.yang.binding.NotificationListener;
import org.opendaylight.yangtools.yang.binding.RpcService;
-public class NoficationTest extends AbstractTest {
+@Ignore
+public class NotificationTest extends AbstractTest {
private final FlowListener listener1 = new FlowListener();
private final FlowListener listener2 = new FlowListener();
</provider>
</instance>
</service>
+
<service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
binding:binding-broker-osgi-registry
</provider>
</instance>
</service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <instance>
+ <name>binding-rpc-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ </instance>
+ </service>
<service>
<type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
binding-impl:binding-dom-mapping-service
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
public final class ImmutableDataChangeEvent<P extends Path<P>, D> implements DataChangeEvent<P,D> {
originalOperational.putAll(Maps.filterKeys(data.getOriginalOperationalData(), keyFilter));
createdOperational.putAll(Maps.filterKeys(data.getCreatedOperationalData(), keyFilter));
createdConfiguration.putAll(Maps.filterKeys(data.getCreatedConfigurationData(), keyFilter));
+ removedOperational.addAll(Sets.filter(data.getRemovedOperationalData(), keyFilter));
+ removedConfiguration.addAll(Sets.filter(data.getRemovedConfigurationData(), keyFilter));
return this;
}
Builder eventBuilder = builder(potentialScope) //
.setBefore(beforeCont) //
- .setAfter(afterCont);
+ .setAfter(afterCont)
+ .addUpdated(path, beforeCont, afterCont);
for (DOMImmutableDataChangeEvent childChange : childChanges) {
eventBuilder.merge(childChange);
}
final Collection<Node> listeners, final NormalizedNode<PathArgument, ?> node,
final SimpleEventFactory eventFactory) {
- DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
-
- if (!listeners.isEmpty()) {
+ final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
+ DOMImmutableDataChangeEvent propagateEvent = event;
// We have listeners for this node or it's children, so we will try
// to do additional processing
- if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
- // Node has children, so we will try to resolve it's children
- // changes.
- @SuppressWarnings("unchecked")
- NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> container = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) node;
- for (NormalizedNode<PathArgument, ?> child : container.getValue()) {
- PathArgument childId = child.getIdentifier();
- Collection<Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
- if (!childListeners.isEmpty()) {
- resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory);
- }
- }
+ if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
+ Builder eventBuilder = builder(DataChangeScope.BASE);
+ eventBuilder.merge(event);
+ eventBuilder.setBefore(event.getOriginalSubtree());
+ eventBuilder.setAfter(event.getUpdatedSubtree());
+
+ // Node has children, so we will try to resolve it's children
+ // changes.
+ @SuppressWarnings("unchecked")
+ NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> container = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) node;
+ for (NormalizedNode<PathArgument, ?> child : container.getValue()) {
+ PathArgument childId = child.getIdentifier();
+ Collection<Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
+ eventBuilder.merge(resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory));
}
+ propagateEvent = eventBuilder.build();
+ } else {
+ // We do not dispatch leaf events since Binding Aware components do not support them.
+ propagateEvent = builder(DataChangeScope.BASE).build();
+ }
+ if (!listeners.isEmpty()) {
addPartialTask(listeners, event);
}
- return event;
+ return propagateEvent;
}
private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path,
Builder one = builder(DataChangeScope.ONE).setBefore(before.getData()).setAfter(after.getData());
- Builder subtree = builder(DataChangeScope.SUBTREE);
+ Builder subtree = builder(DataChangeScope.SUBTREE).setBefore(before.getData()).setAfter(after.getData());
for (NodeModification childMod : modification.getModifications()) {
PathArgument childId = childMod.getIdentifier();
import static com.google.common.base.Preconditions.checkArgument;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
} else if (schemaNode instanceof ChoiceNode) {
return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
} else if (schemaNode instanceof LeafListSchemaNode) {
- return new LeafSetEntryModificationStrategy((LeafListSchemaNode) schemaNode);
+ return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
} else if (schemaNode instanceof LeafSchemaNode) {
return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
}
return new UnorderedMapModificationStrategy(schemaNode);
}
+ private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
+ if(schemaNode.isUserOrdered()) {
+ return new OrderedLeafSetModificationStrategy(schemaNode);
+ } else {
+ return new UnorderedLeafSetModificationStrategy(schemaNode);
+ }
+ }
+
+
public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
AugmentationSchema augSchema = null;
DataNodeContainerModificationStrategy<AugmentationSchema> {
protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
- super(schema, AugmentationNode.class);
+ super(createAugmentProxy(schema,resolved), AugmentationNode.class);
// FIXME: Use resolved children instead of unresolved.
}
}
- public static class LeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+ public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
private final Optional<ModificationApplyOperation> entryStrategy;
@SuppressWarnings({ "unchecked", "rawtypes" })
- protected LeafSetModificationStrategy(final LeafListSchemaNode schema) {
+ protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
super((Class) LeafSetNode.class);
entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
}
}
+ public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
+ super((Class) LeafSetNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
+ return ImmutableOrderedLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ if (identifier instanceof NodeWithValue) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ }
+
public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
private final Optional<ModificationApplyOperation> entryStrategy;
}
+ public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
+ Set<DataSchemaNode> realChildSchemas = new HashSet<>();
+ for(DataSchemaNode augChild : schema.getChildNodes()) {
+ realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
+ }
+ return new AugmentationSchemaProxy(schema, realChildSchemas);
+ }
+
}
@Override
public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
- return listener.sendRequest(toRpcMessage(rpc, input, getSchemaContext()));
+ return listener.sendRequest(toRpcMessage(rpc, input, getSchemaContext()), rpc);
}
@Override
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
import org.opendaylight.yangtools.yang.common.QName;
private static final class Request {
final UncancellableFuture<RpcResult<CompositeNode>> future;
final NetconfMessage request;
+ final QName rpc;
- private Request(UncancellableFuture<RpcResult<CompositeNode>> future, NetconfMessage request) {
+ private Request(UncancellableFuture<RpcResult<CompositeNode>> future, NetconfMessage request, final QName rpc) {
this.future = future;
this.request = request;
+ this.rpc = rpc;
}
}
return;
}
- r.future.set(Rpcs.getRpcResult(true, NetconfMapping.toNotificationNode(message, device.getSchemaContext()),
- Collections.<RpcError>emptyList()));
+ r.future.set(NetconfMapping.toRpcResult(message, r.rpc, device.getSchemaContext()));
} else {
LOG.warn("Ignoring unsolicited message", message);
}
}
- synchronized ListenableFuture<RpcResult<CompositeNode>> sendRequest(final NetconfMessage message) {
+ synchronized ListenableFuture<RpcResult<CompositeNode>> sendRequest(final NetconfMessage message, final QName rpc) {
if (session == null) {
LOG.debug("Session to {} is disconnected, failing RPC request {}", device.getName(), message);
return Futures.<RpcResult<CompositeNode>>immediateFuture(new RpcResult<CompositeNode>() {
});
}
- final Request req = new Request(new UncancellableFuture<RpcResult<CompositeNode>>(true), message);
+ final Request req = new Request(new UncancellableFuture<RpcResult<CompositeNode>>(true), message, rpc);
requests.add(req);
session.sendMessage(req.request).addListener(new FutureListener<Void>() {
public void operationComplete(final Future<Void> future) throws Exception {
if (!future.isSuccess()) {
// We expect that a session down will occur at this point
- LOG.debug("Failed to send request {}", req.request, future.cause());
+ LOG.debug("Failed to send request {}", XmlUtil.toString(req.request.getDocument()), future.cause());
req.future.setException(future.cause());
} else {
LOG.trace("Finished sending request {}", req.request);
rawRpc = it.toInstance();
// sys(xmlData)
} else {
- RpcDefinition rpcSchema = Iterables.find(context.get().getOperations(), new Predicate<RpcDefinition>() {
- @Override
- public boolean apply(final RpcDefinition input) {
- return rpc == input.getQName();
- }
- });
rawRpc = (CompositeNode) toCompositeNode(message.getDocument());
}
else {
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider<String> {
private final NetconfDevice device;
+ private final Logger logger;
+
public NetconfRemoteSchemaSourceProvider(NetconfDevice device) {
this.device = Preconditions.checkNotNull(device);
+ logger = LoggerFactory.getLogger(NetconfDevice.class + "#" + device.getName());
}
@Override
request.addLeaf("version", revision.get());
}
- device.logger.trace("Loading YANG schema source for {}:{}", moduleName, revision);
+ logger.trace("Loading YANG schema source for {}:{}", moduleName, revision);
try {
RpcResult<CompositeNode> schemaReply = device.invokeRpc(GET_SCHEMA_QNAME, request.toInstance()).get();
if (schemaReply.isSuccessful()) {
return Optional.of(schemaBody);
}
}
- device.logger.warn("YANG shcema was not successfully retrieved.");
+ logger.warn("YANG shcema was not successfully retrieved.");
} catch (InterruptedException | ExecutionException e) {
- device.logger.warn("YANG shcema was not successfully retrieved.", e);
+ logger.warn("YANG shcema was not successfully retrieved.", e);
}
return Optional.absent();
}
// it could be identityref Built-In Type
URI namespace = getNamespaceFor(value);
if (namespace != null) {
- return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null);
+ return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null,value);
}
// it is not "prefix:value" but just "value"
return value;
if (xPathParts.length < 2) { // must be at least "/pr:node"
return null;
}
- IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
+ IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(value);
for (int i = 1; i < xPathParts.length; i++) {
String xPathPartTrimmed = xPathParts[i].trim();
if (namespaceAndValue.length == 2) {
String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
if (namespace != null && !namespace.isEmpty()) {
- return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0]);
+ return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0],value);
}
}
// it is not "prefix:value" but just "value"
public final class IdentityValuesDTO {
private final List<IdentityValue> elementData = new ArrayList<>();
+ private final String originValue;
- public IdentityValuesDTO(String namespace, String value, String prefix) {
+ public IdentityValuesDTO(String namespace, String value, String prefix,String originValue) {
elementData.add(new IdentityValue(namespace, value, prefix));
+ this.originValue = originValue;
+ }
+
+ public IdentityValuesDTO(String originValue) {
+ this.originValue = originValue;
}
public IdentityValuesDTO() {
-
+ originValue = null;
}
public void add(String namespace, String value, String prefix) {
public String toString() {
return elementData.toString();
}
+
+ public String getOriginValue() {
+ return originValue;
+ }
public static final class IdentityValue {
input == null ? "null" : input.getClass(), String.valueOf(input));
return null;
} else if (type instanceof LeafrefTypeDefinition) {
+ if (input instanceof IdentityValuesDTO) {
+ return LEAFREF_DEFAULT_CODEC.deserialize(((IdentityValuesDTO)input).getOriginValue());
+ }
return LEAFREF_DEFAULT_CODEC.deserialize(input);
} else if (type instanceof InstanceIdentifierTypeDefinition) {
if (input instanceof IdentityValuesDTO) {
TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
.from(type);
if (typeAwarecodec != null) {
+ if (input instanceof IdentityValuesDTO) {
+ return typeAwarecodec.deserialize(((IdentityValuesDTO)input).getOriginValue());
+ }
return typeAwarecodec.deserialize(String.valueOf(input));
} else {
logger.debug("Codec for type \"" + type.getQName().getLocalName()
@Override
public IdentityValuesDTO serialize(QName data) {
- return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix());
+ return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix(),null);
}
@Override
if (schema.typeDefinition instanceof IdentityrefTypeDefinition) {
if (value instanceof String) {
- inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null)
+ inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null,value as String);
} // else value is already instance of IdentityValuesDTO
}
--- /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.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+
+public class XmlAndJsonToCnSnLeafRefTest extends YangAndXmlAndDataSchemaLoader {
+
+ @BeforeClass
+ public static void initialize() {
+ dataLoad("/leafref/yang", 2, "leafref-module", "cont");
+ }
+
+ @Test
+ public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException {
+ CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/xml/xmldata.xml", XmlToCompositeNodeProvider.INSTANCE);
+ TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
+ verifyContPredicate(cnSn, "/ns:cont/ns:lf1", "/cont/lf1", "/ns:cont/ns:lf1", "../lf1");
+ }
+
+ @Test
+ public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException {
+ CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/json/jsondata.json",
+ JsonToCompositeNodeProvider.INSTANCE);
+ TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
+ verifyContPredicate(cnSn, "/leafref-module:cont/leafref-module:lf1", "/leafref-module:cont/leafref-module:lf1",
+ "/referenced-module:cont/referenced-module:lf1", "/leafref-module:cont/leafref-module:lf1");
+ }
+
+ private void verifyContPredicate(CompositeNode cnSn, String... values) throws URISyntaxException {
+ Object lf2Value = null;
+ Object lf3Value = null;
+ Object lf4Value = null;
+ Object lf5Value = null;
+
+ for (Node<?> node : cnSn.getValue()) {
+ if (node.getNodeType().getLocalName().equals("lf2")) {
+ lf2Value = ((SimpleNode<?>) node).getValue();
+ } else if (node.getNodeType().getLocalName().equals("lf3")) {
+ lf3Value = ((SimpleNode<?>) node).getValue();
+ } else if (node.getNodeType().getLocalName().equals("lf4")) {
+ lf4Value = ((SimpleNode<?>) node).getValue();
+ } else if (node.getNodeType().getLocalName().equals("lf5")) {
+ lf5Value = ((SimpleNode<?>) node).getValue();
+ }
+ }
+ assertEquals(values[0], lf2Value);
+ assertEquals(values[1], lf3Value);
+ assertEquals(values[2], lf4Value);
+ assertEquals(values[3], lf5Value);
+ }
+
+}
--- /dev/null
+{
+ "leafref-module:cont" : {
+ "lf4" : "/referenced-module:cont/referenced-module:lf1",
+ "lf2" : "/leafref-module:cont/leafref-module:lf1",
+ "lf3" : "/leafref-module:cont/leafref-module:lf1",
+ "lf5" : "/leafref-module:cont/leafref-module:lf1"
+ }
+}
\ No newline at end of file
--- /dev/null
+<cont xmlns="leafref:module">
+ <lf4 xmlns:ns="referenced:module">/ns:cont/ns:lf1</lf4>
+ <lf2 xmlns:ns="leafref:module">/ns:cont/ns:lf1</lf2>
+ <lf3 xmlns:ns="leafref:module">/cont/lf1</lf3>
+ <lf5 xmlns:ns="leafref:module">../lf1</lf5>
+</cont>
--- /dev/null
+module leafref-module {
+ namespace "leafref:module";
+
+
+ prefix "lfrfmodule";
+
+ import referenced-module { prefix refmod; revision-date 2014-04-17;}
+
+
+ revision 2014-04-17 {
+ }
+
+
+ container cont {
+ leaf lf1 {
+ type instance-identifier;
+ }
+
+ leaf lf2 {
+ type leafref {
+ path "../lf1";
+ }
+ }
+
+ leaf lf3 {
+ type leafref {
+ path "/refmod:cont/refmod:lf1";
+ }
+ }
+
+ leaf lf4 {
+ type leafref {
+ path "/cont/lf1";
+ }
+ }
+
+ leaf lf5 {
+ type leafref {
+ path "../lf1";
+ }
+ }
+
+ }
+}
\ No newline at end of file
--- /dev/null
+module referenced-module {
+ namespace "referenced:module";
+
+ prefix "refmodule";
+ revision 2014-04-17 {
+ }
+
+ container cont {
+ leaf lf1 {
+ type instance-identifier;
+ }
+ }
+}
\ No newline at end of file
private static final Logger logger = LoggerFactory.getLogger(AbstractListeningStatsTracker.class);
private ListenerRegistration<?> reg;
- protected AbstractListeningStatsTracker(FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ protected AbstractListeningStatsTracker(FlowCapableContext context) {
+ super(context);
}
protected abstract InstanceIdentifier<?> listenPath();
abstract class AbstractStatsTracker<I, K> {
private static final Logger logger = LoggerFactory.getLogger(AbstractStatsTracker.class);
+
+ private static final int WAIT_FOR_REQUEST_CYCLE = 2;
+
private final FutureCallback<RpcResult<? extends TransactionAware>> callback =
new FutureCallback<RpcResult<? extends TransactionAware>>() {
@Override
private final Map<K, Long> trackedItems = new HashMap<>();
private final FlowCapableContext context;
- private final long lifetimeNanos;
+ private long requestCounter;
- protected AbstractStatsTracker(final FlowCapableContext context, final long lifetimeNanos) {
+ protected AbstractStatsTracker(final FlowCapableContext context) {
this.context = Preconditions.checkNotNull(context);
- this.lifetimeNanos = lifetimeNanos;
+ this.requestCounter = 0;
}
protected final InstanceIdentifierBuilder<Node> getNodeIdentifierBuilder() {
return context.startDataModification();
}
+ public final synchronized void increaseRequestCounter(){
+ this.requestCounter++;
+ }
protected abstract void cleanupSingleStat(DataModificationTransaction trans, K item);
protected abstract K updateSingleStat(DataModificationTransaction trans, I item);
+ public abstract void request();
public final synchronized void updateStats(List<I> list) {
- final Long expiryTime = System.nanoTime() + lifetimeNanos;
+
final DataModificationTransaction trans = startTransaction();
for (final I item : list) {
- trackedItems.put(updateSingleStat(trans, item), expiryTime);
+ trackedItems.put(updateSingleStat(trans, item), requestCounter);
}
trans.commit();
}
- public final synchronized void cleanup(final DataModificationTransaction trans, long now) {
+ /**
+ * Statistics will be cleaned up if not update in last two request cycles.
+ * @param trans
+ */
+ public final synchronized void cleanup(final DataModificationTransaction trans) {
for (Iterator<Entry<K, Long>> it = trackedItems.entrySet().iterator();it.hasNext();){
Entry<K, Long> e = it.next();
- if (now > e.getValue()) {
+ if (requestCounter >= e.getValue()+WAIT_FOR_REQUEST_CYCLE) {
cleanupSingleStat(trans, e.getKey());
it.remove();
}
*/
package org.opendaylight.controller.md.statistics.manager;
+import java.util.Collection;
import java.util.Map.Entry;
import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatisticsMapList, FlowStatsEntry> {
private static final Logger logger = LoggerFactory.getLogger(FlowStatsTracker.class);
private final OpendaylightFlowStatisticsService flowStatsService;
+ private FlowTableStatsTracker flowTableStats;
private int unaccountedFlowsCounter = 1;
- FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context) {
+ super(context);
this.flowStatsService = flowStatsService;
}
+ FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context, FlowTableStatsTracker flowTableStats) {
+ this(flowStatsService, context);
+ this.flowTableStats = flowTableStats;
+ }
@Override
protected void cleanupSingleStat(DataModificationTransaction trans, FlowStatsEntry item) {
return "Flow";
}
+ @Override
+ public void request() {
+ // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest()
+ // comes back -- we do not have any tables anyway.
+ final Collection<TableKey> tables = flowTableStats.getTables();
+ logger.debug("Node {} supports {} table(s)", this.getNodeRef(), tables.size());
+ for (final TableKey key : tables) {
+ logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), this.getNodeRef());
+ this.requestAggregateFlows(key);
+ }
+
+ this.requestAllFlowsAllTables();
+
+ }
public void requestAllFlowsAllTables() {
if (flowStatsService != null) {
final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder();
private final Set<TableKey> tables = Collections.unmodifiableSet(privateTables);
private final OpendaylightFlowTableStatisticsService flowTableStatsService;
- FlowTableStatsTracker(OpendaylightFlowTableStatisticsService flowTableStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ FlowTableStatsTracker(OpendaylightFlowTableStatisticsService flowTableStatsService, final FlowCapableContext context) {
+ super(context);
this.flowTableStatsService = flowTableStatsService;
}
return item;
}
+ @Override
public void request() {
if (flowTableStatsService != null) {
final GetFlowTablesStatisticsInputBuilder input = new GetFlowTablesStatisticsInputBuilder();
private static final Logger logger = LoggerFactory.getLogger(GroupDescStatsTracker.class);
private final OpendaylightGroupStatisticsService groupStatsService;
- public GroupDescStatsTracker(OpendaylightGroupStatisticsService groupStatsService, final FlowCapableContext context, final long lifetimeNanos) {
- super(context, lifetimeNanos);
+ public GroupDescStatsTracker(OpendaylightGroupStatisticsService groupStatsService, final FlowCapableContext context) {
+ super(context);
this.groupStatsService = groupStatsService;
}
return "Group Descriptor";
}
+ @Override
public void request() {
if (groupStatsService != null) {
final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder();
private static final Logger logger = LoggerFactory.getLogger(GroupStatsTracker.class);
private final OpendaylightGroupStatisticsService groupStatsService;
- GroupStatsTracker(OpendaylightGroupStatisticsService groupStatsService, FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ GroupStatsTracker(OpendaylightGroupStatisticsService groupStatsService, FlowCapableContext context) {
+ super(context);
this.groupStatsService = Preconditions.checkNotNull(groupStatsService);
}
return "Group";
}
+ @Override
public void request() {
final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
input.setNode(getNodeRef());
private static final Logger logger = LoggerFactory.getLogger(MeterConfigStatsTracker.class);
private final OpendaylightMeterStatisticsService meterStatsService;
- protected MeterConfigStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ protected MeterConfigStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context) {
+ super(context);
this.meterStatsService = meterStatsService;
}
return item;
}
+ @Override
public void request() {
if (meterStatsService != null) {
GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder();
private static final Logger logger = LoggerFactory.getLogger(MeterStatsTracker.class);
private final OpendaylightMeterStatisticsService meterStatsService;
- MeterStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ MeterStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context) {
+ super(context);
this.meterStatsService = meterStatsService;
}
return item;
}
+ @Override
public void request() {
if (meterStatsService != null) {
GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder();
private static final Logger logger = LoggerFactory.getLogger(NodeConnectorStatsTracker.class);
private final OpendaylightPortStatisticsService portStatsService;
- NodeConnectorStatsTracker(final OpendaylightPortStatisticsService portStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ NodeConnectorStatsTracker(final OpendaylightPortStatisticsService portStatsService, final FlowCapableContext context) {
+ super(context);
this.portStatsService = portStatsService;
}
return item;
}
+ @Override
public void request() {
if (portStatsService != null) {
final GetAllNodeConnectorsStatisticsInputBuilder input = new GetAllNodeConnectorsStatisticsInputBuilder();
*/
package org.opendaylight.controller.md.statistics.manager;
-import java.util.Collection;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
private static final int NUMBER_OF_WAIT_CYCLES = 2;
private final MultipartMessageManager msgManager;
+ private final StatisticsRequestScheduler srScheduler;
private final InstanceIdentifier<Node> targetNodeIdentifier;
private final FlowStatsTracker flowStats;
private final FlowTableStatsTracker flowTableStats;
final OpendaylightGroupStatisticsService groupStatsService,
final OpendaylightMeterStatisticsService meterStatsService,
final OpendaylightPortStatisticsService portStatsService,
- final OpendaylightQueueStatisticsService queueStatsService) {
+ final OpendaylightQueueStatisticsService queueStatsService,
+ final StatisticsRequestScheduler srScheduler) {
this.dps = Preconditions.checkNotNull(dps);
this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
+ this.srScheduler = Preconditions.checkNotNull(srScheduler);
this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
this.targetNodeRef = new NodeRef(targetNodeIdentifier);
final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
msgManager = new MultipartMessageManager(lifetimeNanos);
- flowStats = new FlowStatsTracker(flowStatsService, this, lifetimeNanos);
- flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this, lifetimeNanos);
- groupDescStats = new GroupDescStatsTracker(groupStatsService, this, lifetimeNanos);
- groupStats = new GroupStatsTracker(groupStatsService, this, lifetimeNanos);
- meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this, lifetimeNanos);
- meterStats = new MeterStatsTracker(meterStatsService, this, lifetimeNanos);
- nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this, lifetimeNanos);
- queueStats = new QueueStatsTracker(queueStatsService, this, lifetimeNanos);
+ flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this);
+ flowStats = new FlowStatsTracker(flowStatsService, this, flowTableStats);
+ groupDescStats = new GroupDescStatsTracker(groupStatsService, this);
+ groupStats = new GroupStatsTracker(groupStatsService, this);
+ meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this);
+ meterStats = new MeterStatsTracker(meterStatsService, this);
+ nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this);
+ queueStats = new QueueStatsTracker(queueStatsService, this);
}
public NodeKey getTargetNodeKey() {
@Override
public DataModificationTransaction startDataModification() {
- return dps.beginTransaction();
+ DataModificationTransaction dmt = dps.beginTransaction();
+ dmt.registerListener(this.srScheduler);
+ return dmt;
}
public synchronized void updateGroupDescStats(TransactionAware transaction, List<GroupDescStats> list) {
public synchronized void updateAggregateFlowStats(TransactionAware transaction, AggregateFlowStatistics flowStats) {
final Short tableId = msgManager.isExpectedTableTransaction(transaction);
if (tableId != null) {
- final DataModificationTransaction trans = dps.beginTransaction();
+ final DataModificationTransaction trans = this.startDataModification();
InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
}
public synchronized void updateGroupFeatures(GroupFeatures notification) {
- final DataModificationTransaction trans = dps.beginTransaction();
+ final DataModificationTransaction trans = this.startDataModification();
final NodeBuilder nodeData = new NodeBuilder();
nodeData.setKey(targetNodeKey);
}
public synchronized void updateMeterFeatures(MeterFeatures features) {
- final DataModificationTransaction trans = dps.beginTransaction();
+ final DataModificationTransaction trans = this.startDataModification();
final NodeBuilder nodeData = new NodeBuilder();
nodeData.setKey(targetNodeKey);
}
public synchronized void cleanStaleStatistics() {
- final DataModificationTransaction trans = dps.beginTransaction();
- final long now = System.nanoTime();
-
- flowStats.cleanup(trans, now);
- groupDescStats.cleanup(trans, now);
- groupStats.cleanup(trans, now);
- meterConfigStats.cleanup(trans, now);
- meterStats.cleanup(trans, now);
- nodeConnectorStats.cleanup(trans, now);
- queueStats.cleanup(trans, now);
+ final DataModificationTransaction trans = this.startDataModification();
+
+ flowStats.cleanup(trans);
+ groupDescStats.cleanup(trans);
+ groupStats.cleanup(trans);
+ meterConfigStats.cleanup(trans);
+ meterStats.cleanup(trans);
+ nodeConnectorStats.cleanup(trans);
+ queueStats.cleanup(trans);
msgManager.cleanStaleTransactionIds();
trans.commit();
public synchronized void requestPeriodicStatistics() {
logger.debug("Send requests for statistics collection to node : {}", targetNodeKey);
- flowTableStats.request();
-
- // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest()
- // comes back -- we do not have any tables anyway.
- final Collection<TableKey> tables = flowTableStats.getTables();
- logger.debug("Node {} supports {} table(s)", targetNodeKey, tables.size());
- for (final TableKey key : tables) {
- logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), targetNodeKey);
- flowStats.requestAggregateFlows(key);
- }
-
- flowStats.requestAllFlowsAllTables();
- nodeConnectorStats.request();
- groupStats.request();
- groupDescStats.request();
- meterStats.request();
- meterConfigStats.request();
- queueStats.request();
+ this.srScheduler.addRequestToSchedulerQueue(flowTableStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(flowStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(nodeConnectorStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(groupStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(groupDescStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(meterStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(meterConfigStats);
+
+ this.srScheduler.addRequestToSchedulerQueue(queueStats);
}
-
+
public synchronized void start(final Timer timer) {
flowStats.start(dps);
groupDescStats.start(dps);
private static final Logger logger = LoggerFactory.getLogger(QueueStatsTracker.class);
private final OpendaylightQueueStatisticsService queueStatsService;
- QueueStatsTracker(OpendaylightQueueStatisticsService queueStatsService, final FlowCapableContext context, long lifetimeNanos) {
- super(context, lifetimeNanos);
+ QueueStatsTracker(OpendaylightQueueStatisticsService queueStatsService, final FlowCapableContext context) {
+ super(context);
this.queueStatsService = queueStatsService;
}
return queueEntry;
}
+ @Override
public void request() {
if (queueStatsService != null) {
GetAllQueuesStatisticsFromAllPortsInputBuilder input = new GetAllQueuesStatisticsFromAllPortsInputBuilder();
private OpendaylightFlowTableStatisticsService flowTableStatsService;
private OpendaylightQueueStatisticsService queueStatsService;
+
+ private final StatisticsRequestScheduler srScheduler;
public StatisticsProvider(final DataProviderService dataService) {
this.dps = Preconditions.checkNotNull(dataService);
+ this.srScheduler = new StatisticsRequestScheduler();
}
private final StatisticsListener updateCommiter = new StatisticsListener(StatisticsProvider.this);
portStatsService = rpcRegistry.getRpcService(OpendaylightPortStatisticsService.class);
flowTableStatsService = rpcRegistry.getRpcService(OpendaylightFlowTableStatisticsService.class);
queueStatsService = rpcRegistry.getRpcService(OpendaylightQueueStatisticsService.class);
-
+ this.srScheduler.start();
+
// Start receiving notifications
this.listenerRegistration = nps.registerNotificationListener(this.updateCommiter);
final NodeStatisticsHandler h = new NodeStatisticsHandler(dps, key,
flowStatsService, flowTableStatsService, groupStatsService,
- meterStatsService, portStatsService, queueStatsService);
+ meterStatsService, portStatsService, queueStatsService,srScheduler);
final NodeStatisticsHandler old = handlers.putIfAbsent(key.getId(), h);
if (old == null) {
spLogger.debug("Started node handler for {}", key.getId());
--- /dev/null
+/*
+ * Copyright IBM Corporation, 2013. 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.statistics.manager;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Main responsibility of the class is to check the MD-SAL data store read/write
+ * transaction accumulation level and send statistics request if number of pending
+ * read/write transactions are zero.
+ * @author avishnoi@in.ibm.com
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class StatisticsRequestScheduler implements DataTransactionListener {
+
+ private static final Logger srsLogger = LoggerFactory.getLogger(StatisticsRequestScheduler.class);
+ private final Timer timer = new Timer("request-monitor", true);
+
+ // We need ordered retrieval, and O(1) contains operation
+ private final Map<AbstractStatsTracker,Integer> requestQueue =
+ Collections.synchronizedMap(new LinkedHashMap<AbstractStatsTracker,Integer>());
+
+ private Long PendingTransactions;
+
+ private long lastRequestTime = System.nanoTime();
+
+ private static final long REQUEST_MONITOR_INTERVAL = 1000;
+
+ private final TimerTask task = new TimerTask() {
+ @Override
+ public void run() {
+ long now = System.nanoTime();
+ if(now > lastRequestTime+TimeUnit.MILLISECONDS.toNanos(REQUEST_MONITOR_INTERVAL)){
+ requestStatistics();
+ }
+ }
+ };
+
+ public StatisticsRequestScheduler(){
+ PendingTransactions = (long) 0;
+ }
+
+ public void addRequestToSchedulerQueue(AbstractStatsTracker statsRequest){
+ requestQueue.put(statsRequest, null);
+ }
+
+ public AbstractStatsTracker getNextRequestFromSchedulerQueue(){
+ //Remove first element
+ AbstractStatsTracker stats = null;
+ synchronized(requestQueue){
+ Iterator<Map.Entry<AbstractStatsTracker, Integer>> nodesItr = requestQueue.entrySet().iterator();
+ if(nodesItr.hasNext()){
+ stats = nodesItr.next().getKey();
+ srsLogger.debug("{} chosen up for execution",stats.getNodeRef());
+ nodesItr.remove();
+ return stats;
+ }
+ }
+ return stats;
+ }
+
+ private void requestStatistics(){
+ AbstractStatsTracker stats = this.getNextRequestFromSchedulerQueue();
+ if(stats != null) {
+ stats.request();
+ stats.increaseRequestCounter();
+ }
+ }
+ @Override
+ public void onStatusUpdated(DataModificationTransaction transaction, TransactionStatus status) {
+
+ AbstractStatsTracker stats = null;
+ synchronized(PendingTransactions){
+ switch(status){
+ case SUBMITED:
+ this.PendingTransactions++;
+ break;
+ case COMMITED:
+ case FAILED:
+ this.PendingTransactions--;
+ if(PendingTransactions == 0){
+ lastRequestTime = System.nanoTime();
+ stats = this.getNextRequestFromSchedulerQueue();
+ }
+ srsLogger.debug("Pending MD-SAL transactions : {} & Scheduler queue size : {}",this.PendingTransactions,this.requestQueue.size());
+ break;
+ default:
+ break;
+ }
+ }
+ if(stats != null){
+ stats.request();
+ stats.increaseRequestCounter();
+ }
+ }
+
+ public void start(){
+ timer.schedule(task, 0, REQUEST_MONITOR_INTERVAL);
+ }
+}
<groupId>equinoxSDK381</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
<manifestLocation>${project.basedir}/META-INF</manifestLocation>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
</plugins>
</build>
<scm>
--- /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.md.controller.topology.lldp;
+
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.osgi.framework.BundleContext;
+
+public class LLDPActivator extends AbstractBindingAwareProvider {
+ private static LLDPDiscoveryProvider provider = new LLDPDiscoveryProvider();
+
+ public void onSessionInitiated(final ProviderContext session) {
+ DataProviderService dataService = session.<DataProviderService>getSALService(DataProviderService.class);
+ provider.setDataService(dataService);
+ NotificationProviderService notificationService = session.<NotificationProviderService>getSALService(NotificationProviderService.class);
+ provider.setNotificationService(notificationService);
+ provider.start();
+ }
+
+ protected void stopImpl(final BundleContext context) {
+ provider.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.md.controller.topology.lldp
-
-import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.osgi.framework.BundleContext
-
-class LLDPActivator extends AbstractBindingAwareProvider {
-
- static var LLDPDiscoveryProvider provider = new LLDPDiscoveryProvider();
-
- override onSessionInitiated(ProviderContext session) {
- provider.dataService = session.getSALService(DataProviderService)
- provider.notificationService = session.getSALService(NotificationProviderService)
- provider.start();
- }
-
- override protected stopImpl(BundleContext context) {
- provider.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.md.controller.topology.lldp;
+
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LLDPDiscoveryProvider implements AutoCloseable {
+ private final static Logger LOG = LoggerFactory.getLogger(LLDPDiscoveryProvider.class);
+ private DataProviderService dataService;
+ private NotificationProviderService notificationService;
+ private final LLDPDiscoveryListener commiter = new LLDPDiscoveryListener(LLDPDiscoveryProvider.this);
+ private Registration<NotificationListener> listenerRegistration;
+
+ public DataProviderService getDataService() {
+ return this.dataService;
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public NotificationProviderService getNotificationService() {
+ return this.notificationService;
+ }
+
+ public void setNotificationService(final NotificationProviderService notificationService) {
+ this.notificationService = notificationService;
+ }
+
+ public void start() {
+ Registration<NotificationListener> registerNotificationListener = this.getNotificationService().registerNotificationListener(this.commiter);
+ this.listenerRegistration = registerNotificationListener;
+ LLDPLinkAger.getInstance().setManager(this);
+ LOG.info("LLDPDiscoveryListener Started.");
+ }
+
+ public void close() {
+ try {
+ LOG.info("LLDPDiscoveryListener stopped.");
+ if (this.listenerRegistration!=null) {
+ this.listenerRegistration.close();
+ }
+ LLDPLinkAger.getInstance().close();
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+}
+++ /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.md.controller.topology.lldp
-
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.NotificationListener
-import org.slf4j.LoggerFactory
-
-class LLDPDiscoveryProvider implements AutoCloseable {
-
-
- static val LOG = LoggerFactory.getLogger(LLDPDiscoveryProvider);
-
- @Property
- DataProviderService dataService;
-
- @Property
- NotificationProviderService notificationService;
-
- val LLDPDiscoveryListener commiter = new LLDPDiscoveryListener(this);
-
- Registration<NotificationListener> listenerRegistration
-
- def void start() {
- listenerRegistration = notificationService.registerNotificationListener(commiter);
- LLDPLinkAger.instance.manager = this;
- LOG.info("LLDPDiscoveryListener Started.");
-
- }
-
- override close() {
- LOG.info("LLDPDiscoveryListener stopped.");
- listenerRegistration?.close();
- LLDPLinkAger.instance.close();
- }
-
-}
-
-
public abstract class AttributeIfcSwitchStatement<T> {
- protected AttributeIfc lastAttribute;
+ private AttributeIfc lastAttribute;
public T switchAttribute(AttributeIfc attributeIfc) {
return caseJavaUnionAttribute(openType);
} else if(((JavaAttribute)attributeIfc).isIdentityRef()) {
return caseJavaIdentityRefAttribute(openType);
- } else
+ } else {
return caseJavaAttribute(openType);
+ }
} catch (UnknownOpenTypeException e) {
throw getIllegalArgumentException(attributeIfc);
}
throw getIllegalArgumentException(attributeIfc);
}
+ public AttributeIfc getLastAttribute() {
+ return lastAttribute;
+ }
+
protected T caseJavaIdentityRefAttribute(OpenType<?> openType) {
return caseJavaAttribute(openType);
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
import javax.management.openmbean.OpenType;
}
public void resolveValue(AttributeResolvingStrategy<?, ? extends OpenType<?>> attributeResolvingStrategy,
- String attrName) {
+ String attrName) throws NetconfDocumentedException {
resolvedValue = attributeResolvingStrategy.parseAttribute(attrName, value);
Optional<?> resolvedDefault = attributeResolvingStrategy.parseAttribute(attrName, dafaultValue);
resolvedDefaultValue = resolvedDefault.isPresent() ? resolvedDefault.get() : null;
public static String checkPrefixAndExtractServiceName(XmlElement typeElement, Map.Entry<String, String> prefixNamespace) throws NetconfDocumentedException {
String serviceName = typeElement.getTextContent();
- Preconditions.checkState(prefixNamespace.equals("") == false, "Service %s value not prefixed with namespace",
+ Preconditions.checkState(!prefixNamespace.equals(""), "Service %s value not prefixed with namespace",
XmlNetconfConstants.TYPE_KEY);
String prefix = prefixNamespace.getKey() + PREFIX_SEPARATOR;
Preconditions.checkState(serviceName.startsWith(prefix),
@Override
protected AttributeReadingStrategy caseJavaBinaryAttribute(OpenType<?> openType) {
- return new SimpleBinaryAttributeReadingStrategy(lastAttribute.getNullableDefault());
+ return new SimpleBinaryAttributeReadingStrategy(getLastAttribute().getNullableDefault());
}
@Override
protected AttributeReadingStrategy caseJavaUnionAttribute(OpenType<?> openType) {
String mappingKey = JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
- return new SimpleUnionAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey);
+ return new SimpleUnionAttributeReadingStrategy(getLastAttribute().getNullableDefault(), mappingKey);
}
@Override
public AttributeReadingStrategy caseJavaSimpleAttribute(SimpleType<?> openType) {
- return new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault());
+ return new SimpleAttributeReadingStrategy(getLastAttribute().getNullableDefault());
}
@Override
public AttributeReadingStrategy caseJavaArrayAttribute(ArrayType<?> openType) {
- SimpleAttributeReadingStrategy innerStrategy = new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault());
- return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
+ SimpleAttributeReadingStrategy innerStrategy = new SimpleAttributeReadingStrategy(getLastAttribute().getNullableDefault());
+ return new ArrayAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategy);
}
@Override
public AttributeReadingStrategy caseJavaCompositeAttribute(CompositeType openType) {
Preconditions.checkState(openType.keySet().size() == 1, "Unexpected number of elements for open type %s, should be 1", openType);
String mappingKey = openType.keySet().iterator().next();
- return new SimpleCompositeAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey);
+ return new SimpleCompositeAttributeReadingStrategy(getLastAttribute().getNullableDefault(), mappingKey);
}
@Override
Set<String> keys = ((CompositeType) openType).keySet();
Preconditions.checkState(keys.size() == 1, "Unexpected number of elements for open type %s, should be 1", openType);
String mappingKey = keys.iterator().next();
- return new SimpleIdentityRefAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey, identityMap);
+ return new SimpleIdentityRefAttributeReadingStrategy(getLastAttribute().getNullableDefault(), mappingKey, identityMap);
}
@Override
protected AttributeReadingStrategy caseDependencyAttribute(SimpleType<?> openType) {
- return new ObjectNameAttributeReadingStrategy(lastAttribute.getNullableDefault());
+ return new ObjectNameAttributeReadingStrategy(getLastAttribute().getNullableDefault());
}
@Override
protected AttributeReadingStrategy caseTOAttribute(CompositeType openType) {
- Preconditions.checkState(lastAttribute instanceof TOAttribute);
- Map<String, AttributeIfc> inner = ((TOAttribute)lastAttribute).getYangPropertiesToTypesMap();
+ Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
+ Map<String, AttributeIfc> inner = ((TOAttribute)getLastAttribute()).getYangPropertiesToTypesMap();
Map<String, AttributeReadingStrategy> innerStrategies = Maps.newHashMap();
innerStrategies.put(innerAttrEntry.getKey(), innerStrat);
}
- return new CompositeAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategies);
+ return new CompositeAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategies);
}
@Override
protected AttributeReadingStrategy caseListAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListAttribute);
- AttributeReadingStrategy innerStrategy = prepareReadingStrategy(key, ((ListAttribute) lastAttribute).getInnerAttribute());
- return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
+ Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
+ AttributeReadingStrategy innerStrategy = prepareReadingStrategy(key, ((ListAttribute) getLastAttribute()).getInnerAttribute());
+ return new ArrayAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategy);
}
@Override
protected AttributeReadingStrategy caseListDependeciesAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
AttributeReadingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME);
- return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
+ return new ArrayAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategy);
}
}
revision = date;
}
}
- } else
+ } else {
revision = revisions.keySet().iterator().next();
-
+ }
return QName.create(URI.create(namespace), revision, localName).toString();
}
@Override
public Optional<List<Object>> mapAttribute(Object value) {
- if (value == null)
+ if (value == null){
return Optional.absent();
+ }
Preconditions.checkArgument(value.getClass().isArray(), "Value has to be instanceof Array ");
for (int i = 0; i < Array.getLength(value); i++) {
Object innerValue = Array.get(value, i);
- // String expectedClassName =
- // getOpenType().getElementOpenType().getClassName();
- // String realClassName = value.getClass().getName();
-
- // Preconditions.checkState(realClassName.contains(expectedClassName),
- // "Element in collection/array should be of type " +
- // expectedClassName + " but was "
- // + realClassName + " for attribute: " + getOpenType());
-
Optional<?> mapAttribute = innerElementStrategy.mapAttribute(innerValue);
- if (mapAttribute.isPresent())
+ if (mapAttribute.isPresent()){
retVal.add(mapAttribute.get());
+ }
}
return Optional.of(retVal);
@Override
public Optional<Map<String, Object>> mapAttribute(Object value) {
- if (value == null)
+ if (value == null){
return Optional.absent();
+ }
Util.checkType(value, CompositeDataSupport.class);
for (String jmxName : jmxToJavaNameMapping.keySet()) {
Optional<?> mapped = mapInnerAttribute(compositeData, jmxName, expectedType.getDescription(jmxName));
- if(mapped.isPresent())
+ if(mapped.isPresent()){
retVal.put(jmxToJavaNameMapping.get(jmxName), mapped.get());
+ }
}
return Optional.of(retVal);
AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = innerStrategies
.get(jmxName);
- Optional<?> mapAttribute = attributeMappingStrategy.mapAttribute(innerValue);
- return mapAttribute;
+ return attributeMappingStrategy.mapAttribute(innerValue);
}
}
@Override
protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseDependencyAttribute(
SimpleType<?> openType) {
- return new ObjectNameAttributeMappingStrategy(openType, dependencyTracker,
+ return new ObjectNameAttributeMappingStrategy(openType,
serviceNameOfDepAttr, namespaceOfDepAttr);
}
protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseTOAttribute(CompositeType openType) {
Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies = Maps.newHashMap();
- Preconditions.checkState(lastAttribute instanceof TOAttribute);
- TOAttribute lastTO = (TOAttribute) lastAttribute;
+ Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
+ TOAttribute lastTO = (TOAttribute) getLastAttribute();
- for (Entry<String, AttributeIfc> innerAttrEntry : ((TOAttribute)lastAttribute).getJmxPropertiesToTypesMap().entrySet()) {
+ for (Entry<String, AttributeIfc> innerAttrEntry : ((TOAttribute)getLastAttribute()).getJmxPropertiesToTypesMap().entrySet()) {
innerStrategies.put(innerAttrEntry.getKey(), prepareStrategy(innerAttrEntry.getValue()));
}
@Override
protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseListAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
return new ArrayAttributeMappingStrategy(openType,
- prepareStrategy(((ListAttribute) lastAttribute).getInnerAttribute()));
+ prepareStrategy(((ListAttribute) getLastAttribute()).getInnerAttribute()));
}
@Override
protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseListDependeciesAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
return new ArrayAttributeMappingStrategy(openType, caseDependencyAttribute(SimpleType.OBJECTNAME));
}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
-import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
-
import javax.management.ObjectName;
import javax.management.openmbean.SimpleType;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
public class ObjectNameAttributeMappingStrategy extends
AbstractAttributeMappingStrategy<ObjectNameAttributeMappingStrategy.MappedDependency, SimpleType<?>> {
- private final ServiceRegistryWrapper tracker;
private final String serviceName;
private final String namespace;
- public ObjectNameAttributeMappingStrategy(SimpleType<?> openType, ServiceRegistryWrapper dependencyTracker, String serviceName, String namespace) {
+ public ObjectNameAttributeMappingStrategy(SimpleType<?> openType, String serviceName, String namespace) {
super(openType);
- this.tracker = dependencyTracker;
this.serviceName = serviceName;
this.namespace = namespace;
}
@Override
public Optional<MappedDependency> mapAttribute(Object value) {
- if (value == null)
+ if (value == null){
return Optional.absent();
+ }
String expectedClass = getOpenType().getClassName();
String realClass = value.getClass().getName();
@Override
public Optional<String> mapAttribute(Object value) {
- if (value == null)
+ if (value == null){
return Optional.absent();
+ }
String expectedClass = getOpenType().getClassName();
String realClass = value.getClass().getName();
@Override
protected Optional<?> mapInnerAttribute(CompositeDataSupport compositeData, String jmxName, String description) {
- if(description.equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION) == false)
+ if(!description.equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION)){
return Optional.absent();
-
+ }
return super.mapInnerAttribute(compositeData, jmxName, description);
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@Override
- public Optional<Object> parseAttribute(String attrName, Object value) {
+ public Optional<Object> parseAttribute(String attrName, Object value) throws NetconfDocumentedException {
if (value == null) {
return Optional.absent();
}
if (innerTypeResolvingStrategy.getOpenType() instanceof CompositeType) {
innerTypeClass = CompositeDataSupport.class;
- } else
+ } else {
try {
innerTypeClass = Class.forName(getOpenType().getElementOpenType().getClassName());
} catch (ClassNotFoundException e) {
- throw new RuntimeException("Unable to locate class for "
+ throw new IllegalStateException("Unable to locate class for "
+ getOpenType().getElementOpenType().getClassName(), e);
}
+ }
Object parsedArray = null;
if (getOpenType().isPrimitiveArray()) {
Class<?> primitiveType = getPrimitiveType(innerTypeClass);
parsedArray = Array.newInstance(primitiveType, valueList.size());
- } else
+ } else {
parsedArray = Array.newInstance(innerTypeClass, valueList.size());
+ }
int i = 0;
for (Object innerValue : valueList) {
Optional<?> parsedElement = innerTypeResolvingStrategy.parseAttribute(attrName + "_" + i, innerValue);
-
- if (!parsedElement.isPresent())
+ if (!parsedElement.isPresent()){
continue;
-
+ }
Array.set(parsedArray, i, parsedElement.get());
- // parsedArray[i] = parsedElement.get();
i++;
}
try {
return (Class<?>) innerTypeClass.getField("TYPE").get(null);
} catch (Exception e) {
- throw new RuntimeException("Unable to determine primitive type to " + innerTypeClass);
+ throw new IllegalStateException("Unable to determine primitive type to " + innerTypeClass);
}
}
import com.google.common.base.Optional;
import javax.management.openmbean.OpenType;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
/**
* Create real object from String or Map that corresponds to given opentype.
public interface AttributeResolvingStrategy<T, O extends OpenType<?>> {
O getOpenType();
- Optional<T> parseAttribute(String attrName, Object value);
+ Optional<T> parseAttribute(String attrName, Object value) throws NetconfDocumentedException;
}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@Override
- public Optional<CompositeDataSupport> parseAttribute(String attrName, Object value) {
+ public Optional<CompositeDataSupport> parseAttribute(String attrName, Object value) throws NetconfDocumentedException {
if (value == null) {
return Optional.absent();
try {
parsedValue = new CompositeDataSupport(getOpenType(), items);
} catch (OpenDataException e) {
- throw new RuntimeException("An error occured during restoration of composite type " + this
+ throw new IllegalStateException("An error occured during restoration of composite type " + this
+ " for attribute " + attrName + " from value " + value, e);
}
@Override
protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseTOAttribute(CompositeType openType) {
- Preconditions.checkState(lastAttribute instanceof TOAttribute);
- TOAttribute toAttribute = (TOAttribute) lastAttribute;
+ Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
+ TOAttribute toAttribute = (TOAttribute) getLastAttribute();
Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap = Maps.newHashMap();
@Override
protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseListAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListAttribute);
- AttributeIfc innerAttribute = ((ListAttribute) lastAttribute).getInnerAttribute();
+ Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
+ AttributeIfc innerAttribute = ((ListAttribute) getLastAttribute()).getInnerAttribute();
return new ArrayAttributeResolvingStrategy(prepareStrategy(innerAttribute), openType);
}
@Override
protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseListDependeciesAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
return new ArrayAttributeResolvingStrategy(caseDependencyAttribute(SimpleType.OBJECTNAME), openType);
}
import com.google.common.base.Optional;
import com.google.common.collect.Maps;
+import java.lang.reflect.InvocationTargetException;
+import java.text.ParseException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@Override
- public Optional<Object> parseAttribute(String attrName, Object value) {
+ public Optional<Object> parseAttribute(String attrName, Object value) throws NetconfDocumentedException {
if (value == null) {
return Optional.absent();
}
}
static interface Resolver {
- Object resolveObject(Class<?> type, String attrName, String value);
+ Object resolveObject(Class<?> type, String attrName, String value) throws NetconfDocumentedException;
}
static class DefaultResolver implements Resolver {
@Override
- public Object resolveObject(Class<?> type, String attrName, String value) {
+ public Object resolveObject(Class<?> type, String attrName, String value) throws NetconfDocumentedException {
try {
- Object parsedValue = parseObject(type, value);
- return parsedValue;
+ return parseObject(type, value);
} catch (Exception e) {
- throw new RuntimeException("Unable to resolve attribute " + attrName + " from " + value, e);
+ throw new NetconfDocumentedException("Unable to resolve attribute " + attrName + " from " + value,
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
}
- protected Object parseObject(Class<?> type, String value) throws Exception {
- Method method = type.getMethod("valueOf", String.class);
- Object parsedValue = method.invoke(null, value);
- return parsedValue;
+ protected Object parseObject(Class<?> type, String value) throws NetconfDocumentedException {
+ Method method = null;
+ try {
+ method = type.getMethod("valueOf", String.class);
+ return method.invoke(null, value);
+ } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+ logger.trace("Error parsing object {}",e);
+ throw new NetconfDocumentedException("Error parsing object.",
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
}
static class StringResolver extends DefaultResolver {
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
+ protected Object parseObject(Class<?> type, String value) {
return value;
}
}
static class BigIntegerResolver extends DefaultResolver {
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
+ protected Object parseObject(Class<?> type, String value) {
return new BigInteger(value);
}
}
static class BigDecimalResolver extends DefaultResolver {
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
+ protected Object parseObject(Class<?> type, String value) {
return new BigDecimal(value);
}
}
static class CharResolver extends DefaultResolver {
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
+ protected Object parseObject(Class<?> type, String value) {
return new Character(value.charAt(0));
}
}
static class DateResolver extends DefaultResolver {
-
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
- return Util.readDate(value);
+ protected Object parseObject(Class<?> type, String value) throws NetconfDocumentedException {
+ try {
+ return Util.readDate(value);
+ } catch (ParseException e) {
+ logger.trace("Unable parse value {} due to {}",value, e);
+ throw new NetconfDocumentedException("Unable to parse value "+value+" as date.",
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
}
Map<String, Object> newMap = Maps.newHashMap();
for (String key : openType.keySet()) {
- if (openType.getDescription(key).equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION))
+ if (openType.getDescription(key).equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION)){
newMap.put(key, valueMap.get(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION));
- else
+ } else {
newMap.put(key, null);
+ }
}
return newMap;
}
--- /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.confignetconfconnector.mapping.attributes.toxml;
+
+public abstract class AbstractAttributeWritingStrategy {
+ protected Object preprocess(Object value) {
+ return value;
+ }
+}
public class CompositeAttributeWritingStrategy implements AttributeWritingStrategy {
- protected final String key;
- protected final Document document;
- protected final Map<String, AttributeWritingStrategy> innerStrats;
+ private final String key;
+ private final Document document;
+ private final Map<String, AttributeWritingStrategy> innerStrats;
public CompositeAttributeWritingStrategy(Document document, String key,
Map<String, AttributeWritingStrategy> innerStrats) {
}
parentElement.appendChild(innerNode);
}
+
+ public String getKey() {
+ return key;
+ }
+
+ public Document getDocument() {
+ return document;
+ }
+
+ public Map<String, AttributeWritingStrategy> getInnerStrats() {
+ return innerStrats;
+ }
}
@Override
protected AttributeWritingStrategy caseTOAttribute(CompositeType openType) {
- Preconditions.checkState(lastAttribute instanceof TOAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
Map<String, AttributeWritingStrategy> innerStrats = Maps.newHashMap();
String currentKey = key;
- for (Entry<String, AttributeIfc> innerAttrEntry : ((TOAttribute) lastAttribute).getYangPropertiesToTypesMap().entrySet()) {
+ for (Entry<String, AttributeIfc> innerAttrEntry : ((TOAttribute) getLastAttribute()).getYangPropertiesToTypesMap().entrySet()) {
AttributeWritingStrategy innerStrategy = prepareWritingStrategy(innerAttrEntry.getKey(),
innerAttrEntry.getValue(), document);
@Override
protected AttributeWritingStrategy caseListAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListAttribute);
- AttributeIfc innerAttribute = ((ListAttribute) lastAttribute).getInnerAttribute();
+ Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
+ AttributeIfc innerAttribute = ((ListAttribute) getLastAttribute()).getInnerAttribute();
AttributeWritingStrategy innerStrategy = prepareWritingStrategy(key, innerAttribute, document);
return new ArrayAttributeWritingStrategy(innerStrategy);
@Override
protected AttributeWritingStrategy caseListDependeciesAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
AttributeWritingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME);
return new ArrayAttributeWritingStrategy(innerStrategy);
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
-import java.util.Map;
-import java.util.Map.Entry;
-
+import com.google.common.base.Optional;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
+import java.util.Map;
+import java.util.Map.Entry;
public class RuntimeBeanEntryWritingStrategy extends CompositeAttributeWritingStrategy {
public void writeElement(Element parentElement, String namespace, Object value) {
Util.checkType(value, Map.class);
- Element innerNode = XmlUtil.createElement(document, key, Optional.<String>absent());
+ Element innerNode = XmlUtil.createElement(getDocument(), getKey(), Optional.<String>absent());
Map<?, ?> map = (Map<?, ?>) value;
// bean
Util.checkType(runtimeBeanInstanceMappingEntry.getValue(), Map.class);
Map<?, ?> innerMap = (Map<?, ?>) runtimeBeanInstanceMappingEntry.getValue();
- Element runtimeInstanceNode = XmlUtil.createElement(document, "_"
+ Element runtimeInstanceNode = XmlUtil.createElement(getDocument(), "_"
+ (String) runtimeBeanInstanceMappingEntry.getKey(), Optional.<String>absent());
innerNode.appendChild(runtimeInstanceNode);
String innerKey = (String) innerObjectEntry.getKey();
Object innerValue = innerObjectEntry.getValue();
- innerStrats.get(innerKey).writeElement(runtimeInstanceNode, namespace, innerValue);
+ getInnerStrats().get(innerKey).writeElement(runtimeInstanceNode, namespace, innerValue);
}
}
parentElement.appendChild(innerNode);
typeElement.appendChild(document.createTextNode(value));
return typeElement;
}
-
protected Object preprocess(Object value) {
return value;
}
super(document, key);
}
+ @Override
protected Object preprocess(Object value) {
Util.checkType(value, List.class);
BaseEncoding en = BaseEncoding.base64();
public class SimpleIdentityRefAttributeWritingStrategy extends SimpleAttributeWritingStrategy {
- private static final char QNAME_SEPARATOR = ':';
private static final String PREFIX = "prefix";
/**
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-
import javax.management.ObjectName;
-
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
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 static com.google.common.base.Preconditions.checkState;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
public class Config {
- private final Logger logger = LoggerFactory.getLogger(Config.class);
private final Map<String/* Namespace from yang file */,
Map<String /* Name of module entry from yang file */, ModuleConfig>> moduleConfigs;
- private final Map<String, ModuleConfig> moduleNamesToConfigs;
private final Map<String, Map<Date, EditConfig.IdentityMapping>> identityMap;
public Config(Map<String, Map<String, ModuleConfig>> moduleConfigs, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
this.moduleConfigs = moduleConfigs;
- Map<String, ModuleConfig> moduleNamesToConfigs = new HashMap<>();
- for (Entry<String, Map<String, ModuleConfig>> entry : moduleConfigs.entrySet()) {
- moduleNamesToConfigs.putAll(entry.getValue());
- }
- this.moduleNamesToConfigs = Collections.unmodifiableMap(moduleNamesToConfigs);
this.identityMap = identityMap;
}
// TODO, this code does not support same module names from different namespaces
// Namespace should be present in ObjectName
- if (instances == null)
+ if (instances == null){
continue;
+ }
innerRetVal.put(moduleName, instances);
return retVal;
}
- // public Element toXml(Set<ObjectName> instancesToMap, String namespace,
- // Document document) {
- // return toXml(instancesToMap, Optional.of(namespace), document);
- // }
-
public Element toXml(Set<ObjectName> instancesToMap, Optional<String> maybeNamespace, Document document,
Element dataElement, ServiceRegistryWrapper serviceTracker) {
Optional<XmlElement> modulesOpt = getModulesElement(parent);
List<XmlElement> recognised = Lists.newArrayList();
- if(servicesOpt.isPresent())
+ if(servicesOpt.isPresent()){
recognised.add(servicesOpt.get());
- if(modulesOpt.isPresent())
+ }
+ if(modulesOpt.isPresent()){
recognised.add(modulesOpt.get());
+ }
parent.checkUnrecognisedElements(recognised);
}
private String getFactoryName(String factoryNameWithPrefix, String prefixOrEmptyString) {
checkState(
factoryNameWithPrefix.startsWith(prefixOrEmptyString),
- format("Internal error: text " + "content '%s' of type node does not start with prefix '%s'",
+ String.format("Internal error: text " + "content '%s' of type node does not start with prefix '%s'",
factoryNameWithPrefix, prefixOrEmptyString));
int factoryNameAfterPrefixIndex;
Map<String, Object> toXml = Maps.newHashMap();
for (Entry<String, AttributeIfc> configDefEntry : jmxToAttrConfig.entrySet()) {
-
// Skip children runtime beans as they are mapped by InstanceRuntime
- if (configDefEntry.getValue() instanceof RuntimeBeanEntry)
+ if (configDefEntry.getValue() instanceof RuntimeBeanEntry){
continue;
-
+ }
Object value = configRegistryClient.getAttributeCurrentValue(on, configDefEntry.getKey());
try {
AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = mappingStrategies
.get(configDefEntry.getKey());
Optional<?> a = attributeMappingStrategy.mapAttribute(value);
- if (a.isPresent() == false)
+ if (!a.isPresent()){
continue;
-
+ }
toXml.put(configDefEntry.getValue().getAttributeYangName(), a.get());
} catch (Exception e) {
throw new IllegalStateException("Unable to map value " + value + " to attribute "
+ configDefEntry.getKey(), e);
}
}
-
return toXml;
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
import com.google.common.collect.Multimap;
+import java.util.Map;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigStrategy;
-import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
-import java.util.Map;
-
/**
* Parsed xml element containing whole configuration for an instance of some
* module. Contains preferred edit strategy type.
static EditStrategyType parseStrategy(String currentStrategy, EditStrategyType defaultStrategy) throws OperationNotPermittedException {
- if (null == currentStrategy || currentStrategy.equals("")){
- throw new OperationNotPermittedException(String.format("With "
- + defaultStrategy
- + " as "
- + EditConfigXmlParser.DEFAULT_OPERATION_KEY
- + " operations on module elements are not permitted since the default option is restrictive"),
- NetconfDocumentedException.ErrorType.application,
- NetconfDocumentedException.ErrorTag.operation_failed,
- NetconfDocumentedException.ErrorSeverity.error);
- }
EditStrategyType parsedStrategy = EditStrategyType.valueOf(currentStrategy);
EditStrategyType.compareParsedStrategyToDefaultEnforcing(parsedStrategy,defaultStrategy);
return parsedStrategy;
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Optional;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import javax.management.ObjectName;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
public class ModuleConfig {
Element root = XmlUtil.createElement(document, XmlNetconfConstants.MODULE_KEY, Optional.<String>absent());
// Xml.addNamespaceAttr(document, root, namespace);
- final String prefix = getPrefix(namespace);
+ final String prefix = getPrefix();
Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(prefix, XmlNetconfConstants.TYPE_KEY), prefix,
moduleName, Optional.<String>of(namespace));
// Xml.addNamespaceAttr(document, typeElement,
return root;
}
- private String getPrefix(String namespace) {
- // if(namespace.contains(":")==false)
+ private String getPrefix() {
return XmlNetconfConstants.PREFIX;
- // return namespace.substring(namespace.lastIndexOf(':') + 1,
- // namespace.length());
-
}
public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName,
public ModuleElementDefinition(String instanceName, String currentStrategy, EditStrategyType defaultStrategy) {
this.instanceName = instanceName;
- EditStrategyType _edStrategy = null;
- try {
- _edStrategy = InstanceConfigElementResolved.parseStrategy(currentStrategy, defaultStrategy);
- } catch (OperationNotPermittedException e) {
- _edStrategy = defaultStrategy;
- logger.warn("Operation not permitted on current strategy {} while default strategy is {}. Element definition strategy set to default.",
- currentStrategy,
- defaultStrategy,
- e);
+ if (currentStrategy == null || currentStrategy.isEmpty()) {
+ this.editStrategy = defaultStrategy;
+ } else {
+ EditStrategyType _edStrategy = null;
+ try {
+ _edStrategy = InstanceConfigElementResolved.parseStrategy(currentStrategy, defaultStrategy);
+ } catch (OperationNotPermittedException e) {
+ _edStrategy = defaultStrategy;
+ logger.warn("Operation not permitted on current strategy {} while default strategy is {}. Element definition strategy set to default.",
+ currentStrategy,
+ defaultStrategy,
+ e);
+ }
+ this.editStrategy = _edStrategy;
}
- if (currentStrategy == null || currentStrategy.isEmpty())
- _edStrategy = defaultStrategy;
- this.editStrategy = _edStrategy;
}
public String getInstanceName() {
public boolean hasRefName(String namespace, String serviceName, ObjectName on) {
String qname = configServiceRefRegistry.getServiceInterfaceName(namespace, serviceName);
Map<String, ObjectName> forQName = configServiceRefRegistry.getServiceMapping().get(qname);
- if(forQName==null) return false;
+ if(forQName==null){
+ return false;
+ }
return forQName.values().contains(on);
}
Map<String, Map<String, Map<String, String>>> retVal = Maps.newHashMap();
Map<String, Map<String, ObjectName>> serviceMapping = configServiceRefRegistry.getServiceMapping();
- for (String serviceQName : serviceMapping.keySet())
+ for (String serviceQName : serviceMapping.keySet()){
for (String refName : serviceMapping.get(serviceQName).keySet()) {
ObjectName on = serviceMapping.get(serviceQName).get(refName);
serviceToRefs.put(localName, refsToSis);
}
- Preconditions.checkState(refsToSis.containsKey(refName) == false,
+ Preconditions.checkState(!refsToSis.containsKey(refName),
"Duplicate reference name %s for service %s:%s, now for instance %s", refName, namespace,
localName, on);
refsToSis.put(refName, si.toString());
}
+ }
return retVal;
}
Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
Map<String, String> refNameToInstance;
- if(serviceNameToRefNameToInstance == null || serviceNameToRefNameToInstance.containsKey(serviceName) == false) {
+ if(serviceNameToRefNameToInstance == null || !serviceNameToRefNameToInstance.containsKey(serviceName)) {
refNameToInstance = Collections.emptyMap();
- } else
+ } else {
refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
+ }
final Set<String> refNamesAsSet = toSet(refNameToInstance.keySet());
if (refNamesAsSet.contains(refName)) {
}
private String findAvailableRefName(String refName, Set<String> refNamesAsSet) {
- String intitialRefName = refName;
+ String availableRefName = "";
while (true) {
- refName = intitialRefName + "_" + suffix++;
- if (refNamesAsSet.contains(refName) == false)
- return refName;
+ availableRefName = refName + "_" + suffix++;
+ if (!refNamesAsSet.contains(availableRefName)){
+ return availableRefName;
+ }
}
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectNameAttributeReadingStrategy;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
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 com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
+import javax.management.ObjectName;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public final class Services {
- private static final Logger logger = LoggerFactory.getLogger(Services.class);
-
private static final String PROVIDER_KEY = "provider";
private static final String NAME_KEY = "name";
public static final String TYPE_KEY = "type";
XmlElement typeElement = service.getOnlyChildElement(TYPE_KEY);
Entry<String, String> prefixNamespace = typeElement.findNamespaceOfTextContent();
- Preconditions.checkState(prefixNamespace.getKey()!=null && prefixNamespace.getKey().equals("") == false, "Type attribute was not prefixed");
+ Preconditions.checkState(prefixNamespace.getKey()!=null && !prefixNamespace.getKey().equals(""), "Type attribute was not prefixed");
Map<String, Map<String, String>> namespaceToServices = retVal.get(prefixNamespace.getValue());
if(namespaceToServices == null) {
public static ServiceInstance fromString(String instanceId) {
instanceId = instanceId.trim();
Matcher matcher = p.matcher(instanceId);
- if(matcher.matches() == false) {
+ if(!matcher.matches()) {
matcher = pDeprecated.matcher(instanceId);
}
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj){
return true;
- if (obj == null)
+ }
+ if (obj == null){
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()){
return false;
+ }
ServiceInstance other = (ServiceInstance) obj;
if (instanceName == null) {
- if (other.instanceName != null)
+ if (other.instanceName != null){
return false;
- } else if (!instanceName.equals(other.instanceName))
+ }
+ } else if (!instanceName.equals(other.instanceName)){
return false;
+ }
if (moduleName == null) {
- if (other.moduleName != null)
+ if (other.moduleName != null){
return false;
- } else if (!moduleName.equals(other.moduleName))
+ }
+ } else if (!moduleName.equals(other.moduleName)){
return false;
+ }
return true;
}
public final class ModuleRpcs {
- Map<String, String> yangToJavaNames = Maps.newHashMap();
- Map<String, Map<String, InstanceRuntimeRpc>> rpcMapping = Maps.newHashMap();
+ private final Map<String, String> yangToJavaNames = Maps.newHashMap();
+ private final Map<String, Map<String, InstanceRuntimeRpc>> rpcMapping = Maps.newHashMap();
public void addNameMapping(RuntimeBeanEntry runtimeEntry) {
String yangName = runtimeEntry.getYangName();
- Preconditions.checkState(yangToJavaNames.containsKey(yangName) == false,
+ Preconditions.checkState(!yangToJavaNames.containsKey(yangName),
"RuntimeBean %s found twice in same namespace", yangName);
yangToJavaNames.put(yangName, runtimeEntry.getJavaNamePrefix());
}
rpcMapping.put(yangName, map);
}
- Preconditions.checkState(map.containsKey(rpc.getYangName()) == false, "Rpc %s for runtime bean %s added twice",
+ Preconditions.checkState(!map.containsKey(rpc.getYangName()), "Rpc %s for runtime bean %s added twice",
rpc.getYangName(), yangName);
map.put(rpc.getYangName(), new InstanceRuntimeRpc(rpc));
}
Preconditions.checkState(rpc != null, "No rpc found for runtime bean %s with name %s", rbeName, rpcName);
return rpc;
}
+
+ public Map<String, String> getYangToJavaNames() {
+ return yangToJavaNames;
+ }
+
+ public Map<String, Map<String, InstanceRuntimeRpc>> getRpcMapping() {
+ return rpcMapping;
+ }
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Sets;
+import javax.management.ObjectName;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
public class InstanceRuntime {
* root + any number of additional properties
*/
private Set<ObjectName> findChildren(ObjectName innerRootBean, Set<ObjectName> childRbeOns) {
- final Hashtable<String, String> wantedProperties = innerRootBean.getKeyPropertyList();
+ final Map<String, String> wantedProperties = innerRootBean.getKeyPropertyList();
return Sets.newHashSet(Collections2.filter(childRbeOns, new Predicate<ObjectName>() {
@Override
public boolean apply(ObjectName on) {
- Hashtable<String, String> localProperties = on.getKeyPropertyList();
+ Map<String, String> localProperties = on.getKeyPropertyList();
for (Entry<String, String> propertyEntry : wantedProperties.entrySet()) {
- if (!localProperties.containsKey(propertyEntry.getKey()))
+ if (!localProperties.containsKey(propertyEntry.getKey())){
return false;
- if (!localProperties.get(propertyEntry.getKey()).equals(propertyEntry.getValue()))
+ }
+ if (!localProperties.get(propertyEntry.getKey()).equals(propertyEntry.getValue())){
return false;
- if (localProperties.size() <= wantedProperties.size())
+ }
+ if (localProperties.size() <= wantedProperties.size()){
return false;
+ }
}
return true;
}
@Override
public boolean apply(ObjectName on) {
- if (on.getKeyPropertyList().size() != keyListSize + 1)
+ if (on.getKeyPropertyList().size() != keyListSize + 1){
return false;
- if (!on.getKeyPropertyList().containsKey(string))
+ }
+ if (!on.getKeyPropertyList().containsKey(string)){
return false;
+ }
return true;
}
}));
public class ModuleRuntime {
- private final String moduleName;
private final InstanceRuntime instanceRuntime;
public ModuleRuntime(String moduleName, InstanceRuntime instanceRuntime) {
- this.moduleName = moduleName;
this.instanceRuntime = instanceRuntime;
}
private ObjectName findRoot(Collection<ObjectName> runtimeBeanOns) {
for (ObjectName objectName : runtimeBeanOns) {
- if (objectName.getKeyPropertyList().size() == 3)
+ if (objectName.getKeyPropertyList().size() == 3){
return objectName;
+ }
}
throw new IllegalStateException("Root runtime bean not found among " + runtimeBeanOns);
}
Element runtimeXml;
ModuleConfig moduleConfig = moduleConfigs.get(localNamespace).get(moduleName);
- if(instanceToRbe==null || instanceToRbe.containsKey(instanceName) == false) {
+ if(instanceToRbe==null || !instanceToRbe.containsKey(instanceName)) {
runtimeXml = moduleConfig.toXml(instanceON, serviceRegistry, document, localNamespace);
} else {
ModuleRuntime moduleRuntime = moduleRuntimes.get(localNamespace).get(moduleName);
return root;
}
- private ObjectName findInstance(Collection<ObjectName> objectNames, String instanceName) {
- for (ObjectName objectName : objectNames) {
- String name = ObjectNameUtil.getInstanceName(objectName);
- if(name.equals(instanceName))
- return objectName;
- }
-
- throw new UnsupportedOperationException("Unable to find config bean instance under name " + instanceName + " among " + objectNames);
- }
-
}
public abstract class AbstractConfigNetconfOperation extends AbstractLastNetconfOperation {
- protected final ConfigRegistryClient configRegistryClient;
+ private final ConfigRegistryClient configRegistryClient;
protected AbstractConfigNetconfOperation(ConfigRegistryClient configRegistryClient,
String netconfSessionIdForReporting) {
super(netconfSessionIdForReporting);
this.configRegistryClient = configRegistryClient;
}
+
+ public ConfigRegistryClient getConfigRegistryClient() {
+ return configRegistryClient;
+ }
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import java.util.Map;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Map;
-
public class DeleteEditConfigStrategy extends AbstractEditConfigStrategy {
private static final Logger logger = LoggerFactory.getLogger(DeleteEditConfigStrategy.class);
- private final Multimap<String, String> providedServices;
-
- public DeleteEditConfigStrategy() {
- this.providedServices = HashMultimap.create();
- }
-
- public DeleteEditConfigStrategy(Multimap<String, String> providedServices) {
- this.providedServices = providedServices;
- }
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException, NetconfConfigHandlingException {
if (editConfigExecution.shouldTest()) {
- executeTests(configRegistryClient, editConfigExecution);
+ executeTests(getConfigRegistryClient(), editConfigExecution);
}
if (editConfigExecution.shouldSet()) {
- executeSet(configRegistryClient, editConfigExecution);
+ executeSet(getConfigRegistryClient(), editConfigExecution);
}
logger.trace("Operation {} successful", EditConfigXmlParser.EDIT_CONFIG);
void addIdSchemaNode(IdentitySchemaNode node) {
String name = node.getQName().getLocalName();
- Preconditions.checkState(identityNameToSchemaNode.containsKey(name) == false);
+ Preconditions.checkState(!identityNameToSchemaNode.containsKey(name));
identityNameToSchemaNode.put(name, node);
}
}
Date revision = module.getRevision();
- Preconditions.checkState(revisionsByNamespace.containsKey(revision) == false,
+ Preconditions.checkState(!revisionsByNamespace.containsKey(revision),
"Duplicate revision %s for namespace %s", revision, namespace);
IdentityMapping identityMapping = revisionsByNamespace.get(revision);
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
EditConfigXmlParser.EditConfigExecution editConfigExecution;
- Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot);
- editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, configRegistryClient);
+ Config cfg = getConfigMapping(getConfigRegistryClient(), yangStoreSnapshot);
+ editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, getConfigRegistryClient());
Element responseInternal;
responseInternal = getResponseInternal(document, editConfigExecution);
.getOnlyChildElementWithSameNamespaceOptionally(EditConfigXmlParser.ERROR_OPTION_KEY);
if (errorOptionElement.isPresent()) {
String errorOptionParsed = errorOptionElement.get().getTextContent();
- if (false == errorOptionParsed.equals(EditConfigXmlParser.DEFAULT_ERROR_OPTION))
+ if (!errorOptionParsed.equals(EditConfigXmlParser.DEFAULT_ERROR_OPTION)){
throw new UnsupportedOperationException("Only " + EditConfigXmlParser.DEFAULT_ERROR_OPTION
+ " supported for " + EditConfigXmlParser.ERROR_OPTION_KEY + ", was " + errorOptionParsed);
+ }
}
// Default op
case replace:
return new ReplaceEditConfigStrategy(providedServices);
case delete:
- return new DeleteEditConfigStrategy(providedServices);
+ return new DeleteEditConfigStrategy();
case remove:
return new RemoveEditConfigStrategy();
case none:
for (Entry<String, String> namespaceToService : providedServices.entries()) {
if(services.hasRefName(namespaceToService.getKey(),
- namespaceToService.getValue(), on))
+ namespaceToService.getValue(), on)){
continue;
+ }
String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
for (Entry<String, String> namespaceToService : providedServices.entries()) {
if(services.hasRefName(namespaceToService.getKey(),
- namespaceToService.getValue(), on))
+ namespaceToService.getValue(), on)){
continue;
+ }
String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
RuntimeBeanEntry root = null;
for (RuntimeBeanEntry rbe : mbe.getRuntimeBeans()) {
cache.put(rbe, new InstanceConfig(configRegistryClient, rbe.getYangPropertiesToTypesMap()));
- if (rbe.isRoot())
+ if (rbe.isRoot()){
root = rbe;
+ }
}
- if (root == null)
+ if (root == null){
continue;
+ }
InstanceRuntime rootInstanceRuntime = createInstanceRuntime(root, cache);
ModuleRuntime moduleRuntime = new ModuleRuntime(module, rootInstanceRuntime);
xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
// Filter option - unsupported
- if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0)
+ if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0){
throw new UnsupportedOperationException("Unsupported option " + XmlNetconfConstants.FILTER + " for " + XmlNetconfConstants.GET);
+ }
}
@Override
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
checkXml(xml);
- final Set<ObjectName> runtimeBeans = configRegistryClient.lookupRuntimeBeans();
+ final Set<ObjectName> runtimeBeans = getConfigRegistryClient().lookupRuntimeBeans();
//Transaction provider required only for candidate datastore
final Set<ObjectName> configBeans = Datastore.getInstanceQueryStrategy(Datastore.running, null)
- .queryInstances(configRegistryClient);
+ .queryInstances(getConfigRegistryClient());
- final Map<String, Map<String, ModuleRuntime>> moduleRuntimes = createModuleRuntimes(configRegistryClient,
+ final Map<String, Map<String, ModuleRuntime>> moduleRuntimes = createModuleRuntimes(getConfigRegistryClient(),
yangStoreSnapshot.getModuleMXBeanEntryMap());
final Map<String, Map<String, ModuleConfig>> moduleConfigs = EditConfig.transformMbeToModuleConfigs(
- configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap());
+ getConfigRegistryClient(), yangStoreSnapshot.getModuleMXBeanEntryMap());
final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs);
ObjectName txOn = transactionProvider.getOrCreateTransaction();
- ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(txOn);
+ ConfigTransactionClient ta = getConfigRegistryClient().getConfigTransactionClient(txOn);
final Element element = runtime.toXml(runtimeBeans, configBeans, document, new ServiceRegistryWrapper(ta));
logger.trace("{} operation successful", XmlNetconfConstants.GET);
Datastore sourceDatastore = Datastore.valueOf(sourceParsed);
// Filter option - unsupported
- if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0)
+ if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0){
throw new UnsupportedOperationException("Unsupported option " + XmlNetconfConstants.FILTER + " for "
+ GET_CONFIG);
+ }
return sourceDatastore;
public Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
Datastore source;
source = fromXml(xml);
- return getResponseInternal(document, configRegistryClient, source);
+ return getResponseInternal(document, getConfigRegistryClient(), source);
}
}
final Optional<XmlElement> contextInstanceElement = operationElement
.getOnlyChildElementOptionally(CONTEXT_INSTANCE);
- if (contextInstanceElement.isPresent() == false)
+ if (!contextInstanceElement.isPresent()){
return HandlingPriority.CANNOT_HANDLE;
+ }
final RuntimeRpcElementResolved id = RuntimeRpcElementResolved.fromXpath(contextInstanceElement.get()
.getTextContent(), netconfOperationName, netconfOperationNamespace);
logger.debug("Invoking operation {} on {} with arguments {}", execution.operationName, execution.on,
execution.attributes);
- final Object result = executeOperation(configRegistryClient, execution.on, execution.operationName,
+ final Object result = executeOperation(getConfigRegistryClient(), execution.on, execution.operationName,
execution.attributes);
logger.trace("Operation {} called successfully on {} with arguments {} with result {}", execution.operationName,
for (XmlElement xmlElement : xml.getChildElements()) {
final String name = xmlElement.getName();
- if (CONTEXT_INSTANCE.equals(name) == false) { // skip context
+ if (!CONTEXT_INSTANCE.equals(name)) { // skip context
// instance child node
// because it
// specifies
RuntimeRpc.CONTEXT_INSTANCE, xpath, elementName, xpathPatternBlueprint);
PatternGroupResolver groups = new PatternGroupResolver(matcher.group("key1"), matcher.group("value1"),
- matcher.group("key2"), matcher.group("value2"), matcher.group("additional"));
+ matcher.group("value2"), matcher.group("additional"));
String moduleName = groups.getModuleName();
String instanceName = groups.getInstanceName();
- HashMap<String, String> additionalAttributes = groups.getAdditionalKeys(elementName, moduleName);
+ Map<String, String> additionalAttributes = groups.getAdditionalKeys(elementName, moduleName);
return new RuntimeRpcElementResolved(namespace, moduleName, instanceName, groups.getRuntimeBeanYangName(),
additionalAttributes);
private static final class PatternGroupResolver {
- private final String key1, key2, value1, value2;
+ private final String key1, value1, value2;
private final String additional;
private String runtimeBeanYangName;
- PatternGroupResolver(String key1, String value1, String key2, String value2, String additional) {
+ PatternGroupResolver(String key1, String value1, String value2, String additional) {
this.key1 = Preconditions.checkNotNull(key1);
this.value1 = Preconditions.checkNotNull(value1);
- this.key2 = Preconditions.checkNotNull(key2);
this.value2 = Preconditions.checkNotNull(value2);
this.additional = Preconditions.checkNotNull(additional);
return key1.equals(XmlNetconfConstants.NAME_KEY) ? value1 : value2;
}
- HashMap<String, String> getAdditionalKeys(String elementName, String moduleName) {
+ Map<String, String> getAdditionalKeys(String elementName, String moduleName) {
HashMap<String, String> additionalAttributes = Maps.newHashMap();
runtimeBeanYangName = moduleName;
for (String additionalKeyValue : additional.split("/")) {
- if (Strings.isNullOrEmpty(additionalKeyValue))
+ if (Strings.isNullOrEmpty(additionalKeyValue)){
continue;
+ }
Matcher matcher = additionalPattern.matcher(additionalKeyValue);
Preconditions
.checkState(
}
@Override
- public void stop(BundleContext context) throws Exception {
+ public void stop(BundleContext context) {
if (configRegistryLookup != null) {
configRegistryLookup.interrupt();
}
import java.util.Set;
final class NetconfOperationProvider {
- private final YangStoreSnapshot yangStoreSnapshot;
private final Set<NetconfOperation> operations;
- private final ConfigRegistryClient configRegistryClient;
- private final TransactionProvider transactionProvider;
NetconfOperationProvider(YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient,
TransactionProvider transactionProvider, String netconfSessionIdForReporting) {
- this.yangStoreSnapshot = yangStoreSnapshot;
- this.configRegistryClient = configRegistryClient;
- this.transactionProvider = transactionProvider;
operations = setUpOperations(yangStoreSnapshot, configRegistryClient, transactionProvider,
netconfSessionIdForReporting);
}
Thread.sleep(ATTEMPT_TIMEOUT_MS);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
- throw new RuntimeException("Interrupted while reattempting connection", e1);
+ throw new IllegalStateException("Interrupted while reattempting connection", e1);
}
}
}
for (Map<String, ModuleMXBeanEntry> moduleNameToMBE : moduleMXBeanEntryMap.values()) {
for (ModuleMXBeanEntry moduleMXBeanEntry : moduleNameToMBE.values()) {
String moduleSeenByYangStore = moduleMXBeanEntry.getYangModuleQName().toString();
- if(modulesSeenByConfig.contains(moduleSeenByYangStore) == false)
+ if(!modulesSeenByConfig.contains(moduleSeenByYangStore)){
missingModulesFromConfig.add(moduleSeenByYangStore);
+ }
}
}
}
}
- private static class YangStoreCapability extends BasicCapability {
+ private static final class YangStoreCapability extends BasicCapability {
private final String content;
private final String revision;
private final String netconfSessionIdForReporting;
private ObjectName transaction;
private final List<ObjectName> allOpenedTransactions = new ArrayList<>();
+ private static final String NO_TRANSACTION_FOUND_FOR_SESSION = "No transaction found for session ";
public TransactionProvider(ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) {
this.configRegistryClient = configRegistryClient;
public Optional<ObjectName> getTransaction() {
- if (transaction == null)
+ if (transaction == null){
return Optional.absent();
+ }
// Transaction was already closed somehow
- if (isStillOpenTransaction(transaction) == false) {
+ if (!isStillOpenTransaction(transaction)) {
logger.warn("Fixing illegal state: transaction {} was closed in {}", transaction,
netconfSessionIdForReporting);
transaction = null;
}
private boolean isStillOpenTransaction(ObjectName transaction) {
- boolean isStillOpenTransaction = configRegistryClient.getOpenConfigs().contains(transaction);
- return isStillOpenTransaction;
+ return configRegistryClient.getOpenConfigs().contains(transaction);
}
public synchronized ObjectName getOrCreateTransaction() {
public synchronized void abortTransaction() {
logger.debug("Aborting current transaction");
Optional<ObjectName> taON = getTransaction();
- Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
+ Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get());
transactionClient.abortConfig();
public void validateTransaction() throws ValidationException {
Optional<ObjectName> taON = getTransaction();
- Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
+ Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get());
transactionClient.validateConfig();
try {
transactionClient.destroyModule(instance);
} catch (InstanceNotFoundException e) {
- if (isTest)
+ if (isTest){
logger.debug("Unable to clean configuration in transactiom {}", taON, e);
- else
+ } else {
logger.warn("Unable to clean configuration in transactiom {}", taON, e);
+ }
throw new IllegalStateException("Unable to clean configuration in transactiom " + taON, e);
}
public void wipeTransaction() {
Optional<ObjectName> taON = getTransaction();
- Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
+ Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
wipeInternal(taON.get(), false, null);
}
this.factory = new NetconfTestImplModuleFactory();
this.factory2 = new DepTestImplModuleFactory();
this.factory3 = new IdentityTestModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.factory, this.factory2,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, this.factory, this.factory2,
this.factory3));
transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID);
try {
mBeanServerConnection.addNotificationListener(DefaultCommitOperationMXBean.OBJECT_NAME, listener, null, null);
} catch (InstanceNotFoundException | IOException e) {
- throw new RuntimeException("Cannot register as JMX listener to netconf", e);
+ throw new IllegalStateException("Cannot register as JMX listener to netconf", e);
}
}
@Override
public void handleNotification(Notification notification, Object handback) {
- if (notification instanceof NetconfJMXNotification == false) {
+ if (!(notification instanceof NetconfJMXNotification))
return;
- }
// Socket should not be closed at this point
// Activator unregisters this as JMX listener before close is called
package org.opendaylight.controller.netconf.persist.impl;
import com.google.common.annotations.VisibleForTesting;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
import org.opendaylight.controller.config.persist.api.Persister;
+import org.opendaylight.controller.config.persist.api.PropertiesProvider;
import org.opendaylight.controller.config.persist.api.StorageAdapter;
import org.opendaylight.controller.netconf.persist.impl.osgi.ConfigPersisterActivator;
-import org.opendaylight.controller.netconf.persist.impl.osgi.PropertiesProviderBaseImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.ListIterator;
-
/**
* {@link Persister} implementation that delegates persisting functionality to
* underlying {@link Persister} storages. Each storage has unique id, class, readonly value.
}
}
- private static PersisterWithConfiguration loadConfiguration(final String index, final PropertiesProviderBaseImpl propertiesProvider) {
+ private static PersisterWithConfiguration loadConfiguration(final String index, final PropertiesProvider propertiesProvider) {
String classKey = index + "." + ConfigPersisterActivator.STORAGE_ADAPTER_CLASS_PROP_SUFFIX;
String storageAdapterClass = propertiesProvider.getProperty(classKey);
try {
Class<?> clazz = Class.forName(storageAdapterClass);
boolean implementsCorrectIfc = StorageAdapter.class.isAssignableFrom(clazz);
- if (implementsCorrectIfc == false) {
+ if (!implementsCorrectIfc) {
throw new IllegalArgumentException("Storage adapter " + clazz + " does not implement " + StorageAdapter.class);
}
storageAdapter = StorageAdapter.class.cast(clazz.newInstance());
}
- public static PersisterAggregator createFromProperties(PropertiesProviderBaseImpl propertiesProvider) {
+ public static PersisterAggregator createFromProperties(PropertiesProvider propertiesProvider) {
List<PersisterWithConfiguration> persisterWithConfigurations = new ArrayList<>();
String prefixes = propertiesProvider.getProperty("active");
- if (prefixes!=null && prefixes.isEmpty() == false) {
+ if (prefixes!=null && !prefixes.isEmpty()) {
String [] keys = prefixes.split(",");
for (String index: keys) {
persisterWithConfigurations.add(PersisterAggregator.loadConfiguration(index, propertiesProvider));
} catch (IOException e) {
throw new RuntimeException("Error while calling loadLastConfig on " + persisterWithConfiguration, e);
}
- if (configs.isEmpty() == false) {
+ if (!configs.isEmpty()) {
logger.debug("Found non empty configs using {}:{}", persisterWithConfiguration, configs);
return configs;
}
package org.opendaylight.controller.netconf.persist.impl;
import org.opendaylight.controller.config.persist.api.PropertiesProvider;
-import org.opendaylight.controller.netconf.persist.impl.osgi.PropertiesProviderBaseImpl;
public class PropertiesProviderAdapterImpl implements PropertiesProvider {
- private final PropertiesProviderBaseImpl inner;
+ private final PropertiesProvider inner;
private final String index;
- public PropertiesProviderAdapterImpl(PropertiesProviderBaseImpl inner, String index) {
+ public PropertiesProviderAdapterImpl(PropertiesProvider inner, String index) {
this.inner = inner;
this.index = index;
}
return inner.getPrefix() + "." + index + ".properties";
}
+ @Override
+ public String getPropertyWithoutPrefix(String fullKey) {
+ return inner.getPropertyWithoutPrefix(fullKey);
+ }
+
+
@Override
public String getFullKeyForReporting(String key) {
return getPrefix() + "." + key;
long maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesMillis(propertiesProvider);
List<ConfigSnapshotHolder> configs = persisterAggregator.loadLastConfigs();
long conflictingVersionTimeoutMillis = getConflictingVersionTimeoutMillis(propertiesProvider);
- logger.trace("Following configs will be pushed: {}", configs);
+ logger.debug("Following configs will be pushed: {}", configs);
InnerCustomizer innerCustomizer = new InnerCustomizer(configs, maxWaitForCapabilitiesMillis,
conflictingVersionTimeoutMillis, persisterAggregator);
// this means pushing of config was successful
public void assertCannotRegisterAsJMXListener_pushWasSuccessful() {
- handler.assertException(RuntimeException.class, "Cannot register as JMX listener to netconf");
+ handler.assertException(IllegalStateException.class, "Cannot register as JMX listener to netconf");
}
public NetconfOperationService getWorkingService(Document document) throws SAXException, IOException, NetconfDocumentedException {
/**
**/
-public class LocationBuilder {
+public final class LocationBuilder {
public static Location getDefaultInstance(String defaultValue) {
return defaultValue.equals("NETCONF") ? new Location(Location.Enumeration.NETCONF) : new Location(new Uri(
--- /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.client;
+
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GlobalEventExecutor;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.TimedReconnectStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Sets;
+
+/**
+ * @deprecated Use {@link NetconfClientDispatcher.createClient()} or {@link NetconfClientDispatcher.createReconnectingClient()} instead.
+ */
+@Deprecated
+public class NetconfClient implements Closeable {
+
+ private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
+
+ public static final int DEFAULT_CONNECT_TIMEOUT = 5000;
+ private final NetconfClientDispatcher dispatch;
+ private final String label;
+ private final NetconfClientSession clientSession;
+ private final NetconfClientSessionListener sessionListener;
+ private final long sessionId;
+ private final InetSocketAddress address;
+
+ // TODO test reconnecting constructor
+ public NetconfClient(String clientLabelForLogging, InetSocketAddress address, int connectionAttempts,
+ int attemptMsTimeout, NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ this(clientLabelForLogging, address, getReconnectStrategy(connectionAttempts, attemptMsTimeout),
+ netconfClientDispatcher);
+ }
+
+ private NetconfClient(String clientLabelForLogging, InetSocketAddress address, ReconnectStrategy strat, NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ this.label = clientLabelForLogging;
+ dispatch = netconfClientDispatcher;
+ sessionListener = new SimpleNetconfClientSessionListener();
+ Future<NetconfClientSession> clientFuture = dispatch.createClient(address, sessionListener, strat);
+ this.address = address;
+ clientSession = get(clientFuture);
+ this.sessionId = clientSession.getSessionId();
+ }
+
+ private NetconfClientSession get(Future<NetconfClientSession> clientFuture) throws InterruptedException {
+ try {
+ return clientFuture.get();
+ } catch (CancellationException e) {
+ throw new RuntimeException("Cancelling " + this, e);
+ } catch (ExecutionException e) {
+ throw new IllegalStateException("Unable to create " + this, e);
+ }
+ }
+
+ public static NetconfClient clientFor(String clientLabelForLogging, InetSocketAddress address, ReconnectStrategy strategy, NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ return new NetconfClient(clientLabelForLogging,address,strategy,netconfClientDispatcher);
+ }
+
+ public static NetconfClient clientFor(String clientLabelForLogging, InetSocketAddress address,
+ ReconnectStrategy strategy, NetconfClientDispatcher netconfClientDispatcher, NetconfClientSessionListener listener) throws InterruptedException {
+ return new NetconfClient(clientLabelForLogging,address,strategy,netconfClientDispatcher,listener);
+ }
+
+ public NetconfClient(String clientLabelForLogging, InetSocketAddress address, int connectTimeoutMs,
+ NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ this(clientLabelForLogging, address,
+ new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, connectTimeoutMs), netconfClientDispatcher);
+ }
+
+ public NetconfClient(String clientLabelForLogging, InetSocketAddress address,
+ NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ this(clientLabelForLogging, address, new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE,
+ DEFAULT_CONNECT_TIMEOUT), netconfClientDispatcher);
+ }
+
+ public NetconfClient(String clientLabelForLogging, InetSocketAddress address, ReconnectStrategy strategy,
+ NetconfClientDispatcher netconfClientDispatcher, NetconfClientSessionListener listener) throws InterruptedException{
+ this.label = clientLabelForLogging;
+ dispatch = netconfClientDispatcher;
+ sessionListener = listener;
+ Future<NetconfClientSession> clientFuture = dispatch.createClient(address, sessionListener, strategy);
+ this.address = address;
+ clientSession = get(clientFuture);
+ this.sessionId = clientSession.getSessionId();
+ }
+
+ public Future<NetconfMessage> sendRequest(NetconfMessage message) {
+ return ((SimpleNetconfClientSessionListener)sessionListener).sendRequest(message);
+ }
+
+ /**
+ * @deprecated Use {@link sendRequest} instead
+ */
+ @Deprecated
+ public NetconfMessage sendMessage(NetconfMessage message) throws ExecutionException, InterruptedException, TimeoutException {
+ return sendMessage(message, 5, 1000);
+ }
+
+ /**
+ * @deprecated Use {@link sendRequest} instead
+ */
+ @Deprecated
+ public NetconfMessage sendMessage(NetconfMessage message, int attempts, int attemptMsDelay) throws ExecutionException, InterruptedException, TimeoutException {
+ final Stopwatch stopwatch = new Stopwatch().start();
+
+ try {
+ return sendRequest(message).get(attempts * attemptMsDelay, TimeUnit.MILLISECONDS);
+ } finally {
+ stopwatch.stop();
+ logger.debug("Total time spent waiting for response from {}: {} ms", address, stopwatch.elapsed(TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ clientSession.close();
+ }
+
+ public NetconfClientDispatcher getNetconfClientDispatcher() {
+ return dispatch;
+ }
+
+ private static ReconnectStrategy getReconnectStrategy(int connectionAttempts, int attemptMsTimeout) {
+ return new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, attemptMsTimeout, 1000, 1.0, null,
+ Long.valueOf(connectionAttempts), null);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("NetconfClient{");
+ sb.append("label=").append(label);
+ sb.append(", sessionId=").append(sessionId);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public long getSessionId() {
+ return sessionId;
+ }
+
+ public Set<String> getCapabilities() {
+ Preconditions.checkState(clientSession != null, "Client was not initialized successfully");
+ return Sets.newHashSet(clientSession.getServerCapabilities());
+ }
+
+ public NetconfClientSession getClientSession() {
+ return clientSession;
+ }
+}
});
}
- private static class ClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
+ private static final class ClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
private final NetconfClientSessionNegotiatorFactory negotiatorFactory;
private final NetconfClientSessionListener sessionListener;
package org.opendaylight.controller.netconf.client;
-import io.netty.channel.Channel;
+import java.util.Collection;
+
import org.opendaylight.controller.netconf.util.AbstractNetconfSession;
import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
import org.opendaylight.controller.netconf.util.handler.NetconfEXIToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Collection;
+import io.netty.channel.Channel;
public final class NetconfClientSession extends AbstractNetconfSession<NetconfClientSession, NetconfClientSessionListener> {
return capabilities;
}
-
@Override
protected NetconfClientSession thisInstance() {
return this;
package org.opendaylight.controller.netconf.client;
-import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
+import java.util.Collection;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+
import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
+import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
+import io.netty.channel.Channel;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
public class NetconfClientSessionNegotiator extends
AbstractNetconfSessionNegotiator<NetconfClientSessionPreferences, NetconfClientSession, NetconfClientSessionListener>
@Override
protected void handleMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException {
- NetconfClientSession session = super.getSessionForHelloMessage(netconfMessage);
-
- if (shouldUseExi(netconfMessage.getDocument())){
- logger.debug("Netconf session: {} should use exi.", session);
- tryToStartExi(session);
+ final NetconfClientSession session = getSessionForHelloMessage(netconfMessage);
+ replaceHelloMessageInboundHandler(session);
+
+ // If exi should be used, try to initiate exi communication
+ // Call negotiationSuccessFul after exi negotiation is finished successfully or not
+ if (shouldUseExi(netconfMessage)) {
+ logger.debug("Netconf session {} should use exi.", session);
+ NetconfStartExiMessage startExiMessage = (NetconfStartExiMessage) sessionPreferences.getStartExiMessage();
+ tryToInitiateExi(session, startExiMessage);
+ // Exi is not supported, release session immediately
} else {
logger.debug("Netconf session {} isn't capable using exi.", session);
negotiationSuccessful(session);
}
}
- private boolean shouldUseExi(Document doc) {
- return containsExi10Capability(doc)
+ /**
+ * Initiates exi communication by sending start-exi message and waiting for positive/negative response.
+ *
+ * @param startExiMessage
+ */
+ void tryToInitiateExi(final NetconfClientSession session, final NetconfStartExiMessage startExiMessage) {
+ session.sendMessage(startExiMessage).addListener(new ChannelFutureListener() {
+ @Override
+ public void operationComplete(final ChannelFuture f) {
+ if (!f.isSuccess()) {
+ logger.warn("Failed to send start-exi message {} on session {}", startExiMessage, this, f.cause());
+ } else {
+ logger.trace("Start-exi message {} sent to socket on session {}", startExiMessage, this);
+ channel.pipeline().addAfter(
+ AbstractChannelInitializer.NETCONF_MESSAGE_DECODER, ExiConfirmationInboundHandler.EXI_CONFIRMED_HANDLER,
+ new ExiConfirmationInboundHandler(session, startExiMessage));
+ }
+ }
+ });
+ }
+
+ private boolean shouldUseExi(NetconfHelloMessage helloMsg) {
+ return containsExi10Capability(helloMsg.getDocument())
&& containsExi10Capability(sessionPreferences.getHelloMessage().getDocument());
}
return false;
}
- private void tryToStartExi(final NetconfClientSession session) {
- final NetconfMessage startExi = sessionPreferences.getStartExiMessage();
- session.sendMessage(startExi).addListener(new ChannelFutureListener() {
- @Override
- public void operationComplete(final ChannelFuture f) {
- if (!f.isSuccess()) {
- logger.warn("Failed to send start-exi message {} on session {}", startExi, session, f.cause());
- } else {
- logger.trace("Start-exi message {} sent to socket on session {}", startExi, session);
- NetconfClientSessionNegotiator.this.channel.pipeline().addAfter(
- AbstractChannelInitializer.NETCONF_MESSAGE_DECODER, ExiConfirmationInboundHandler.EXI_CONFIRMED_HANDLER,
- new ExiConfirmationInboundHandler(session));
- }
- }
- });
- }
-
private long extractSessionId(Document doc) {
final Node sessionIdNode = (Node) XmlUtil.evaluateXPath(sessionIdXPath, doc, XPathConstants.NODE);
String textContent = sessionIdNode.getTextContent();
}
@Override
- protected NetconfClientSession getSession(NetconfClientSessionListener sessionListener, Channel channel, NetconfHelloMessage message) throws NetconfDocumentedException {
- return new NetconfClientSession(sessionListener, channel, extractSessionId(message.getDocument()),
- NetconfMessageUtil.extractCapabilitiesFromHello(message.getDocument()));
+ protected NetconfClientSession getSession(NetconfClientSessionListener sessionListener, Channel channel,
+ NetconfHelloMessage message) throws NetconfDocumentedException {
+ long sessionId = extractSessionId(message.getDocument());
+ Collection<String> capabilities = NetconfMessageUtil.extractCapabilitiesFromHello(message.getDocument());
+ return new NetconfClientSession(sessionListener, channel, sessionId, capabilities);
}
/**
private static final String EXI_CONFIRMED_HANDLER = "exiConfirmedHandler";
private final NetconfClientSession session;
+ private NetconfStartExiMessage startExiMessage;
- ExiConfirmationInboundHandler(NetconfClientSession session) {
+ ExiConfirmationInboundHandler(NetconfClientSession session, final NetconfStartExiMessage startExiMessage) {
this.session = session;
+ this.startExiMessage = startExiMessage;
}
@Override
if (NetconfMessageUtil.isOKMessage(netconfMessage)) {
logger.trace("Positive response on start-exi call received on session {}", session);
try {
- session.startExiCommunication(sessionPreferences.getStartExiMessage());
+ session.startExiCommunication(startExiMessage);
} catch (RuntimeException e) {
// Unable to add exi, continue without exi
logger.warn("Unable to start exi communication, Communication will continue without exi on session {}", session, e);
}
- // Error response
+ // Error response
} else if(NetconfMessageUtil.isErrorMessage(netconfMessage)) {
logger.warn(
"Error response to start-exi message {}, Communication will continue without exi on session {}",
XmlUtil.toString(netconfMessage.getDocument()), session);
- // Unexpected response to start-exi, throwing message away, continue without exi
+ // Unexpected response to start-exi, throwing message away, continue without exi
} else {
logger.warn(
"Unexpected response to start-exi message, should be ok, was {}, " +
negotiationSuccessful(session);
}
}
+
}
public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorFactory<NetconfMessage, NetconfClientSession, NetconfClientSessionListener> {
public static final java.util.Set<String> CLIENT_CAPABILITIES = Sets.newHashSet(
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_1,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1,
XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0);
private static final String START_EXI_MESSAGE_ID = "default-start-exi";
throw new IllegalStateException(e);
}
- NetconfClientSessionPreferences proposal = new NetconfClientSessionPreferences(helloMessage,startExiMessage);
+ NetconfClientSessionPreferences proposal = new NetconfClientSessionPreferences(helloMessage, startExiMessage);
return new NetconfClientSessionNegotiator(proposal, promise, channel, timer,
sessionListenerFactory.getSessionListener(),connectionTimeoutMillis);
}
public class SimpleNetconfClientSessionListener implements NetconfClientSessionListener {
private static final class RequestEntry {
- final Promise<NetconfMessage> promise;
- final NetconfMessage request;
+ private final Promise<NetconfMessage> promise;
+ private final NetconfMessage request;
public RequestEntry(Promise<NetconfMessage> future, NetconfMessage request) {
this.promise = Preconditions.checkNotNull(future);
final Set<Capability> caps = netconfOperationService.getCapabilities();
for (Capability cap : caps) {
- if (cap.getModuleName().isPresent() == false)
- continue;
- if (cap.getRevision().isPresent() == false)
- continue;
- if (cap.getCapabilitySchema().isPresent() == false)
+ if (!cap.getModuleName().isPresent()
+ || !cap.getRevision().isPresent()
+ || !cap.getCapabilitySchema().isPresent()){
continue;
+ }
final String currentModuleName = cap.getModuleName().get();
Map<String, String> revisionMap = mappedModulesToRevisionToSchema.get(currentModuleName);
public DefaultCommitNotificationProducer(MBeanServer mBeanServer) {
this.mbeanServer = mBeanServer;
+ logger.debug("Registering to JMX under {}", on);
registerMBean(this, mbeanServer, on);
}
try {
mbs.registerMBean(instance, on);
} catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
- throw new RuntimeException("Unable to register " + instance + " as " + on, e);
+ throw new IllegalStateException("Unable to register " + instance + " as " + on, e);
}
}
package org.opendaylight.controller.netconf.impl;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-
public class NetconfServerSessionListener implements NetconfSessionListener<NetconfServerSession> {
static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionListener.class);
// TODO: should send generic error or close session?
logger.error("Unexpected exception", e);
session.onIncommingRpcFail();
- throw new RuntimeException("Unable to process incoming message " + netconfMessage, e);
+ throw new IllegalStateException("Unable to process incoming message " + netconfMessage, e);
} catch (NetconfDocumentedException e) {
+ logger.trace("Error occured while processing mesage {}",e);
session.onOutgoingRpcError();
session.onIncommingRpcFail();
SendErrorExceptionUtil.sendErrorMessage(session, e, netconfMessage);
package org.opendaylight.controller.netconf.impl;
-import com.google.common.base.Optional;
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
+import java.net.InetSocketAddress;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.net.InetSocketAddress;
+import com.google.common.base.Optional;
+
+import io.netty.channel.Channel;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
public class NetconfServerSessionNegotiator extends
AbstractNetconfSessionNegotiator<NetconfServerSessionPreferences, NetconfServerSession, NetconfServerSessionListener> {
super(sessionPreferences, promise, channel, timer, sessionListener, connectionTimeoutMillis);
}
+ @Override
+ protected void handleMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException {
+ NetconfServerSession session = getSessionForHelloMessage(netconfMessage);
+ replaceHelloMessageInboundHandler(session);
+ // Negotiation successful after all non hello messages were processed
+ negotiationSuccessful(session);
+ }
+
@Override
protected NetconfServerSession getSession(NetconfServerSessionListener sessionListener, Channel channel, NetconfHelloMessage message) {
Optional<NetconfHelloMessageAdditionalHeader> additionalHeader = message.getAdditionalHeader();
package org.opendaylight.controller.netconf.impl;
-import com.google.common.collect.Sets;
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
+import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider.NetconfOperationProviderUtil.getNetconfSessionIdForReporting;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
import org.opendaylight.protocol.framework.SessionListenerFactory;
import org.opendaylight.protocol.framework.SessionNegotiator;
import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.util.Set;
+import com.google.common.collect.Sets;
-import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider.NetconfOperationProviderUtil.getNetconfSessionIdForReporting;
+import io.netty.channel.Channel;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorFactory<NetconfHelloMessage, NetconfServerSession, NetconfServerSessionListener> {
- private static final Set<String> DEFAULT_CAPABILITIES = Sets.newHashSet(
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
- XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0);
+ public static final Set<String> DEFAULT_BASE_CAPABILITIES = ImmutableSet.of(
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0
+ );
private final Timer timer;
private final DefaultCommitNotificationProducer commitNotificationProducer;
private final SessionMonitoringService monitoringService;
private static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionNegotiatorFactory.class);
+ private final Set<String> baseCapabilities;
+
+ // TODO too many params, refactor
+ public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider,
+ SessionIdProvider idProvider, long connectionTimeoutMillis,
+ DefaultCommitNotificationProducer commitNot,
+ SessionMonitoringService monitoringService) {
+ this(timer, netconfOperationProvider, idProvider, connectionTimeoutMillis, commitNot, monitoringService, DEFAULT_BASE_CAPABILITIES);
+ }
+ // TODO too many params, refactor
public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider,
SessionIdProvider idProvider, long connectionTimeoutMillis,
- DefaultCommitNotificationProducer commitNot, SessionMonitoringService monitoringService) {
+ DefaultCommitNotificationProducer commitNot,
+ SessionMonitoringService monitoringService, Set<String> baseCapabilities) {
this.timer = timer;
this.netconfOperationProvider = netconfOperationProvider;
this.idProvider = idProvider;
this.connectionTimeoutMillis = connectionTimeoutMillis;
this.commitNotificationProducer = commitNot;
this.monitoringService = monitoringService;
+ this.baseCapabilities = validateBaseCapabilities(baseCapabilities);
+ }
+
+ private ImmutableSet<String> validateBaseCapabilities(final Set<String> baseCapabilities) {
+ // Check base capabilities to be supported by the server
+ Sets.SetView<String> unknownBaseCaps = Sets.difference(baseCapabilities, DEFAULT_BASE_CAPABILITIES);
+ Preconditions.checkArgument(unknownBaseCaps.isEmpty(),
+ "Base capabilities that will be supported by netconf server have to be subset of %s, unknown base capabilities: %s",
+ DEFAULT_BASE_CAPABILITIES, unknownBaseCaps);
+
+ ImmutableSet.Builder<String> b = ImmutableSet.builder();
+ b.addAll(baseCapabilities);
+ // Base 1.0 capability is supported by default
+ b.add(XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0);
+ return b.build();
}
/**
}
private NetconfHelloMessage createHelloMessage(long sessionId, CapabilityProvider capabilityProvider) throws NetconfDocumentedException {
- return NetconfHelloMessage.createServerHello(Sets.union(capabilityProvider.getCapabilities(), DEFAULT_CAPABILITIES), sessionId);
+ return NetconfHelloMessage.createServerHello(Sets.union(capabilityProvider.getCapabilities(), baseCapabilities), sessionId);
}
}
@Override
public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
- Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false,
+ Preconditions.checkArgument(!subsequentOperation.isExecutionTermination(),
"Subsequent netconf operation expected by %s", this);
if (isCommitWithoutNotification(requestMessage)) {
logger.debug("Skipping commit notification");
} else {
// Send commit notification if commit was not issued by persister
- requestMessage = removePersisterAttributes(requestMessage);
+ removePersisterAttributes(requestMessage);
Element cfgSnapshot = getConfigSnapshot(operationRouter);
logger.debug("Config snapshot retrieved successfully {}", cfgSnapshot);
notificationProducer.sendCommitNotification("ok", cfgSnapshot, cap.getCapabilities());
return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.increasePriority(1);
}
- private Document removePersisterAttributes(Document message) {
- final Element documentElement = message.getDocumentElement();
- documentElement.removeAttribute(NOTIFY_ATTR);
- return message;
+ private void removePersisterAttributes(Document message) {
+ message.getDocumentElement().removeAttribute(NOTIFY_ATTR);
}
private boolean isCommitWithoutNotification(Document message) {
String attr = xmlElement.getAttribute(NOTIFY_ATTR);
- if (attr == null || attr.equals(""))
+ if (attr == null || attr.equals("")){
return false;
- else if (attr.equals(Boolean.toString(false))) {
+ } else if (attr.equals(Boolean.toString(false))) {
logger.debug("Commit operation received with notify=false attribute {}", message);
return true;
} else {
private ServiceRegistration<NetconfMonitoringService> regMonitoring;
@Override
- public void start(final BundleContext context) throws Exception {
+ public void start(final BundleContext context) {
InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
"TCP is not configured, netconf not available.", false);
}
@Override
- public void stop(final BundleContext context) throws Exception {
+ public void stop(final BundleContext context) {
logger.info("Shutting down netconf because YangStoreService service was removed");
commitNot.close();
@Override
public void onSessionUp(NetconfManagementSession session) {
logger.debug("Session {} up", session);
- Preconditions.checkState(sessions.contains(session) == false, "Session %s was already added", session);
+ Preconditions.checkState(!sessions.contains(session), "Session %s was already added", session);
sessions.add(session);
}
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultNetconfOperation;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi;
-import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultNetconfOperation;
import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
+import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;
for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
final Set<NetconfOperation> netOpsFromService = netconfOperationService.getNetconfOperations();
for (NetconfOperation netconfOperation : netOpsFromService) {
- Preconditions.checkState(result.contains(netconfOperation) == false,
+ Preconditions.checkState(!result.contains(netconfOperation),
"Netconf operation %s already present", netconfOperation);
result.add(netconfOperation);
}
Preconditions.checkNotNull(allNetconfOperations, "Operation router was not initialized properly");
NetconfOperationExecution netconfOperationExecution;
- String messageAsString = XmlUtil.toString(message);
+ String messageAsString = "";
try {
+ messageAsString = XmlUtil.toString(message);
netconfOperationExecution = getNetconfOperationWithHighestPriority(message, session);
} catch (IllegalArgumentException | IllegalStateException e) {
logger.warn("Unable to handle rpc {} on session {}", messageAsString, session, e);
private NetconfOperationExecution getNetconfOperationWithHighestPriority(
Document message, NetconfServerSession session) throws NetconfDocumentedException {
- TreeMap<HandlingPriority, NetconfOperation> sortedByPriority = getSortedNetconfOperationsWithCanHandle(
+ NavigableMap<HandlingPriority, NetconfOperation> sortedByPriority = getSortedNetconfOperationsWithCanHandle(
message, session);
Preconditions.checkArgument(sortedByPriority.isEmpty() == false,
if (netconfOperation instanceof DefaultNetconfOperation) {
((DefaultNetconfOperation) netconfOperation).setNetconfSession(session);
}
- if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
+ if (!handlingPriority.equals(HandlingPriority.CANNOT_HANDLE)) {
- Preconditions.checkState(sortedPriority.containsKey(handlingPriority) == false,
+ Preconditions.checkState(!sortedPriority.containsKey(handlingPriority),
"Multiple %s available to handle message %s with priority %s",
NetconfOperation.class.getName(), message, handlingPriority);
sortedPriority.put(handlingPriority, netconfOperation);
}
public static NetconfOperationExecution createExecutionChain(
- TreeMap<HandlingPriority, NetconfOperation> sortedByPriority, HandlingPriority handlingPriority) {
+ NavigableMap<HandlingPriority, NetconfOperation> sortedByPriority, HandlingPriority handlingPriority) {
NetconfOperation netconfOperation = sortedByPriority.get(handlingPriority);
HandlingPriority subsequentHandlingPriority = sortedByPriority.lowerKey(handlingPriority);
package org.opendaylight.controller.netconf.impl;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import io.netty.channel.ChannelFuture;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.io.IOUtils;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
import org.opendaylight.controller.netconf.mapping.api.Capability;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
+import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import java.io.DataOutputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
+import com.google.common.collect.Sets;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.nio.NioEventLoopGroup;
+@RunWith(Parameterized.class)
public class ConcurrentClientsTest {
+ private static final Logger logger = LoggerFactory.getLogger(ConcurrentClientsTest.class);
- private static final int CONCURRENCY = 16;
- private EventLoopGroup nettyGroup;
- private NetconfClientDispatcher netconfClientDispatcher;
+ private static ExecutorService clientExecutor;
- private final InetSocketAddress netconfAddress = new InetSocketAddress("127.0.0.1", 8303);
+ private static final int CONCURRENCY = 32;
+ private static final InetSocketAddress netconfAddress = new InetSocketAddress("127.0.0.1", 8303);
- static final Logger logger = LoggerFactory.getLogger(ConcurrentClientsTest.class);
+ private int nettyThreads;
+ private Class<? extends Runnable> clientRunnable;
+ private Set<String> serverCaps;
- private DefaultCommitNotificationProducer commitNot;
- private NetconfServerDispatcher dispatch;
+ public ConcurrentClientsTest(int nettyThreads, Class<? extends Runnable> clientRunnable, Set<String> serverCaps) {
+ this.nettyThreads = nettyThreads;
+ this.clientRunnable = clientRunnable;
+ this.serverCaps = serverCaps;
+ }
+
+ @Parameterized.Parameters()
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {4, TestingNetconfClientRunnable.class, NetconfServerSessionNegotiatorFactory.DEFAULT_BASE_CAPABILITIES},
+ {1, TestingNetconfClientRunnable.class, NetconfServerSessionNegotiatorFactory.DEFAULT_BASE_CAPABILITIES},
+ // empty set of capabilities = only base 1.0 netconf capability
+ {4, TestingNetconfClientRunnable.class, Collections.emptySet()},
+ {4, TestingNetconfClientRunnable.class, getOnlyExiServerCaps()},
+ {4, TestingNetconfClientRunnable.class, getOnlyChunkServerCaps()},
+
+ {4, BlockingClientRunnable.class, getOnlyExiServerCaps()},
+ {1, BlockingClientRunnable.class, getOnlyExiServerCaps()},
+ });
+ }
+ private EventLoopGroup nettyGroup;
+ private NetconfClientDispatcher netconfClientDispatcher;
+ private DefaultCommitNotificationProducer commitNot;
HashedWheelTimer hashedWheelTimer;
+ private TestingNetconfOperation testingNetconfOperation;
public static SessionMonitoringService createMockedMonitoringService() {
SessionMonitoringService monitoring = mock(SessionMonitoringService.class);
return monitoring;
}
+ @BeforeClass
+ public static void setUpClientExecutor() {
+ clientExecutor = Executors.newFixedThreadPool(CONCURRENCY, new ThreadFactory() {
+ int i = 1;
+
+ @Override
+ public Thread newThread(final Runnable r) {
+ Thread thread = new Thread(r);
+ thread.setName("client-" + i++);
+ thread.setDaemon(true);
+ return thread;
+ }
+ });
+ }
+
@Before
public void setUp() throws Exception {
- nettyGroup = new NioEventLoopGroup();
+ nettyGroup = new NioEventLoopGroup(nettyThreads);
NetconfHelloMessageAdditionalHeader additionalHeader = new NetconfHelloMessageAdditionalHeader("uname", "10.10.10.1", "830", "tcp", "client");
netconfClientDispatcher = new NetconfClientDispatcher( nettyGroup, nettyGroup, additionalHeader, 5000);
NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
- factoriesListener.onAddNetconfOperationServiceFactory(mockOpF());
+
+ testingNetconfOperation = new TestingNetconfOperation();
+ factoriesListener.onAddNetconfOperationServiceFactory(new TestingOperationServiceFactory(testingNetconfOperation));
SessionIdProvider idProvider = new SessionIdProvider();
hashedWheelTimer = new HashedWheelTimer();
+
NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
- hashedWheelTimer, factoriesListener, idProvider, 5000, commitNot, createMockedMonitoringService());
+ hashedWheelTimer, factoriesListener, idProvider, 5000, commitNot, createMockedMonitoringService(), serverCaps);
commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
-
-
NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(serverNegotiatorFactory);
- dispatch = new NetconfServerDispatcher(serverChannelInitializer, nettyGroup, nettyGroup);
+ final NetconfServerDispatcher dispatch = new NetconfServerDispatcher(serverChannelInitializer, nettyGroup, nettyGroup);
ChannelFuture s = dispatch.createServer(netconfAddress);
s.await();
@After
public void tearDown(){
+ commitNot.close();
hashedWheelTimer.stop();
- nettyGroup.shutdownGracefully();
+ try {
+ nettyGroup.shutdownGracefully().get();
+ } catch (InterruptedException | ExecutionException e) {
+ logger.warn("Ignoring exception while cleaning up after test", e);
+ }
}
- private NetconfOperationServiceFactory mockOpF() {
- return new NetconfOperationServiceFactory() {
- @Override
- public NetconfOperationService createService(String netconfSessionIdForReporting) {
- return new NetconfOperationService() {
- @Override
- public Set<Capability> getCapabilities() {
- return Collections.emptySet();
- }
-
- @Override
- public Set<NetconfOperation> getNetconfOperations() {
- return Sets.<NetconfOperation> newHashSet(new NetconfOperation() {
- @Override
- public HandlingPriority canHandle(Document message) {
- return HandlingPriority.getHandlingPriority(Integer.MAX_VALUE);
- }
-
- @Override
- public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
- try {
- return XmlUtil.readXmlToDocument("<test/>");
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- });
- }
-
- @Override
- public void close() {
- }
- };
- }
- };
+ @AfterClass
+ public static void tearDownClientExecutor() {
+ clientExecutor.shutdownNow();
}
- @After
- public void cleanUp() throws Exception {
- commitNot.close();
- }
+ @Test(timeout = CONCURRENCY * 1000)
+ public void testConcurrentClients() throws Exception {
- @Test
- public void multipleClients() throws Exception {
- List<TestingThread> threads = new ArrayList<>();
+ List<Future<?>> futures = Lists.newArrayListWithCapacity(CONCURRENCY);
- final int attempts = 5;
for (int i = 0; i < CONCURRENCY; i++) {
- TestingThread thread = new TestingThread(String.valueOf(i), attempts);
- threads.add(thread);
- thread.start();
+ futures.add(clientExecutor.submit(getInstanceOfClientRunnable()));
}
- for (TestingThread thread : threads) {
- thread.join();
- if(thread.thrownException.isPresent()) {
- Exception exception = thread.thrownException.get();
- logger.error("Thread for testing client failed", exception);
- fail("Client thread " + thread + " failed: " + exception.getMessage());
+ for (Future<?> future : futures) {
+ try {
+ future.get();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException(e);
+ } catch (ExecutionException e) {
+ logger.error("Thread for testing client failed", e);
+ fail("Client failed: " + e.getMessage());
}
}
+
+ assertEquals(CONCURRENCY, testingNetconfOperation.getMessageCount());
}
- @Test
- public void synchronizationTest() throws Exception {
- new BlockingThread("foo").run2();
+ public static Set<String> getOnlyExiServerCaps() {
+ return Sets.newHashSet(
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0
+ );
}
- @Test
- public void multipleBlockingClients() throws Exception {
- List<BlockingThread> threads = new ArrayList<>();
- for (int i = 0; i < CONCURRENCY; i++) {
- BlockingThread thread = new BlockingThread(String.valueOf(i));
- threads.add(thread);
- thread.start();
+ public static Set<String> getOnlyChunkServerCaps() {
+ return Sets.newHashSet(
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1
+ );
+ }
+
+ public Runnable getInstanceOfClientRunnable() throws Exception {
+ return clientRunnable.getConstructor(ConcurrentClientsTest.class).newInstance(this);
+ }
+
+ /**
+ * Responds to all operations except start-exi and counts all requests
+ */
+ private static class TestingNetconfOperation implements NetconfOperation {
+
+ private final AtomicLong counter = new AtomicLong();
+
+ @Override
+ public HandlingPriority canHandle(Document message) {
+ return XmlUtil.toString(message).contains(NetconfStartExiMessage.START_EXI) ?
+ HandlingPriority.CANNOT_HANDLE :
+ HandlingPriority.HANDLE_WITH_MAX_PRIORITY;
}
- for (BlockingThread thread : threads) {
- thread.join();
- if(thread.thrownException.isPresent()) {
- Exception exception = thread.thrownException.get();
- logger.error("Thread for testing client failed", exception);
- fail("Client thread " + thread + " failed: " + exception.getMessage());
+ @Override
+ public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
+ try {
+ logger.info("Handling netconf message from test {}", XmlUtil.toString(requestMessage));
+ counter.getAndIncrement();
+ return XmlUtil.readXmlToDocument("<test/>");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
}
}
+
+ public long getMessageCount() {
+ return counter.get();
+ }
}
- class BlockingThread extends Thread {
- private Optional<Exception> thrownException;
+ /**
+ * Hardcoded operation service factory
+ */
+ private static class TestingOperationServiceFactory implements NetconfOperationServiceFactory {
+ private final NetconfOperation[] operations;
+
+ public TestingOperationServiceFactory(final NetconfOperation... operations) {
+ this.operations = operations;
+ }
- public BlockingThread(String name) {
- super("client-" + name);
+ @Override
+ public NetconfOperationService createService(String netconfSessionIdForReporting) {
+ return new NetconfOperationService() {
+ @Override
+ public Set<Capability> getCapabilities() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<NetconfOperation> getNetconfOperations() {
+ return Sets.newHashSet(operations);
+ }
+
+ @Override
+ public void close() {}
+ };
}
+ }
+
+ /**
+ * Pure socket based blocking client
+ */
+ public final class BlockingClientRunnable implements Runnable {
@Override
public void run() {
try {
run2();
- thrownException = Optional.absent();
} catch (Exception e) {
- thrownException = Optional.of(e);
+ throw new IllegalStateException(Thread.currentThread().getName(), e);
}
}
}
}
- class TestingThread extends Thread {
-
- private final String clientId;
- private final int attempts;
- private Optional<Exception> thrownException;
-
- TestingThread(String clientId, int attempts) {
- this.clientId = clientId;
- this.attempts = attempts;
- setName("client-" + clientId);
- }
+ /**
+ * TestingNetconfClient based runnable
+ */
+ public final class TestingNetconfClientRunnable implements Runnable {
@Override
public void run() {
try {
- final TestingNetconfClient netconfClient = new TestingNetconfClient(clientId, netconfAddress, netconfClientDispatcher);
+ final TestingNetconfClient netconfClient = new TestingNetconfClient(Thread.currentThread().getName(),
+ netconfAddress, netconfClientDispatcher);
long sessionId = netconfClient.getSessionId();
- logger.info("Client with sessionid {} hello exchanged", sessionId);
+ logger.info("Client with session id {}: hello exchanged", sessionId);
final NetconfMessage getMessage = XmlFileLoader
.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
NetconfMessage result = netconfClient.sendRequest(getMessage).get();
- logger.info("Client with sessionid {} got result {}", sessionId, result);
+ logger.info("Client with session id {}: got result {}", sessionId, result);
+
+ Preconditions.checkState(NetconfMessageUtil.isErrorMessage(result) == false,
+ "Received error response: " + XmlUtil.toString(result.getDocument()) + " to request: "
+ + XmlUtil.toString(getMessage.getDocument()));
+
netconfClient.close();
- logger.info("Client with session id {} ended", sessionId);
- thrownException = Optional.absent();
+ logger.info("Client with session id {}: ended", sessionId);
} catch (final Exception e) {
- thrownException = Optional.of(e);
+ throw new IllegalStateException(Thread.currentThread().getName(), e);
}
}
}
+++ /dev/null
-
-#24
-<rpc message-id="101" xm
-#28
-lns="urn:ietf:params:xml:ns:
-#2
-ne
-#33
-tconf:base:1.0">
- <my-own-method
-#3
- xm
-#13
-lns="http://e
-#34
-xample.net/me/my-own/1.0">
- <my
-#8
--first-p
-#21
-arameter>14</my-first
-#26
--parameter>
- <another-p
-#23
-arameter>fred</another-
-#31
-parameter>
- </my-own-method>
- <
-#2
-/r
-#3
-pc>
-##
+++ /dev/null
-
-#22
-<rpc message-id="101"
-#24
-xmlns="urn:ietf:params:x
-#15
-ml:ns:netconf:b
-#54
-ase:1.0">
- <get-config>
- <source>
- <r
-#2
-un
-#9
-ning/>
-
-#18
- </source> <fi
-#33
-lter type="subtree">
- <top x
-#4
-mlns
-#31
-="http://example.com/schema/1.2
-#15
-/config">
-
-#19
- <users>
-
-#8
- <us
-#3
-er/
-#5
->
-
-#77
- </users>
- </top>
- </filter>
- </g
-#17
-et-config>
-</rpc>
-##
+++ /dev/null
-
-#43
-<rpc message-id="101" xmlns="urn:ietf:param
-#14
-s:xml:ns:netco
-#14
-nf:base:1.0">
-
-#26
-<get-config>
- <source>
-
-#35
- <running/>
- </source>
-
-#39
- <filter type="subtree">
- <
-#40
-top xmlns="http://example.com/schema/1.2
-#26
-/config">
- <users>
-
-#36
- <user>
- <name>f
-#56
-red</name>
- </user>
- </users>
-
-#28
- </top>
- </fil
-#1
-t
-#28
-er>
- </get-config>
- </rpc>
-##
+++ /dev/null
-
-#17
-<rpc message-id="
-#25
-101" xmlns="urn:ietf:para
-#19
-ms:xml:ns:netconf:b
-#3
-ase
-#19
-:1.0">
- <get-confi
-#61
-g>
- <source>
- <running/>
- </source>
-
-#43
- <filter type="subtree">
- <!-- requ
-#13
-est a text ve
-#22
-rsion of the configura
-#9
-tion -->
-
-#16
- <config-text
-#45
-xmlns="http://example.com/text/1.2/config"/>
-
-#22
- </filter>
- </
-#18
-get-config>
-</rpc>
-##
+++ /dev/null
-
-#43
-<rpc message-id="101" xmlns="urn:ietf:param
-#41
-s:xml:ns:netconf:base:1.0">
- <edit-confi
-#29
-g>
- <target>
- <ru
-#13
-nning/>
- <
-#4
-/tar
-#18
-get>
- <config>
-
-#41
- <top xmlns="http://example.com/schema/1
-#32
-.2/config">
- <interface>
-
-#29
- <name>Ethernet0/0</na
-#30
-me>
- <mtu>1500</mtu>
-
-#61
-</interface>
- </top>
- </config>
- </e
-#9
-dit-confi
-#9
-g>
-</rpc>
-##
+++ /dev/null
-curl http://localhost:17777/jolokia/read/org.opendaylight.controller:instanceName=fixed1,type=ConfigBean,interfaceName=testing-threadpool | jsonpp
-{
- "request": {
- "mbean": "org.opendaylight.controller:instanceName=fixed1,interfaceName=testing-threadpool,type=ConfigBean",
- "type": "read"
- },
- "status": 200,
- "timestamp": 1362416252,
- "value": {
- "ExportedInterfaces": [
- "testing-threadpool",
- "modifiable-threadpool"
- ],
- "ImplementationName": "fixed",
- "ThreadCount": 10,
- "TriggerNewInstanceCreation": false
- }
-}
\ No newline at end of file
+++ /dev/null
-$ curl 'http://localhost:17777/jolokia/exec/org.opendaylight.controller:type=ConfigRegistry/lookupConfigBeans()' | jsonpp
-{
- "request": {
- "mbean": "org.opendaylight.controller:type=ConfigRegistry",
- "operation": "lookupConfigBeans()",
- "type": "exec"
- },
- "status": 200,
- "timestamp": 1362417043,
- "value": [
- {
- "objectName": "org.opendaylight.controller:instanceName=fixed1,interfaceName=modifiable-threadpool,type=ConfigBean"
- },
- {
- "objectName": "org.opendaylight.controller:instanceName=fixed1,interfaceName=testing-threadpool,type=ConfigBean"
- }
- ]
-}
+++ /dev/null
-<rpc message-id="104"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <commit/>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="102"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <lock>
- <target>
- <candidate/>
- </target>
- </lock>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="101"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <lock>
- <target>
- <running/>
- </target>
- </lock>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="103"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <edit-config>
- <target>
- <candidate/>
- </target>
- <default-operation>none</default-operation>
- <test-option>test-then-set</test-option>
- <error-option>stop-on-error</error-option>
- <nc:config
- xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
- xmlns="uri-for-my-data-model-namespace">
- <some-existing-node>
- <my-new-node nc:operation="create">
- <my-new-leaf>7</my-new-leaf>
- </my-new-node>
- </some-existing-node>
- </nc:config>
- </edit-config>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="105"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <unlock>
- <target>
- <candidate/>
- </target>
- </unlock>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="106"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <unlock>
- <target>
- <running/>
- </target>
- </unlock>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <rpc-error>
- <error-type>rpc</error-type>
- <error-tag>missing-attribute</error-tag>
- <error-severity>error</error-severity>
- <error-info>
- <bad-attribute>message-id</bad-attribute>
- <bad-element>rpc</bad-element>
- </error-info>
- </rpc-error>
-</rpc-reply>
+++ /dev/null
-{
- "value":null,
- "status":200,
- "request": {
- "type":"exec",
- "mbean":"java.util.logging:type=Logging",
- "operation":"setLoggerLevel",
- "arguments":["global","INFO"]
- }
-}
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <arguments>abc,bcd.aas</arguments>
- <arguments>64</arguments>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <arguments>
- <elements>22</elements>
- <elements>69</elements>
- </arguments>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <arguments>
- <map>
- <topology-registry>single</topology-registry>
- <bgp-update>mock</bgp-update>
- </map>
- <array>2</array>
- <array>22</array>
- <anotherArg>arg</anotherArg>
- </arguments>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<config>
- <jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <attribute>abc,bcd.aas</attribute>
- <attribute>22</attribute>
- </jmxbean>
- <jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>WRITE</type>
- <attribute>attribute</attribute>
- <value>22</value>
- </jmxbean>
- <jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <arguments>
- <map>
- <topology-registry>single</topology-registry>
- <bgp-update>mock</bgp-update>
- </map>
- <array>2</array>
- <array>22</array>
- <anotherArg>arg</anotherArg>
- </arguments>
- </jmxbean>
-</config>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>WRITE</type>
- <attribute>attribute</attribute>
- <value>22</value>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>WRITE</type>
- <attribute>attribute</attribute>
- <value>22</value>
- <value>222</value>
- <value>223</value>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>WRITE</type>
- <attribute>setAtr</attribute>
- <value>
- <abc>1</abc>
- <bcd>2</bcd>
- </value>
-</jmxbean>
+++ /dev/null
-{
- "timestamp":1362488209,
- "status":200,
- "request":{
- "mbean":"org.opendaylight.controller:type=ConfigRegistry",
- "attribute":"AvailableInterfacesAndImplementations",
- "type":"read"
- },
- "value":{
- "topology-registry":[
- "single"
- ],
- "bgp-update":[
- "mock",
- "bgp-impl"
- ],
- "positioning-service":[
- "combine",
- "onehop",
- "ondemand",
- "pxe",
- "precompute"
- ],
- "serializer":[
- "serializer-impl"
- ],
- "network-topology-factory":[
- "mock-xml",
- "bgp-network-topology-factory",
- "transient"
- ],
- "dwe-topology":[
- "ebgp",
- "defaultmetric",
- "igp",
- "network"
- ],
- "thread-factory":[
- "naming-thread-factory"
- ],
- "bgp-parser":[
- "parser"
- ],
- "pcep-dispatcher":[
- "dispatcher"
- ],
- "threadpool":[
- "flexible",
- "fixed",
- "scheduled"
- ],
- "scheduled-threadpool":[
- "scheduled"
- ],
- "positioning-onehop":[
- "onehop"
- ],
- "bgp-dispatcher":[
- "bgp-dispatcher-impl"
- ],
- "cost-combiner":[
- "pxe"
- ],
- "apsp-provider":[
- "jgrapht",
- "parallel",
- "single-threaded"
- ],
- "topology":[
- "ebgp",
- "defaultmetric",
- "igp",
- "network"
- ],
- "soap-resource":[
- "positioning-adaptor-pxe"
- ],
- "database-provider-factory":[
- "transient"
- ],
- "bgp-proposal-checker":[
- "bgp-proposal-checker-impl"
- ],
- "bgp-proposal":[
- "bgp-proposal-impl"
- ],
- "listenable-network-topology-factory":[
- "transient"
- ],
- "event-bus":[
- "sync",
- "async"
- ],
- "topology-registry-provider":[
- "single"
- ],
- "topology-provider-factory":[
- "transient"
- ],
- "rest-resource":[
- "topology-resource-holder",
- "alto-resource-holder",
- "topology-visual-holder",
- "network-resource-holder",
- "path-resource-holder"
- ],
- "listenable-database-provider-factory":[
- "transient"
- ],
- "topology-validator":[
- "accept-all",
- "threshold"
- ],
- "replicator":[
- "replicator-impl"
- ],
- "server":[
- "soap",
- "rest"
- ],
- "combiner-pxe":[
- "pxe"
- ],
- "rest":[
- "rest"
- ],
- "soap":[
- "soap"
- ],
- "path-service":[
- "cariden"
- ]
- }
-}
\ No newline at end of file
</properties>
<dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sal-binding-it</artifactId>
+ <exclusions>
+ <!-- FIXME see IdentityRefNetconfTest -->
+ <!-- Pax-url-aether contains guava classes e.g. ImmutableSet that clashes with guava and causes tests to fail-->
+ <exclusion>
+ <groupId>org.ops4j.pax.url</groupId>
+ <artifactId>pax-url-aether</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.logback_settings</artifactId>
<artifactId>netty-config-api</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>sal-binding-it</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang-test</artifactId>
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,NetconfITTest.getModuleFactoriesS().toArray(
new ModuleFactory[0])));
NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,getModuleFactories().toArray(
new ModuleFactory[0])));
NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.netty.channel.ChannelFuture;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
import junit.framework.Assert;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
-
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
import static java.util.Collections.emptyList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,getModuleFactories().toArray(
new ModuleFactory[0])));
loadMessages();
try {
c = sess.getStdout().read(bytes);
} catch (IOException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ throw new IllegalStateException("IO exception while reading data on ssh bridge.");
}
logger.info("got data:" + bytes);
if (c == 0) {
import org.mockito.Mock;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, NetconfITTest.getModuleFactoriesS().toArray(
new ModuleFactory[0])));
monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
/*
- * 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
- */
+* 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.it.pax;
import static org.junit.Assert.fail;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
-import javax.inject.Inject;
import javax.xml.parsers.ParserConfigurationException;
import org.junit.Assert;
public static final int CLIENT_CONNECTION_TIMEOUT_MILLIS = 15000;
// Wait for controller to start
- @Inject
+
+ // FIXME move this (pax) test to different module
+ // pax jars contain guava classes that clash with real guava dependencies in non-pax tests
+ //
+ //@Inject
@Filter(timeout = 60 * 1000)
BindingAwareBroker broker;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-public class HandlingPriority implements Comparable<HandlingPriority> {
+public final class HandlingPriority implements Comparable<HandlingPriority> {
public static final HandlingPriority CANNOT_HANDLE = new HandlingPriority();
public static final HandlingPriority HANDLE_WITH_DEFAULT_PRIORITY = new HandlingPriority(Integer.MIN_VALUE);
@Override
public int compareTo(HandlingPriority o) {
- if (this == o)
+ if (this == o){
return 0;
- if (this == CANNOT_HANDLE)
+ }
+ if (this.equals(CANNOT_HANDLE)){
return -1;
- if (o == CANNOT_HANDLE)
+ }
+ if (o.equals(CANNOT_HANDLE)){
return 1;
+ }
- if (priority > o.priority)
+ if (priority > o.priority){
return 1;
- if (priority == o.priority)
+ }
+ if (priority.equals(o.priority)){
return 0;
- if (priority < o.priority)
+ }
+ if (priority < o.priority){
return -1;
-
+ }
throw new IllegalStateException("Unexpected state");
}
@Override
public boolean equals(Object o) {
- if (this == o)
+ if (this == o){
return true;
- if (!(o instanceof HandlingPriority))
+ }
+ if (!(o instanceof HandlingPriority)){
return false;
+ }
HandlingPriority that = (HandlingPriority) o;
- if (priority != null ? !priority.equals(that.priority) : that.priority != null)
+ if (priority != null ? !priority.equals(that.priority) : that.priority != null){
return false;
+ }
return true;
}
*/
package org.opendaylight.controller.netconf.monitoring;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
@Override
public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
throws NetconfDocumentedException {
- Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false,
- "Subsequent netconf operation expected by %s", this);
+ if (subsequentOperation.isExecutionTermination()){
+ throw new NetconfDocumentedException(String.format("Subsequent netconf operation expected by %s", this),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
try {
Document innerResult = subsequentOperation.execute(requestMessage);
*/
package org.opendaylight.controller.netconf.monitoring;
-public class MonitoringConstants {
+public final class MonitoringConstants {
+ private MonitoringConstants(){
+ // not called - private constructor for utility class
+ }
public static final String MODULE_NAME = "ietf-netconf-monitoring";
public static final String MODULE_REVISION = "2010-10-04";
private NetconfMonitoringServiceTracker monitor;
@Override
- public void start(final BundleContext context) throws Exception {
+ public void start(final BundleContext context) {
monitor = new NetconfMonitoringServiceTracker(context);
monitor.open();
}
@Override
- public void stop(final BundleContext context) throws Exception {
+ public void stop(final BundleContext context) {
if(monitor!=null) {
try {
monitor.close();
*/
package org.opendaylight.controller.netconf.monitoring.osgi;
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.HashSet;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
import java.util.List;
import java.util.Set;
-
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.mapping.api.Capability;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.controller.netconf.monitoring.Get;
import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-import com.google.common.io.Files;
public class NetconfMonitoringOperationService implements NetconfOperationService {
- public static final HashSet<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
+ public static final Set<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
@Override
public String getCapabilityUri() {
this.monitor = monitor;
}
- private static String readSchema() {
- String schemaLocation = "/META-INF/yang/ietf-netconf-monitoring.yang";
- URL resource = Schemas.class.getClassLoader().getResource(schemaLocation);
- Preconditions.checkNotNull(resource, "Unable to read schema content from %s", schemaLocation);
- File file = new File(resource.getFile());
- try {
- return Files.toString(file, Charsets.UTF_8);
- } catch (IOException e) {
- throw new RuntimeException("Unable to load schema from " + schemaLocation, e);
- }
- }
-
@Override
public Set<Capability> getCapabilities() {
return CAPABILITIES;
import java.util.concurrent.atomic.AtomicLong;
@ThreadSafe
-public class NetconfSSHServer implements Runnable {
+public final class NetconfSSHServer implements Runnable {
private ServerSocket ss = null;
private static final Logger logger = LoggerFactory.getLogger(NetconfSSHServer.class);
private final AuthProvider authProvider;
private boolean up = false;
- private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws Exception{
+ private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws IllegalStateException, IOException {
logger.trace("Creating SSH server socket on port {}",serverPort);
this.ss = new ServerSocket(serverPort);
if (!ss.isBound()){
- throw new Exception("Socket can't be bound to requested port :"+serverPort);
+ throw new IllegalStateException("Socket can't be bound to requested port :"+serverPort);
}
logger.trace("Server socket created.");
this.clientAddress = clientAddress;
this.up = true;
}
- public static NetconfSSHServer start(int serverPort, InetSocketAddress clientAddress,AuthProvider authProvider) throws Exception {
+ public static NetconfSSHServer start(int serverPort, InetSocketAddress clientAddress,AuthProvider authProvider) throws IllegalStateException, IOException {
return new NetconfSSHServer(serverPort, clientAddress,authProvider);
}
- public void stop() throws Exception {
+ public void stop() throws IOException {
up = false;
logger.trace("Closing SSH server socket.");
ss.close();
*/
package org.opendaylight.controller.netconf.ssh.authentication;
+import java.io.IOException;
import org.opendaylight.controller.sal.authorization.AuthResultEnum;
-import org.opendaylight.controller.sal.authorization.UserLevel;
import org.opendaylight.controller.usermanager.IUserManager;
-import org.opendaylight.controller.usermanager.UserConfig;
-
-import java.util.ArrayList;
-import java.util.List;
-
import static com.google.common.base.Preconditions.checkNotNull;
public class AuthProvider implements AuthProviderInterface {
- private static IUserManager um; //FIXME static mutable state, no locks
- private static final String DEFAULT_USER = "netconf";
- private static final String DEFAULT_PASSWORD = "netconf";
+ private IUserManager um;
private final String pem;
- public AuthProvider(IUserManager ium, String pemCertificate) throws Exception {
+ public AuthProvider(IUserManager ium, String pemCertificate) throws IllegalArgumentException, IOException {
checkNotNull(pemCertificate, "Parameter 'pemCertificate' is null");
- AuthProvider.um = ium;
- if (AuthProvider.um == null) {
- throw new Exception("No usermanager service available.");
- }
-
- List<String> roles = new ArrayList<String>(1);
- roles.add(UserLevel.SYSTEMADMIN.toString());
- AuthProvider.um.addLocalUser(new UserConfig(DEFAULT_USER, DEFAULT_PASSWORD, roles)); //FIXME hardcoded auth
+ checkNotNull(ium, "No user manager service available.");
+ this.um = ium;
pem = pemCertificate;
}
@Override
- public boolean authenticated(String username, String password) throws Exception {
- if (AuthProvider.um == null) {
- throw new Exception("No usermanager service available.");
- }
- AuthResultEnum authResult = AuthProvider.um.authenticate(username, password);
+ public boolean authenticated(String username, String password) {
+ AuthResultEnum authResult = this.um.authenticate(username, password);
return authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC);
}
@Override
public void removeUserManagerService() {
- AuthProvider.um = null;
+ this.um = null;
}
@Override
public void addUserManagerService(IUserManager userManagerService) {
- AuthProvider.um = userManagerService;
+ this.um = userManagerService;
}
}
public interface AuthProviderInterface {
- public boolean authenticated(String username, String password) throws Exception;
+ public boolean authenticated(String username, String password) throws IllegalStateException;
public char[] getPEMAsCharArray() throws Exception;
public void removeUserManagerService();
public void addUserManagerService(IUserManager userManagerService);
package org.opendaylight.controller.netconf.ssh.osgi;
import com.google.common.base.Optional;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
+import org.opendaylight.controller.sal.authorization.UserLevel;
import org.opendaylight.controller.usermanager.IUserManager;
+import org.opendaylight.controller.usermanager.UserConfig;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.InetSocketAddress;
+import static com.google.common.base.Preconditions.checkNotNull;
/**
* Activator for netconf SSH bundle which creates SSH bridge between netconf client and netconf server. Activator
* starts SSH Server in its own thread. This thread is closed when activator calls stop() method. Server opens socket
- * and listen for client connections. Each client connection creation is handled in separate
+ * and listens for client connections. Each client connection creation is handled in separate
* {@link org.opendaylight.controller.netconf.ssh.threads.SocketThread} thread.
* This thread creates two additional threads {@link org.opendaylight.controller.netconf.ssh.threads.IOThread}
* forwarding data from/to client.IOThread closes servers session and server connection when it gets -1 on input stream.
private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
private IUserManager iUserManager;
private BundleContext context = null;
+ private Optional<String> defaultPassword;
+ private Optional<String> defaultUser;
- ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
+ private ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
@Override
public IUserManager addingService(ServiceReference<IUserManager> reference) {
logger.trace("Service {} added, let there be SSH bridge.", reference);
@Override
- public void start(BundleContext context) throws Exception {
+ public void start(BundleContext context) {
this.context = context;
listenForManagerService();
}
@Override
- public void stop(BundleContext context) throws Exception {
+ public void stop(BundleContext context) throws IOException {
+ if (this.defaultUser.isPresent()){
+ this.iUserManager.removeLocalUser(this.defaultUser.get());
+ }
if (server != null){
server.stop();
logger.trace("Netconf SSH bridge is down ...");
}
}
- private void startSSHServer() throws Exception {
+ private void startSSHServer() throws IllegalStateException, IOException {
+ checkNotNull(this.iUserManager, "No user manager service available.");
logger.trace("Starting netconf SSH bridge.");
Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
EXCEPTION_MESSAGE, true);
if (sshSocketAddressOptional.isPresent()){
- String path = NetconfConfigUtil.getPrivateKeyPath(context);
- path = path.replace("\\", "/"); // FIXME: shouldn't this convert lines to system dependent path separator?
+ String path = FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(context));
if (path.equals("")){
- throw new Exception("Missing netconf.ssh.pk.path key in configuration file.");
+ throw new IllegalStateException("Missing netconf.ssh.pk.path key in configuration file.");
}
File privateKeyFile = new File(path);
- String privateKeyPEMString;
+ String privateKeyPEMString = null;
if (privateKeyFile.exists() == false) {
- // generate & save to file
- privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
+ try {
+ privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
+ } catch (Exception e) {
+ logger.error("Exception occurred while generating PEM string {}",e);
+ }
} else {
// read from file
try (FileInputStream fis = new FileInputStream(path)) {
throw new IllegalStateException("Error reading RSA key from file " + path);
}
}
- AuthProvider authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
+ AuthProvider authProvider = null;
+ try {
+ this.defaultPassword = NetconfConfigUtil.getSSHDefaultPassword(context);
+ this.defaultUser = NetconfConfigUtil.getSSHDefaultUser(context);
+ // Since there is no user data store yet (ldap, ...) this adds default user/password to UserManager
+ // if these parameters are set in netconf configuration file.
+ if (defaultUser.isPresent() &&
+ defaultPassword.isPresent()){
+ logger.trace(String.format("Default username and password for netconf ssh bridge found. Adding user %s to user manager.",defaultUser.get()));
+ List<String> roles = new ArrayList<String>(1);
+ roles.add(UserLevel.SYSTEMADMIN.toString());
+ iUserManager.addLocalUser(new UserConfig(defaultUser.get(), defaultPassword.get(), roles));
+ }
+ authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
+ } catch (Exception e) {
+ logger.error("Error instantiating AuthProvider {}",e);
+ }
this.server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress,authProvider);
Thread serverThread = new Thread(server,"netconf SSH server thread");
logger.trace("Netconf SSH bridge up and running.");
} else {
logger.trace("No valid connection configuration for SSH bridge found.");
- throw new Exception("No valid connection configuration for SSH bridge found.");
+ throw new IllegalStateException("No valid connection configuration for SSH bridge found.");
}
}
- private void onUserManagerFound(IUserManager userManager) throws Exception{
+ private void onUserManagerFound(IUserManager userManager) throws IOException {
if (server!=null && server.isUp()){
server.addUserManagerService(userManager);
} else {
if (netconf_ssh_input != null) {
netconf_ssh_input.join();
}
- } catch (InterruptedException e) {
+ } catch (InterruptedException e1) {
Thread.currentThread().interrupt();
- logger.error("netconf_ssh_input join error ", e);
+ logger.error("netconf_ssh_input join error ", e1);
}
try {
if (netconf_ssh_output != null) {
netconf_ssh_output.join();
}
- } catch (InterruptedException e) {
+ } catch (InterruptedException e2) {
Thread.currentThread().interrupt();
- logger.error("netconf_ssh_output join error ", e);
+ logger.error("netconf_ssh_output join error ", e2);
}
}
} else {
@Override
public ChannelFuture sendMessage(final NetconfMessage netconfMessage) {
final ChannelFuture future = channel.writeAndFlush(netconfMessage);
- if (delayedEncoder !=null) {
+ if (delayedEncoder != null) {
replaceMessageEncoder(delayedEncoder);
delayedEncoder = null;
}
return sb.toString();
}
- protected <T extends ChannelHandler> T removeHandler(final Class<T> handlerType) {
- return this.channel.pipeline().remove(handlerType);
- }
-
- protected void replaceMessageDecoder(final ChannelHandler handler) {
+ protected final void replaceMessageDecoder(final ChannelHandler handler) {
replaceChannelHandler(AbstractChannelInitializer.NETCONF_MESSAGE_DECODER, handler);
}
- protected void replaceMessageEncoder(final ChannelHandler handler) {
+ protected final void replaceMessageEncoder(final ChannelHandler handler) {
replaceChannelHandler(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER, handler);
}
- protected void replaceMessageEncoderAfterNextMessage(final ChannelHandler handler) {
+ protected final void replaceMessageEncoderAfterNextMessage(final ChannelHandler handler) {
this.delayedEncoder = handler;
}
- protected void replaceChannelHandler(final String handlerName, final ChannelHandler handler) {
+ protected final void replaceChannelHandler(final String handlerName, final ChannelHandler handler) {
channel.pipeline().replace(handlerName, handlerName, handler);
}
}
final NetconfEXICodec exiCodec = new NetconfEXICodec(exiParams.getOptions());
addExiHandlers(exiCodec);
- logger.debug("EXI handlers added to pipeline on session {}", this);
+ logger.debug("Session {} EXI handlers added to pipeline", this);
}
protected abstract void addExiHandlers(NetconfEXICodec exiCodec);
import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
}
@Override
- protected void startNegotiation() {
+ protected final void startNegotiation() {
final Optional<SslHandler> sslHandler = getSslHandler(channel);
if (sslHandler.isPresent()) {
Future<Channel> future = sslHandler.get().handshakeFuture();
// FIXME, make sessionPreferences return HelloMessage, move NetconfHelloMessage to API
sendMessage((NetconfHelloMessage)helloMessage);
+
+ replaceHelloMessageOutboundHandler();
changeState(State.OPEN_WAIT);
}
+
private void cancelTimeout() {
if(timeout!=null) {
timeout.cancel();
}
}
- @Override
- protected void handleMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException {
- S session = getSessionForHelloMessage(netconfMessage) ;
- negotiationSuccessful(session);
- }
-
protected final S getSessionForHelloMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException {
Preconditions.checkNotNull(netconfMessage, "netconfMessage");
final Document doc = netconfMessage.getDocument();
- replaceHelloMessageHandlers();
-
if (shouldUseChunkFraming(doc)) {
insertChunkFramingToPipeline();
}
/**
* Insert chunk framing handlers into the pipeline
*/
- protected void insertChunkFramingToPipeline() {
+ private void insertChunkFramingToPipeline() {
replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_FRAME_ENCODER,
FramingMechanismHandlerFactory.createHandler(FramingMechanism.CHUNK));
replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_AGGREGATOR,
new NetconfChunkAggregator());
}
- protected boolean shouldUseChunkFraming(Document doc) {
+ private boolean shouldUseChunkFraming(Document doc) {
return containsBase11Capability(doc)
&& containsBase11Capability(sessionPreferences.getHelloMessage().getDocument());
}
/**
- * Remove special handlers for hello message. Insert regular netconf xml message (en|de)coders.
+ * Remove special inbound handler for hello message. Insert regular netconf xml message (en|de)coders.
+ *
+ * Inbound hello message handler should be kept until negotiation is successful
+ * It caches any non-hello messages while negotiation is still in progress
+ */
+ protected final void replaceHelloMessageInboundHandler(final S session) {
+ ChannelHandler helloMessageHandler = replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_DECODER, new NetconfXMLToMessageDecoder());
+
+ Preconditions.checkState(helloMessageHandler instanceof NetconfXMLToHelloMessageDecoder,
+ "Pipeline handlers misplaced on session: %s, pipeline: %s", session, channel.pipeline());
+ Iterable<NetconfMessage> netconfMessagesFromNegotiation =
+ ((NetconfXMLToHelloMessageDecoder) helloMessageHandler).getPostHelloNetconfMessages();
+
+ // Process messages received during negotiation
+ // The hello message handler does not have to be synchronized, since it is always call from the same thread by netty
+ // It means, we are now using the thread now
+ for (NetconfMessage message : netconfMessagesFromNegotiation) {
+ session.handleMessage(message);
+ }
+ }
+
+ /**
+ * Remove special outbound handler for hello message. Insert regular netconf xml message (en|de)coders.
*/
- protected void replaceHelloMessageHandlers() {
- replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_DECODER, new NetconfXMLToMessageDecoder());
+ private void replaceHelloMessageOutboundHandler() {
replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER, new NetconfMessageToXMLEncoder());
}
protected abstract S getSession(L sessionListener, Channel channel, NetconfHelloMessage message) throws NetconfDocumentedException;
- protected synchronized void changeState(final State newState) {
+ private synchronized void changeState(final State newState) {
logger.debug("Changing state from : {} to : {}", state, newState);
Preconditions.checkState(isStateChangePermitted(state, newState), "Cannot change state from %s to %s", state,
newState);
}
@Override
- protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
+ protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) {
while (msg.readableBytes() > chunkSize) {
ByteBuf chunk = Unpooled.buffer(chunkSize);
chunk.writeBytes(createChunkHeader(chunkSize));
public class EOMFramingMechanismEncoder extends MessageToByteEncoder<ByteBuf> {
@Override
- protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
+ protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) {
out.writeBytes(msg);
out.writeBytes(NetconfMessageConstants.END_OF_MESSAGE);
}
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.MessageToByteEncoder;
-public class FramingMechanismHandlerFactory {
+public final class FramingMechanismHandlerFactory {
private static final Logger logger = LoggerFactory.getLogger(FramingMechanismHandlerFactory.class);
- private FramingMechanismHandlerFactory() {}
+ private FramingMechanismHandlerFactory() {
+ // not called - private constructor for utility class
+ }
public static MessageToByteEncoder<ByteBuf> createHandler(FramingMechanism framingMechanism) {
logger.debug("{} framing mechanism was selected.", framingMechanism);
public class NetconfChunkAggregator extends ByteToMessageDecoder {
private final static Logger logger = LoggerFactory.getLogger(NetconfChunkAggregator.class);
+ private static final String GOT_PARAM_WHILE_WAITING_FOR_PARAM = "Got byte {} while waiting for {}";
+ private static final String GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM = "Got byte {} while waiting for {}-{}";
public static final int DEFAULT_MAXIMUM_CHUNK_SIZE = 16 * 1024 * 1024;
private static enum State {
private long chunkSize;
private CompositeByteBuf chunk;
+ private void checkNewLine(byte b,String errorMessage){
+ if (b != '\n') {
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM, b, (byte)'\n');
+ throw new IllegalStateException(errorMessage);
+ }
+ }
+
+ private void checkHash(byte b,String errorMessage){
+ if (b != '#') {
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM, b, (byte)'#');
+ throw new IllegalStateException(errorMessage);
+ }
+ }
+
+ private void checkChunkSize(){
+ if (chunkSize > maxChunkSize) {
+ logger.debug("Parsed chunk size {}, maximum allowed is {}", chunkSize, maxChunkSize);
+ throw new IllegalStateException("Maximum chunk size exceeded");
+ }
+
+ }
@Override
- protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws IllegalStateException {
while (in.isReadable()) {
switch (state) {
case HEADER_ONE:
{
final byte b = in.readByte();
- if (b != '\n') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
- throw new IllegalStateException("Malformed chunk header encountered (byte 0)");
- }
+ checkNewLine(b, "Malformed chunk header encountered (byte 0)");
state = State.HEADER_TWO;
case HEADER_TWO:
{
final byte b = in.readByte();
- if (b != '#') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
- throw new IllegalStateException("Malformed chunk header encountered (byte 1)");
- }
+ checkHash(b, "Malformed chunk header encountered (byte 1)");
state = State.HEADER_LENGTH_FIRST;
break;
}
if (b < '0' || b > '9') {
- logger.debug("Got byte {} while waiting for {}-{}", b, (byte)'0', (byte)'9');
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM, b, (byte)'0', (byte)'9');
throw new IllegalStateException("Invalid chunk size encountered");
}
chunkSize *= 10;
chunkSize += b - '0';
-
- if (chunkSize > maxChunkSize) {
- logger.debug("Parsed chunk size {}, maximum allowed is {}", chunkSize, maxChunkSize);
- throw new IllegalStateException("Maximum chunk size exceeded");
- }
+ checkChunkSize();
break;
}
case DATA:
in.discardReadBytes();
return;
}
-
aggregateChunks(in.readBytes((int) chunkSize));
state = State.FOOTER_ONE;
break;
case FOOTER_ONE:
{
final byte b = in.readByte();
- if (b != '\n') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
- throw new IllegalStateException("Malformed chunk footer encountered (byte 0)");
- }
-
+ checkNewLine(b,"Malformed chunk footer encountered (byte 0)");
state = State.FOOTER_TWO;
chunkSize = 0;
break;
case FOOTER_TWO:
{
final byte b = in.readByte();
-
- if (b != '#') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
- throw new IllegalStateException("Malformed chunk footer encountered (byte 1)");
- }
-
+ checkHash(b,"Malformed chunk footer encountered (byte 1)");
state = State.FOOTER_THREE;
break;
}
// In this state, either header-of-new-chunk or message-end is expected
// Depends on the next character
- if (isHeaderLengthFirst(b)) {
- // Extract header length#1 from new chunk
- chunkSize = processHeaderLengthFirst(b);
- // Proceed with next chunk processing
- state = State.HEADER_LENGTH_OTHER;
- } else if (b == '#') {
- state = State.FOOTER_FOUR;
- } else {
- logger.debug("Got byte {} while waiting for {} or {}-{}", b, (byte) '#', (byte) '1', (byte) '9');
- throw new IllegalStateException("Malformed chunk footer encountered (byte 2)");
- }
+ extractNewChunkOrMessageEnd(b);
break;
}
case FOOTER_FOUR:
{
final byte b = in.readByte();
- if (b != '\n') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
- throw new IllegalStateException("Malformed chunk footer encountered (byte 3)");
- }
-
+ checkNewLine(b,"Malformed chunk footer encountered (byte 3)");
state = State.HEADER_ONE;
out.add(chunk);
chunk = null;
in.discardReadBytes();
}
+ private void extractNewChunkOrMessageEnd(byte b) {
+ if (isHeaderLengthFirst(b)) {
+ // Extract header length#1 from new chunk
+ chunkSize = processHeaderLengthFirst(b);
+ // Proceed with next chunk processing
+ state = State.HEADER_LENGTH_OTHER;
+ } else if (b == '#') {
+ state = State.FOOTER_FOUR;
+ } else {
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM, b, (byte) '#', (byte) '1', (byte) '9');
+ throw new IllegalStateException("Malformed chunk footer encountered (byte 2)");
+ }
+ }
+
private void initChunk() {
chunk = Unpooled.compositeBuffer();
}
}
private static int processHeaderLengthFirst(byte b) {
- if (isHeaderLengthFirst(b) == false) {
- logger.debug("Got byte {} while waiting for {}-{}", b, (byte)'1', (byte)'9');
+ if (!isHeaderLengthFirst(b)) {
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM, b, (byte)'1', (byte)'9');
throw new IllegalStateException("Invalid chunk size encountered (byte 0)");
}
private final static Logger logger = LoggerFactory.getLogger(NetconfEOMAggregator.class);
@Override
- protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
int index = indexOfSequence(in, NetconfMessageConstants.END_OF_MESSAGE);
if (index == -1) {
logger.debug("Message is not complete, read again.");
private static final Logger LOG = LoggerFactory.getLogger(NetconfEXIToMessageDecoder.class);
-// private static final SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
-
private final NetconfEXICodec codec;
public NetconfEXIToMessageDecoder(final NetconfEXICodec codec) {
* the use of EXI, which means the next message needs to be decoded not by us, but rather
* by the XML decoder.
*/
- // If empty Byte buffer is passed to r.parse, EOFException is thrown
- if (in.readableBytes() == 0) {
+ // If empty Byte buffer is passed to r.parse, EOFException is thrown
+ if (in.isReadable() == false) {
LOG.debug("No more content in incoming buffer.");
return;
}
final DOMResult domResult = new DOMResult();
handler.setResult(domResult);
-
try (final InputStream is = new ByteBufInputStream(in)) {
r.parse(new InputSource(is));
}
*/
package org.opendaylight.controller.netconf.util.handler;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
+import org.xml.sax.SAXException;
/**
* Customized NetconfXMLToMessageDecoder that reads additional header with
* session metadata from
* {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage}
- * . Used by netconf server to retrieve information about session metadata.
+ *
+ *
+ * This handler should be replaced in pipeline by regular message handler as last step of negotiation.
+ * It serves as a message barrier and halts all non-hello netconf messages.
+ * Netconf messages after hello should be processed once the negotiation succeeded.
+ *
*/
public final class NetconfXMLToHelloMessageDecoder extends ByteToMessageDecoder {
private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToHelloMessageDecoder.class);
new byte[] { '\r', '\n', '[' },
new byte[] { '\n', '[' });
+ // State variables do not have to by synchronized
+ // Netty uses always the same (1) thread per pipeline
+ // We use instance of this per pipeline
+ private List<NetconfMessage> nonHelloMessages = Lists.newArrayList();
+ private boolean helloReceived = false;
+
@Override
@VisibleForTesting
- public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+ public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws IOException, SAXException, NetconfDocumentedException {
if (in.readableBytes() == 0) {
LOG.debug("No more content in incoming buffer.");
return;
Document doc = XmlUtil.readXmlToDocument(new ByteArrayInputStream(bytes));
- final NetconfMessage message;
- if (additionalHeader != null) {
- message = new NetconfHelloMessage(doc, NetconfHelloMessageAdditionalHeader.fromString(additionalHeader));
+ final NetconfMessage message = getNetconfMessage(additionalHeader, doc);
+ if (message instanceof NetconfHelloMessage) {
+ Preconditions.checkState(helloReceived == false,
+ "Multiple hello messages received, unexpected hello: %s",
+ XmlUtil.toString(message.getDocument()));
+ out.add(message);
+ helloReceived = true;
+ // Non hello message, suspend the message and insert into cache
} else {
- message = new NetconfHelloMessage(doc);
+ Preconditions.checkState(helloReceived, "Hello message not received, instead received: %s",
+ XmlUtil.toString(message.getDocument()));
+ LOG.debug("Netconf message received during negotiation, caching {}",
+ XmlUtil.toString(message.getDocument()));
+ nonHelloMessages.add(message);
}
- out.add(message);
} finally {
in.discardReadBytes();
}
}
+ private NetconfMessage getNetconfMessage(final String additionalHeader, final Document doc) throws NetconfDocumentedException {
+ NetconfMessage msg = new NetconfMessage(doc);
+ if(NetconfHelloMessage.isHelloMessage(msg)) {
+ if (additionalHeader != null) {
+ return new NetconfHelloMessage(doc, NetconfHelloMessageAdditionalHeader.fromString(additionalHeader));
+ } else {
+ return new NetconfHelloMessage(doc);
+ }
+ }
+
+ return msg;
+ }
+
private int getAdditionalHeaderEndIndex(byte[] bytes) {
for (byte[] possibleEnd : POSSIBLE_ENDS) {
int idx = findByteSequence(bytes, possibleEnd);
return Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString();
}
+ /**
+ * @return Collection of NetconfMessages that were not hello, but were received during negotiation
+ */
+ public Iterable<NetconfMessage> getPostHelloNetconfMessages() {
+ return nonHelloMessages;
+ }
}
*/
package org.opendaylight.controller.netconf.util.handler;
-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 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;
+
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) {
LOG.trace("Received to decode: {}", ByteBufUtil.hexDump(in));
out.add(new NetconfMessage(XmlUtil.readXmlToDocument(new ByteBufInputStream(in))));
public void authenticate(Connection connection) throws IOException {
boolean isAuthenticated = connection.authenticateWithPassword(username, password);
- if (isAuthenticated == false) {
+ if (!isAuthenticated) {
throw new IOException("Authentication failed.");
}
}
}
public void close() {
- for (SshSession session : openSessions.values())
+ for (SshSession session : openSessions.values()){
closeSession(session);
+ }
openSessions.clear();
}
}
- while (stopRequested.get() == false) {
+ while (!stopRequested.get()) {
byte[] readBuff = new byte[BUFFER_SIZE];
int c = stdOut.read(readBuff);
if (c == -1) {
// Netty closed connection prematurely.
// Just pass and move on.
} catch (Exception e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
} finally {
sshClient.close();
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
-
import java.io.IOException;
import java.io.InputStream;
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
return this.bb.readByte() & 0xFF;
package org.opendaylight.controller.netconf.util.messages;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
+
+import java.util.Set;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import java.util.Set;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
/**
* NetconfMessage that can carry additional header with session metadata. See {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader}
return additionalHeader== null ? Optional.<NetconfHelloMessageAdditionalHeader>absent() : Optional.of(additionalHeader);
}
- private static void checkHelloMessage(Document doc) throws NetconfDocumentedException {
- XmlElement.fromDomElementWithExpected(doc.getDocumentElement(), HELLO_TAG,
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
-
+ private static void checkHelloMessage(Document doc) {
+ Preconditions.checkArgument(isHelloMessage(doc),
+ "Hello message invalid format, should contain %s tag from namespace %s, but is: %s", HELLO_TAG,
+ XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, XmlUtil.toString(doc));
}
public static NetconfHelloMessage createClientHello(Iterable<String> capabilities,
doc.getDocumentElement().appendChild(sessionIdElement);
return new NetconfHelloMessage(doc);
}
+
+ public static boolean isHelloMessage(final NetconfMessage msg) {
+ Document document = msg.getDocument();
+ return isHelloMessage(document);
+ }
+
+ private static boolean isHelloMessage(final Document document) {
+ XmlElement element = XmlElement.fromDomElement(document.getDocumentElement());
+ try {
+ return element.getName().equals(HELLO_TAG) &&
+ element.hasNamespace() &&
+ element.getNamespace().equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ } catch (MissingNameSpaceException e) {
+ // Cannot happen, since we check for hasNamespace
+ throw new IllegalStateException(e);
+ }
+ }
}
import com.google.common.base.Charsets;
-public class NetconfMessageConstants {
+public final class NetconfMessageConstants {
+
+ private NetconfMessageConstants(){}
/**
* The NETCONF 1.0 old-style message separator. This is framing mechanism
* is used by default.
public static final int MAX_HEADER_LENGTH = 13;
public static final byte[] END_OF_CHUNK = "\n##\n".getBytes(Charsets.UTF_8);
+
}
import com.google.common.base.Preconditions;
import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
final NetconfDocumentedException sendErrorException) {
logger.trace("Sending error {}", sendErrorException.getMessage(), sendErrorException);
final Document errorDocument = createDocument(sendErrorException);
- session.sendMessage(new NetconfMessage(errorDocument));
+ ChannelFuture f = session.sendMessage(new NetconfMessage(errorDocument));
+ f.addListener(new SendErrorVerifyingListener(sendErrorException));
}
public static void sendErrorMessage(Channel channel, NetconfDocumentedException sendErrorException) {
logger.trace("Sending error {}", sendErrorException.getMessage(), sendErrorException);
final Document errorDocument = createDocument(sendErrorException);
- channel.writeAndFlush(new NetconfMessage(errorDocument));
+ ChannelFuture f = channel.writeAndFlush(new NetconfMessage(errorDocument));
+ f.addListener(new SendErrorVerifyingListener(sendErrorException));
}
public static void sendErrorMessage(NetconfSession session, NetconfDocumentedException sendErrorException,
final Document errorDocument = createDocument(sendErrorException);
logger.trace("Sending error {}", XmlUtil.toString(errorDocument));
tryToCopyAttributes(incommingMessage.getDocument(), errorDocument, sendErrorException);
- session.sendMessage(new NetconfMessage(errorDocument));
+ ChannelFuture f = session.sendMessage(new NetconfMessage(errorDocument));
+ f.addListener(new SendErrorVerifyingListener(sendErrorException));
}
private static void tryToCopyAttributes(final Document incommingDocument, final Document errorDocument,
XPathConstants.NODE);
errorSeverityNode.setTextContent(sendErrorException.getErrorSeverity().getTagValue());
- if (sendErrorException.getErrorInfo() != null && sendErrorException.getErrorInfo().isEmpty() == false) {
+ if (sendErrorException.getErrorInfo() != null && !sendErrorException.getErrorInfo().isEmpty()) {
/*
* <error-info> <bad-attribute>message-id</bad-attribute>
* <bad-element>rpc</bad-element> </error-info>
return errorDocument;
}
+ /**
+ * Checks if netconf error was sent successfully.
+ */
+ private static final class SendErrorVerifyingListener implements ChannelFutureListener {
+ private final NetconfDocumentedException sendErrorException;
+
+ public SendErrorVerifyingListener(final NetconfDocumentedException sendErrorException) {
+ this.sendErrorException = sendErrorException;
+ }
+
+ @Override
+ public void operationComplete(final ChannelFuture channelFuture) throws Exception {
+ Preconditions.checkState(channelFuture.isSuccess(), "Unable to send exception {}", sendErrorException,
+ channelFuture.cause());
+ }
+ }
}
package org.opendaylight.controller.netconf.util.osgi;
import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import java.net.InetSocketAddress;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import java.net.InetSocketAddress;
-
import static com.google.common.base.Preconditions.checkNotNull;
public final class NetconfConfigUtil {
private static final String ADDRESS_SUFFIX_PROP = ".address";
private static final String CLIENT_PROP = ".client";
private static final String PRIVATE_KEY_PATH_PROP = ".pk.path";
+ private static final String SSH_DEFAULT_USER = ".default.user";
+ private static final String SSH_DEFAULT_PASSWORD = ".default.password";
private static final String CONNECTION_TIMEOUT_MILLIS_PROP = "connectionTimeoutMillis";
private static final long DEFAULT_TIMEOUT_MILLIS = 5000;
Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound, forClient);
- if (inetSocketAddressOptional.isPresent() == false) {
+ if (!inetSocketAddressOptional.isPresent()) {
throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
}
InetSocketAddress inetSocketAddress = inetSocketAddressOptional.get();
public static String getPrivateKeyPath(BundleContext context){
return getPropertyValue(context,PREFIX_PROP + InfixProp.ssh +PRIVATE_KEY_PATH_PROP);
}
+ public static Optional<String> getSSHDefaultUser(BundleContext context){
+ return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_USER);
+ }
+ public static Optional<String> getSSHDefaultPassword(BundleContext context){
+ return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_PASSWORD);
+ }
+
private static String getPropertyValue(BundleContext context, String propertyName){
String propertyValue = context.getProperty(propertyName);
if (propertyValue == null){
}
return propertyValue;
}
+ private static Optional<String> getOptionalPropertyValue(BundleContext context, String propertyName){
+ String propertyValue = context.getProperty(propertyName);
+ if (Strings.isNullOrEmpty(propertyValue)){
+ return Optional.absent();
+ }
+ return Optional.fromNullable(propertyValue);
+ }
/**
* @param context
* from which properties are being read.
final List<XmlElement> result = new ArrayList<>();
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
- if (item instanceof Element == false) {
+ if (!(item instanceof Element)) {
continue;
}
if (strat.accept((Element) item)) {
} else {
prefix = "";
}
- if (namespaces.containsKey(prefix) == false) {
+ if (!namespaces.containsKey(prefix)) {
throw new IllegalArgumentException("Cannot find namespace for " + XmlUtil.toString(element) + ". Prefix from content is "
+ prefix + ". Found namespaces " + namespaces);
}
// TODO duplicate
public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0";
public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0";
- public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_1 = "urn:ietf:params:xml:ns:netconf:base:1.1";
+// public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_1 = "urn:ietf:params:xml:ns:netconf:base:1.1";
+ public static final String URN_IETF_PARAMS_NETCONF_BASE_1_0 = "urn:ietf:params:netconf:base:1.0";
+ public static final String URN_IETF_PARAMS_NETCONF_BASE_1_1 = "urn:ietf:params:netconf:base:1.1";
public static final String URN_IETF_PARAMS_XML_NS_NETCONF_EXI_1_0 = "urn:ietf:params:xml:ns:netconf:exi:1.0";
public static final String URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0 = "urn:ietf:params:netconf:capability:exi:1.0";
package org.opendaylight.controller.netconf.util.xml;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.SchemaFactory;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
public final class XmlUtil {
try {
dBuilder = BUILDERFACTORY.newDocumentBuilder();
} catch (ParserConfigurationException e) {
- throw new RuntimeException("Failed to parse XML document", e);
+ throw new IllegalStateException("Failed to parse XML document", e);
}
Document doc = dBuilder.parse(xmlContent);
public static Document newDocument() {
try {
DocumentBuilder builder = BUILDERFACTORY.newDocumentBuilder();
- Document document = builder.newDocument();
- return document;
+ return builder.newDocument();
} catch (ParserConfigurationException e) {
- throw new RuntimeException("Failed to create document", e);
+ throw new IllegalStateException("Failed to create document", e);
}
}
transformer.transform(source, result);
return result.getWriter().toString();
- } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
- throw new RuntimeException("Unable to serialize xml element " + xml, e);
+ } catch (Exception | TransformerFactoryConfigurationError e) {
+ throw new IllegalStateException("Unable to serialize xml element " + xml, e);
}
}
* only subnet returned. As soon as a user-configured subnet is created this one will
* vanish.
*/
+ private static final String DISABLE_DEFAULT_SUBNET_PROP = "switchmanager.disableDefaultSubnetGateway";
+ private static final String DISABLE_DEFAULT_SUBNET_PROP_VAL = System.getProperty(DISABLE_DEFAULT_SUBNET_PROP);
+ private static final boolean USE_DEFAULT_SUBNET_GW = !Boolean.valueOf(DISABLE_DEFAULT_SUBNET_PROP_VAL);
protected static final SubnetConfig DEFAULT_SUBNETCONFIG;
protected static final Subnet DEFAULT_SUBNET;
protected static final String DEFAULT_SUBNET_NAME = "default (cannot be modifed)";
@Override
public List<SubnetConfig> getSubnetsConfigList() {
// if there are no subnets, return the default subnet
- if(subnetsConfigList.size() == 0){
+ if (USE_DEFAULT_SUBNET_GW && subnetsConfigList.isEmpty()) {
return Collections.singletonList(DEFAULT_SUBNETCONFIG);
- }else{
+ } else {
return new ArrayList<SubnetConfig>(subnetsConfigList.values());
}
}
@Override
public SubnetConfig getSubnetConfig(String subnet) {
// if there are no subnets, return the default subnet
- if(subnetsConfigList.isEmpty() && subnet.equalsIgnoreCase(DEFAULT_SUBNET_NAME)){
+ if (USE_DEFAULT_SUBNET_GW && subnetsConfigList.isEmpty() && subnet.equalsIgnoreCase(DEFAULT_SUBNET_NAME)) {
return DEFAULT_SUBNETCONFIG;
- }else{
+ } else {
return subnetsConfigList.get(subnet);
}
}