Refactor NETCONF node defaults 33/99133/3
authorIvan Hrasko <ivan.hrasko@pantheon.tech>
Mon, 6 Dec 2021 10:58:02 +0000 (11:58 +0100)
committerRobert Varga <nite@hq.sk>
Wed, 22 Dec 2021 12:50:40 +0000 (12:50 +0000)
In fact, the difference between devices connected by call-home and
created manually in NETCONF topology is that call-home devices do
not have any data in configuration data-store.

Configuration data is used during the connection setup.

We can create full default configuration node for call-home connected
device to unify the processing of both kind of devices.

In addition, MDSAL now supports default values in data-store so we
can remove those values from AbstractNetconfTopology.

JIRA: NETCONF-832
Change-Id: Ib58ca344a7d74612cb7d049805a3e3c9279986d4
Signed-off-by: Ivan Hrasko <ivan.hrasko@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 2dfc7efb77c6704a0cd397dbd82c2709b14d29ee)

netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallHomeMountSessionContext.java
netconf/callhome-provider/src/test/java/org/opendaylight/netconf/callhome/mount/CallHomeMountSessionContextTest.java
netconf/netconf-topology-impl/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/AbstractNetconfTopology.java

index 16257a76d202a862531c7bb6c6f9aed38b153442..5d30148108d43b5a4059e6f6e9d96b31493d05e2 100644 (file)
@@ -12,6 +12,7 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.base.MoreObjects;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import io.netty.util.concurrent.Future;
+import java.math.BigDecimal;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.api.NetconfTerminationReason;
 import org.opendaylight.netconf.callhome.protocol.CallHomeChannelActivator;
@@ -20,10 +21,14 @@ import org.opendaylight.netconf.client.NetconfClientSession;
 import org.opendaylight.netconf.client.NetconfClientSessionListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.ProtocolBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yangtools.yang.common.Uint16;
+import org.opendaylight.yangtools.yang.common.Uint32;
 
 // Non-final to allow mocking
 class CallHomeMountSessionContext {
@@ -61,18 +66,41 @@ class CallHomeMountSessionContext {
         return key;
     }
 
+    /**
+     * Create device default configuration.
+     *
+     * <p>
+     * This configuration is a replacement of configuration device data
+     * which is normally stored in configuration datastore but is absent for call-home devices.
+     *
+     * @return {@link Node} containing the default device configuration
+     */
+    // FIXME make these defaults tune-able in odl-netconf-callhome-server
     Node getConfigNode() {
         return new NodeBuilder()
                 .setNodeId(getId())
                 .addAugmentation(new NetconfNodeBuilder()
-                    .setHost(new Host(key.getIpAddress()))
-                    .setPort(key.getPort())
-                    .setTcpOnly(Boolean.FALSE)
-                    .setCredentials(new LoginPasswordBuilder()
-                        .setUsername("ommited")
-                        .setPassword("ommited")
-                        .build())
-                    .setSchemaless(Boolean.FALSE)
+                        .setHost(new Host(key.getIpAddress()))
+                        .setPort(key.getPort())
+                        .setTcpOnly(false)
+                        .setProtocol(new ProtocolBuilder()
+                                .setName(Protocol.Name.valueOf(protocol.getTransportType().name()))
+                                .build())
+                        .setSchemaless(false)
+                        .setReconnectOnChangedSchema(false)
+                        .setConnectionTimeoutMillis(Uint32.valueOf(20000))
+                        .setDefaultRequestTimeoutMillis(Uint32.valueOf(60000))
+                        .setMaxConnectionAttempts(Uint32.ZERO)
+                        .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(2000))
+                        .setSleepFactor(new BigDecimal("1.5"))
+                        .setKeepaliveDelay(Uint32.valueOf(120))
+                        .setConcurrentRpcLimit(Uint16.ZERO)
+                        .setActorResponseWaitTime(Uint16.valueOf(5))
+                        // the real call-home device credentials are applied in CallHomeAuthProviderImpl
+                        .setCredentials(new LoginPasswordBuilder()
+                                .setUsername("omitted")
+                                .setPassword("omitted")
+                                .build())
                     .build())
                 .build();
     }
index 784168c81f3ea07d270f324e8a218ccc21dbaf41..8e196568d8da4969cf48860041097e8ed11773d6 100644 (file)
@@ -5,7 +5,6 @@
  * 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.netconf.callhome.mount;
 
 import static org.junit.Assert.assertNotNull;
@@ -25,6 +24,7 @@ import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.api.NetconfTerminationReason;
 import org.opendaylight.netconf.callhome.protocol.CallHomeChannelActivator;
 import org.opendaylight.netconf.callhome.protocol.CallHomeProtocolSessionContext;
+import org.opendaylight.netconf.callhome.protocol.TransportType;
 import org.opendaylight.netconf.client.NetconfClientSession;
 import org.opendaylight.netconf.client.NetconfClientSessionListener;
 
@@ -45,6 +45,7 @@ public class CallHomeMountSessionContextTest {
         mockActivator = mock(CallHomeChannelActivator.class);
         mockCallback = mock(CallHomeMountSessionContext.CloseCallback.class);
         doReturn(someSocketAddress).when(mockProtocol).getRemoteAddress();
+        doReturn(TransportType.SSH).when(mockProtocol).getTransportType();
 
         instance = new CallHomeMountSessionContext("test",mockProtocol, mockActivator, mockCallback);
     }
index 7607189c3ba21db76e0baddd93e79f0e138cadf9..6245fbaf0ab29130b1052dcb35558fcee3e37bdd 100644 (file)
@@ -26,6 +26,7 @@ import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import io.netty.util.concurrent.EventExecutor;
+import java.math.BigDecimal;
 import java.util.Collection;
 import java.util.HashSet;
 import org.junit.Before;
@@ -56,7 +57,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 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.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-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.NetconfNodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol.Name;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.ProtocolBuilder;
@@ -151,7 +151,6 @@ public class NetconfTopologyImplTest {
 
     @Test
     public void testOnDataTreeChange() {
-
         final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
 
@@ -177,7 +176,6 @@ public class NetconfTopologyImplTest {
 
         when(newNode.getDataAfter()).thenReturn(nn.build());
 
-
         final Collection<DataTreeModification<Node>> changes = new HashSet<>();
         final DataTreeModification<Node> ch = mock(DataTreeModification.class);
         when(ch.getRootNode()).thenReturn(newNode);
@@ -195,83 +193,45 @@ public class NetconfTopologyImplTest {
         //one in previous creating and deleting node and one in updating
         verify(spyTopology, times(2)).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
         verify(spyTopology, times(2)).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
-
-
     }
 
     @Test
     public void testGetClientConfig() {
         final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
-
-        final NetconfNode testingNode = new NetconfNodeBuilder()
+        final NetconfNodeBuilder nodeBuilder = new NetconfNodeBuilder()
                 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
                 .setPort(new PortNumber(Uint16.valueOf(9999)))
                 .setReconnectOnChangedSchema(true)
                 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
                 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
                 .setKeepaliveDelay(Uint32.valueOf(1000))
-                .setTcpOnly(true)
-                .setCredentials(new LoginPasswordBuilder()
-                        .setUsername("testuser").setPassword("testpassword").build())
-                .build();
+                .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
+                .setMaxConnectionAttempts(Uint32.ZERO)
+                .setSleepFactor(new BigDecimal("1.5"))
+                .setConnectionTimeoutMillis(Uint32.valueOf(20000));
+
         final NetconfReconnectingClientConfiguration configuration =
-                spyTopology.getClientConfig(sessionListener, testingNode);
+                spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(true).build());
         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
         assertNotNull(configuration.getAuthHandler());
         assertNull(configuration.getSslHandlerFactory());
 
-
-        final NetconfNode testingNode2 = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(Uint16.valueOf(9999)))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
-                .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
-                .setKeepaliveDelay(Uint32.valueOf(1000))
-                .setTcpOnly(false)
-                .setCredentials(new LoginPasswordBuilder()
-                        .setUsername("testuser").setPassword("testpassword").build())
-                .build();
         final NetconfReconnectingClientConfiguration configuration2 =
-                spyTopology.getClientConfig(sessionListener, testingNode2);
+                spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(false).build());
         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
         assertNotNull(configuration2.getAuthHandler());
         assertNull(configuration2.getSslHandlerFactory());
 
-
-        final NetconfNode testingNode3 = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(Uint16.valueOf(9999)))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
-                .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
-                .setKeepaliveDelay(Uint32.valueOf(1000))
-                .setTcpOnly(false)
-                .setProtocol(new ProtocolBuilder().setName(Name.SSH).build())
-                .setCredentials(new LoginPasswordBuilder()
-                        .setUsername("testuser").setPassword("testpassword").build())
-                .build();
         final NetconfReconnectingClientConfiguration configuration3 =
-                spyTopology.getClientConfig(sessionListener, testingNode3);
+                spyTopology.getClientConfig(sessionListener, nodeBuilder
+                        .setProtocol(new ProtocolBuilder().setName(Name.SSH).build()).build());
         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
         assertNotNull(configuration3.getAuthHandler());
         assertNull(configuration3.getSslHandlerFactory());
 
-
-        final NetconfNode testingNode4 = new NetconfNodeBuilder()
-                .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
-                .setPort(new PortNumber(Uint16.valueOf(9999)))
-                .setReconnectOnChangedSchema(true)
-                .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
-                .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
-                .setKeepaliveDelay(Uint32.valueOf(1000))
-                .setTcpOnly(false)
-                .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
-                .setCredentials(new LoginPasswordBuilder()
-                        .setUsername("testuser").setPassword("testpassword").build())
-                .build();
         final NetconfReconnectingClientConfiguration configuration4 =
-                spyTopology.getClientConfig(sessionListener, testingNode4);
+                spyTopology.getClientConfig(sessionListener, nodeBuilder
+                        .setProtocol(new ProtocolBuilder().setName(Name.TLS).build()).build());
         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
         assertNull(configuration4.getAuthHandler());
         assertNotNull(configuration4.getSslHandlerFactory());
index 8feec9d0e58a0a379b3e3e37ed62f7f9a7b9f6de..f134fe88e9882f8742c5f9004cee81d92d22be1b 100644 (file)
@@ -17,7 +17,6 @@ import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 import io.netty.util.concurrent.EventExecutor;
-import java.math.BigDecimal;
 import java.net.InetSocketAddress;
 import java.net.URL;
 import java.util.ArrayList;
@@ -90,16 +89,6 @@ import org.slf4j.LoggerFactory;
 public abstract class AbstractNetconfTopology implements NetconfTopology {
     private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class);
 
-    protected static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
-    protected static final int DEFAULT_KEEPALIVE_DELAY = 0;
-    protected static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
-    protected static final int DEFAULT_CONCURRENT_RPC_LIMIT = 0;
-    private static final boolean DEFAULT_IS_TCP_ONLY = false;
-    private static final int DEFAULT_MAX_CONNECTION_ATTEMPTS = 0;
-    private static final int DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS = 2000;
-    private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
-    private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
-
     private final NetconfClientDispatcher clientDispatcher;
     private final EventExecutor eventExecutor;
     private final DeviceActionFactory deviceActionFactory;
@@ -117,7 +106,6 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
     protected final AAAEncryptionService encryptionService;
     protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
 
-
     protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
                                       final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
                                       final ThreadPool processingExecutor, final SchemaResourceManager schemaManager,
@@ -214,15 +202,9 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
 
     protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node,
             final NetconfNodeAugmentedOptional nodeOptional) {
-        //setup default values since default value is not supported in mdsal
-        final long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null
-                ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis().toJava();
-        final long keepaliveDelay = node.getKeepaliveDelay() == null
-                ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay().toJava();
-
-        final InetSocketAddress address;
         final Host host = node.getHost();
         final IpAddress ipAddress = host.getIpAddress();
+        final InetSocketAddress address;
         if (ipAddress != null) {
             address = new InetSocketAddress(IetfInetUtil.INSTANCE.inetAddressFor(ipAddress),
                     node.getPort().getValue().toJava());
@@ -232,12 +214,12 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
         }
         final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
 
+        final long keepaliveDelay = node.getKeepaliveDelay().toJava();
         RemoteDeviceHandler<NetconfSessionPreferences> salFacade = createSalFacade(remoteDeviceId);
-
         if (keepaliveDelay > 0) {
-            LOG.warn("Adding keepalive facade, for device {}", nodeId);
+            LOG.info("Adding keepalive facade, for device {}", nodeId);
             salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, this.keepaliveExecutor.getExecutor(),
-                    keepaliveDelay, defaultRequestTimeoutMillis);
+                    keepaliveDelay, node.getDefaultRequestTimeoutMillis().toJava());
         }
 
         final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
@@ -246,9 +228,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
             device = new SchemalessNetconfDevice(baseSchemas, remoteDeviceId, salFacade);
             yanglibRegistrations = List.of();
         } else {
-            final boolean reconnectOnChangedSchema = node.getReconnectOnChangedSchema() == null
-                ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.getReconnectOnChangedSchema();
-
+            final boolean reconnectOnChangedSchema = node.getReconnectOnChangedSchema();
             final SchemaResourcesDTO resources = schemaManager.getSchemaResources(node, nodeId.getValue());
             device = new NetconfDeviceBuilder()
                 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
@@ -262,18 +242,16 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
                 .setDeviceActionFactory(deviceActionFactory)
                 .setBaseSchemas(baseSchemas)
                 .build();
-            yanglibRegistrations = registerDeviceSchemaSources(remoteDeviceId, nodeId, node, resources);
+            yanglibRegistrations = registerDeviceSchemaSources(remoteDeviceId, node, resources);
         }
 
         final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
-        final int rpcMessageLimit = node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT
-            : node.getConcurrentRpcLimit().toJava();
-
+        final int rpcMessageLimit = node.getConcurrentRpcLimit().toJava();
         if (rpcMessageLimit < 1) {
             LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
         }
 
-        NetconfDeviceCommunicator netconfDeviceCommunicator =
+        final NetconfDeviceCommunicator netconfDeviceCommunicator =
              userCapabilities.isPresent() ? new NetconfDeviceCommunicator(remoteDeviceId, device,
                      userCapabilities.get(), rpcMessageLimit)
             : new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit);
@@ -286,7 +264,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
     }
 
     private List<SchemaSourceRegistration<?>> registerDeviceSchemaSources(final RemoteDeviceId remoteDeviceId,
-            final NodeId nodeId, final NetconfNode node, final SchemaResourcesDTO resources) {
+            final NetconfNode node, final SchemaResourcesDTO resources) {
         final YangLibrary yangLibrary = node.getYangLibrary();
         if (yangLibrary != null) {
             final Uri uri = yangLibrary.getYangLibraryUrl();
@@ -334,25 +312,12 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
 
     public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener,
                                                                   final NetconfNode node) {
-
-        //setup default values since default value is not supported in mdsal
-        final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null
-                ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis().toJava();
-        final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null
-                ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts().toJava();
-        final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null
-                ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis().toJava();
-        final boolean useTcp = node.getTcpOnly() == null ? DEFAULT_IS_TCP_ONLY : node.getTcpOnly();
-        final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
-
-        final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue().toJava());
-
         final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
-                maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
-
+                node.getMaxConnectionAttempts().toJava(), node.getBetweenAttemptsTimeoutMillis().toJava(),
+                node.getSleepFactor());
         final NetconfReconnectingClientConfigurationBuilder reconnectingClientConfigurationBuilder;
         final Protocol protocol = node.getProtocol();
-        if (useTcp) {
+        if (node.getTcpOnly()) {
             reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
                     .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TCP)
                     .withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
@@ -374,8 +339,8 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
         }
 
         return reconnectingClientConfigurationBuilder
-                .withAddress(socketAddress)
-                .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
+                .withAddress(getSocketAddress(node.getHost(), node.getPort().getValue().toJava()))
+                .withConnectionTimeoutMillis(node.getConnectionTimeoutMillis().toJava())
                 .withReconnectStrategy(sf.createReconnectStrategy())
                 .withConnectStrategyFactory(sf)
                 .withSessionListener(listener)