From: Alessandro Boch Date: Tue, 12 Nov 2013 20:00:35 +0000 (+0000) Subject: Merge "Bring some reliability in the eclipse and maven mixed builds" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~416 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=7021b10a1222828229378743de6d3286741adc3c;hp=ea5c80dd44a09bcf3309ec05491a1e1e87664719 Merge "Bring some reliability in the eclipse and maven mixed builds" --- diff --git a/opendaylight/archetypes/odl-model-project/src/main/resources/archetype-resources/pom.xml b/opendaylight/archetypes/odl-model-project/src/main/resources/archetype-resources/pom.xml index 1f9bc7477e..77f419a4ff 100644 --- a/opendaylight/archetypes/odl-model-project/src/main/resources/archetype-resources/pom.xml +++ b/opendaylight/archetypes/odl-model-project/src/main/resources/archetype-resources/pom.xml @@ -217,12 +217,7 @@ org.opendaylight.yangtools yang-binding - ${yang.version} - - - org.opendaylight.yangtools - yang-common - ${yang.version} + ${yang.codegen.version} diff --git a/opendaylight/config/netty-event-executor-config/pom.xml b/opendaylight/config/netty-event-executor-config/pom.xml new file mode 100644 index 0000000000..a2ce94f340 --- /dev/null +++ b/opendaylight/config/netty-event-executor-config/pom.xml @@ -0,0 +1,106 @@ + + + org.opendaylight.controller + config-subsystem + 0.2.3-SNAPSHOT + + 4.0.0 + netty-event-executor-config + Configuration Wrapper around netty's event executor + bundle + ${project.artifactId} + + 3.0.4 + + + + + org.opendaylight.controller + config-api + + + org.opendaylight.controller + threadpool-config-api + ${project.version} + + + org.slf4j + slf4j-api + + + com.google.guava + guava + + + + + junit + junit + test + + + org.opendaylight.controller + config-manager + test + test-jar + + + org.opendaylight.controller + config-manager + test + + + org.opendaylight.controller + config-util + test + + + org.opendaylight.bgpcep + mockito-configuration + test + + + + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.groupId}.${project.artifactId} + + + + com.google.common.base, + org.opendaylight.controller.config.yang.threadpool, + io.netty.util.concurrent, + org.opendaylight.controller.config.api, + org.opendaylight.controller.config.api.annotations, + org.opendaylight.controller.config.api.runtime, + org.opendaylight.controller.config.spi, + org.slf4j, + org.osgi.framework + + + + + + + + + + ${project.artifactId} + NETTY-EVENT-EXECUTOR-CONFIG Module site + ${basedir}/target/site/${project.artifactId} + + + + \ No newline at end of file diff --git a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java new file mode 100644 index 0000000000..3707f016a2 --- /dev/null +++ b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java @@ -0,0 +1,113 @@ +/** + * Generated file + + * Generated from: yang module name: netty-event-executor yang module local name: netty-global-event-executor + * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + * Generated at: Tue Nov 12 10:44:21 CET 2013 + * + * Do not modify this file unless it is present under src/main directory + */ +package org.opendaylight.controller.config.yang.netty.eventexecutor; + +import io.netty.util.concurrent.AbstractEventExecutor; +import io.netty.util.concurrent.EventExecutor; +import io.netty.util.concurrent.EventExecutorGroup; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GlobalEventExecutor; + +import java.util.concurrent.TimeUnit; + +/** +* +*/ +public final class GlobalEventExecutorModule extends + org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModule { + + public GlobalEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public GlobalEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, + org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + GlobalEventExecutorModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void validate() { + super.validate(); + // Add custom validation for module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new GlobalEventExecutorCloseable(GlobalEventExecutor.INSTANCE); + } + + static final private class GlobalEventExecutorCloseable extends AbstractEventExecutor implements AutoCloseable { + + private EventExecutor executor; + + public GlobalEventExecutorCloseable(EventExecutor executor) { + this.executor = executor; + } + + @Override + public EventExecutorGroup parent() { + return this.executor.parent(); + } + + @Override + public boolean inEventLoop(Thread thread) { + return this.executor.inEventLoop(thread); + } + + @Override + public boolean isShuttingDown() { + return this.executor.isShuttingDown(); + } + + @Override + public Future shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) { + return this.executor.shutdownGracefully(quietPeriod, timeout, unit); + } + + @Override + public Future terminationFuture() { + return this.executor.terminationFuture(); + } + + @Override + public boolean isShutdown() { + return this.executor.isShutdown(); + } + + @Override + public boolean isTerminated() { + return this.executor.isTerminated(); + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + return this.executor.awaitTermination(timeout, unit); + } + + @Override + public void execute(Runnable command) { + this.executor.execute(command); + } + + @Override + public void close() throws Exception { + shutdownGracefully(); + } + + @SuppressWarnings("deprecation") + @Override + public void shutdown() { + this.executor.shutdown(); + } + + } +} diff --git a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java new file mode 100644 index 0000000000..79a5121fa8 --- /dev/null +++ b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java @@ -0,0 +1,19 @@ +/** +* Generated file + +* Generated from: yang module name: netty-event-executor yang module local name: netty-global-event-executor +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Tue Nov 12 10:44:21 CET 2013 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.netty.eventexecutor; + +/** +* +*/ +public class GlobalEventExecutorModuleFactory extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModuleFactory +{ + + +} diff --git a/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang b/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang new file mode 100644 index 0000000000..d45eccded8 --- /dev/null +++ b/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang @@ -0,0 +1,44 @@ +// vi: set smarttab et sw=4 tabstop=4: +module netty-event-executor { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor"; + prefix "netty-t"; + + import config { prefix config; revision-date 2013-04-05; } + import threadpool { prefix th; revision-date 2013-04-09; } + + organization "Cisco Systems, Inc."; + + contact "Milos Fabian "; + + description + "This module contains the base YANG definitions for NS-OS + thread-related services. + + Copyright (c)2013 Cisco Systems, Inc. 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"; + + revision "2013-11-12" { + description + "Initial revision"; + } + + identity netty-global-event-executor { + base config:module-type; + config:provided-service th:netty-event-executor; + config:java-name-prefix GlobalEventExecutor; + } + + augment "/config:modules/config:module/config:configuration" { + case netty-global-event-executor { + when "/config:modules/config:module/config:type = 'netty-global-event-executor'"; + + } + } + + +} diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java new file mode 100644 index 0000000000..6af508829b --- /dev/null +++ b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java @@ -0,0 +1,64 @@ +package org.opendaylight.controller.config.yang.netty.eventexecutor; + +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.api.ValidationException; +import org.opendaylight.controller.config.api.jmx.CommitStatus; +import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; +import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; +import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; + +public class GlobalEventExecutorModuleTest extends AbstractConfigTest { + + private GlobalEventExecutorModuleFactory factory; + private final String instanceName = "netty1"; + + @Before + public void setUp() { + factory = new GlobalEventExecutorModuleFactory(); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory)); + } + + @Test + public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException, + ConflictingVersionException { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + + createInstance(transaction, instanceName); + createInstance(transaction, instanceName + 2); + transaction.validateConfig(); + CommitStatus status = transaction.commit(); + + assertBeanCount(2, factory.getImplementationName()); + assertStatus(status, 2, 0, 0); + } + + @Test + public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException, + ValidationException { + + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + createInstance(transaction, instanceName); + + transaction.commit(); + + transaction = configRegistryClient.createTransaction(); + assertBeanCount(1, factory.getImplementationName()); + CommitStatus status = transaction.commit(); + + assertBeanCount(1, factory.getImplementationName()); + assertStatus(status, 0, 0, 1); + } + + private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName) + throws InstanceAlreadyExistsException { + ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName); + transaction.newMBeanProxy(nameCreated, GlobalEventExecutorModuleMXBean.class); + return nameCreated; + } + +} diff --git a/opendaylight/config/pom.xml b/opendaylight/config/pom.xml index 2842b5c450..3f27ff1055 100755 --- a/opendaylight/config/pom.xml +++ b/opendaylight/config/pom.xml @@ -32,6 +32,7 @@ threadpool-config-api threadpool-config-impl netty-threadgroup-config + netty-event-executor-config diff --git a/opendaylight/config/threadpool-config-api/pom.xml b/opendaylight/config/threadpool-config-api/pom.xml index d8ddc4f24d..cddfb64830 100644 --- a/opendaylight/config/threadpool-config-api/pom.xml +++ b/opendaylight/config/threadpool-config-api/pom.xml @@ -39,6 +39,7 @@ org.opendaylight.controller.config.api.*, com.google.common.eventbus, io.netty.channel, + io.netty.util.concurrent org.opendaylight.controller.config.threadpool, diff --git a/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang b/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang index 5cc17e52ff..9c73711c17 100644 --- a/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang +++ b/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang @@ -82,6 +82,14 @@ module threadpool { base "config:service-type"; config:java-class "io.netty.channel.EventLoopGroup"; } + + identity netty-event-executor { + description + "Configuration wrapper around netty's event executor"; + + base "config:service-type"; + config:java-class "io.netty.util.concurrent.EventExecutor"; + } } diff --git a/opendaylight/md-sal/clustered-data-store/implementation/pom.xml b/opendaylight/md-sal/clustered-data-store/implementation/pom.xml index bb43809a5c..a3d11d0374 100644 --- a/opendaylight/md-sal/clustered-data-store/implementation/pom.xml +++ b/opendaylight/md-sal/clustered-data-store/implementation/pom.xml @@ -29,6 +29,7 @@ + org.opendaylight.controller.datastore javax.xml.bind.annotation, @@ -38,6 +39,7 @@ org.opendaylight.controller.sal.topology, org.opendaylight.controller.clustering.services, org.opendaylight.controller.md.sal.common.api.data, + org.opendaylight.controller.sal.common.util, org.opendaylight.yangtools.yang.binding, org.osgi.service.component, org.slf4j, @@ -45,7 +47,8 @@ org.apache.commons.lang3.builder, org.apache.commons.lang3.tuple, org.eclipse.osgi.framework.console, - org.osgi.framework + org.osgi.framework, + com.google.common.base org.opendaylight.controller.datastore.internal.Activator diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java index f2e7773a45..18b9892563 100644 --- a/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java +++ b/opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java @@ -35,19 +35,19 @@ public class ClusteredDataStoreImpl implements ClusteredDataStore { public static final String OPERATIONAL_DATA_CACHE = "clustered_data_store.operational_data_cache"; public static final String CONFIGURATION_DATA_CACHE = "clustered_data_store.configuration_data_cache"; - private ConcurrentMap operationalDataCache; - private ConcurrentMap configurationDataCache; + private final ConcurrentMap operationalDataCache; + private final ConcurrentMap configurationDataCache; public ClusteredDataStoreImpl(IClusterGlobalServices clusterGlobalServices) throws CacheExistException, CacheConfigException { Preconditions.checkNotNull(clusterGlobalServices, "clusterGlobalServices cannot be null"); - operationalDataCache = clusterGlobalServices.createCache(OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + operationalDataCache = getOrCreateCache(clusterGlobalServices, OPERATIONAL_DATA_CACHE); if(operationalDataCache == null){ Preconditions.checkNotNull(operationalDataCache, "operationalDataCache cannot be null"); } - configurationDataCache = clusterGlobalServices.createCache(CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + configurationDataCache = getOrCreateCache(clusterGlobalServices, CONFIGURATION_DATA_CACHE); if(configurationDataCache == null){ Preconditions.checkNotNull(configurationDataCache, "configurationDataCache cannot be null"); @@ -95,6 +95,20 @@ public class ClusteredDataStoreImpl implements ClusteredDataStore { return Rpcs.getRpcResult(true, null, _emptySet); } + + private ConcurrentMap getOrCreateCache(IClusterGlobalServices clusterGlobalServices, String name) throws CacheConfigException { + ConcurrentMap cache = clusterGlobalServices.getCache(name); + + if(cache == null) { + try { + cache = clusterGlobalServices.createCache(name, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + } catch (CacheExistException e) { + cache = clusterGlobalServices.getCache(name); + } + } + return cache; + } + private class ClusteredDataStoreTransaction implements DataCommitTransaction, Object> { private final DataModification,Object> modification; diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java index 8049bae5af..d7ae4bf2e5 100644 --- a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java +++ b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java @@ -64,6 +64,31 @@ public class ClusteredDataStoreImplTest { } } + @Test + public void constructor_WhenOperationalDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException { + IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class); + + Mockito.>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap()); + Mockito.>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap()); + + new ClusteredDataStoreImpl(mockClusterGlobalServices); + + verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + } + + @Test + public void constructor_WhenConfigurationDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException { + IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class); + + Mockito.>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap()); + Mockito.>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap()); + + new ClusteredDataStoreImpl(mockClusterGlobalServices); + + verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + } + + @Test public void constructor_WhenPassedAValidClusteringServices_ShouldNotThrowAnyExceptions() throws CacheExistException, CacheConfigException { IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices(); diff --git a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java index 84b07e7cd4..5609134a1a 100644 --- a/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java +++ b/opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java @@ -1,3 +1,12 @@ + +/* + * 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.datastore.internal; import org.apache.felix.dm.Component; diff --git a/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml b/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml index 407b46bed1..9615decbe9 100644 --- a/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml +++ b/opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml @@ -18,15 +18,50 @@ clustered-datastore.integrationtest 0.4.0-SNAPSHOT + + + com.google.guava + guava + + + org.opendaylight.controller + sal-common-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-impl + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-broker-impl + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.1-SNAPSHOT + + + org.opendaylight.controller + clustering.services + 0.4.1-SNAPSHOT + + + org.opendaylight.yangtools + yang-binding + + org.opendaylight.controller protocol_plugins.stub 0.4.1-SNAPSHOT - - - org.opendaylight.controller - sal - 0.5.0-SNAPSHOT org.opendaylight.controller @@ -43,11 +78,6 @@ containermanager.it.implementation 0.5.0-SNAPSHOT - - org.opendaylight.controller - clustering.services - 0.4.0-SNAPSHOT - org.opendaylight.controller clustering.stub @@ -59,7 +89,33 @@ 0.4.1-SNAPSHOT - + + org.opendaylight.controller + sal-common + 1.0-SNAPSHOT + + + org.opendaylight.yangtools + yang-common + + + org.opendaylight.yangtools + concepts + 0.1.1-SNAPSHOT + + + org.mockito + mockito-all + 1.9.5 + test + + + org.osgi + org.osgi.core + 5.0.0 + + + ../implementation/target/jacoco.exec diff --git a/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/java/org/opendaylight/controller/datastore/ClusteredDataStoreIT.java b/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/java/org/opendaylight/controller/datastore/ClusteredDataStoreIT.java index ddf275ec14..e5861ab3c0 100644 --- a/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/java/org/opendaylight/controller/datastore/ClusteredDataStoreIT.java +++ b/opendaylight/md-sal/clustered-data-store/integrationtest/src/test/java/org/opendaylight/controller/datastore/ClusteredDataStoreIT.java @@ -8,6 +8,11 @@ package org.opendaylight.controller.datastore; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Configuration; @@ -16,18 +21,26 @@ import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.util.PathUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; -import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; import static org.ops4j.pax.exam.CoreOptions.junitBundles; import static org.ops4j.pax.exam.CoreOptions.mavenBundle; import static org.ops4j.pax.exam.CoreOptions.options; import static org.ops4j.pax.exam.CoreOptions.systemPackages; import static org.ops4j.pax.exam.CoreOptions.systemProperty; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import static org.mockito.Mockito.mock; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; @RunWith(PaxExam.class) public class ClusteredDataStoreIT { @@ -36,7 +49,8 @@ public class ClusteredDataStoreIT { // get the OSGI bundle context @Inject private BundleContext bc; - + @Inject + private ClusteredDataStore clusteredDS; // Configure the OSGi container @Configuration public Option[] config() { @@ -49,6 +63,7 @@ public class ClusteredDataStoreIT { systemProperty("osgi.console").value("2401"), // Set the systemPackages (used by clustering) systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"), + systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG"), // List framework bundles mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(), mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(), @@ -83,6 +98,32 @@ public class ClusteredDataStoreIT { mavenBundle("org.opendaylight.controller", "protocol_plugins.stub") .versionAsInProject(), + //clustered-data-store-implementation dependencies + mavenBundle("com.google.guava", "guava") + .versionAsInProject(), + mavenBundle("org.opendaylight.controller", "sal-common-api") + .versionAsInProject(), + mavenBundle("org.opendaylight.controller", "sal-common-util") + .versionAsInProject(), + mavenBundle("org.opendaylight.controller", "sal-common-impl") + .versionAsInProject(), + mavenBundle("org.opendaylight.yangtools", "yang-binding") + .versionAsInProject(), + + + //sal-common-api dependencies + mavenBundle("org.opendaylight.controller", "sal-common") + .versionAsInProject(), + mavenBundle("org.opendaylight.yangtools", "yang-common") + .versionAsInProject(), + mavenBundle("org.opendaylight.yangtools", "concepts") + .versionAsInProject(), + mavenBundle("org.osgi", "org.osgi.core") + .versionAsInProject(), + //adding new maven bundles + mavenBundle("org.mockito", "mockito-all") + .versionAsInProject(), + // needed by hosttracker mavenBundle("org.opendaylight.controller", "clustered-datastore-implementation") .versionAsInProject(), @@ -110,9 +151,137 @@ public class ClusteredDataStoreIT { } } + @Before + public void areWeReady() { + assertNotNull(bc); + boolean debugit = false; + Bundle b[] = bc.getBundles(); + for (int i = 0; i < b.length; i++) { + int state = b[i].getState(); + if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) { + log.debug("Bundle:" + b[i].getSymbolicName() + " state:" + + stateToString(state)); + debugit = true; + } + } + if (debugit) { + log.debug("Do some debugging because some bundle is " + + "unresolved"); + } + } + + @Test + public void testBundleContextClusteredDS_NotNull() throws Exception{ + ServiceReference serviceReference = bc.getServiceReference(ClusteredDataStore.class); + ClusteredDataStore store = ClusteredDataStore.class.cast(bc.getService(serviceReference)); + assertNotNull(store); + } + + @Test + public void testInjected_ClusteredDS_NotNull(){ + assertNotNull(clusteredDS); + } + @Test - public void testDoNothing() throws Exception{ - assertTrue(true); + public void requestCommit_readConfigurationData_ShouldVerifyDataAndNoException(){ + DataModification dataModification = mock(DataModification.class); + HashMap map = new HashMap(); + List list = new ArrayList(); + list.add("key"); + InstanceIdentifier key = new InstanceIdentifier(list,String.class); + map.put(key, "value"); + when(dataModification.getUpdatedConfigurationData()).thenReturn(map); + DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification); + dataCommitTrans.finish(); + String value = (String)clusteredDS.readConfigurationData(key); + assertEquals("value",value); } + @Test(expected = NullPointerException.class) + public void requestCommit_ShouldThrowException(){ + DataModification dataModification = null; + DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification); + dataCommitTrans.finish(); + } + + @Test + public void requestCommit_readOperationalData_ShouldVerifyDataAndNoException(){ + DataModification dataModification = mock(DataModification.class); + HashMap map = new HashMap(); + List list = new ArrayList(); + list.add("key"); + InstanceIdentifier key = new InstanceIdentifier(list,String.class); + map.put(key, "value"); + when(dataModification.getUpdatedOperationalData()).thenReturn(map); + DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification); + dataCommitTrans.finish(); + String value = (String)clusteredDS.readOperationalData(key); + assertEquals("value",value); + } + + @Test + public void requestCommit_readConfigurationData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException(){ + DataModification dataModification = mock(DataModification.class); + HashMap map = new HashMap(); + List list = new ArrayList(); + list.add("key"); + InstanceIdentifier key = new InstanceIdentifier(list,String.class); + map.put(key, "value"); + when(dataModification.getUpdatedConfigurationData()).thenReturn(map); + DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification); + dataCommitTrans.finish(); + list = new ArrayList(); + list.add("key1"); + InstanceIdentifier key1 = new InstanceIdentifier(list,String.class); + + String value = (String)clusteredDS.readConfigurationData(key1); + assertNull(value); + } + + @Test + public void requestCommit_readOperationalData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException(){ + DataModification dataModification = mock(DataModification.class); + HashMap map = new HashMap(); + List list = new ArrayList(); + list.add("key"); + InstanceIdentifier key = new InstanceIdentifier(list,String.class); + map.put(key, "value"); + when(dataModification.getUpdatedOperationalData()).thenReturn(map); + DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification); + dataCommitTrans.finish(); + list = new ArrayList(); + list.add("key1"); + InstanceIdentifier key1 = new InstanceIdentifier(list,String.class); + + String value = (String)clusteredDS.readOperationalData(key1); + assertNull(value); + } + + @Test(expected = NullPointerException.class) + public void requestCommit_readConfigurationData_WithNullPathShouldThrowException(){ + DataModification dataModification = mock(DataModification.class); + HashMap map = new HashMap(); + List list = new ArrayList(); + list.add("key"); + InstanceIdentifier key = new InstanceIdentifier(list,String.class); + map.put(key, "value"); + when(dataModification.getUpdatedConfigurationData()).thenReturn(map); + DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification); + dataCommitTrans.finish(); + String value = (String)clusteredDS.readConfigurationData(null); + } + + @Test(expected = NullPointerException.class) + public void requestCommit_readOperationalData_WithNullPathShouldThrowException(){ + DataModification dataModification = mock(DataModification.class); + HashMap map = new HashMap(); + List list = new ArrayList(); + list.add("key"); + InstanceIdentifier key = new InstanceIdentifier(list,String.class); + map.put(key, "value"); + when(dataModification.getOriginalOperationalData()).thenReturn(map); + DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification); + dataCommitTrans.finish(); + String value = (String)clusteredDS.readOperationalData(null); + } } diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang new file mode 100644 index 0000000000..d589f45332 --- /dev/null +++ b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang @@ -0,0 +1,85 @@ +module opendaylight-group-statistics { + namespace "urn:opendaylight:group:statistics"; + prefix groupstat; + + import yang-ext {prefix ext; revision-date "2013-07-09";} + import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} + import opendaylight-group-types {prefix group-types;revision-date "2013-10-18";} + import flow-capable-transaction {prefix tr;} + + revision "2013-11-11" { + description "Initial revision of group statistics service"; + } + + // RPC calls + rpc get-all-group-statistics { + input { + uses inv:node-context-ref; + } + output { + list group-statistics { + uses group-types:group-statistics; + } + uses tr:transaction-aware; + } + + } + + rpc get-group-statistics { + input { + uses inv:node-context-ref; + leaf group-id{ + type group-types:group-id; + } + } + output { + uses group-types:group-statistics; + uses tr:transaction-aware; + } + + } + + rpc get-group-description { + input { + uses inv:node-context-ref; + leaf group-id{ + type group-types:group-id; + } + } + output { + uses group-types:group-desc-stats; + uses tr:transaction-aware; + } + } + + rpc get-group-features { + input { + uses inv:node-context-ref; + leaf group-id{ + type group-types:group-id; + } + } + output { + uses group-types:group-features; + uses tr:transaction-aware; + } + } + + + //Notification calls + + notification group-statistics-updated { + uses group-types:group-statistics; + uses tr:transaction-aware; + } + + notification group-desc-stats-updated { + uses group-types:group-desc-stats; + uses tr:transaction-aware; + } + + notification group-features { + uses group-types:group-features; + uses tr:transaction-aware; + } +} diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/meter-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/meter-statistics.yang new file mode 100644 index 0000000000..5aea6b7499 --- /dev/null +++ b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/meter-statistics.yang @@ -0,0 +1,87 @@ +module opendaylight-meter-statistics { + namespace "urn:opendaylight:meter:statistics"; + prefix meterstat; + + import yang-ext {prefix ext; revision-date "2013-07-09";} + import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} + import opendaylight-meter-types {prefix meter-types;revision-date "2013-09-18";} + import flow-capable-transaction {prefix tr;} + + + revision "2013-11-11" { + description "Initial revision of meter statistics service"; + } + + // RPC calls + rpc get-all-meter-statistics { + input { + uses inv:node-context-ref; + } + output { + list meter-statistics { + uses meter-types:meter-statistics; + uses tr:transaction-aware; + } + } + + } + + rpc get-meter-statistics { + description "RPC Method to send meter statistics request to the give switch for specific meter"; + input { + uses inv:node-context-ref; + leaf meter-id{ + type meter-types:meter-id; + } + } + output { + uses meter-types:meter-statistics; + uses tr:transaction-aware; + } + + } + + rpc get-meter-config-statistics { + input { + uses inv:node-context-ref; + leaf meter-id{ + type meter-types:meter-id; + } + } + output { + uses meter-types:meter-config-stats; + uses tr:transaction-aware; + } + } + + rpc get-meter-features { + input { + uses inv:node-context-ref; + leaf meter-id{ + type meter-types:meter-id; + } + } + output { + uses meter-types:meter-features; + uses tr:transaction-aware; + } + } + + + //Notification calls + + notification meter-statistics-updated { + uses meter-types:meter-statistics; + uses tr:transaction-aware; + } + + notification meter-config-stats-updated { + uses meter-types:meter-config-stats; + uses tr:transaction-aware; + } + + notification meter-features { + uses meter-types:meter-features; + uses tr:transaction-aware; + } +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java index 55751e5ac7..04556bbe54 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java @@ -7,6 +7,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import javax.activation.UnsupportedDataTypeException; + import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.Node; import org.opendaylight.yangtools.yang.data.api.SimpleNode; @@ -33,8 +35,18 @@ class JsonMapper { public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException { writer.beginObject(); - writeChildrenOfParent(writer, data, schema); + + if (schema instanceof ContainerSchemaNode) { + writeContainer(writer, (CompositeNode) data, (ContainerSchemaNode) schema); + } else if (schema instanceof ListSchemaNode) { + writeList(writer, (CompositeNode) data, (ListSchemaNode) schema); + } else { + throw new UnsupportedDataTypeException( + "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet."); + } + writer.endObject(); + foundLeafLists.clear(); foundLists.clear(); } @@ -45,6 +57,11 @@ class JsonMapper { for (Node child : parent.getChildren()) { DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes()); + if (childSchema == null) { + throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName() + + "\" is not conform to schema"); + } + if (childSchema instanceof ContainerSchemaNode) { writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema); } else if (childSchema instanceof ListSchemaNode) { @@ -59,6 +76,9 @@ class JsonMapper { } } else if (childSchema instanceof LeafSchemaNode) { writeLeaf(writer, (SimpleNode) child, (LeafSchemaNode) childSchema); + } else { + throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode, ListSchemaNode, " + + "LeafListSchemaNode, or LeafSchemaNode. Other types are not supported yet."); } } @@ -145,7 +165,9 @@ class JsonMapper { } else if (type instanceof BooleanTypeDefinition) { writer.value(Boolean.parseBoolean(value)); } else if (type instanceof EmptyTypeDefinition) { - writer.value("[null]"); + writer.beginArray(); + writer.nullValue(); + writer.endArray(); } else { writer.value(value); } diff --git a/opendaylight/netconf/config-persister-impl/pom.xml b/opendaylight/netconf/config-persister-impl/pom.xml index 85592e5aa2..21ecd31339 100644 --- a/opendaylight/netconf/config-persister-impl/pom.xml +++ b/opendaylight/netconf/config-persister-impl/pom.xml @@ -78,6 +78,9 @@ org.opendaylight.controller.netconf.client, org.opendaylight.controller.netconf.util.osgi, org.opendaylight.controller.netconf.util.xml, + io.netty.channel, + io.netty.channel.nio, + io.netty.util.concurrent, org.osgi.framework, org.slf4j, org.w3c.dom, diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java index d390161aff..a20e00bcff 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java @@ -11,6 +11,8 @@ package org.opendaylight.controller.netconf.persist.impl; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; import org.opendaylight.controller.config.persist.api.Persister; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification; @@ -53,6 +55,7 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, private final InetSocketAddress address; private final NetconfClientDispatcher dispatcher; + private final EventLoopGroup nettyThreadgroup; private NetconfClient netconfClient; @@ -76,7 +79,9 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, this.address = address; this.mbeanServer = mbeanServer; this.timeout = timeout; - this.dispatcher = new NetconfClientDispatcher(Optional.absent()); + + this.nettyThreadgroup = new NioEventLoopGroup(); + this.dispatcher = new NetconfClientDispatcher(Optional.absent(), nettyThreadgroup, nettyThreadgroup); } public void init() throws InterruptedException { @@ -314,9 +319,9 @@ public class ConfigPersisterNotificationHandler implements NotificationListener, } try { - dispatcher.close(); + nettyThreadgroup.shutdownGracefully(); } catch (Exception e) { - logger.warn("Unable to close netconf client dispatcher {}", dispatcher, e); + logger.warn("Unable to close netconf client thread group {}", dispatcher, e); } // unregister from JMX diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/AbstractNetconfClientNotifySessionListener.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/AbstractNetconfClientNotifySessionListener.java new file mode 100644 index 0000000000..48109d1353 --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/AbstractNetconfClientNotifySessionListener.java @@ -0,0 +1,54 @@ +/* + * 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 org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; + +/** + * Class extending {@link NetconfClientSessionListener} to provide notification capability. + */ +public abstract class AbstractNetconfClientNotifySessionListener extends NetconfClientSessionListener { + /* + * Maybe some capabilities could be expressed as internal NetconfClientSessionListener handlers. + * It would enable NetconfClient functionality to be extended by using namespace handlers. + * So far let just enable notification capability by extending and let parent class intact. + */ + + /** + * As class purpose is to provide notification capability to session listener + * onMessage method is not allowed to be further overridden. + * {@see #onNotification(NetconfClientSession, NetconfMessage)} + * + * @param session {@see NetconfClientSessionListener#onMessage(NetconfClientSession, NetconfMessage)} + * @param message {@see NetconfClientSessionListener#onMessage(NetconfClientSession, NetconfMessage)} + */ + @Override + public final synchronized void onMessage(NetconfClientSession session, NetconfMessage message) { + if (isNotification(message)) { + onNotification(session, message); + } else { + super.onMessage(session, message); + } + } + + /** + * Method intended to customize notification processing. + * + * @param session {@see NetconfClientSessionListener#onMessage(NetconfClientSession, NetconfMessage)} + * @param message {@see NetconfClientSessionListener#onMessage(NetconfClientSession, NetconfMessage)} + */ + public abstract void onNotification(NetconfClientSession session, NetconfMessage message); + + private boolean isNotification(NetconfMessage message) { + XmlElement xmle = XmlElement.fromDomDocument(message.getDocument()); + return XmlNetconfConstants.NOTIFICATION_ELEMENT_NAME.equals(xmle.getName()) ; + } +} diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java index 4df8235441..6fc4da026f 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.client; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.util.HashedWheelTimer; import io.netty.util.concurrent.Future; @@ -17,7 +18,7 @@ import io.netty.util.concurrent.Promise; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfSession; import org.opendaylight.controller.netconf.api.NetconfTerminationReason; -import org.opendaylight.controller.netconf.util.AbstractChannelInitializer; +import org.opendaylight.controller.netconf.util.AbstractSslChannelInitializer; import org.opendaylight.protocol.framework.AbstractDispatcher; import org.opendaylight.protocol.framework.ReconnectStrategy; import org.opendaylight.protocol.framework.SessionListener; @@ -32,7 +33,8 @@ public class NetconfClientDispatcher extends AbstractDispatcher maybeContext; private final NetconfClientSessionNegotiatorFactory negotatorFactory; - public NetconfClientDispatcher(final Optional maybeContext) { + public NetconfClientDispatcher(final Optional maybeContext, EventLoopGroup bossGroup, EventLoopGroup workerGroup) { + super(bossGroup, workerGroup); this.maybeContext = Preconditions.checkNotNull(maybeContext); this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(new HashedWheelTimer()); } @@ -48,18 +50,18 @@ public class NetconfClientDispatcher extends AbstractDispatcher promise) { - new ClientChannelInitializer(maybeContext, negotatorFactory, sessionListener).initialize(ch, promise); + new ClientSslChannelInitializer(maybeContext, negotatorFactory, sessionListener).initialize(ch, promise); } }); } - private static class ClientChannelInitializer extends AbstractChannelInitializer { + private static class ClientSslChannelInitializer extends AbstractSslChannelInitializer { private final NetconfClientSessionNegotiatorFactory negotiatorFactory; private final NetconfClientSessionListener sessionListener; - private ClientChannelInitializer(Optional maybeContext, - NetconfClientSessionNegotiatorFactory negotiatorFactory, NetconfClientSessionListener sessionListener) { + private ClientSslChannelInitializer(Optional maybeContext, + NetconfClientSessionNegotiatorFactory negotiatorFactory, NetconfClientSessionListener sessionListener) { super(maybeContext); this.negotiatorFactory = negotiatorFactory; this.sessionListener = sessionListener; diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java new file mode 100644 index 0000000000..ce0f427475 --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java @@ -0,0 +1,18 @@ +/* + * 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.channel.EventLoopGroup; + +public class NetconfSshClientDispatcher extends NetconfClientDispatcher { + + public NetconfSshClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup) { + super(null, bossGroup, workerGroup); + } +} diff --git a/opendaylight/netconf/netconf-impl/pom.xml b/opendaylight/netconf/netconf-impl/pom.xml index 33fa675a92..f1e3f891ee 100644 --- a/opendaylight/netconf/netconf-impl/pom.xml +++ b/opendaylight/netconf/netconf-impl/pom.xml @@ -111,6 +111,7 @@ io.netty.util.concurrent, io.netty.buffer, io.netty.handler.codec, + io.netty.channel.nio, javax.management, javax.net.ssl, javax.xml.namespace, diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java index 324da56ca5..882d368a1a 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java @@ -10,11 +10,12 @@ package org.opendaylight.controller.netconf.impl; import com.google.common.base.Optional; import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.util.concurrent.Promise; import org.opendaylight.controller.netconf.api.NetconfSession; import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler; -import org.opendaylight.controller.netconf.util.AbstractChannelInitializer; +import org.opendaylight.controller.netconf.util.AbstractSslChannelInitializer; import org.opendaylight.protocol.framework.AbstractDispatcher; import javax.net.ssl.SSLContext; @@ -23,16 +24,14 @@ import java.net.InetSocketAddress; public class NetconfServerDispatcher extends AbstractDispatcher { - private final ServerChannelInitializer initializer; + private final ServerSslChannelInitializer initializer; - public NetconfServerDispatcher(final Optional maybeContext, - NetconfServerSessionNegotiatorFactory serverNegotiatorFactory, - NetconfServerSessionListenerFactory listenerFactory) { - this.initializer = new ServerChannelInitializer(maybeContext, serverNegotiatorFactory, listenerFactory); + public NetconfServerDispatcher(ServerSslChannelInitializer serverChannelInitializer, EventLoopGroup bossGroup, + EventLoopGroup workerGroup) { + super(bossGroup, workerGroup); + this.initializer = serverChannelInitializer; } - // FIXME change headers for all new source code files - // TODO test create server with same address twice public ChannelFuture createServer(InetSocketAddress address) { @@ -44,14 +43,14 @@ public class NetconfServerDispatcher extends AbstractDispatcher maybeContext, - NetconfServerSessionNegotiatorFactory negotiatorFactory, - NetconfServerSessionListenerFactory listenerFactory) { + public ServerSslChannelInitializer(Optional maybeContext, + NetconfServerSessionNegotiatorFactory negotiatorFactory, + NetconfServerSessionListenerFactory listenerFactory) { super(maybeContext); this.negotiatorFactory = negotiatorFactory; this.listenerFactory = listenerFactory; diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java index fc240f91c9..1a4888ba93 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.netconf.impl.osgi; import com.google.common.base.Optional; +import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; @@ -35,6 +36,7 @@ public class NetconfImplActivator implements BundleActivator { private NetconfOperationServiceFactoryTracker factoriesTracker; private DefaultCommitNotificationProducer commitNot; private NetconfServerDispatcher dispatch; + private NioEventLoopGroup eventLoopGroup; @Override public void start(final BundleContext context) throws Exception { @@ -56,10 +58,14 @@ public class NetconfImplActivator implements BundleActivator { NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory( factoriesListener, commitNot, idProvider); + eventLoopGroup = new NioEventLoopGroup(); + if (maybeTCPAddress.isPresent()) { Optional maybeSSLContext = Optional.absent(); InetSocketAddress address = maybeTCPAddress.get(); - dispatch = new NetconfServerDispatcher(maybeSSLContext, serverNegotiatorFactory, listenerFactory); + NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer( + maybeSSLContext, serverNegotiatorFactory, listenerFactory); + dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup); logger.info("Starting TCP netconf server at {}", address); dispatch.createServer(address); @@ -67,7 +73,9 @@ public class NetconfImplActivator implements BundleActivator { if (maybeTLSConfiguration.isPresent()) { Optional maybeSSLContext = Optional.of(maybeTLSConfiguration.get().getSslContext()); InetSocketAddress address = maybeTLSConfiguration.get().getAddress(); - dispatch = new NetconfServerDispatcher(maybeSSLContext, serverNegotiatorFactory, listenerFactory); + NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer( + maybeSSLContext, serverNegotiatorFactory, listenerFactory); + dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup); logger.info("Starting TLS netconf server at {}", address); dispatch.createServer(address); @@ -79,6 +87,6 @@ public class NetconfImplActivator implements BundleActivator { logger.info("Shutting down netconf because YangStoreService service was removed"); commitNot.close(); - dispatch.close(); + eventLoopGroup.shutdownGracefully(); } } diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java index 1295149c02..b363976aae 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java @@ -11,6 +11,8 @@ package org.opendaylight.controller.netconf.impl; import com.google.common.base.Optional; import com.google.common.collect.Sets; import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; import org.apache.commons.io.IOUtils; import org.junit.After; @@ -64,7 +66,10 @@ import static org.mockito.Mockito.mock; public class ConcurrentClientsTest { private static final int CONCURRENCY = 16; - public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher(Optional.absent()); + private static EventLoopGroup nettyGroup = new NioEventLoopGroup(); + public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher( + Optional. absent(), nettyGroup, nettyGroup); + @Mock private YangStoreService yangStoreService; @Mock @@ -77,6 +82,7 @@ public class ConcurrentClientsTest { private DefaultCommitNotificationProducer commitNot; private NetconfServerDispatcher dispatch; + @Before public void setUp() throws Exception { { // init mocks @@ -103,7 +109,9 @@ public class ConcurrentClientsTest { NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory( factoriesListener, commitNot, idProvider); - dispatch = new NetconfServerDispatcher(Optional. absent(), serverNegotiatorFactory, listenerFactory); + NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer( + Optional. absent(), serverNegotiatorFactory, listenerFactory); + dispatch = new NetconfServerDispatcher(serverChannelInitializer, nettyGroup, nettyGroup); ChannelFuture s = dispatch.createServer(netconfAddress); s.await(); @@ -111,7 +119,7 @@ public class ConcurrentClientsTest { @AfterClass public static void tearDownStatic() { - NETCONF_CLIENT_DISPATCHER.close(); + nettyGroup.shutdownGracefully(); } private NetconfOperationServiceFactory mockOpF() { @@ -160,7 +168,6 @@ public class ConcurrentClientsTest { @After public void cleanUp() throws Exception { commitNot.close(); - dispatch.close(); } @Test diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java index 233fffda02..e43febec79 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java @@ -8,22 +8,35 @@ package org.opendaylight.controller.netconf.impl; -import java.lang.management.ManagementFactory; -import java.net.InetSocketAddress; - -import javax.net.ssl.SSLContext; - +import com.google.common.base.Optional; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.HashedWheelTimer; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; -import com.google.common.base.Optional; - -import io.netty.channel.ChannelFuture; -import io.netty.util.HashedWheelTimer; +import javax.net.ssl.SSLContext; +import java.lang.management.ManagementFactory; +import java.net.InetSocketAddress; public class NetconfDispatcherImplTest { + private EventLoopGroup nettyGroup; + + @Before + public void setUp() throws Exception { + nettyGroup = new NioEventLoopGroup(); + } + + @After + public void tearDown() throws Exception { + nettyGroup.shutdownGracefully(); + } + @Test public void test() throws Exception { @@ -37,13 +50,15 @@ public class NetconfDispatcherImplTest { NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory( factoriesListener, commitNot, idProvider); - NetconfServerDispatcher dispatch = new NetconfServerDispatcher(Optional. absent(), - serverNegotiatorFactory, listenerFactory); + NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(Optional.absent(), serverNegotiatorFactory, listenerFactory); + + + NetconfServerDispatcher dispatch = new NetconfServerDispatcher( + serverChannelInitializer, nettyGroup, nettyGroup); InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 8333); ChannelFuture s = dispatch.createServer(addr); commitNot.close(); - dispatch.close(); } } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java index 9a4bc2aa5d..0c22a71c6b 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java @@ -10,6 +10,8 @@ package org.opendaylight.controller.netconf.it; import com.google.common.base.Optional; import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; import org.junit.After; import org.junit.Before; @@ -51,6 +53,8 @@ public class NetconfITSecureTest extends AbstractConfigTest { private DefaultCommitNotificationProducer commitNot; private NetconfServerDispatcher dispatchS; + private EventLoopGroup nettyThreadgroup; + @Before public void setUp() throws Exception { @@ -62,6 +66,8 @@ public class NetconfITSecureTest extends AbstractConfigTest { commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); + nettyThreadgroup = new NioEventLoopGroup(); + dispatchS = createDispatcher(Optional.of(getSslContext()), factoriesListener); ChannelFuture s = dispatchS.createServer(tlsAddress); s.await(); @@ -76,13 +82,15 @@ public class NetconfITSecureTest extends AbstractConfigTest { NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory( factoriesListener, commitNot, idProvider); - return new NetconfServerDispatcher(sslC, serverNegotiatorFactory, listenerFactory); + NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer( + sslC, serverNegotiatorFactory, listenerFactory); + return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); } @After public void tearDown() throws Exception { commitNot.close(); - dispatchS.close(); + nettyThreadgroup.shutdownGracefully(); } private SSLContext getSslContext() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, @@ -106,8 +114,8 @@ public class NetconfITSecureTest extends AbstractConfigTest { @Test public void testSecure() throws Exception { - try (NetconfClientDispatcher dispatch = new NetconfClientDispatcher(Optional.of(getSslContext())); - NetconfClient netconfClient = new NetconfClient("tls-client", tlsAddress, 4000, dispatch)) { + NetconfClientDispatcher dispatch = new NetconfClientDispatcher(Optional.of(getSslContext()), nettyThreadgroup, nettyThreadgroup); + try (NetconfClient netconfClient = new NetconfClient("tls-client", tlsAddress, 4000, dispatch)) { } } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java index e9fe857bca..403ba3d0fc 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java @@ -12,9 +12,10 @@ import com.google.common.base.Optional; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; import org.junit.After; -import org.junit.AfterClass; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -90,8 +91,9 @@ public class NetconfITTest extends AbstractConfigTest { closeSession, startExi, stopExi; private DefaultCommitNotificationProducer commitNot; private NetconfServerDispatcher dispatch; + private EventLoopGroup nettyThreadgroup; - private static NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher(Optional.absent()); + private NetconfClientDispatcher clientDispatcher; @Before public void setUp() throws Exception { @@ -103,11 +105,15 @@ public class NetconfITTest extends AbstractConfigTest { NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore())); + nettyThreadgroup = new NioEventLoopGroup(); + commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); dispatch = createDispatcher(Optional. absent(), factoriesListener); ChannelFuture s = dispatch.createServer(tcpAddress); s.await(); + + clientDispatcher = new NetconfClientDispatcher(Optional.absent(), nettyThreadgroup, nettyThreadgroup); } private NetconfServerDispatcher createDispatcher(Optional sslC, @@ -119,18 +125,15 @@ public class NetconfITTest extends AbstractConfigTest { NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory( factoriesListener, commitNot, idProvider); - return new NetconfServerDispatcher(sslC, serverNegotiatorFactory, listenerFactory); + NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer( + sslC, serverNegotiatorFactory, listenerFactory); + return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); } @After public void tearDown() throws Exception { commitNot.close(); - dispatch.close(); - } - - @AfterClass - public static void tearDownStatic() { - NETCONF_CLIENT_DISPATCHER.close(); + nettyThreadgroup.shutdownGracefully(); } private void loadMessages() throws IOException, SAXException, ParserConfigurationException { @@ -171,7 +174,7 @@ public class NetconfITTest extends AbstractConfigTest { @Test public void testNetconfClientDemonstration() throws Exception { - try (NetconfClient netconfClient = new NetconfClient("client", tcpAddress, 4000, NETCONF_CLIENT_DISPATCHER)) { + try (NetconfClient netconfClient = new NetconfClient("client", tcpAddress, 4000, clientDispatcher)) { Set capabilitiesFromNetconfServer = netconfClient.getCapabilities(); long sessionId = netconfClient.getSessionId(); @@ -186,8 +189,8 @@ public class NetconfITTest extends AbstractConfigTest { @Test public void testTwoSessions() throws Exception { - try (NetconfClient netconfClient = new NetconfClient("1", tcpAddress, 4000, NETCONF_CLIENT_DISPATCHER)) { - try (NetconfClient netconfClient2 = new NetconfClient("2", tcpAddress, 4000, NETCONF_CLIENT_DISPATCHER)) { + try (NetconfClient netconfClient = new NetconfClient("1", tcpAddress, 4000, clientDispatcher)) { + try (NetconfClient netconfClient2 = new NetconfClient("2", tcpAddress, 4000, clientDispatcher)) { } } } @@ -387,7 +390,7 @@ public class NetconfITTest extends AbstractConfigTest { // final InputStream resourceAsStream = // AbstractListenerTest.class.getResourceAsStream(fileName); // assertNotNull(resourceAsStream); - try (NetconfClient netconfClient = new NetconfClient("test", tcpAddress, 5000, NETCONF_CLIENT_DISPATCHER)) { + try (NetconfClient netconfClient = new NetconfClient("test", tcpAddress, 5000, clientDispatcher)) { // IOUtils.copy(resourceAsStream, netconfClient.getStream()); // netconfClient.getOutputStream().write(NetconfMessageFactory.endOfMessage); // server should not write anything back @@ -436,7 +439,7 @@ public class NetconfITTest extends AbstractConfigTest { } private NetconfClient createSession(final InetSocketAddress address, final String expected) throws Exception { - final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, NETCONF_CLIENT_DISPATCHER); + final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, clientDispatcher); assertEquals(expected, Long.toString(netconfClient.getSessionId())); return netconfClient; } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java index 5d082c92cd..caee542152 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java @@ -8,73 +8,14 @@ package org.opendaylight.controller.netconf.util; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; - -import org.opendaylight.controller.netconf.api.NetconfMessage; -import org.opendaylight.controller.netconf.api.NetconfSession; -import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory; -import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator; -import org.opendaylight.controller.netconf.util.messages.FramingMechanism; -import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory; -import org.opendaylight.protocol.framework.ProtocolHandlerFactory; -import org.opendaylight.protocol.framework.ProtocolMessageDecoder; -import org.opendaylight.protocol.framework.ProtocolMessageEncoder; - -import com.google.common.base.Optional; - -import io.netty.channel.ChannelHandler; import io.netty.channel.socket.SocketChannel; -import io.netty.handler.ssl.SslHandler; import io.netty.util.concurrent.Promise; +import org.opendaylight.controller.netconf.api.NetconfSession; public abstract class AbstractChannelInitializer { - private final Optional maybeContext; - private final NetconfHandlerFactory handlerFactory; - - public AbstractChannelInitializer(Optional maybeContext) { - this.maybeContext = maybeContext; - this.handlerFactory = new NetconfHandlerFactory(new NetconfMessageFactory()); - } - - public void initialize(SocketChannel ch, Promise promise) { - if (maybeContext.isPresent()) { - initSsl(ch); - } - - ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM)); - ch.pipeline().addLast(handlerFactory.getDecoders()); - initializeAfterDecoder(ch, promise); - ch.pipeline().addLast("frameEncoder", FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM)); - ch.pipeline().addLast(handlerFactory.getEncoders()); - } + public abstract void initialize(SocketChannel ch, Promise promise); protected abstract void initializeAfterDecoder(SocketChannel ch, Promise promise); - private void initSsl(SocketChannel ch) { - SSLEngine sslEngine = maybeContext.get().createSSLEngine(); - initSslEngine(sslEngine); - final SslHandler handler = new SslHandler(sslEngine); - ch.pipeline().addLast("ssl", handler); - } - - protected abstract void initSslEngine(SSLEngine sslEngine); - - private static final class NetconfHandlerFactory extends ProtocolHandlerFactory { - - public NetconfHandlerFactory(final NetconfMessageFactory msgFactory) { - super(msgFactory); - } - - @Override - public ChannelHandler[] getEncoders() { - return new ChannelHandler[] { new ProtocolMessageEncoder(this.msgFactory) }; - } - - @Override - public ChannelHandler[] getDecoders() { - return new ChannelHandler[] { new ProtocolMessageDecoder(this.msgFactory) }; - } - } } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractSslChannelInitializer.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractSslChannelInitializer.java new file mode 100644 index 0000000000..d490eb2be6 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractSslChannelInitializer.java @@ -0,0 +1,79 @@ +/* + * 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.util; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; + +import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.api.NetconfSession; +import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory; +import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator; +import org.opendaylight.controller.netconf.util.messages.FramingMechanism; +import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory; +import org.opendaylight.protocol.framework.ProtocolHandlerFactory; +import org.opendaylight.protocol.framework.ProtocolMessageDecoder; +import org.opendaylight.protocol.framework.ProtocolMessageEncoder; + +import com.google.common.base.Optional; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.ssl.SslHandler; +import io.netty.util.concurrent.Promise; + +public abstract class AbstractSslChannelInitializer extends AbstractChannelInitializer { + + private final Optional maybeContext; + private final NetconfHandlerFactory handlerFactory; + + public AbstractSslChannelInitializer(Optional maybeContext) { + this.maybeContext = maybeContext; + this.handlerFactory = new NetconfHandlerFactory(new NetconfMessageFactory()); + } + + @Override + public void initialize(SocketChannel ch, Promise promise) { + if (maybeContext.isPresent()) { + initSsl(ch); + } + + ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM)); + ch.pipeline().addLast(handlerFactory.getDecoders()); + initializeAfterDecoder(ch, promise); + ch.pipeline().addLast("frameEncoder", FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM)); + ch.pipeline().addLast(handlerFactory.getEncoders()); + } + + private void initSsl(SocketChannel ch) { + SSLEngine sslEngine = maybeContext.get().createSSLEngine(); + initSslEngine(sslEngine); + final SslHandler handler = new SslHandler(sslEngine); + ch.pipeline().addLast("ssl", handler); + } + + protected abstract void initSslEngine(SSLEngine sslEngine); + + private static final class NetconfHandlerFactory extends ProtocolHandlerFactory { + + public NetconfHandlerFactory(final NetconfMessageFactory msgFactory) { + super(msgFactory); + } + + @Override + public ChannelHandler[] getEncoders() { + return new ChannelHandler[] { new ProtocolMessageEncoder(this.msgFactory) }; + } + + @Override + public ChannelHandler[] getDecoders() { + return new ChannelHandler[] { new ProtocolMessageDecoder(this.msgFactory) }; + } + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java index 3e862faa7b..2a900e052b 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java @@ -31,6 +31,8 @@ public class XmlNetconfConstants { public static final String RPC_REPLY_KEY = "rpc-reply"; public static final String RPC_ERROR = "rpc-error"; public static final String NAME_KEY = "name"; + public static final String NOTIFICATION_ELEMENT_NAME = "notification"; + // // public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0";