From 443935e4231d1d5fb9520a99d5931fa5185230f4 Mon Sep 17 00:00:00 2001 From: Ruslan Kashapov Date: Thu, 26 Oct 2023 10:17:22 +0300 Subject: [PATCH] Migrate test-tool StressClient to transport-api JIRA: NETCONF-1108 Change-Id: I7517bc2c2e69303fc853198ca59cdd4247cea556 Signed-off-by: Ruslan Kashapov --- .../stress/ConfigurableClientDispatcher.java | 68 -------------- .../test/tool/client/stress/StressClient.java | 91 +++++++++++++------ .../client/stress/StressClientCallable.java | 51 ++++------- 3 files changed, 80 insertions(+), 130 deletions(-) delete mode 100644 netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/ConfigurableClientDispatcher.java diff --git a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/ConfigurableClientDispatcher.java b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/ConfigurableClientDispatcher.java deleted file mode 100644 index c2bf229803..0000000000 --- a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/ConfigurableClientDispatcher.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2015 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.netconf.test.tool.client.stress; - -import io.netty.channel.EventLoopGroup; -import io.netty.util.Timer; -import java.util.Set; -import org.opendaylight.netconf.client.NetconfClientDispatcherImpl; -import org.opendaylight.netconf.client.NetconfClientSessionNegotiatorFactory; -import org.opendaylight.netconf.client.conf.NetconfClientConfiguration; - -@Deprecated -public final class ConfigurableClientDispatcher extends NetconfClientDispatcherImpl { - private final Set capabilities; - - private ConfigurableClientDispatcher(final EventLoopGroup bossGroup, final EventLoopGroup workerGroup, - final Timer timer, final Set capabilities) { - super(bossGroup, workerGroup, timer); - this.capabilities = capabilities; - } - - /** - * EXI + chunked framing. - */ - public static ConfigurableClientDispatcher createChunkedExi(final EventLoopGroup bossGroup, - final EventLoopGroup workerGroup, final Timer timer) { - return new ConfigurableClientDispatcher(bossGroup, workerGroup, timer, - NetconfClientSessionNegotiatorFactory.EXI_CLIENT_CAPABILITIES); - } - - /** - * EXI + ]]gt;]]gt; framing. - */ - public static ConfigurableClientDispatcher createLegacyExi(final EventLoopGroup bossGroup, - final EventLoopGroup workerGroup, final Timer timer) { - return new ConfigurableClientDispatcher(bossGroup, workerGroup, timer, - NetconfClientSessionNegotiatorFactory.LEGACY_EXI_CLIENT_CAPABILITIES); - } - - /** - * Chunked framing. - */ - public static ConfigurableClientDispatcher createChunked(final EventLoopGroup bossGroup, - final EventLoopGroup workerGroup, final Timer timer) { - return new ConfigurableClientDispatcher(bossGroup, workerGroup, timer, - NetconfClientSessionNegotiatorFactory.DEFAULT_CLIENT_CAPABILITIES); - } - - /** - * ]]gt;]]gt; framing. - */ - public static ConfigurableClientDispatcher createLegacy(final EventLoopGroup bossGroup, - final EventLoopGroup workerGroup, final Timer timer) { - return new ConfigurableClientDispatcher(bossGroup, workerGroup, timer, - NetconfClientSessionNegotiatorFactory.LEGACY_FRAMING_CLIENT_CAPABILITIES); - } - - @Override - protected NetconfClientSessionNegotiatorFactory getNegotiatorFactory(final NetconfClientConfiguration cfg) { - return new NetconfClientSessionNegotiatorFactory(getTimer(), cfg.getAdditionalHeader(), - cfg.getConnectionTimeoutMillis(), capabilities); - } -} diff --git a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/StressClient.java b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/StressClient.java index 33dd641839..d06340e7f4 100644 --- a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/StressClient.java +++ b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/StressClient.java @@ -10,29 +10,40 @@ package org.opendaylight.netconf.test.tool.client.stress; import ch.qos.logback.classic.Level; import com.google.common.base.Stopwatch; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; -import io.netty.util.Timer; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import net.sourceforge.argparse4j.inf.ArgumentParserException; +import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader; import org.opendaylight.netconf.api.messages.NetconfMessage; import org.opendaylight.netconf.api.xml.XmlUtil; -import org.opendaylight.netconf.client.NetconfClientDispatcherImpl; +import org.opendaylight.netconf.client.NetconfClientFactoryImpl; +import org.opendaylight.netconf.client.NetconfClientSessionNegotiatorFactory; +import org.opendaylight.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.netconf.client.mdsal.NetconfDeviceCommunicator; import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences; import org.opendaylight.netconf.client.mdsal.api.RemoteDevice; -import org.opendaylight.netconf.nettyutil.handler.ssh.client.AsyncSshHandler; import org.opendaylight.netconf.test.tool.TestToolUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.CommitInput; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.EditConfigInput; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.crypto.types.rev230417.password.grouping.password.type.CleartextPasswordBuilder; +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.IetfInetUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.client.rev230417.netconf.client.initiate.stack.grouping.transport.ssh.ssh.SshClientParametersBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.client.rev230417.netconf.client.initiate.stack.grouping.transport.ssh.ssh.TcpClientParametersBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev230417.ssh.client.grouping.ClientIdentityBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev230417.ssh.client.grouping.client.identity.PasswordBuilder; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.Uint16; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -154,14 +165,11 @@ public final class StressClient { } } - final var nioGroup = new NioEventLoopGroup(); - final var timer = new HashedWheelTimer(); - - final var netconfClientDispatcher = configureClientDispatcher(nioGroup, timer); + final var netconfClientFactory = new NetconfClientFactoryImpl(); final var callables = new ArrayList(threadAmount); for (var messages : allPreparedMessages) { - callables.add(new StressClientCallable(params, netconfClientDispatcher, messages)); + callables.add(new StressClientCallable(params, netconfClientFactory, getBaseConfiguration(), messages)); } final var executorService = Executors.newFixedThreadPool(threadAmount); @@ -179,16 +187,7 @@ public final class StressClient { LOG.info("Requests per second: {}", params.editCount * 1000.0 / sw.elapsed(TimeUnit.MILLISECONDS)); // Cleanup - timer.stop(); - try { - nioGroup.shutdownGracefully().get(20L, TimeUnit.SECONDS); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - LOG.warn("Unable to close executor properly", e); - } - //stop the underlying ssh thread that gets spawned if we use ssh - if (params.ssh) { - AsyncSshHandler.DEFAULT_CLIENT.stop(); - } + netconfClientFactory.close(); } static NetconfMessage prepareMessage(final int id, final String editContentString) { @@ -235,14 +234,52 @@ public final class StressClient { return false; } - @Deprecated - private static NetconfClientDispatcherImpl configureClientDispatcher(final NioEventLoopGroup nioGroup, - final Timer timer) { + private static NetconfClientConfiguration getBaseConfiguration() { + final var confBuilder = NetconfClientConfigurationBuilder.create() + .withProtocol(params.ssh ? NetconfClientConfiguration.NetconfClientProtocol.SSH + : NetconfClientConfiguration.NetconfClientProtocol.TCP) + .withConnectionTimeoutMillis(20000L) + .withOdlHelloCapabilities(getCapabilities().stream().map(Uri::new).toList()) + .withTcpParameters(new TcpClientParametersBuilder() + .setRemoteAddress(new Host(IetfInetUtil.ipAddressFor(params.ip))) + .setRemotePort(new PortNumber(Uint16.valueOf(params.port))).build()); + if (params.ssh) { + confBuilder.withSshParameters(new SshClientParametersBuilder() + .setClientIdentity(new ClientIdentityBuilder() + .setUsername(params.username) + .setPassword(new PasswordBuilder() + .setPasswordType( + new CleartextPasswordBuilder().setCleartextPassword(params.password).build()) + .build()) + .build()) + .build()); + } + if (params.tcpHeader != null) { + final String header = params.tcpHeader.replace("\"", "").trim() + "\n"; + confBuilder.withAdditionalHeader( + new NetconfHelloMessageAdditionalHeader(null, null, null, null, null) { + @Override + public String toFormattedString() { + LOG.debug("Sending TCP header {}", header); + return header; + } + }); + } + return confBuilder.build(); + } + + private static Set getCapabilities() { if (params.exi) { - return params.legacyFraming ? ConfigurableClientDispatcher.createLegacyExi(nioGroup, nioGroup, timer) - : ConfigurableClientDispatcher.createChunkedExi(nioGroup, nioGroup, timer); + return params.legacyFraming + // EXI + ]]gt;]]gt; framing. + ? NetconfClientSessionNegotiatorFactory.LEGACY_EXI_CLIENT_CAPABILITIES + // EXI + chunked framing + : NetconfClientSessionNegotiatorFactory.EXI_CLIENT_CAPABILITIES; } - return params.legacyFraming ? ConfigurableClientDispatcher.createLegacy(nioGroup, nioGroup, timer) - : ConfigurableClientDispatcher.createChunked(nioGroup, nioGroup, timer); + return params.legacyFraming + // ]]gt;]]gt; framing. + ? NetconfClientSessionNegotiatorFactory.LEGACY_FRAMING_CLIENT_CAPABILITIES + // Chunked framing + : NetconfClientSessionNegotiatorFactory.DEFAULT_CLIENT_CAPABILITIES; } } diff --git a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/StressClientCallable.java b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/StressClientCallable.java index 09dfe880ba..b4b78923b3 100644 --- a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/StressClientCallable.java +++ b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/client/stress/StressClientCallable.java @@ -11,15 +11,14 @@ import java.net.InetSocketAddress; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; -import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader; import org.opendaylight.netconf.api.messages.NetconfMessage; -import org.opendaylight.netconf.client.NetconfClientDispatcherImpl; +import org.opendaylight.netconf.client.NetconfClientFactory; import org.opendaylight.netconf.client.NetconfClientSession; import org.opendaylight.netconf.client.conf.NetconfClientConfiguration; import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.netconf.client.mdsal.NetconfDeviceCommunicator; import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId; -import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPasswordHandler; +import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,27 +26,21 @@ public class StressClientCallable implements Callable { private static final Logger LOG = LoggerFactory.getLogger(StressClientCallable.class); - private final Parameters params; private final NetconfDeviceCommunicator sessionListener; - private final NetconfClientDispatcherImpl netconfClientDispatcher; - private final NetconfClientConfiguration cfg; private final NetconfClientSession netconfClientSession; private final ExecutionStrategy executionStrategy; public StressClientCallable(final Parameters params, - final NetconfClientDispatcherImpl netconfClientDispatcher, + final NetconfClientFactory netconfClientFactory, + final NetconfClientConfiguration baseConfiguration, final List preparedMessages) { - this.params = params; sessionListener = getSessionListener(params.getInetAddress(), params.concurrentMessageLimit); - this.netconfClientDispatcher = netconfClientDispatcher; - cfg = getNetconfClientConfiguration(this.params, sessionListener); + final var cfg = getNetconfClientConfiguration(baseConfiguration, sessionListener); LOG.info("Connecting to netconf server {}:{}", params.ip, params.port); try { - netconfClientSession = netconfClientDispatcher.createClient(cfg).get(); - } catch (final InterruptedException e) { - throw new IllegalStateException(e); - } catch (final ExecutionException e) { + netconfClientSession = netconfClientFactory.createClient(cfg).get(); + } catch (final InterruptedException | ExecutionException | UnsupportedConfigurationException e) { throw new IllegalStateException("Unable to connect", e); } executionStrategy = getExecutionStrategy(params, preparedMessages, sessionListener); @@ -75,27 +68,15 @@ public class StressClientCallable implements Callable { StressClient.LOGGING_REMOTE_DEVICE, messageLimit); } - private static NetconfClientConfiguration getNetconfClientConfiguration(final Parameters params, + private static NetconfClientConfiguration getNetconfClientConfiguration(final NetconfClientConfiguration base, final NetconfDeviceCommunicator sessionListener) { - final var netconfClientConfigurationBuilder = NetconfClientConfigurationBuilder.create() - .withSessionListener(sessionListener) - .withAddress(params.getInetAddress()) - .withProtocol(params.ssh ? NetconfClientConfiguration.NetconfClientProtocol.SSH - : NetconfClientConfiguration.NetconfClientProtocol.TCP) - .withAuthHandler(new LoginPasswordHandler(params.username, params.password)) - .withConnectionTimeoutMillis(20000L); - - if (params.tcpHeader != null) { - final String header = params.tcpHeader.replace("\"", "").trim() + "\n"; - netconfClientConfigurationBuilder.withAdditionalHeader( - new NetconfHelloMessageAdditionalHeader(null, null, null, null, null) { - @Override - public String toFormattedString() { - LOG.debug("Sending TCP header {}", header); - return header; - } - }); - } - return netconfClientConfigurationBuilder.build(); + return NetconfClientConfigurationBuilder.create() + .withProtocol(base.getProtocol()) + .withTcpParameters(base.getTcpParameters()) + .withSshParameters(base.getSshParameters()) + .withOdlHelloCapabilities(base.getOdlHelloCapabilities()) + .withAdditionalHeader(base.getAdditionalHeader().orElse(null)) + .withConnectionTimeoutMillis(base.getConnectionTimeoutMillis()) + .withSessionListener(sessionListener).build(); } } -- 2.36.6