From 87e068952fe9207ccccbcebdaac2de09743e2403 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Wed, 23 Apr 2014 15:12:47 +0200 Subject: [PATCH] BUG-693 Config module for netconf client dispatcher. netconf/ NetconfClientDispatcher and NetconfSSHClientDispatcher merged into NetconfClientDispatcherImpl. Introduced NetconfClientConfiguration to contain all configuration attributes for netconf clients. Introduced interface for NetconfClientDispatchers. Removed NetconfITSecureTest since it did not test secure connection. config/ Added netconf-config-api maven module, which contains service definition of client-dispatcher. Added netconf-config-dispatcher maven module, which contains config module for client-dispatcher. md-sal/ Updated configuration for sal-netconf-connector with client dispatcher dependency (backwards compatibility preserved). Change-Id: I05e784af6a9b8e11fad21d3bad0311c110754d31 Signed-off-by: Maros Marsalek --- opendaylight/commons/opendaylight/pom.xml | 7 + .../config/netconf-config-dispatcher/pom.xml | 52 ++++++ .../NetconfClientDispatcherModule.java | 36 ++++ .../NetconfClientDispatcherModuleFactory.java | 17 ++ .../src/main/yang/odl-netconf-cfg.yang | 31 ++++ .../main/yang/odl-netconfig-client-cfg.yang | 64 +++++++ opendaylight/config/pom.xml | 1 + .../distribution/opendaylight/pom.xml | 6 + .../initial/01-netconf-connector.xml | 73 ++++++++ .../initial/04-netconf-connector.xml | 45 ----- .../md-sal/sal-netconf-connector/pom.xml | 4 + .../netconf/NetconfConnectorModule.java | 125 ++++++++----- .../sal/connect/netconf/NetconfDevice.java | 13 +- .../netconf/NetconfDeviceListener.java | 3 +- .../NetconfRemoteSchemaSourceProvider.java | 2 +- .../yang/odl-sal-netconf-connector-cfg.yang | 31 +++- opendaylight/netconf/netconf-client/pom.xml | 2 +- .../netconf/client/NetconfClient.java | 171 ------------------ .../client/NetconfClientDispatcher.java | 119 ++---------- .../client/NetconfClientDispatcherImpl.java | 122 +++++++++++++ .../client/NetconfSshClientDispatcher.java | 120 ------------ .../client/SshClientChannelInitializer.java | 56 ++++++ .../client/TcpClientChannelInitializer.java | 41 +++++ .../conf/NetconfClientConfiguration.java | 114 ++++++++++++ .../NetconfClientConfigurationBuilder.java | 103 +++++++++++ ...etconfReconnectingClientConfiguration.java | 46 +++++ ...econnectingClientConfigurationBuilder.java | 76 ++++++++ .../client/test/TestingNetconfClient.java | 30 +-- .../netconf/impl/ConcurrentClientsTest.java | 37 ++-- .../netconf/it/AbstractNetconfConfigTest.java | 33 +++- .../netconf/it/HardcodedYangStoreService.java | 18 +- .../it/NetconfConfigPersisterITTest.java | 14 +- .../netconf/it/NetconfITSecureTest.java | 37 +++- .../controller/netconf/it/NetconfITTest.java | 44 +++-- .../netconf/it/NetconfMonitoringITTest.java | 50 ++--- .../it/pax/IdentityRefNetconfTest.java | 33 +++- .../netconf/mapping/api/HandlingPriority.java | 17 +- .../netconf/ssh/NetconfSSHServer.java | 2 +- 38 files changed, 1176 insertions(+), 619 deletions(-) create mode 100644 opendaylight/config/netconf-config-dispatcher/pom.xml create mode 100644 opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModule.java create mode 100644 opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleFactory.java create mode 100644 opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconf-cfg.yang create mode 100644 opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconfig-client-cfg.yang create mode 100644 opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf-connector.xml delete mode 100644 opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/04-netconf-connector.xml delete mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java create mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcherImpl.java delete mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java create mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/SshClientChannelInitializer.java create mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/TcpClientChannelInitializer.java create mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfiguration.java create mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfigurationBuilder.java create mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfiguration.java create mode 100644 opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index e0891662ea..8588a6050a 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -870,6 +870,13 @@ netconf-client ${netconf.version} + + + + org.opendaylight.controller + netconf-config-dispatcher + ${netconf.version} + org.opendaylight.controller netconf-impl diff --git a/opendaylight/config/netconf-config-dispatcher/pom.xml b/opendaylight/config/netconf-config-dispatcher/pom.xml new file mode 100644 index 0000000000..65ebdaf938 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/pom.xml @@ -0,0 +1,52 @@ + + + + 4.0.0 + + org.opendaylight.controller + config-plugin-parent + 0.2.5-SNAPSHOT + ../config-plugin-parent + + + netconf-config-dispatcher + bundle + + + + ${project.groupId} + config-api + + + ${project.groupId} + netconf-client + ${netconf.version} + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.opendaylight.controller.config.yang.config.netconf, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.netconf.rev140408, + * + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + + diff --git a/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModule.java b/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModule.java new file mode 100644 index 0000000000..344ef3dec3 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModule.java @@ -0,0 +1,36 @@ +/* + * 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.yang.config.netconf.client.dispatcher; + +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; + +/** +* +*/ +public final class NetconfClientDispatcherModule extends org.opendaylight.controller.config.yang.config.netconf.client.dispatcher.AbstractNetconfClientDispatcherModule + { + + public NetconfClientDispatcherModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public NetconfClientDispatcherModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + NetconfClientDispatcherModule oldModule, java.lang.AutoCloseable oldInstance) { + + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + protected void customValidation(){ + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new NetconfClientDispatcherImpl(getBossThreadGroupDependency(), getWorkerThreadGroupDependency(), getTimerDependency()); + } +} diff --git a/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleFactory.java b/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleFactory.java new file mode 100644 index 0000000000..cfd4ef69a5 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleFactory.java @@ -0,0 +1,17 @@ +/* + * 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.yang.config.netconf.client.dispatcher; + +/** +* +*/ +public class NetconfClientDispatcherModuleFactory extends org.opendaylight.controller.config.yang.config.netconf.client.dispatcher.AbstractNetconfClientDispatcherModuleFactory +{ + + +} diff --git a/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconf-cfg.yang b/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconf-cfg.yang new file mode 100644 index 0000000000..16c2bcb062 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconf-cfg.yang @@ -0,0 +1,31 @@ +// vi: set smarttab et sw=4 tabstop=4: +module odl-netconf-cfg { + + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:netconf"; + prefix "cfg-net"; + + import config { prefix config; revision-date 2013-04-05; } + + description + "This module contains the base YANG definitions for + netconf 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 "2014-04-08" { + description + "Initial revision."; + } + + identity netconf-client-dispatcher { + + base "config:service-type"; + config:java-class "org.opendaylight.controller.netconf.client.NetconfClientDispatcher"; + } +} \ No newline at end of file diff --git a/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconfig-client-cfg.yang b/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconfig-client-cfg.yang new file mode 100644 index 0000000000..e00bdeb687 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconfig-client-cfg.yang @@ -0,0 +1,64 @@ +// vi: set smarttab et sw=4 tabstop=4: +module odl-netconfig-client-cfg { + + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher"; + prefix "cfg-net-client"; + + import config { prefix config; revision-date 2013-04-05; } + import odl-netconf-cfg { prefix cfg-net; revision-date 2014-04-08; } + import netty {prefix netty; } + + description + "This module contains the base YANG definitions for + netconf-client-dispatcher implementation. + + 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 "2014-04-08" { + description + "Initial revision."; + } + + identity netconf-client-dispatcher { + base config:module-type; + config:provided-service cfg-net:netconf-client-dispatcher; + config:java-name-prefix NetconfClientDispatcher; + } + + augment "/config:modules/config:module/config:configuration" { + case netconf-client-dispatcher { + when "/config:modules/config:module/config:type = 'netconf-client-dispatcher'"; + + container boss-thread-group { + uses config:service-ref { + refine type { + config:required-identity netty:netty-threadgroup; + } + } + } + + container worker-thread-group { + uses config:service-ref { + refine type { + config:required-identity netty:netty-threadgroup; + } + } + } + + container timer { + uses config:service-ref { + refine type { + config:required-identity netty:netty-timer; + } + } + } + } + } + +} \ No newline at end of file diff --git a/opendaylight/config/pom.xml b/opendaylight/config/pom.xml index bd2924ad9d..8bf9a0f3cd 100644 --- a/opendaylight/config/pom.xml +++ b/opendaylight/config/pom.xml @@ -38,6 +38,7 @@ yang-test-plugin shutdown-api shutdown-impl + netconf-config-dispatcher config-module-archetype diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index f9985cbcc1..648c59e906 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -865,6 +865,12 @@ org.opendaylight.controller netconf-client + + + + org.opendaylight.controller + netconf-config-dispatcher + org.opendaylight.controller netconf-impl diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf-connector.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf-connector.xml new file mode 100644 index 0000000000..fcbec19f5f --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf-connector.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + prefix:netconf-client-dispatcher + global-netconf-dispatcher + + prefix:netty-threadgroup + global-boss-group + + + prefix:netty-threadgroup + global-worker-group + + + prefix:netty-timer + global-timer + + + + + + prefix:sal-netconf-connector + controller-config +
127.0.0.1
+ 1830 + admin + admin + false + + prefix:netty-event-executor + global-event-executor + + + prefix:dom-broker-osgi-registry + dom-broker + + + prefix:netconf-client-dispatcher + global-netconf-dispatcher + +
+
+ + + + prefix:netconf-client-dispatcher + + global-netconf-dispatcher + /modules/module[type='netconf-client-dispatcher'][name='global-netconf-dispatcher'] + + + + +
+
+ + urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf?module=odl-sal-netconf-connector-cfg&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher?module=odl-netconfig-client-cfg&revision=2014-04-08 + +
diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/04-netconf-connector.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/04-netconf-connector.xml deleted file mode 100644 index 8143a38f34..0000000000 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/04-netconf-connector.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - prefix:sal-netconf-connector - controller-config - 1830 - admin - - prefix:netty-threadgroup - global-worker-group - -
127.0.0.1
- false - - prefix:netty-event-executor - global-event-executor - - admin - - prefix:netty-threadgroup - global-boss-group - - - prefix:dom-broker-osgi-registry - dom-broker - -
-
-
-
- - urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf?module=odl-sal-netconf-connector-cfg&revision=2013-10-28 - -
diff --git a/opendaylight/md-sal/sal-netconf-connector/pom.xml b/opendaylight/md-sal/sal-netconf-connector/pom.xml index 27d320f03e..ef485bbadf 100644 --- a/opendaylight/md-sal/sal-netconf-connector/pom.xml +++ b/opendaylight/md-sal/sal-netconf-connector/pom.xml @@ -17,6 +17,10 @@ netconf-client ${netconf.version}
+ + ${project.groupId} + netconf-config-dispatcher + ${project.groupId} sal-common-util diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java index ddaf6ea6c3..6e924221cf 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java @@ -9,7 +9,8 @@ package org.opendaylight.controller.config.yang.md.sal.connector.netconf; import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkCondition; import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkNotNull; -import io.netty.channel.EventLoopGroup; + +import io.netty.util.HashedWheelTimer; import io.netty.util.concurrent.GlobalEventExecutor; import java.io.File; @@ -20,10 +21,12 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; -import org.opendaylight.controller.netconf.client.NetconfSshClientDispatcher; -import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.controller.netconf.util.handler.ssh.authentication.LoginPassword; import org.opendaylight.controller.sal.connect.netconf.NetconfDevice; +import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener; import org.opendaylight.protocol.framework.ReconnectStrategy; import org.opendaylight.protocol.framework.TimedReconnectStrategy; import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider; @@ -69,6 +72,18 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co checkNotNull(getBetweenAttemptsTimeoutMillis(), betweenAttemptsTimeoutMillisJmxAttribute); checkCondition(getBetweenAttemptsTimeoutMillis() > 0, "must be > 0", betweenAttemptsTimeoutMillisJmxAttribute); + // FIXME BUG-944 remove backwards compatibility + if(getClientDispatcher() == null) { + checkCondition(getBossThreadGroup() != null, "Client dispatcher was not set, thread groups have to be set instead", bossThreadGroupJmxAttribute); + checkCondition(getWorkerThreadGroup() != null, "Client dispatcher was not set, thread groups have to be set instead", workerThreadGroupJmxAttribute); + } + + // Check username + password in case of ssh + if(getTcpOnly() == false) { + checkNotNull(getUsername(), usernameJmxAttribute); + checkNotNull(getPassword(), passwordJmxAttribute); + } + } @Override @@ -76,42 +91,13 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co getDomRegistryDependency(); NetconfDevice device = new NetconfDevice(getIdentifier().getInstanceName()); - String addressValue = getAddress(); - - Long connectionAttempts; - if (getMaxConnectionAttempts() != null && getMaxConnectionAttempts() > 0) { - connectionAttempts = getMaxConnectionAttempts(); - } else { - logger.trace("Setting {} on {} to infinity", maxConnectionAttemptsJmxAttribute, this); - connectionAttempts = null; - } - long clientConnectionTimeoutMillis = getConnectionTimeoutMillis(); - /* - * Uncomment after Switch to IP Address - if(getAddress().getIpv4Address() != null) { - addressValue = getAddress().getIpv4Address().getValue(); - } else { - addressValue = getAddress().getIpv6Address().getValue(); - } - */ - double sleepFactor = 1.0; - int minSleep = 1000; - Long maxSleep = null; - Long deadline = null; - ReconnectStrategy strategy = new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, getBetweenAttemptsTimeoutMillis(), - minSleep, sleepFactor, maxSleep, connectionAttempts, deadline); - - device.setReconnectStrategy(strategy); - - InetAddress addr = InetAddresses.forString(addressValue); - InetSocketAddress socketAddress = new InetSocketAddress(addr , getPort().intValue()); + device.setClientConfig(getClientConfig(device)); device.setProcessingExecutor(getGlobalProcessingExecutor()); - device.setSocketAddress(socketAddress); device.setEventExecutor(getEventExecutorDependency()); - device.setDispatcher(createDispatcher(clientConnectionTimeoutMillis)); + device.setDispatcher(getClientDispatcher() == null ? createDispatcher() : getClientDispatcherDependency()); device.setSchemaSourceProvider(getGlobalNetconfSchemaProvider(bundleContext)); getDomRegistryDependency().registerProvider(device, bundleContext); @@ -120,12 +106,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co } private ExecutorService getGlobalProcessingExecutor() { - if(GLOBAL_PROCESSING_EXECUTOR == null) { - - GLOBAL_PROCESSING_EXECUTOR = Executors.newCachedThreadPool(); - - } - return GLOBAL_PROCESSING_EXECUTOR; + return GLOBAL_PROCESSING_EXECUTOR == null ? Executors.newCachedThreadPool() : GLOBAL_PROCESSING_EXECUTOR; } private synchronized AbstractCachingSchemaSourceProvider getGlobalNetconfSchemaProvider(BundleContext bundleContext) { @@ -139,18 +120,64 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co return GLOBAL_NETCONF_SOURCE_PROVIDER; } - private NetconfClientDispatcher createDispatcher(long clientConnectionTimeoutMillis) { - EventLoopGroup bossGroup = getBossThreadGroupDependency(); - EventLoopGroup workerGroup = getWorkerThreadGroupDependency(); - if(getTcpOnly()) { - return new NetconfClientDispatcher( bossGroup, workerGroup, clientConnectionTimeoutMillis); - } else { - AuthenticationHandler authHandler = new LoginPassword(getUsername(),getPassword()); - return new NetconfSshClientDispatcher(authHandler , bossGroup, workerGroup, clientConnectionTimeoutMillis); - } + // FIXME BUG-944 remove backwards compatibility + /** + * @deprecated Use getClientDispatcherDependency method instead to retrieve injected dispatcher. + * This one creates new instance of NetconfClientDispatcher and will be removed in near future. + */ + @Deprecated + private NetconfClientDispatcher createDispatcher() { + return new NetconfClientDispatcherImpl(getBossThreadGroupDependency(), getWorkerThreadGroupDependency(), new HashedWheelTimer()); } public void setBundleContext(BundleContext bundleContext) { this.bundleContext = bundleContext; } + + public NetconfClientConfiguration getClientConfig(final NetconfDevice device) { + InetSocketAddress socketAddress = getSocketAddress(); + ReconnectStrategy strategy = getReconnectStrategy(); + long clientConnectionTimeoutMillis = getConnectionTimeoutMillis(); + + return NetconfClientConfigurationBuilder.create() + .withAddress(socketAddress) + .withConnectionTimeoutMillis(clientConnectionTimeoutMillis) + .withReconnectStrategy(strategy) + .withSessionListener(new NetconfDeviceListener(device)) + .withAuthHandler(new LoginPassword(getUsername(),getPassword())) + .withProtocol(getTcpOnly() ? + NetconfClientConfiguration.NetconfClientProtocol.TCP : + NetconfClientConfiguration.NetconfClientProtocol.SSH) + .build(); + } + + private ReconnectStrategy getReconnectStrategy() { + Long connectionAttempts; + if (getMaxConnectionAttempts() != null && getMaxConnectionAttempts() > 0) { + connectionAttempts = getMaxConnectionAttempts(); + } else { + logger.trace("Setting {} on {} to infinity", maxConnectionAttemptsJmxAttribute, this); + connectionAttempts = null; + } + double sleepFactor = 1.0; + int minSleep = 1000; + Long maxSleep = null; + Long deadline = null; + + return new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, getBetweenAttemptsTimeoutMillis(), + minSleep, sleepFactor, maxSleep, connectionAttempts, deadline); + } + + private InetSocketAddress getSocketAddress() { + /* + * Uncomment after Switch to IP Address + if(getAddress().getIpv4Address() != null) { + addressValue = getAddress().getIpv4Address().getValue(); + } else { + addressValue = getAddress().getIpv6Address().getValue(); + } + */ + InetAddress inetAddress = InetAddresses.forString(getAddress()); + return new InetSocketAddress(inetAddress, getPort().intValue()); + } } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java index aa5c6f40a9..e3f8649cd1 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java @@ -21,6 +21,7 @@ import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.toF import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.toRpcMessage; import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.wrap; +import com.google.common.base.Preconditions; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.URI; @@ -38,6 +39,7 @@ 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.DataReader; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; import org.opendaylight.controller.sal.core.api.Provider; @@ -121,6 +123,7 @@ public class NetconfDevice implements Provider, // private boolean rollbackSupported; + private NetconfClientConfiguration clientConfig; public NetconfDevice(String name) { this.name = name; @@ -134,11 +137,12 @@ public class NetconfDevice implements Provider, // checkState(schemaSourceProvider != null, "Schema Source Provider must be set."); checkState(eventExecutor != null, "Event executor must be set."); - listener = new NetconfDeviceListener(this); + Preconditions.checkArgument(clientConfig.getSessionListener() instanceof NetconfDeviceListener); + listener = (NetconfDeviceListener) clientConfig.getSessionListener(); logger.info("Starting NETCONF Client {} for address {}", name, socketAddress); - dispatcher.createClient(socketAddress, listener, reconnectStrategy); + dispatcher.createClient(clientConfig); } Optional getSchemaContext() { @@ -464,6 +468,11 @@ public class NetconfDevice implements Provider, // public void setDispatcher(final NetconfClientDispatcher dispatcher) { this.dispatcher = dispatcher; } + + public void setClientConfig(final NetconfClientConfiguration clientConfig) { + this.clientConfig = clientConfig; + } + } class NetconfDeviceSchemaContextProvider { diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java index 1dfc3b44d3..68667f0143 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java @@ -41,8 +41,7 @@ import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -class NetconfDeviceListener implements NetconfClientSessionListener { - +public class NetconfDeviceListener implements NetconfClientSessionListener { private static final class Request { final UncancellableFuture> future; final NetconfMessage request; diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java index abd935dd63..31c6bd0138 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java @@ -59,7 +59,7 @@ class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider return Optional.of(schemaBody); } } - logger.warn("YANG shcema was not successfully retrieved."); + logger.warn("YANG shcema was not successfully retrieved. Errors: {}", schemaReply.getErrors()); } catch (InterruptedException | ExecutionException e) { logger.warn("YANG shcema was not successfully retrieved.", e); } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang b/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang index f0fa452dc5..d4dad11ec3 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang @@ -7,10 +7,11 @@ module odl-sal-netconf-connector-cfg { import threadpool {prefix th;} import netty {prefix netty;} import opendaylight-md-sal-dom {prefix dom;} + import odl-netconf-cfg { prefix cfg-net; revision-date 2014-04-08; } description "Service definition for Binding Aware MD-SAL."; - + revision "2013-10-28" { description "Initial revision"; @@ -26,7 +27,7 @@ module odl-sal-netconf-connector-cfg { leaf address { type string; } - + leaf port { type uint32; } @@ -36,7 +37,7 @@ module odl-sal-netconf-connector-cfg { augment "/config:modules/config:module/config:configuration" { case sal-netconf-connector { when "/config:modules/config:module/config:type = 'sal-netconf-connector'"; - + leaf address { type string; } @@ -44,7 +45,7 @@ module odl-sal-netconf-connector-cfg { leaf port { type uint32; } - + leaf tcp-only { type boolean; } @@ -52,10 +53,11 @@ module odl-sal-netconf-connector-cfg { leaf username { type string; } - + leaf password { type string; } + container dom-registry { uses config:service-ref { refine type { @@ -65,17 +67,25 @@ module odl-sal-netconf-connector-cfg { } } + // FIXME BUG-944 remove backwards compatibility + // Deprecated, replaced by client dispatcher. + // This dependency will be removed in near future and all configurations of netconf-connector need to be changed to use dispatcher dependency. container boss-thread-group { uses config:service-ref { refine type { + mandatory false; config:required-identity netty:netty-threadgroup; } } } + // FIXME BUG-944 remove backwards compatibility + // Deprecated, replaced by client dispatcher. + // This dependency will be removed in near future and all configurations of netconf-connector need to be changed to use dispatcher dependency. container worker-thread-group { uses config:service-ref { refine type { + mandatory false; config:required-identity netty:netty-threadgroup; } } @@ -89,6 +99,16 @@ module odl-sal-netconf-connector-cfg { } } + // Replaces thread group dependencies + container client-dispatcher { + uses config:service-ref { + refine type { + mandatory false; + config:required-identity cfg-net:netconf-client-dispatcher; + } + } + } + leaf connection-timeout-millis { description "Specifies timeout in milliseconds after which connection must be established."; type uint32; @@ -101,7 +121,6 @@ module odl-sal-netconf-connector-cfg { default 0; // retry forever } - leaf between-attempts-timeout-millis { description "Timeout in milliseconds to wait between connection attempts."; type uint16; diff --git a/opendaylight/netconf/netconf-client/pom.xml b/opendaylight/netconf/netconf-client/pom.xml index fd44315499..ce77fdc08e 100644 --- a/opendaylight/netconf/netconf-client/pom.xml +++ b/opendaylight/netconf/netconf-client/pom.xml @@ -41,7 +41,7 @@ maven-bundle-plugin - org.opendaylight.controller.netconf.client, + org.opendaylight.controller.netconf.client.*, com.google.common.base, com.google.common.collect, io.netty.channel, diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java deleted file mode 100644 index d98211d0dd..0000000000 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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 clientFuture = dispatch.createClient(address, sessionListener, strat); - this.address = address; - clientSession = get(clientFuture); - this.sessionId = clientSession.getSessionId(); - } - - private NetconfClientSession get(Future 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 clientFuture = dispatch.createClient(address, sessionListener, strategy); - this.address = address; - clientSession = get(clientFuture); - this.sessionId = clientSession.getSessionId(); - } - - public Future 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 getCapabilities() { - Preconditions.checkState(clientSession != null, "Client was not initialized successfully"); - return Sets.newHashSet(clientSession.getServerCapabilities()); - } - - public NetconfClientSession getClientSession() { - return clientSession; - } -} 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 c7c723cb27..37e29876f3 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 @@ -1,119 +1,26 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ - package org.opendaylight.controller.netconf.client; -import com.google.common.base.Optional; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.util.HashedWheelTimer; import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.Promise; -import org.opendaylight.controller.netconf.util.AbstractChannelInitializer; -import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; -import org.opendaylight.protocol.framework.AbstractDispatcher; -import org.opendaylight.protocol.framework.ReconnectStrategy; -import org.opendaylight.protocol.framework.ReconnectStrategyFactory; -import org.opendaylight.protocol.framework.SessionListenerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Closeable; -import java.net.InetSocketAddress; - -public class NetconfClientDispatcher extends AbstractDispatcher implements Closeable { - - private static final Logger logger = LoggerFactory.getLogger(NetconfClientDispatcher.class); - - private final NetconfClientSessionNegotiatorFactory negotiatorFactory; - private final HashedWheelTimer timer; - - public NetconfClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup, - long clientConnectionTimeoutMillis) { - super(bossGroup, workerGroup); - timer = new HashedWheelTimer(); - this.negotiatorFactory = new NetconfClientSessionNegotiatorFactory(timer, - Optional. absent(), clientConnectionTimeoutMillis); - } - - public NetconfClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup, - NetconfHelloMessageAdditionalHeader additionalHeader, long connectionTimeoutMillis) { - super(bossGroup, workerGroup); - timer = new HashedWheelTimer(); - this.negotiatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.of(additionalHeader), - connectionTimeoutMillis); - } - - public Future createClient(InetSocketAddress address, - final NetconfClientSessionListener sessionListener, ReconnectStrategy strat) { - - return super.createClient(address, strat, new PipelineInitializer() { - - @Override - public void initializeChannel(final SocketChannel ch, final Promise promise) { - initialize(ch, promise); - } - - private void initialize(SocketChannel ch, Promise promise) { - new ClientChannelInitializer(negotiatorFactory, sessionListener).initialize(ch, promise); - } - }); - } - - public Future createReconnectingClient(final InetSocketAddress address, - final NetconfClientSessionListener listener, - final ReconnectStrategyFactory connectStrategyFactory, final ReconnectStrategy reestablishStrategy) { - final ClientChannelInitializer init = new ClientChannelInitializer(negotiatorFactory, listener); - - return super.createReconnectingClient(address, connectStrategyFactory, reestablishStrategy, - new PipelineInitializer() { - @Override - public void initializeChannel(final SocketChannel ch, final Promise promise) { - init.initialize(ch, promise); - } - }); - } - - private static final class ClientChannelInitializer extends AbstractChannelInitializer { - - private final NetconfClientSessionNegotiatorFactory negotiatorFactory; - private final NetconfClientSessionListener sessionListener; - - private ClientChannelInitializer(NetconfClientSessionNegotiatorFactory negotiatorFactory, - NetconfClientSessionListener sessionListener) { - this.negotiatorFactory = negotiatorFactory; - this.sessionListener = sessionListener; - } +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration; - @Override - public void initialize(SocketChannel ch, Promise promise) { - super.initialize(ch,promise); - } +public interface NetconfClientDispatcher { - @Override - protected void initializeSessionNegotiator(SocketChannel ch, Promise promise) { - ch.pipeline().addAfter(NETCONF_MESSAGE_DECODER, AbstractChannelInitializer.NETCONF_SESSION_NEGOTIATOR, - negotiatorFactory.getSessionNegotiator( - new SessionListenerFactory() { - @Override - public NetconfClientSessionListener getSessionListener() { - return sessionListener; - } - }, ch, promise)); - } - } + /** + * + * Create netconf client. Network communication has to be set up based on network protocol specified in clientConfiguration + * + * @param clientConfiguration + * @return netconf client based on provided configuration + */ + Future createClient(NetconfClientConfiguration clientConfiguration); - @Override - public void close() { - try { - timer.stop(); - } catch (Exception e) { - logger.debug("Ignoring exception while closing {}", timer, e); - } - } + Future createReconnectingClient(NetconfReconnectingClientConfiguration clientConfiguration); } diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcherImpl.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcherImpl.java new file mode 100644 index 0000000000..bdebfa28cc --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcherImpl.java @@ -0,0 +1,122 @@ +/* + * 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 java.io.Closeable; + +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration; +import org.opendaylight.protocol.framework.AbstractDispatcher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.util.Timer; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.Promise; + +public class NetconfClientDispatcherImpl extends AbstractDispatcher + implements NetconfClientDispatcher, Closeable { + + private static final Logger logger = LoggerFactory.getLogger(NetconfClientDispatcherImpl.class); + + private final Timer timer; + + public NetconfClientDispatcherImpl(final EventLoopGroup bossGroup, final EventLoopGroup workerGroup, final Timer timer) { + super(bossGroup, workerGroup); + this.timer = timer; + } + + @Override + public Future createClient(final NetconfClientConfiguration clientConfiguration) { + switch (clientConfiguration.getProtocol()) { + case TCP: + return createTcpClient(clientConfiguration); + case SSH: + return createSshClient(clientConfiguration); + } + throw new IllegalArgumentException("Unknown client protocol " + clientConfiguration.getProtocol()); + } + + @Override + public Future createReconnectingClient(final NetconfReconnectingClientConfiguration clientConfiguration) { + switch (clientConfiguration.getProtocol()) { + case TCP: return createReconnectingTcpClient(clientConfiguration); + case SSH: return createReconnectingSshClient(clientConfiguration); + default: throw new IllegalArgumentException("Unknown client protocol " + clientConfiguration.getProtocol()); + } + } + + private Future createTcpClient(final NetconfClientConfiguration currentConfiguration) { + logger.debug("Creating TCP client with configuration: {}", currentConfiguration); + return super.createClient(currentConfiguration.getAddress(), currentConfiguration.getReconnectStrategy(), + new PipelineInitializer() { + + @Override + public void initializeChannel(final SocketChannel ch, final Promise promise) { + initialize(ch, promise); + } + + private void initialize(final SocketChannel ch, final Promise promise) { + new TcpClientChannelInitializer(getNegotiatorFactory(currentConfiguration), currentConfiguration + .getSessionListener()).initialize(ch, promise); + } + }); + } + + private Future createReconnectingTcpClient(final NetconfReconnectingClientConfiguration currentConfiguration) { + logger.debug("Creating reconnecting TCP client with configuration: {}", currentConfiguration); + final TcpClientChannelInitializer init = new TcpClientChannelInitializer(getNegotiatorFactory(currentConfiguration), + currentConfiguration.getSessionListener()); + + return super.createReconnectingClient(currentConfiguration.getAddress(), currentConfiguration.getConnectStrategyFactory(), + currentConfiguration.getReconnectStrategy(), new PipelineInitializer() { + @Override + public void initializeChannel(final SocketChannel ch, final Promise promise) { + init.initialize(ch, promise); + } + }); + } + + private Future createSshClient(final NetconfClientConfiguration currentConfiguration) { + logger.debug("Creating SSH client with configuration: {}", currentConfiguration); + return super.createClient(currentConfiguration.getAddress(), currentConfiguration.getReconnectStrategy(), + new PipelineInitializer() { + + @Override + public void initializeChannel(final SocketChannel ch, + final Promise sessionPromise) { + new SshClientChannelInitializer(currentConfiguration.getAuthHandler(), + getNegotiatorFactory(currentConfiguration), currentConfiguration.getSessionListener()) + .initialize(ch, sessionPromise); + } + + }); + } + + private Future createReconnectingSshClient(final NetconfReconnectingClientConfiguration currentConfiguration) { + logger.debug("Creating reconnecting SSH client with configuration: {}", currentConfiguration); + final SshClientChannelInitializer init = new SshClientChannelInitializer(currentConfiguration.getAuthHandler(), + getNegotiatorFactory(currentConfiguration), currentConfiguration.getSessionListener()); + + return super.createReconnectingClient(currentConfiguration.getAddress(), currentConfiguration.getConnectStrategyFactory(), currentConfiguration.getReconnectStrategy(), + new PipelineInitializer() { + @Override + public void initializeChannel(final SocketChannel ch, final Promise promise) { + init.initialize(ch, promise); + } + }); + } + + protected NetconfClientSessionNegotiatorFactory getNegotiatorFactory(final NetconfClientConfiguration cfg) { + return new NetconfClientSessionNegotiatorFactory(timer, cfg.getAdditionalHeader(), + cfg.getConnectionTimeoutMillis()); + } +} 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 deleted file mode 100644 index 5b82ff2215..0000000000 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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; -import io.netty.channel.socket.SocketChannel; -import io.netty.util.HashedWheelTimer; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.Promise; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import org.opendaylight.controller.netconf.util.AbstractChannelInitializer; -import org.opendaylight.controller.netconf.util.handler.ssh.SshHandler; -import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; -import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker; -import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; -import org.opendaylight.protocol.framework.ReconnectStrategy; -import org.opendaylight.protocol.framework.ReconnectStrategyFactory; -import org.opendaylight.protocol.framework.SessionListenerFactory; - -import com.google.common.base.Optional; - -public class NetconfSshClientDispatcher extends NetconfClientDispatcher { - - private final AuthenticationHandler authHandler; - private final HashedWheelTimer timer; - private final NetconfClientSessionNegotiatorFactory negotiatorFactory; - - public NetconfSshClientDispatcher(AuthenticationHandler authHandler, EventLoopGroup bossGroup, - EventLoopGroup workerGroup, long connectionTimeoutMillis) { - super(bossGroup, workerGroup, connectionTimeoutMillis); - this.authHandler = authHandler; - this.timer = new HashedWheelTimer(); - this.negotiatorFactory = new NetconfClientSessionNegotiatorFactory(timer, - Optional. absent(), connectionTimeoutMillis); - } - - public NetconfSshClientDispatcher(AuthenticationHandler authHandler, EventLoopGroup bossGroup, - EventLoopGroup workerGroup, NetconfHelloMessageAdditionalHeader additionalHeader, long socketTimeoutMillis) { - super(bossGroup, workerGroup, additionalHeader, socketTimeoutMillis); - this.authHandler = authHandler; - this.timer = new HashedWheelTimer(); - this.negotiatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.of(additionalHeader), - socketTimeoutMillis); - } - - @Override - public Future createClient(InetSocketAddress address, - final NetconfClientSessionListener sessionListener, ReconnectStrategy strat) { - return super.createClient(address, strat, new PipelineInitializer() { - - @Override - public void initializeChannel(SocketChannel arg0, Promise arg1) { - new NetconfSshClientInitializer(authHandler, negotiatorFactory, sessionListener).initialize(arg0, arg1); - } - - }); - } - - @Override - public Future createReconnectingClient(final InetSocketAddress address, - final NetconfClientSessionListener listener, - final ReconnectStrategyFactory connectStrategyFactory, final ReconnectStrategy reestablishStrategy) { - final NetconfSshClientInitializer init = new NetconfSshClientInitializer(authHandler, negotiatorFactory, listener); - - return super.createReconnectingClient(address, connectStrategyFactory, reestablishStrategy, - new PipelineInitializer() { - @Override - public void initializeChannel(final SocketChannel ch, final Promise promise) { - init.initialize(ch, promise); - } - }); - } - - private static final class NetconfSshClientInitializer extends AbstractChannelInitializer { - - private final AuthenticationHandler authenticationHandler; - private final NetconfClientSessionNegotiatorFactory negotiatorFactory; - private final NetconfClientSessionListener sessionListener; - - public NetconfSshClientInitializer(AuthenticationHandler authHandler, - NetconfClientSessionNegotiatorFactory negotiatorFactory, - final NetconfClientSessionListener sessionListener) { - this.authenticationHandler = authHandler; - this.negotiatorFactory = negotiatorFactory; - this.sessionListener = sessionListener; - } - - @Override - public void initialize(SocketChannel ch, Promise promise) { - try { - Invoker invoker = Invoker.subsystem("netconf"); - ch.pipeline().addFirst(new SshHandler(authenticationHandler, invoker)); - super.initialize(ch,promise); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - protected void initializeSessionNegotiator(SocketChannel ch, - Promise promise) { - ch.pipeline().addAfter(NETCONF_MESSAGE_DECODER, AbstractChannelInitializer.NETCONF_SESSION_NEGOTIATOR, - negotiatorFactory.getSessionNegotiator(new SessionListenerFactory() { - @Override - public NetconfClientSessionListener getSessionListener() { - return sessionListener; - } - }, ch, promise)); - } - } -} diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/SshClientChannelInitializer.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/SshClientChannelInitializer.java new file mode 100644 index 0000000000..b86349ddea --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/SshClientChannelInitializer.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.client; + +import io.netty.channel.socket.SocketChannel; +import io.netty.util.concurrent.Promise; +import org.opendaylight.controller.netconf.util.AbstractChannelInitializer; +import org.opendaylight.controller.netconf.util.handler.ssh.SshHandler; +import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker; +import org.opendaylight.protocol.framework.SessionListenerFactory; + +import java.io.IOException; + +final class SshClientChannelInitializer extends AbstractChannelInitializer { + + private final AuthenticationHandler authenticationHandler; + private final NetconfClientSessionNegotiatorFactory negotiatorFactory; + private final NetconfClientSessionListener sessionListener; + + public SshClientChannelInitializer(final AuthenticationHandler authHandler, + final NetconfClientSessionNegotiatorFactory negotiatorFactory, + final NetconfClientSessionListener sessionListener) { + this.authenticationHandler = authHandler; + this.negotiatorFactory = negotiatorFactory; + this.sessionListener = sessionListener; + } + + @Override + public void initialize(final SocketChannel ch, final Promise promise) { + try { + final Invoker invoker = Invoker.subsystem("netconf"); + ch.pipeline().addFirst(new SshHandler(authenticationHandler, invoker)); + super.initialize(ch,promise); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + @Override + protected void initializeSessionNegotiator(final SocketChannel ch, + final Promise promise) { + ch.pipeline().addAfter(NETCONF_MESSAGE_DECODER, AbstractChannelInitializer.NETCONF_SESSION_NEGOTIATOR, + negotiatorFactory.getSessionNegotiator(new SessionListenerFactory() { + @Override + public NetconfClientSessionListener getSessionListener() { + return sessionListener; + } + }, ch, promise)); + } +} diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/TcpClientChannelInitializer.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/TcpClientChannelInitializer.java new file mode 100644 index 0000000000..967d3c6dfb --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/TcpClientChannelInitializer.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.client; + +import io.netty.channel.socket.SocketChannel; +import io.netty.util.concurrent.Promise; +import org.opendaylight.controller.netconf.util.AbstractChannelInitializer; +import org.opendaylight.protocol.framework.SessionListenerFactory; + +class TcpClientChannelInitializer extends AbstractChannelInitializer { + + private final NetconfClientSessionNegotiatorFactory negotiatorFactory; + private final NetconfClientSessionListener sessionListener; + + TcpClientChannelInitializer(final NetconfClientSessionNegotiatorFactory negotiatorFactory, + final NetconfClientSessionListener sessionListener) { + this.negotiatorFactory = negotiatorFactory; + this.sessionListener = sessionListener; + } + + @Override + public void initialize(final SocketChannel ch, final Promise promise) { + super.initialize(ch, promise); + } + + @Override + protected void initializeSessionNegotiator(final SocketChannel ch, final Promise promise) { + ch.pipeline().addAfter(NETCONF_MESSAGE_DECODER, AbstractChannelInitializer.NETCONF_SESSION_NEGOTIATOR, + negotiatorFactory.getSessionNegotiator(new SessionListenerFactory() { + @Override + public NetconfClientSessionListener getSessionListener() { + return sessionListener; + } + }, ch, promise)); + } +} diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfiguration.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfiguration.java new file mode 100644 index 0000000000..5a3ec3a23e --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfiguration.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.client.conf; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import org.opendaylight.controller.netconf.client.NetconfClientSessionListener; +import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; +import org.opendaylight.protocol.framework.ReconnectStrategy; + +import java.net.InetSocketAddress; + +public class NetconfClientConfiguration { + + private final NetconfClientProtocol clientProtocol; + private final InetSocketAddress address; + private final Long connectionTimeoutMillis; + + private final NetconfHelloMessageAdditionalHeader additionalHeader; + private final NetconfClientSessionListener sessionListener; + + private final ReconnectStrategy reconnectStrategy; + + private final AuthenticationHandler authHandler; + + NetconfClientConfiguration(final NetconfClientProtocol protocol, final InetSocketAddress address, final Long connectionTimeoutMillis, final NetconfHelloMessageAdditionalHeader additionalHeader, final NetconfClientSessionListener sessionListener, final ReconnectStrategy reconnectStrategy, final AuthenticationHandler authHandler) { + this.address = address; + this.connectionTimeoutMillis = connectionTimeoutMillis; + this.additionalHeader = additionalHeader; + this.sessionListener = sessionListener; + this.clientProtocol = protocol; + this.reconnectStrategy = reconnectStrategy; + this.authHandler = authHandler; + validateConfiguration(); + } + + public final InetSocketAddress getAddress() { + return address; + } + + public final Long getConnectionTimeoutMillis() { + return connectionTimeoutMillis; + } + + public final Optional getAdditionalHeader() { + return Optional.fromNullable(additionalHeader); + } + + public final NetconfClientSessionListener getSessionListener() { + return sessionListener; + } + + public final ReconnectStrategy getReconnectStrategy() { + return reconnectStrategy; + } + + public final AuthenticationHandler getAuthHandler() { + return authHandler; + } + + public NetconfClientProtocol getProtocol() { + return clientProtocol; + } + + private void validateConfiguration() { + Preconditions.checkNotNull(clientProtocol, " "); + switch (clientProtocol) { + case SSH: + validateSshConfiguration(); + // Fall through intentional (ssh validation is a superset of tcp validation) + case TCP: + validateTcpConfiguration(); + } + } + + protected void validateSshConfiguration() { + Preconditions.checkNotNull(authHandler, "authHandler"); + } + + protected void validateTcpConfiguration() { + Preconditions.checkNotNull(address, "address"); + Preconditions.checkNotNull(clientProtocol, "clientProtocol"); + Preconditions.checkNotNull(connectionTimeoutMillis, "connectionTimeoutMillis"); + Preconditions.checkNotNull(sessionListener, "sessionListener"); + Preconditions.checkNotNull(reconnectStrategy, "reconnectStrategy"); + } + + @Override + public final String toString() { + return buildToStringHelper().toString(); + } + + protected Objects.ToStringHelper buildToStringHelper() { + return Objects.toStringHelper(this) + .add("address", address) + .add("connectionTimeoutMillis", connectionTimeoutMillis) + .add("additionalHeader", additionalHeader) + .add("sessionListener", sessionListener) + .add("reconnectStrategy", reconnectStrategy) + .add("clientProtocol", clientProtocol) + .add("authHandler", authHandler); + } + + public static enum NetconfClientProtocol { + TCP, SSH + } +} \ No newline at end of file diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfigurationBuilder.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfigurationBuilder.java new file mode 100644 index 0000000000..a3e57bd9d3 --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfClientConfigurationBuilder.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.client.conf; + +import org.opendaylight.controller.netconf.client.NetconfClientSessionListener; +import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; +import org.opendaylight.protocol.framework.ReconnectStrategy; + +import java.net.InetSocketAddress; + +public class NetconfClientConfigurationBuilder { + + public static final int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 5000; + public static final NetconfClientConfiguration.NetconfClientProtocol DEFAULT_CLIENT_PROTOCOL = NetconfClientConfiguration.NetconfClientProtocol.TCP; + + private InetSocketAddress address; + private long connectionTimeoutMillis = DEFAULT_CONNECTION_TIMEOUT_MILLIS; + private NetconfHelloMessageAdditionalHeader additionalHeader; + private NetconfClientSessionListener sessionListener; + private ReconnectStrategy reconnectStrategy; + private AuthenticationHandler authHandler; + private NetconfClientConfiguration.NetconfClientProtocol clientProtocol = DEFAULT_CLIENT_PROTOCOL; + + protected NetconfClientConfigurationBuilder() { + } + + public static NetconfClientConfigurationBuilder create() { + return new NetconfClientConfigurationBuilder(); + } + + public NetconfClientConfigurationBuilder withAddress(final InetSocketAddress address) { + this.address = address; + return this; + } + + public NetconfClientConfigurationBuilder withConnectionTimeoutMillis(final long connectionTimeoutMillis) { + this.connectionTimeoutMillis = connectionTimeoutMillis; + return this; + } + + public NetconfClientConfigurationBuilder withProtocol(final NetconfClientConfiguration.NetconfClientProtocol clientProtocol) { + this.clientProtocol = clientProtocol; + return this; + } + + public NetconfClientConfigurationBuilder withAdditionalHeader(final NetconfHelloMessageAdditionalHeader additionalHeader) { + this.additionalHeader = additionalHeader; + return this; + } + + public NetconfClientConfigurationBuilder withSessionListener(final NetconfClientSessionListener sessionListener) { + this.sessionListener = sessionListener; + return this; + } + + public NetconfClientConfigurationBuilder withReconnectStrategy(final ReconnectStrategy reconnectStrategy) { + this.reconnectStrategy = reconnectStrategy; + return this; + } + + public NetconfClientConfigurationBuilder withAuthHandler(final AuthenticationHandler authHandler) { + this.authHandler = authHandler; + return this; + } + + final InetSocketAddress getAddress() { + return address; + } + + final long getConnectionTimeoutMillis() { + return connectionTimeoutMillis; + } + + final NetconfHelloMessageAdditionalHeader getAdditionalHeader() { + return additionalHeader; + } + + final NetconfClientSessionListener getSessionListener() { + return sessionListener; + } + + final ReconnectStrategy getReconnectStrategy() { + return reconnectStrategy; + } + + final AuthenticationHandler getAuthHandler() { + return authHandler; + } + + final NetconfClientConfiguration.NetconfClientProtocol getProtocol() { + return clientProtocol; + } + + public NetconfClientConfiguration build() { + return new NetconfClientConfiguration(clientProtocol, address, connectionTimeoutMillis, additionalHeader, sessionListener, reconnectStrategy, authHandler); + } +} diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfiguration.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfiguration.java new file mode 100644 index 0000000000..64fcc48b25 --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfiguration.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.client.conf; + +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import org.opendaylight.controller.netconf.client.NetconfClientSessionListener; +import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; +import org.opendaylight.protocol.framework.ReconnectStrategy; +import org.opendaylight.protocol.framework.ReconnectStrategyFactory; + +import java.net.InetSocketAddress; + +public final class NetconfReconnectingClientConfiguration extends NetconfClientConfiguration { + + private final ReconnectStrategyFactory connectStrategyFactory; + + NetconfReconnectingClientConfiguration(final NetconfClientProtocol clientProtocol, final InetSocketAddress address, + final Long connectionTimeoutMillis, final NetconfHelloMessageAdditionalHeader additionalHeader, + final NetconfClientSessionListener sessionListener, final ReconnectStrategy reconnectStrategy, + final ReconnectStrategyFactory connectStrategyFactory, final AuthenticationHandler authHandler) { + super(clientProtocol, address, connectionTimeoutMillis, additionalHeader, sessionListener, reconnectStrategy, + authHandler); + this.connectStrategyFactory = connectStrategyFactory; + validateReconnectConfiguration(); + } + + public ReconnectStrategyFactory getConnectStrategyFactory() { + return connectStrategyFactory; + } + + private void validateReconnectConfiguration() { + Preconditions.checkNotNull(connectStrategyFactory); + } + + @Override + protected Objects.ToStringHelper buildToStringHelper() { + return super.buildToStringHelper().add("connectStrategyFactory", connectStrategyFactory); + } +} diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java new file mode 100644 index 0000000000..411ac3c23d --- /dev/null +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.client.conf; + +import java.net.InetSocketAddress; + +import org.opendaylight.controller.netconf.client.NetconfClientSessionListener; +import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; +import org.opendaylight.protocol.framework.ReconnectStrategy; +import org.opendaylight.protocol.framework.ReconnectStrategyFactory; + +public class NetconfReconnectingClientConfigurationBuilder extends NetconfClientConfigurationBuilder { + + private ReconnectStrategyFactory connectStrategyFactory; + + private NetconfReconnectingClientConfigurationBuilder() { + } + + public static NetconfReconnectingClientConfigurationBuilder create() { + return new NetconfReconnectingClientConfigurationBuilder(); + } + + + public NetconfReconnectingClientConfigurationBuilder withConnectStrategyFactory(final ReconnectStrategyFactory connectStrategyFactory) { + this.connectStrategyFactory = connectStrategyFactory; + return this; + } + + @Override + public NetconfReconnectingClientConfiguration build() { + return new NetconfReconnectingClientConfiguration(getProtocol(), getAddress(), getConnectionTimeoutMillis(), getAdditionalHeader(), getSessionListener(), getReconnectStrategy(), connectStrategyFactory, getAuthHandler()); + } + + // Override setter methods to return subtype + + @Override + public NetconfReconnectingClientConfigurationBuilder withAddress(final InetSocketAddress address) { + return (NetconfReconnectingClientConfigurationBuilder) super.withAddress(address); + } + + @Override + public NetconfReconnectingClientConfigurationBuilder withConnectionTimeoutMillis(final long connectionTimeoutMillis) { + return (NetconfReconnectingClientConfigurationBuilder) super.withConnectionTimeoutMillis(connectionTimeoutMillis); + } + + @Override + public NetconfReconnectingClientConfigurationBuilder withAdditionalHeader(final NetconfHelloMessageAdditionalHeader additionalHeader) { + return (NetconfReconnectingClientConfigurationBuilder) super.withAdditionalHeader(additionalHeader); + } + + @Override + public NetconfReconnectingClientConfigurationBuilder withSessionListener(final NetconfClientSessionListener sessionListener) { + return (NetconfReconnectingClientConfigurationBuilder) super.withSessionListener(sessionListener); + } + + @Override + public NetconfReconnectingClientConfigurationBuilder withReconnectStrategy(final ReconnectStrategy reconnectStrategy) { + return (NetconfReconnectingClientConfigurationBuilder) super.withReconnectStrategy(reconnectStrategy); + } + + @Override + public NetconfReconnectingClientConfigurationBuilder withAuthHandler(final AuthenticationHandler authHandler) { + return (NetconfReconnectingClientConfigurationBuilder) super.withAuthHandler(authHandler); + } + + @Override + public NetconfReconnectingClientConfigurationBuilder withProtocol(NetconfClientConfiguration.NetconfClientProtocol clientProtocol) { + return (NetconfReconnectingClientConfigurationBuilder) super.withProtocol(clientProtocol); + } +} diff --git a/opendaylight/netconf/netconf-client/src/test/java/org/opendaylight/controller/netconf/client/test/TestingNetconfClient.java b/opendaylight/netconf/netconf-client/src/test/java/org/opendaylight/controller/netconf/client/test/TestingNetconfClient.java index 32c6ea85d6..60d8f3044a 100644 --- a/opendaylight/netconf/netconf-client/src/test/java/org/opendaylight/controller/netconf/client/test/TestingNetconfClient.java +++ b/opendaylight/netconf/netconf-client/src/test/java/org/opendaylight/controller/netconf/client/test/TestingNetconfClient.java @@ -8,12 +8,8 @@ package org.opendaylight.controller.netconf.client.test; -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; @@ -25,11 +21,11 @@ import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; import org.opendaylight.controller.netconf.client.NetconfClientSession; import org.opendaylight.controller.netconf.client.NetconfClientSessionListener; import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener; -import org.opendaylight.protocol.framework.NeverReconnectStrategy; -import org.opendaylight.protocol.framework.ReconnectStrategy; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; +import io.netty.util.concurrent.Future; /** @@ -44,11 +40,11 @@ public class TestingNetconfClient implements Closeable { private final NetconfClientSessionListener sessionListener; private final long sessionId; - private TestingNetconfClient(String clientLabel, InetSocketAddress address, ReconnectStrategy strat, - NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException { + public TestingNetconfClient(String clientLabel, + NetconfClientDispatcher netconfClientDispatcher, final NetconfClientConfiguration config) throws InterruptedException { this.label = clientLabel; - sessionListener = new SimpleNetconfClientSessionListener(); - Future clientFuture = netconfClientDispatcher.createClient(address, sessionListener, strat); + sessionListener = config.getSessionListener(); + Future clientFuture = netconfClientDispatcher.createClient(config); clientSession = get(clientFuture); this.sessionId = clientSession.getSessionId(); } @@ -63,18 +59,6 @@ public class TestingNetconfClient implements Closeable { } } - public TestingNetconfClient(String clientLabelForLogging, InetSocketAddress address, int connectTimeoutMs, - NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException { - this(clientLabelForLogging, address, - new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, connectTimeoutMs), netconfClientDispatcher); - } - - public TestingNetconfClient(String clientLabelForLogging, InetSocketAddress address, - NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException { - this(clientLabelForLogging, address, new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, - DEFAULT_CONNECT_TIMEOUT), netconfClientDispatcher); - } - public Future sendRequest(NetconfMessage message) { return ((SimpleNetconfClientSessionListener)sessionListener).sendRequest(message); } @@ -111,4 +95,4 @@ public class TestingNetconfClient implements Closeable { Preconditions.checkState(clientSession != null, "Client was not initialized successfully"); return Sets.newHashSet(clientSession.getServerCapabilities()); } -} \ No newline at end of file +} 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 0a0cd22088..b8622d1e91 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 @@ -15,10 +15,6 @@ 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.util.HashedWheelTimer; import java.io.DataOutputStream; import java.io.InputStream; import java.io.InputStreamReader; @@ -30,13 +26,13 @@ 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; @@ -48,6 +44,10 @@ 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.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; +import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; @@ -63,14 +63,20 @@ 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.opendaylight.protocol.framework.NeverReconnectStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; +import com.google.common.base.Preconditions; +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 io.netty.util.concurrent.GlobalEventExecutor; @RunWith(Parameterized.class) public class ConcurrentClientsTest { @@ -138,10 +144,9 @@ public class ConcurrentClientsTest { @Before public void setUp() throws Exception { - + hashedWheelTimer = new HashedWheelTimer(); nettyGroup = new NioEventLoopGroup(nettyThreads); - NetconfHelloMessageAdditionalHeader additionalHeader = new NetconfHelloMessageAdditionalHeader("uname", "10.10.10.1", "830", "tcp", "client"); - netconfClientDispatcher = new NetconfClientDispatcher( nettyGroup, nettyGroup, additionalHeader, 5000); + netconfClientDispatcher = new NetconfClientDispatcherImpl(nettyGroup, nettyGroup, hashedWheelTimer); NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl(); @@ -149,7 +154,6 @@ public class ConcurrentClientsTest { factoriesListener.onAddNetconfOperationServiceFactory(new TestingOperationServiceFactory(testingNetconfOperation)); SessionIdProvider idProvider = new SessionIdProvider(); - hashedWheelTimer = new HashedWheelTimer(); NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( hashedWheelTimer, factoriesListener, idProvider, 5000, commitNot, createMockedMonitoringService(), serverCaps); @@ -333,8 +337,8 @@ public class ConcurrentClientsTest { @Override public void run() { try { - final TestingNetconfClient netconfClient = new TestingNetconfClient(Thread.currentThread().getName(), - netconfAddress, netconfClientDispatcher); + final TestingNetconfClient netconfClient = + new TestingNetconfClient(Thread.currentThread().getName(), netconfClientDispatcher, getClientConfig()); long sessionId = netconfClient.getSessionId(); logger.info("Client with session id {}: hello exchanged", sessionId); @@ -353,5 +357,16 @@ public class ConcurrentClientsTest { throw new IllegalStateException(Thread.currentThread().getName(), e); } } + + private NetconfClientConfiguration getClientConfig() { + final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create(); + b.withAddress(netconfAddress); + b.withAdditionalHeader(new NetconfHelloMessageAdditionalHeader("uname", "10.10.10.1", "830", "tcp", + "client")); + b.withSessionListener(new SimpleNetconfClientSessionListener()); + b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, + NetconfClientConfigurationBuilder.DEFAULT_CONNECTION_TIMEOUT_MILLIS)); + return b.build(); + } } } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java index b81f950cb3..d4073e5c17 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java @@ -7,22 +7,30 @@ */ package org.opendaylight.controller.netconf.it; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; +import java.net.InetSocketAddress; + import org.junit.After; import org.junit.Before; import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; +import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; +import org.opendaylight.protocol.framework.NeverReconnectStrategy; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.HashedWheelTimer; +import io.netty.util.concurrent.GlobalEventExecutor; public class AbstractNetconfConfigTest extends AbstractConfigTest { - protected EventLoopGroup nettyThreadgroup; + private EventLoopGroup nettyThreadgroup; private HashedWheelTimer hashedWheelTimer; @Before @@ -31,7 +39,6 @@ public class AbstractNetconfConfigTest extends AbstractConfigTest { hashedWheelTimer = new HashedWheelTimer(); } - protected NetconfServerDispatcher createDispatcher( NetconfOperationServiceFactoryListenerImpl factoriesListener, SessionMonitoringService sessionMonitoringService, DefaultCommitNotificationProducer commitNotifier) { @@ -45,6 +52,13 @@ public class AbstractNetconfConfigTest extends AbstractConfigTest { return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); } + protected HashedWheelTimer getHashedWheelTimer() { + return hashedWheelTimer; + } + + protected EventLoopGroup getNettyThreadgroup() { + return nettyThreadgroup; + } @After public void cleanUpTimer() { @@ -52,4 +66,13 @@ public class AbstractNetconfConfigTest extends AbstractConfigTest { nettyThreadgroup.shutdownGracefully(); } + public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress, final int timeout) { + final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create(); + b.withAddress(tcpAddress); + b.withSessionListener(new SimpleNetconfClientSessionListener()); + b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, + timeout)); + b.withConnectionTimeoutMillis(timeout); + return b.build(); + } } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/HardcodedYangStoreService.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/HardcodedYangStoreService.java index d7f77148e8..3fa1b0195a 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/HardcodedYangStoreService.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/HardcodedYangStoreService.java @@ -7,14 +7,7 @@ */ package org.opendaylight.controller.netconf.it; -import org.apache.commons.io.IOUtils; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl; -import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; -import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; +import static org.junit.Assert.assertNotNull; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -24,7 +17,14 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; -import static org.junit.Assert.assertNotNull; +import org.apache.commons.io.IOUtils; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; +import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; public class HardcodedYangStoreService implements YangStoreService { diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java index af83fe4602..29afa93d37 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java @@ -17,7 +17,6 @@ import static org.mockito.Mockito.mock; import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithName; import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertElementsCount; import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToDocument; -import io.netty.channel.ChannelFuture; import java.io.IOException; import java.io.InputStream; @@ -43,6 +42,7 @@ import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification; import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; @@ -65,16 +65,14 @@ import org.xml.sax.SAXException; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import io.netty.channel.ChannelFuture; public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023); - - private NetconfClientDispatcher clientDispatcher; - - DefaultCommitNotificationProducer commitNotifier; + private DefaultCommitNotificationProducer commitNotifier; @Before public void setUp() throws Exception { @@ -95,7 +93,7 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { ChannelFuture s = dispatch.createServer(tcpAddress); s.await(); - clientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup, 5000); + clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer()); } @After @@ -124,12 +122,12 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest { VerifyingNotificationListener notificationVerifier = createCommitNotificationListener(); VerifyingPersister mockedAggregator = mockAggregator(); - try (TestingNetconfClient persisterClient = new TestingNetconfClient("persister", tcpAddress, 4000, clientDispatcher)) { + try (TestingNetconfClient persisterClient = new TestingNetconfClient("persister", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) { try (ConfigPersisterNotificationHandler configPersisterNotificationHandler = new ConfigPersisterNotificationHandler( platformMBeanServer, mockedAggregator)) { - try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", tcpAddress, 4000, clientDispatcher)) { + try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) { NetconfMessage response = netconfClient.sendMessage(loadGetConfigMessage()); assertContainsElementWithName(response.getDocument(), "modules"); assertContainsElementWithName(response.getDocument(), "services"); 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 44d8420ba4..4dc4b707d4 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 @@ -34,7 +34,10 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; -import org.opendaylight.controller.netconf.client.NetconfSshClientDispatcher; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; +import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; @@ -50,9 +53,11 @@ import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.opendaylight.controller.sal.authorization.AuthResultEnum; import org.opendaylight.controller.usermanager.IUserManager; +import org.opendaylight.protocol.framework.NeverReconnectStrategy; import ch.ethz.ssh2.Connection; import io.netty.channel.ChannelFuture; +import io.netty.util.concurrent.GlobalEventExecutor; public class NetconfITSecureTest extends AbstractNetconfConfigTest { @@ -60,7 +65,6 @@ public class NetconfITSecureTest extends AbstractNetconfConfigTest { private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023); private DefaultCommitNotificationProducer commitNot; - private NetconfServerDispatcher dispatchS; private NetconfSSHServer sshServer; private NetconfMessage getConfig; @@ -77,7 +81,7 @@ public class NetconfITSecureTest extends AbstractNetconfConfigTest { commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); - dispatchS = createDispatcher(factoriesListener); + final NetconfServerDispatcher dispatchS = createDispatcher(factoriesListener); ChannelFuture s = dispatchS.createServer(tcpAddress); s.await(); @@ -108,14 +112,34 @@ public class NetconfITSecureTest extends AbstractNetconfConfigTest { @Test public void testSecure() throws Exception { - NetconfClientDispatcher dispatch = new NetconfSshClientDispatcher(getAuthHandler(), nettyThreadgroup, nettyThreadgroup, 5000); - try (TestingNetconfClient netconfClient = new TestingNetconfClient("tls-client", tlsAddress, 4000, dispatch)) { + NetconfClientDispatcher dispatch = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer()); + try (TestingNetconfClient netconfClient = new TestingNetconfClient("testing-ssh-client", dispatch, getClientConfiguration())) { NetconfMessage response = netconfClient.sendMessage(getConfig); Assert.assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()), NetconfMessageUtil.isErrorMessage(response)); + + NetconfMessage gs = new NetconfMessage(XmlUtil.readXmlToDocument("\n" + + " \n" + + " config\n" + + " \n" + + "\n")); + + response = netconfClient.sendMessage(gs); + Assert.assertFalse("Unexpected error message " + XmlUtil.toString(response.getDocument()), + NetconfMessageUtil.isErrorMessage(response)); } + } - dispatch.close(); + public NetconfClientConfiguration getClientConfiguration() throws IOException { + final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create(); + b.withAddress(tlsAddress); + b.withSessionListener(new SimpleNetconfClientSessionListener()); + b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 5000)); + b.withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH); + b.withConnectionTimeoutMillis(5000); + b.withAuthHandler(getAuthHandler()); + return b.build(); } public AuthProvider getAuthProvider() throws Exception { @@ -138,6 +162,7 @@ public class NetconfITSecureTest extends AbstractNetconfConfigTest { return null; } }).when(authHandler).authenticate(any(Connection.class)); + doReturn("auth handler").when(authHandler).toString(); return authHandler; } } 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 b77d92e7cb..e99e51e92f 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 @@ -8,11 +8,14 @@ package org.opendaylight.controller.netconf.it; -import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.Session; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import io.netty.channel.ChannelFuture; +import static java.util.Collections.emptyList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + import java.io.IOException; import java.io.InputStream; import java.lang.management.ManagementFactory; @@ -25,9 +28,12 @@ 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.junit.Before; @@ -43,7 +49,7 @@ import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory; import org.opendaylight.controller.netconf.StubUserManager; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; -import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; @@ -66,13 +72,13 @@ import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.SAXException; -import static java.util.Collections.emptyList; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; + +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import io.netty.channel.ChannelFuture; public class NetconfITTest extends AbstractNetconfConfigTest { @@ -90,7 +96,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest { private DefaultCommitNotificationProducer commitNot; private NetconfServerDispatcher dispatch; - private NetconfClientDispatcher clientDispatcher; + private NetconfClientDispatcherImpl clientDispatcher; @Before public void setUp() throws Exception { @@ -109,7 +115,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest { ChannelFuture s = dispatch.createServer(tcpAddress); s.await(); - clientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup, 5000); + clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer()); } private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) { @@ -176,7 +182,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest { @Test public void testNetconfClientDemonstration() throws Exception { - try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", tcpAddress, 4000, clientDispatcher)) { + try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) { Set capabilitiesFromNetconfServer = netconfClient.getCapabilities(); long sessionId = netconfClient.getSessionId(); @@ -191,8 +197,8 @@ public class NetconfITTest extends AbstractNetconfConfigTest { @Test public void testTwoSessions() throws Exception { - try (TestingNetconfClient netconfClient = new TestingNetconfClient("1", tcpAddress, 10000, clientDispatcher)) { - try (TestingNetconfClient netconfClient2 = new TestingNetconfClient("2", tcpAddress, 10000, clientDispatcher)) { + try (TestingNetconfClient netconfClient = new TestingNetconfClient("1", clientDispatcher, getClientConfiguration(tcpAddress, 10000))) { + try (TestingNetconfClient netconfClient2 = new TestingNetconfClient("2", clientDispatcher, getClientConfiguration(tcpAddress, 10000))) { } } } @@ -365,7 +371,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest { } private TestingNetconfClient createSession(final InetSocketAddress address, final String expected) throws Exception { - final TestingNetconfClient netconfClient = new TestingNetconfClient("test " + address.toString(), address, 5000, clientDispatcher); + final TestingNetconfClient netconfClient = new TestingNetconfClient("test " + address.toString(), clientDispatcher, getClientConfiguration(address, 5000)); assertEquals(expected, Long.toString(netconfClient.getSessionId())); return netconfClient; } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java index 8e98ab6320..3b263f7e75 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java @@ -7,11 +7,24 @@ */ package org.opendaylight.controller.netconf.it; -import com.google.common.base.Charsets; -import com.google.common.base.Optional; -import com.google.common.collect.Sets; -import io.netty.channel.ChannelFuture; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Collection; +import java.util.List; +import java.util.Set; + import junit.framework.Assert; + import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -19,7 +32,7 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod import org.opendaylight.controller.config.spi.ModuleFactory; 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.NetconfClientDispatcherImpl; import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException; @@ -40,21 +53,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText; +import com.google.common.base.Charsets; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; +import io.netty.channel.ChannelFuture; public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { @@ -66,7 +68,7 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { private DefaultCommitNotificationProducer commitNot; private NetconfServerDispatcher dispatch; - private NetconfClientDispatcher clientDispatcher; + private NetconfClientDispatcherImpl clientDispatcher; private NetconfMonitoringServiceImpl monitoringService; @@ -88,7 +90,7 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { ChannelFuture s = dispatch.createServer(tcpAddress); s.await(); - clientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup, 5000); + clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer()); } private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException { @@ -120,8 +122,8 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest { @Test public void testGetResponseFromMonitoring() throws Exception { - try (TestingNetconfClient netconfClient = new TestingNetconfClient("client-monitoring", tcpAddress, 4000, clientDispatcher)) { - try (TestingNetconfClient netconfClient2 = new TestingNetconfClient("client-monitoring2", tcpAddress, 4000, clientDispatcher)) { + try (TestingNetconfClient netconfClient = new TestingNetconfClient("client-monitoring", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) { + try (TestingNetconfClient netconfClient2 = new TestingNetconfClient("client-monitoring2", clientDispatcher, getClientConfiguration(tcpAddress, 4000))) { NetconfMessage response = netconfClient.sendMessage(loadGetMessage()); assertSessionElementsInResponse(response.getDocument(), 2); } diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/pax/IdentityRefNetconfTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/pax/IdentityRefNetconfTest.java index c54285bc90..ebfcff3cd4 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/pax/IdentityRefNetconfTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/pax/IdentityRefNetconfTest.java @@ -19,8 +19,9 @@ import static org.ops4j.pax.exam.CoreOptions.options; import static org.ops4j.pax.exam.CoreOptions.streamBundle; import static org.ops4j.pax.exam.CoreOptions.systemPackages; import static org.ops4j.pax.exam.CoreOptions.systemProperty; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; import java.io.IOException; import java.net.InetSocketAddress; import java.util.concurrent.ExecutionException; @@ -34,11 +35,15 @@ import org.junit.Test; import org.junit.matchers.JUnitMatchers; import org.junit.runner.RunWith; import org.opendaylight.controller.netconf.api.NetconfMessage; -import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; +import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.controller.netconf.client.test.TestingNetconfClient; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.protocol.framework.NeverReconnectStrategy; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; @@ -51,6 +56,9 @@ import org.xml.sax.SAXException; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.GlobalEventExecutor; + @Ignore @RunWith(PaxExam.class) public class IdentityRefNetconfTest { @@ -121,15 +129,15 @@ public class IdentityRefNetconfTest { public void testIdRef() throws Exception { Preconditions.checkNotNull(broker, "Controller not initialized"); - NioEventLoopGroup nettyThreadgroup = new NioEventLoopGroup(); - NetconfClientDispatcher clientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup, - CLIENT_CONNECTION_TIMEOUT_MILLIS); NetconfMessage edit = xmlFileToNetconfMessage("netconfMessages/editConfig_identities.xml"); NetconfMessage commit = xmlFileToNetconfMessage("netconfMessages/commit.xml"); NetconfMessage getConfig = xmlFileToNetconfMessage("netconfMessages/getConfig.xml"); - try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", tcpAddress, CLIENT_CONNECTION_TIMEOUT_MILLIS, clientDispatcher)) { + NioEventLoopGroup nettyThreadgroup = new NioEventLoopGroup(); + Timer timer = new HashedWheelTimer(); + NetconfClientDispatcherImpl clientDispatcher = new NetconfClientDispatcherImpl(nettyThreadgroup, nettyThreadgroup, timer); + try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", clientDispatcher, getClientConfiguration(tcpAddress))) { sendMessage(edit, netconfClient); sendMessage(commit, netconfClient); sendMessage(getConfig, netconfClient, "id-test", @@ -141,6 +149,9 @@ public class IdentityRefNetconfTest { clientDispatcher.close(); } catch (Exception e) { fail(Throwables.getStackTraceAsString(e)); + } finally { + nettyThreadgroup.shutdownGracefully().get(); + timer.stop(); } } @@ -160,4 +171,14 @@ public class IdentityRefNetconfTest { ParserConfigurationException { return XmlFileLoader.xmlFileToNetconfMessage(fileName); } + + public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress) { + final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create(); + b.withAddress(tcpAddress); + b.withSessionListener(new SimpleNetconfClientSessionListener()); + b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, + CLIENT_CONNECTION_TIMEOUT_MILLIS)); + b.withConnectionTimeoutMillis(CLIENT_CONNECTION_TIMEOUT_MILLIS); + return b.build(); + } } diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java index c08db906df..1f7eed250f 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.netconf.mapping.api; +import com.google.common.base.Objects; import com.google.common.base.Optional; import com.google.common.base.Preconditions; @@ -51,13 +52,13 @@ public final class HandlingPriority implements Comparable { @Override public int compareTo(HandlingPriority o) { - if (this == o){ + if (this == o) { return 0; } - if (this.equals(CANNOT_HANDLE)){ + if (isCannotHandle()) { return -1; } - if (o.equals(CANNOT_HANDLE)){ + if (o.isCannotHandle()) { return 1; } @@ -70,7 +71,8 @@ public final class HandlingPriority implements Comparable { if (priority < o.priority){ return -1; } - throw new IllegalStateException("Unexpected state"); + + throw new IllegalStateException("Unexpected state comparing " + this + " with " + o); } @Override @@ -95,4 +97,11 @@ public final class HandlingPriority implements Comparable { public int hashCode() { return priority != null ? priority.hashCode() : 0; } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("priority", priority) + .toString(); + } } diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java index adba548b91..ff950e95e9 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java @@ -68,7 +68,7 @@ public final class NetconfSSHServer implements Runnable { while (up) { logger.trace("Starting new socket thread."); try { - SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(),authProvider); + SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(), authProvider); } catch (IOException e) { logger.error("Exception occurred during socket thread initialization {}", e); } -- 2.36.6