use --help to find out all suported args.
Change-Id: Ib9cae0479d672d4432bbc0fe87dc98a32f524784
Signed-off-by: Tomas Cere <tcere@cisco.com>
<artifactId>logback-classic</artifactId>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>com.ning</groupId>
+ <artifactId>async-http-client</artifactId>
+ <version>1.9.24</version>
+ </dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
- <dependency>
- <groupId>xmlunit</groupId>
- <artifactId>xmlunit</artifactId>
- </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.client</exclude>
</excludes>
</filter>
</filters>
+ <artifactSet>
+ <excludes>
+ <exclude>com.ning</exclude>
+ </excludes>
+ </artifactSet>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.client.http</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.rpc</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.AcceptingAuthProvider</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.DummyMonitoringService</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.FakeModuleBuilderCapability</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.Main</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.ModuleBuilderCapability</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.NetconfDeviceSimulator</exclude>
</excludes>
</filter>
</filters>
<shadedClassifierName>stress-client</shadedClassifierName>
</configuration>
</execution>
+
+ <execution>
+ <id>restconf-perf-client</id>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <shadedArtifactId>rest-perf-client</shadedArtifactId>
+ <filters>
+ <filter>
+ <artifact>*:*</artifact>
+ <excludes>
+ <exclude>META-INF/*.SF</exclude>
+ <exclude>META-INF/*.DSA</exclude>
+ <exclude>META-INF/*.RSA</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.rpc</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.AcceptingAuthProvider</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.DummyMonitoringService</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.FakeModuleBuilderCapability</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.Main</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.ModuleBuilderCapability</exclude>
+ <exclude>org.opendaylight.controller.netconf.test.tool.NetconfDeviceSimulator</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ <artifactSet>
+ <excludes>
+ <exclude>org.bouncycastle:*</exclude>
+ <exclude>com.google:*</exclude>
+ <exclude>org.opendaylight.yangtools</exclude>
+ <exclude>org.opendaylight.yang</exclude>
+ </excludes>
+ </artifactSet>
+ <transformers>
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.opendaylight.controller.netconf.test.tool.client.http.perf.RestPerfClient</mainClass>
+ </transformer>
+ </transformers>
+ <shadedArtifactAttached>true</shadedArtifactAttached>
+ <shadedClassifierName>rest-perf-client</shadedClassifierName>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/stress-client.xml</descriptor>
+ </descriptors>
+ <finalName>stress-client-${project.version}-package</finalName>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
</executions>
</plugin>
</plugins>
--- /dev/null
+<!--
+ ~ 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
+ -->
+
+<assembly>
+ <id>stress-client</id>
+ <formats>
+ <format>tar.gz</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>target/lib</directory>
+ <outputDirectory>/lib</outputDirectory>
+ <includes>
+ <include>*</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>stress-client*.jar</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
\ No newline at end of file
--- /dev/null
+/*
+ * 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.controller.netconf.test.tool;
+
+public class TestToolUtils {
+
+ public static String getMac(long mac) {
+ StringBuilder m = new StringBuilder(Long.toString(mac, 16));
+
+ for (int i = m.length(); i < 12; i++) {
+ m.insert(0, "0");
+ }
+
+ for (int j = m.length() - 2; j >= 2; j -= 2) {
+ m.insert(j, ":");
+ }
+
+ return m.toString();
+ }
+}
--- /dev/null
+/*
+ * 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.controller.netconf.test.tool.client.http.perf;
+
+import com.ning.http.client.AsyncCompletionHandler;
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.HttpResponseStatus;
+import com.ning.http.client.ListenableFuture;
+import com.ning.http.client.Request;
+import com.ning.http.client.Response;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+import org.opendaylight.controller.netconf.test.tool.client.stress.ExecutionStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AsyncExecutionStrategy implements ExecutionStrategy{
+
+ private static final Logger LOG = LoggerFactory.getLogger(AsyncExecutionStrategy.class);
+
+ private final Parameters params;
+ private final ArrayList<Request> payloads;
+ private final AsyncHttpClient asyncHttpClient;
+ private final Semaphore semaphore;
+
+ AsyncExecutionStrategy(final Parameters params, final AsyncHttpClient asyncHttpClient, final ArrayList<Request> payloads) {
+ this.params = params;
+ this.asyncHttpClient = asyncHttpClient;
+ this.payloads = payloads;
+ this.semaphore = new Semaphore(RestPerfClient.throttle);
+ }
+
+ @Override
+ public void invoke() {
+ final ArrayList<ListenableFuture<Response>> futures = new ArrayList<>();
+ LOG.info("Begin sending async requests");
+
+ for (final Request request : payloads) {
+ try {
+ semaphore.acquire();
+ } catch (InterruptedException e) {
+ LOG.warn("Semaphore acquire interrupted");
+ }
+ futures.add(asyncHttpClient.executeRequest(request, new AsyncCompletionHandler<Response>() {
+ @Override
+ public STATE onStatusReceived(HttpResponseStatus status) throws Exception {
+ super.onStatusReceived(status);
+ if (status.getStatusCode() != 200 && status.getStatusCode() != 204) {
+ LOG.warn("Request failed, status code: {}", status.getStatusCode() + status.getStatusText());
+ LOG.warn("request: {}", request.toString());
+ }
+ return STATE.CONTINUE;
+ }
+
+ @Override
+ public Response onCompleted(Response response) throws Exception {
+ semaphore.release();
+ return response;
+ }
+ }));
+ }
+ LOG.info("Requests sent, waiting for responses");
+
+ try {
+ semaphore.acquire(RestPerfClient.throttle);
+ } catch (InterruptedException e) {
+ LOG.warn("Semaphore acquire interrupted");
+ }
+
+ LOG.info("Responses received, ending...");
+ }
+}
--- /dev/null
+/*
+ * 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.controller.netconf.test.tool.client.http.perf;
+
+import com.google.common.base.Preconditions;
+import java.io.File;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import net.sourceforge.argparse4j.ArgumentParsers;
+import net.sourceforge.argparse4j.annotation.Arg;
+import net.sourceforge.argparse4j.inf.ArgumentParser;
+
+public class Parameters {
+
+ @Arg(dest = "ip")
+ public String ip;
+
+ @Arg(dest = "port")
+ public int port;
+
+ @Arg(dest = "destination")
+ public String destination;
+
+ @Arg(dest = "edit-count")
+ public int editCount;
+
+ @Arg(dest = "edit-content")
+ public File editContent;
+
+ @Arg(dest = "async")
+ public boolean async;
+
+ @Arg(dest = "thread-amount")
+ public int threadAmount;
+
+ @Arg(dest = "same-device")
+ public boolean sameDevice;
+
+ @Arg(dest = "device-port-range-start")
+ public int devicePortRangeStart;
+
+ @Arg(dest = "throttle")
+ public int throttle;
+
+ static ArgumentParser getParser() {
+ final ArgumentParser parser = ArgumentParsers.newArgumentParser("netconf stress client");
+
+ parser.description("Netconf stress client");
+
+ parser.addArgument("--ip")
+ .type(String.class)
+ .setDefault("127.0.0.1")
+ .help("Restconf server IP")
+ .dest("ip");
+
+ parser.addArgument("--port")
+ .type(Integer.class)
+ .setDefault(8181)
+ .help("Restconf server port")
+ .dest("port");
+
+ parser.addArgument("--destination")
+ .type(String.class)
+ .setDefault("/restconf/config/network-topology:network-topology/topology/topology-netconf/node/" +
+ "{DEVICE_PORT}-sim-device/yang-ext:mount/cisco-vpp:vpp/bridge-domains/bridge-domain/a")
+ .help("Destination to send the requests to after the ip:port part of the uri. " +
+ "Use {DEVICE_PORT} tag to use the device-port-range-start argument")
+ .dest("destination");
+
+ parser.addArgument("--edits")
+ .type(Integer.class)
+ .setDefault(50000)
+ .help("Amount requests to be sent")
+ .dest("edit-count");
+
+ parser.addArgument("--edit-content")
+ .type(File.class)
+ .setDefault(new File("edit.txt"))
+ .dest("edit-content");
+
+ parser.addArgument("--async-requests")
+ .type(Boolean.class)
+ .setDefault(true)
+ .dest("async");
+
+ parser.addArgument("--thread-amount")
+ .type(Integer.class)
+ .setDefault(1)
+ .dest("thread-amount");
+
+ parser.addArgument("--same-device")
+ .type(Boolean.class)
+ .setDefault(true)
+ .help("If true, every thread edits the device at the first port. If false, n-th thread edits device at n-th port.")
+ .dest("same-device");
+
+ parser.addArgument("--device-port-range-start")
+ .type(Integer.class)
+ .setDefault(17830)
+ .dest("device-port-range-start");
+
+ parser.addArgument("--throttle")
+ .type(Integer.class)
+ .setDefault(5000)
+ .help("Maximum amount of async requests that can be open at a time, " +
+ "with mutltiple threads this gets divided among all threads")
+ .dest("throttle");
+
+ return parser;
+ }
+
+ void validate() {
+ Preconditions.checkArgument(port > 0, "Port =< 0");
+ Preconditions.checkArgument(editCount > 0, "Edit count =< 0");
+
+ Preconditions.checkArgument(editContent.exists(), "Edit content file missing");
+ Preconditions.checkArgument(editContent.isDirectory() == false, "Edit content file is a dir");
+ Preconditions.checkArgument(editContent.canRead(), "Edit content file is unreadable");
+ // TODO validate
+ }
+
+ public InetSocketAddress getInetAddress() {
+ try {
+ return new InetSocketAddress(InetAddress.getByName(ip), port);
+ } catch (final UnknownHostException e) {
+ throw new IllegalArgumentException("Unknown ip", e);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.controller.netconf.test.tool.client.http.perf;
+
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.AsyncHttpClientConfig;
+import com.ning.http.client.Request;
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import org.opendaylight.controller.netconf.test.tool.client.http.perf.RestPerfClient.DestToPayload;
+import org.opendaylight.controller.netconf.test.tool.client.stress.ExecutionStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PerfClientCallable implements Callable<Void>{
+
+ private static final Logger LOG = LoggerFactory.getLogger(PerfClientCallable.class);
+
+ private final Parameters params;
+ private final ArrayList<Request> payloads;
+ private final AsyncHttpClient asyncHttpClient;
+ private ExecutionStrategy executionStrategy;
+
+ public PerfClientCallable(Parameters params, ArrayList<DestToPayload> payloads) {
+ this.params = params;
+ this.asyncHttpClient = new AsyncHttpClient(new AsyncHttpClientConfig.Builder()
+ .setConnectTimeout(Integer.MAX_VALUE)
+ .setRequestTimeout(Integer.MAX_VALUE)
+ .setAllowPoolingConnections(true)
+ .build());
+ this.payloads = new ArrayList<>();
+ for (DestToPayload payload : payloads) {
+ this.payloads.add(asyncHttpClient.preparePost(payload.getDestination())
+ .addHeader("content-type", "application/json")
+ .addHeader("Accept", "application/xml")
+ .setBody(payload.getPayload())
+ .setRequestTimeout(Integer.MAX_VALUE)
+ .build());
+ }
+ executionStrategy = getExecutionStrategy();
+ }
+
+ private ExecutionStrategy getExecutionStrategy() {
+ return params.async
+ ? new AsyncExecutionStrategy(params, asyncHttpClient, payloads)
+ : new SyncExecutionStrategy(params, asyncHttpClient, payloads);
+ }
+
+ @Override
+ public Void call() throws Exception{
+
+ executionStrategy.invoke();
+ asyncHttpClient.closeAsynchronously();
+ return null;
+ }
+}
--- /dev/null
+/*
+ * 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.controller.netconf.test.tool.client.http.perf;
+
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Stopwatch;
+import com.google.common.io.Files;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import net.sourceforge.argparse4j.inf.ArgumentParser;
+import net.sourceforge.argparse4j.inf.ArgumentParserException;
+import org.opendaylight.controller.netconf.test.tool.TestToolUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RestPerfClient {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RestPerfClient.class);
+
+ private static final String HOST_KEY = "{HOST}";
+ private static final String PORT_KEY = "{PORT}";
+ private static final String DEVICE_PORT_KEY = "{DEVICE_PORT}";
+
+ private static final String PEER_KEY = "{PEERID}";
+ private static final String INT_LEAF_KEY = "{INTLEAF}";
+
+ private static final String PHYS_ADDR_PLACEHOLDER = "{PHYS_ADDR}";
+
+ private static final String dest = "http://{HOST}:{PORT}";
+
+ private static long macStart = 0xAABBCCDD0000L;
+
+ static int throttle;
+
+ static final class DestToPayload {
+
+ private final String destination;
+ private final String payload;
+
+ public DestToPayload(String destination, String payload) {
+ this.destination = destination;
+ this.payload = payload;
+ }
+
+ public String getDestination() {
+ return destination;
+ }
+
+ public String getPayload() {
+ return payload;
+ }
+ }
+
+ public static void main(String[] args) throws IOException {
+
+ Parameters parameters = parseArgs(args, Parameters.getParser());
+ parameters.validate();
+ throttle = parameters.throttle / parameters.threadAmount;
+
+ if (parameters.async && parameters.threadAmount > 1) {
+ LOG.info("Throttling per thread: {}", throttle);
+ }
+
+ final String editContentString;
+ try {
+ editContentString = Files.toString(parameters.editContent, Charsets.UTF_8);
+ } catch (final IOException e) {
+ throw new IllegalArgumentException("Cannot read content of " + parameters.editContent);
+ }
+
+ final int threadAmount = parameters.threadAmount;
+ LOG.info("thread amount: {}", threadAmount);
+ final int requestsPerThread = parameters.editCount / parameters.threadAmount;
+ LOG.info("requestsPerThread: {}", requestsPerThread);
+ final int leftoverRequests = parameters.editCount % parameters.threadAmount;
+ LOG.info("leftoverRequests: {}", leftoverRequests);
+
+ final ArrayList<ArrayList<DestToPayload>> allThreadsPayloads = new ArrayList<>();
+ for (int i = 0; i < threadAmount; i++) {
+ final ArrayList<DestToPayload> payloads = new ArrayList<>();
+ for (int j = 0; j < requestsPerThread; j++) {
+ final int devicePort = parameters.sameDevice ? parameters.devicePortRangeStart : parameters.devicePortRangeStart + i;
+ final StringBuilder destBuilder = new StringBuilder(dest);
+ destBuilder.replace(destBuilder.indexOf(HOST_KEY), destBuilder.indexOf(HOST_KEY) + HOST_KEY.length(), parameters.ip)
+ .replace(destBuilder.indexOf(PORT_KEY), destBuilder.indexOf(PORT_KEY) + PORT_KEY.length(), parameters.port + "");
+ final StringBuilder suffixBuilder = new StringBuilder(parameters.destination);
+ if (suffixBuilder.indexOf(DEVICE_PORT_KEY) != -1) {
+ suffixBuilder.replace(suffixBuilder.indexOf(DEVICE_PORT_KEY), suffixBuilder.indexOf(DEVICE_PORT_KEY) + DEVICE_PORT_KEY.length(), devicePort + "");
+ }
+ destBuilder.append(suffixBuilder);
+
+ payloads.add(new DestToPayload(destBuilder.toString(), prepareMessage(i, j, editContentString)));
+ }
+ allThreadsPayloads.add(payloads);
+ }
+
+ for (int i = 0; i < leftoverRequests; i++) {
+ ArrayList<DestToPayload> payloads = allThreadsPayloads.get(allThreadsPayloads.size() - 1);
+
+ final int devicePort = parameters.sameDevice ? parameters.devicePortRangeStart : parameters.devicePortRangeStart + threadAmount - 1;
+ final StringBuilder destBuilder = new StringBuilder(dest);
+ destBuilder.replace(destBuilder.indexOf(HOST_KEY), destBuilder.indexOf(HOST_KEY) + HOST_KEY.length(), parameters.ip)
+ .replace(destBuilder.indexOf(PORT_KEY), destBuilder.indexOf(PORT_KEY) + PORT_KEY.length(), parameters.port + "");
+ final StringBuilder suffixBuilder = new StringBuilder(parameters.destination);
+ if (suffixBuilder.indexOf(DEVICE_PORT_KEY) != -1) {
+ suffixBuilder.replace(suffixBuilder.indexOf(DEVICE_PORT_KEY), suffixBuilder.indexOf(DEVICE_PORT_KEY) + DEVICE_PORT_KEY.length(), devicePort + "");
+ }
+ destBuilder.append(suffixBuilder);
+ payloads.add(new DestToPayload(destBuilder.toString(), prepareMessage(threadAmount - 1, requestsPerThread + i, editContentString)));
+ }
+
+ final ArrayList<PerfClientCallable> callables = new ArrayList<>();
+ for (ArrayList<DestToPayload> payloads : allThreadsPayloads) {
+ callables.add(new PerfClientCallable(parameters, payloads));
+ }
+
+ final ExecutorService executorService = Executors.newFixedThreadPool(threadAmount);
+
+ LOG.info("Starting performance test");
+ final Stopwatch started = Stopwatch.createStarted();
+ try {
+ final List<Future<Void>> futures = executorService.invokeAll(callables, 5, TimeUnit.MINUTES);
+ for (final Future<Void> future : futures) {
+ try {
+ future.get(4L, TimeUnit.MINUTES);
+ } catch (ExecutionException | TimeoutException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ executorService.shutdownNow();
+ } catch (final InterruptedException e) {
+ throw new RuntimeException("Unable to execute requests", e);
+ }
+ started.stop();
+
+ LOG.info("FINISHED. Execution time: {}", started);
+ LOG.info("Requests per second: {}", (parameters.editCount * 1000.0 / started.elapsed(TimeUnit.MILLISECONDS)));
+
+ System.exit(0);
+ }
+
+ private static Parameters parseArgs(final String[] args, final ArgumentParser parser) {
+ final Parameters opt = new Parameters();
+ try {
+ parser.parseArgs(args, opt);
+ return opt;
+ } catch (final ArgumentParserException e) {
+ parser.handleError(e);
+ }
+
+ System.exit(1);
+ return null;
+ }
+
+ private static String prepareMessage(final int idi, final int idj, final String editContentString) {
+ StringBuilder messageBuilder = new StringBuilder(editContentString);
+ if (editContentString.contains(PEER_KEY)) {
+ messageBuilder.replace(messageBuilder.indexOf(PEER_KEY), messageBuilder.indexOf(PEER_KEY) + PEER_KEY.length(), Integer.toString(idi))
+ .replace(messageBuilder.indexOf(INT_LEAF_KEY), messageBuilder.indexOf(INT_LEAF_KEY) + INT_LEAF_KEY.length(), Integer.toString(idj));
+ }
+
+ int idx = messageBuilder.indexOf(PHYS_ADDR_PLACEHOLDER);
+
+ while (idx != -1) {
+ messageBuilder.replace(idx, idx + PHYS_ADDR_PLACEHOLDER.length(), TestToolUtils.getMac(macStart++));
+ idx = messageBuilder.indexOf(PHYS_ADDR_PLACEHOLDER);
+ }
+
+ return messageBuilder.toString();
+ }
+}
--- /dev/null
+/*
+ * 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.controller.netconf.test.tool.client.http.perf;
+
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.Request;
+import com.ning.http.client.Response;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.netconf.test.tool.client.stress.ExecutionStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SyncExecutionStrategy implements ExecutionStrategy{
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncExecutionStrategy.class);
+
+ private final Parameters params;
+ private final ArrayList<Request> payloads;
+ private final AsyncHttpClient asyncHttpClient;
+
+ SyncExecutionStrategy(final Parameters params, final AsyncHttpClient asyncHttpClient, final ArrayList<Request> payloads) {
+ this.params = params;
+ this.asyncHttpClient = asyncHttpClient;
+ this.payloads = payloads;
+ }
+
+ @Override
+ public void invoke() {
+
+ LOG.info("Begin sending sync requests");
+ for (Request request : payloads) {
+ try {
+ Response response = asyncHttpClient.executeRequest(request).get();
+ if (response.getStatusCode() != 200 && response.getStatusCode() != 204) {
+ LOG.warn("Status code: {}", response.getStatusCode());
+ LOG.warn("url: {}", request.getUrl());
+ LOG.warn(response.getResponseBody());
+ }
+ } catch (InterruptedException | ExecutionException | IOException e) {
+ LOG.warn(e.toString());
+ }
+ }
+ LOG.info("End sending sync requests");
+
+ }
+}
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandler;
+import org.opendaylight.controller.netconf.test.tool.TestToolUtils;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.controller.sal.connect.api.RemoteDevice;
import org.opendaylight.controller.sal.connect.netconf.listener.NetconfDeviceCommunicator;
final StringBuilder stringBuilder = new StringBuilder(specificEditContent);
int idx = stringBuilder.indexOf(PHYS_ADDR_PLACEHOLDER);
while (idx!= -1) {
- stringBuilder.replace(idx, idx + PHYS_ADDR_PLACEHOLDER.length(), getMac(macStart++));
+ stringBuilder.replace(idx, idx + PHYS_ADDR_PLACEHOLDER.length(), TestToolUtils.getMac(macStart++));
idx = stringBuilder.indexOf(PHYS_ADDR_PLACEHOLDER);
}
specificEditContent = stringBuilder.toString();
return netconfClientDispatcher;
}
- public static String getMac(long mac) {
- StringBuilder m = new StringBuilder(Long.toString(mac, 16));
-
- for (int i = m.length(); i < 12; i++) {
- m.insert(0, "0");
- }
-
- for (int j = m.length() - 2; j >= 2; j-=2) {
- m.insert(j, ":");
- }
-
- return m.toString();
- }
-
private static Parameters parseArgs(final String[] args, final ArgumentParser parser) {
final Parameters opt = new Parameters();
try {
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ ~ 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
+ -->
+
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="INFO">
+ <appender-ref ref="STDOUT"/>
+ </root>
+
+ <logger name="com.ning.http.client" level="WARN"/>
+</configuration>
\ No newline at end of file