From bcb027886de5b84705f8d70ce8fbaa59986919e5 Mon Sep 17 00:00:00 2001 From: Ryan Goulding Date: Mon, 9 Apr 2018 18:47:29 -0400 Subject: [PATCH] Allow specification of ODL's HELLO message Some devices are very particular about what they will accept for a HELLO message. This change allows specification of a custom message per device mount. If one is not specified, then the existing default is utilized. Additionally, certain tests were using very out of date versions of netconf-node-topology. This is due to the fact that the test yang files are located in src/test/resources, and were out of date with the netconf-node-topology used in src/main/yang. These were updated to the most up-to-date version as of this patch. JIRA: NETCONF-543 Change-Id: I4049a87a7781655d8d396bb35eb43aab2eca0223 Signed-off-by: Ryan Goulding --- .../api/messages/NetconfHelloMessage.java | 3 +- .../client/NetconfClientDispatcherImpl.java | 20 ++++- .../conf/NetconfClientConfiguration.java | 12 ++- .../NetconfClientConfigurationBuilder.java | 16 +++- ...etconfReconnectingClientConfiguration.java | 7 +- ...econnectingClientConfigurationBuilder.java | 9 +- .../schemas/netconf-node-topology.yang | 9 ++ .../impl/RemoteDeviceConnectorImpl.java | 38 ++++++--- .../src/main/yang/netconf-node-topology.yang | 9 ++ .../schemas/netconf-node-topology.yang | 85 +++++++++++++++++-- 10 files changed, 183 insertions(+), 25 deletions(-) diff --git a/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/messages/NetconfHelloMessage.java b/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/messages/NetconfHelloMessage.java index d450672638..52ec7e1078 100644 --- a/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/messages/NetconfHelloMessage.java +++ b/netconf/netconf-api/src/main/java/org/opendaylight/netconf/api/messages/NetconfHelloMessage.java @@ -22,7 +22,8 @@ import org.w3c.dom.Element; /** * NetconfMessage that can carry additional header with session metadata. - * See {@link NetconfHelloMessageAdditionalHeader} + * + * @see NetconfHelloMessageAdditionalHeader */ public final class NetconfHelloMessage extends NetconfMessage { diff --git a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientDispatcherImpl.java b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientDispatcherImpl.java index 780ce7ff59..b8fdee2054 100644 --- a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientDispatcherImpl.java +++ b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientDispatcherImpl.java @@ -11,9 +11,13 @@ package org.opendaylight.netconf.client; import io.netty.channel.EventLoopGroup; import io.netty.util.Timer; import io.netty.util.concurrent.Future; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; import org.opendaylight.netconf.client.conf.NetconfClientConfiguration; import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration; import org.opendaylight.protocol.framework.AbstractDispatcher; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -122,7 +126,19 @@ public class NetconfClientDispatcherImpl extends AbstractDispatcher odlHelloCapabilities = cfg.getOdlHelloCapabilities(); + if (odlHelloCapabilities == null || odlHelloCapabilities.isEmpty()) { + return new NetconfClientSessionNegotiatorFactory(timer, cfg.getAdditionalHeader(), + cfg.getConnectionTimeoutMillis()); + } else { + // LinkedHashSet since perhaps the device cares about order of hello message capabilities. + // This allows user control of the order while complying with the existing interface. + final Set stringCapabilities = new LinkedHashSet<>(); + for (final Uri uri : odlHelloCapabilities) { + stringCapabilities.add(uri.getValue()); + } + return new NetconfClientSessionNegotiatorFactory(timer, cfg.getAdditionalHeader(), + cfg.getConnectionTimeoutMillis(), stringCapabilities); + } } } diff --git a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfClientConfiguration.java b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfClientConfiguration.java index ee41da8a8d..b14d152e25 100644 --- a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfClientConfiguration.java +++ b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfClientConfiguration.java @@ -12,11 +12,13 @@ import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import java.net.InetSocketAddress; +import java.util.List; import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader; import org.opendaylight.netconf.client.NetconfClientSessionListener; import org.opendaylight.netconf.client.SslHandlerFactory; import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler; import org.opendaylight.protocol.framework.ReconnectStrategy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,12 +38,15 @@ public class NetconfClientConfiguration { private final AuthenticationHandler authHandler; private final SslHandlerFactory sslHandlerFactory; + private final List odlHelloCapabilities; + NetconfClientConfiguration(final NetconfClientProtocol protocol, final InetSocketAddress address, final Long connectionTimeoutMillis, final NetconfHelloMessageAdditionalHeader additionalHeader, final NetconfClientSessionListener sessionListener, final ReconnectStrategy reconnectStrategy, final AuthenticationHandler authHandler, - final SslHandlerFactory sslHandlerFactory) { + final SslHandlerFactory sslHandlerFactory, + final List odlHelloCapabilities) { this.address = address; this.connectionTimeoutMillis = connectionTimeoutMillis; this.additionalHeader = additionalHeader; @@ -50,6 +55,7 @@ public class NetconfClientConfiguration { this.reconnectStrategy = reconnectStrategy; this.authHandler = authHandler; this.sslHandlerFactory = sslHandlerFactory; + this.odlHelloCapabilities = odlHelloCapabilities; validateConfiguration(); } @@ -85,6 +91,10 @@ public class NetconfClientConfiguration { return sslHandlerFactory; } + public List getOdlHelloCapabilities() { + return odlHelloCapabilities; + } + private void validateConfiguration() { Preconditions.checkNotNull(clientProtocol, " "); switch (clientProtocol) { diff --git a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfClientConfigurationBuilder.java b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfClientConfigurationBuilder.java index fd1d6276e4..9e86c9c4b2 100644 --- a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfClientConfigurationBuilder.java +++ b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfClientConfigurationBuilder.java @@ -8,11 +8,13 @@ package org.opendaylight.netconf.client.conf; import java.net.InetSocketAddress; +import java.util.List; import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader; import org.opendaylight.netconf.client.NetconfClientSessionListener; import org.opendaylight.netconf.client.SslHandlerFactory; import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler; import org.opendaylight.protocol.framework.ReconnectStrategy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; public class NetconfClientConfigurationBuilder { @@ -28,6 +30,8 @@ public class NetconfClientConfigurationBuilder { private AuthenticationHandler authHandler; private NetconfClientConfiguration.NetconfClientProtocol clientProtocol = DEFAULT_CLIENT_PROTOCOL; private SslHandlerFactory sslHandlerFactory; + private List odlHelloCapabilities; + protected NetconfClientConfigurationBuilder() { } @@ -86,6 +90,12 @@ public class NetconfClientConfigurationBuilder { return this; } + @SuppressWarnings("checkstyle:hiddenField") + public NetconfClientConfigurationBuilder withOdlHelloCapabilities(final List odlHelloCapabilities) { + this.odlHelloCapabilities = odlHelloCapabilities; + return this; + } + final InetSocketAddress getAddress() { return address; } @@ -118,8 +128,12 @@ public class NetconfClientConfigurationBuilder { return sslHandlerFactory; } + final List getOdlHelloCapabilities() { + return odlHelloCapabilities; + } + public NetconfClientConfiguration build() { return new NetconfClientConfiguration(clientProtocol, address, connectionTimeoutMillis, additionalHeader, - sessionListener, reconnectStrategy, authHandler, sslHandlerFactory); + sessionListener, reconnectStrategy, authHandler, sslHandlerFactory, odlHelloCapabilities); } } diff --git a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfReconnectingClientConfiguration.java b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfReconnectingClientConfiguration.java index 3c5931e49d..c688534923 100644 --- a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfReconnectingClientConfiguration.java +++ b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfReconnectingClientConfiguration.java @@ -10,12 +10,14 @@ package org.opendaylight.netconf.client.conf; import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Preconditions; import java.net.InetSocketAddress; +import java.util.List; import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader; import org.opendaylight.netconf.client.NetconfClientSessionListener; import org.opendaylight.netconf.client.SslHandlerFactory; import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler; import org.opendaylight.protocol.framework.ReconnectStrategy; import org.opendaylight.protocol.framework.ReconnectStrategyFactory; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; public final class NetconfReconnectingClientConfiguration extends NetconfClientConfiguration { @@ -28,9 +30,10 @@ public final class NetconfReconnectingClientConfiguration extends NetconfClientC final ReconnectStrategy reconnectStrategy, final ReconnectStrategyFactory connectStrategyFactory, final AuthenticationHandler authHandler, - final SslHandlerFactory sslHandlerFactory) { + final SslHandlerFactory sslHandlerFactory, + final List odlHelloCapabilities) { super(clientProtocol, address, connectionTimeoutMillis, additionalHeader, sessionListener, reconnectStrategy, - authHandler, sslHandlerFactory); + authHandler, sslHandlerFactory, odlHelloCapabilities); this.connectStrategyFactory = connectStrategyFactory; validateReconnectConfiguration(); } diff --git a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java index 4d3dcdaaab..670c893a00 100644 --- a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java +++ b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/conf/NetconfReconnectingClientConfigurationBuilder.java @@ -8,12 +8,14 @@ package org.opendaylight.netconf.client.conf; import java.net.InetSocketAddress; +import java.util.List; import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader; import org.opendaylight.netconf.client.NetconfClientSessionListener; import org.opendaylight.netconf.client.SslHandlerFactory; import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler; import org.opendaylight.protocol.framework.ReconnectStrategy; import org.opendaylight.protocol.framework.ReconnectStrategyFactory; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; public final class NetconfReconnectingClientConfigurationBuilder extends NetconfClientConfigurationBuilder { @@ -37,7 +39,7 @@ public final class NetconfReconnectingClientConfigurationBuilder extends Netconf public NetconfReconnectingClientConfiguration build() { return new NetconfReconnectingClientConfiguration(getProtocol(), getAddress(), getConnectionTimeoutMillis(), getAdditionalHeader(), getSessionListener(), getReconnectStrategy(), connectStrategyFactory, - getAuthHandler(), getSslHandlerFactory()); + getAuthHandler(), getSslHandlerFactory(), getOdlHelloCapabilities()); } // Override setter methods to return subtype @@ -88,4 +90,9 @@ public final class NetconfReconnectingClientConfigurationBuilder extends Netconf final SslHandlerFactory sslHandlerFactory) { return (NetconfReconnectingClientConfigurationBuilder) super.withSslHandlerFactory(sslHandlerFactory); } + + @Override + public NetconfReconnectingClientConfigurationBuilder withOdlHelloCapabilities(List odlHelloCapabilities) { + return (NetconfReconnectingClientConfigurationBuilder) super.withOdlHelloCapabilities(odlHelloCapabilities); + } } diff --git a/netconf/netconf-console/src/test/resources/schemas/netconf-node-topology.yang b/netconf/netconf-console/src/test/resources/schemas/netconf-node-topology.yang index 1e1f85545e..231a382f53 100644 --- a/netconf/netconf-console/src/test/resources/schemas/netconf-node-topology.yang +++ b/netconf/netconf-console/src/test/resources/schemas/netconf-node-topology.yang @@ -209,6 +209,15 @@ module netconf-node-topology { default 5; description "Time that slave actor will wait for response from master."; } + + container odl-hello-message-capabilities { + config true; + leaf-list capability { + type inet:uri; + description "Certain devices are non-accepting of ODL's hello message. This allows specification of + a custom ODL hello message based on a list of supported capabilities."; + } + } } grouping netconf-node-connection-status { diff --git a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImpl.java b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImpl.java index 40511bf781..e4fd08b77f 100644 --- a/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImpl.java +++ b/netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImpl.java @@ -60,7 +60,9 @@ import org.opendaylight.protocol.framework.ReconnectStrategyFactory; import org.opendaylight.protocol.framework.TimedReconnectStrategy; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.OdlHelloMessageCapabilities; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.KeyAuth; @@ -291,17 +293,31 @@ public class RemoteDeviceConnectorImpl implements RemoteDeviceConnector { final AuthenticationHandler authHandler = getHandlerFromCredentials(node.getCredentials()); - return NetconfReconnectingClientConfigurationBuilder.create() - .withAddress(socketAddress) - .withConnectionTimeoutMillis(clientConnectionTimeoutMillis) - .withReconnectStrategy(strategy) - .withAuthHandler(authHandler) - .withProtocol(node.isTcpOnly() - ? NetconfClientConfiguration.NetconfClientProtocol.TCP - : NetconfClientConfiguration.NetconfClientProtocol.SSH) - .withConnectStrategyFactory(sf) - .withSessionListener(listener) - .build(); + final NetconfReconnectingClientConfigurationBuilder builder = + NetconfReconnectingClientConfigurationBuilder.create() + .withAddress(socketAddress) + .withConnectionTimeoutMillis(clientConnectionTimeoutMillis) + .withReconnectStrategy(strategy) + .withAuthHandler(authHandler) + .withProtocol(node.isTcpOnly() + ? NetconfClientConfiguration.NetconfClientProtocol.TCP + : NetconfClientConfiguration.NetconfClientProtocol.SSH) + .withConnectStrategyFactory(sf) + .withSessionListener(listener); + + final List odlHelloCapabilities = getOdlHelloCapabilities(node); + if (odlHelloCapabilities != null) { + builder.withOdlHelloCapabilities(odlHelloCapabilities); + } + return builder.build(); + } + + private List getOdlHelloCapabilities(final NetconfNode node) { + final OdlHelloMessageCapabilities helloCapabilities = node.getOdlHelloMessageCapabilities(); + if (helloCapabilities != null) { + return helloCapabilities.getCapability(); + } + return null; } private AuthenticationHandler getHandlerFromCredentials(final Credentials credentials) { diff --git a/netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang b/netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang index 1e1f85545e..231a382f53 100644 --- a/netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang +++ b/netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang @@ -209,6 +209,15 @@ module netconf-node-topology { default 5; description "Time that slave actor will wait for response from master."; } + + container odl-hello-message-capabilities { + config true; + leaf-list capability { + type inet:uri; + description "Certain devices are non-accepting of ODL's hello message. This allows specification of + a custom ODL hello message based on a list of supported capabilities."; + } + } } grouping netconf-node-connection-status { diff --git a/netconf/sal-netconf-connector/src/test/resources/schemas/netconf-node-topology.yang b/netconf/sal-netconf-connector/src/test/resources/schemas/netconf-node-topology.yang index 8488211364..231a382f53 100644 --- a/netconf/sal-netconf-connector/src/test/resources/schemas/netconf-node-topology.yang +++ b/netconf/sal-netconf-connector/src/test/resources/schemas/netconf-node-topology.yang @@ -15,17 +15,50 @@ module netconf-node-topology { } } - grouping netconf-node-credentials { + grouping username-password { + leaf username { + type string; + } + leaf password { + type string; + } + } + + grouping netconf-node-credentials { choice credentials { config true; case login-password { - leaf username { - type string; + description "Deprecated way of storing credentials, unencrypted."; + + status deprecated; + uses username-password; + } + case login-pw { + description "login-password credentials, encrypted."; + + container login-password { + uses username-password; } + } + case login-pw-unencrypted { + description "login-password credentials, not encrypted."; - leaf password { - type string; + container login-password-unencrypted { + uses username-password; + } + } + case key-auth { + description "key-based authentication, use the id for the pair thats stored in the keystore."; + + container key-based { + leaf key-id { + type string; + } + + leaf username { + type string; + } } } } @@ -167,6 +200,24 @@ module netconf-node-topology { description "Limit of concurrent messages that can be send before reply messages are received. If value <1 is provided, no limit will be enforced"; } + + leaf actor-response-wait-time { + config true; + type uint16 { + range "1..max"; + } + default 5; + description "Time that slave actor will wait for response from master."; + } + + container odl-hello-message-capabilities { + config true; + leaf-list capability { + type inet:uri; + description "Certain devices are non-accepting of ODL's hello message. This allows specification of + a custom ODL hello message based on a list of supported capabilities."; + } + } } grouping netconf-node-connection-status { @@ -194,6 +245,10 @@ module netconf-node-topology { } } } + leaf netconf-master-node { + config false; + type string; + } } leaf connected-message { @@ -283,10 +338,28 @@ module netconf-node-topology { } + rpc create-device { + input { + uses netconf-node-fields; + leaf node-id { + type string; + } + } + } + + rpc delete-device { + input { + leaf node-id { + type string; + } + } + } + augment "/nt:network-topology/nt:topology/nt:node" { when "../../nt:topology-types/topology-netconf"; ext:augment-identifier "netconf-node"; uses netconf-node-fields; } -} \ No newline at end of file + +} -- 2.36.6