2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.test.tool;
10 import com.google.common.collect.Lists;
11 import java.io.IOException;
12 import java.net.Authenticator;
13 import java.net.PasswordAuthentication;
15 import java.net.http.HttpClient;
16 import java.net.http.HttpRequest;
17 import java.net.http.HttpRequest.BodyPublishers;
18 import java.net.http.HttpResponse;
19 import java.net.http.HttpResponse.BodyHandlers;
20 import java.nio.charset.StandardCharsets;
21 import java.util.List;
22 import java.util.Locale;
23 import java.util.concurrent.Callable;
24 import java.util.concurrent.Semaphore;
25 import java.util.stream.Collectors;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
29 final class Execution implements Callable<Void> {
30 private static final Logger LOG = LoggerFactory.getLogger(Execution.class);
31 private static final String NETCONF_TOPOLOGY_DESTINATION =
32 "http://%s:%s/rests/data/network-topology:network-topology/topology=topology-netconf";
34 private final HttpClient httpClient;
35 private final String destination;
36 private final List<Integer> openDevices;
37 private final TesttoolParameters params;
38 private final Semaphore semaphore;
40 private final int throttle;
41 private final boolean isAsync;
43 Execution(final List<Integer> openDevices, final TesttoolParameters params) {
44 httpClient = HttpClient.newBuilder()
45 .authenticator(new Authenticator() {
47 protected PasswordAuthentication getPasswordAuthentication() {
48 return new PasswordAuthentication(params.controllerAuthUsername,
49 params.controllerAuthPassword.toCharArray());
53 destination = String.format(Locale.ROOT, NETCONF_TOPOLOGY_DESTINATION,
54 params.controllerIp, params.controllerPort);
55 this.openDevices = openDevices;
58 throttle = params.throttle / params.threadAmount;
59 isAsync = params.async;
61 if (params.async && params.threadAmount > 1) {
62 LOG.info("Throttling per thread: {}", throttle);
64 semaphore = new Semaphore(throttle);
69 final List<HttpRequest> requests = prepareRequests();
78 private List<HttpRequest> prepareRequests() {
79 final List<List<Integer>> batches = Lists.partition(openDevices, params.generateConfigBatchSize);
80 return batches.stream()
81 .map(b -> PayloadCreator.createStringPayload(b, params))
82 .map(this::prepareRequest)
83 .collect(Collectors.toList());
86 private void sendAsync(final List<HttpRequest> requests) {
87 LOG.info("Begin sending async requests");
88 for (final HttpRequest request : requests) {
91 } catch (final InterruptedException e) {
92 LOG.warn("Semaphore acquire interrupted");
94 httpClient.sendAsync(request, BodyHandlers.ofString()).whenComplete((response, error) -> {
95 if (response.statusCode() != 200) {
96 LOG.warn("Unexpected status code: {} for request to uri: {} with body: {}",
97 response.statusCode(), request.uri(), response.body());
102 LOG.info("Requests sent, waiting for responses");
104 semaphore.acquire(throttle);
105 } catch (final InterruptedException e) {
106 LOG.warn("Semaphore acquire interrupted");
108 LOG.info("Responses received, ending...");
111 private void sendSync(final List<HttpRequest> requests) {
112 LOG.info("Begin sending sync requests");
113 for (final HttpRequest request : requests) {
115 final HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
116 if (response.statusCode() != 200) {
117 LOG.warn("Unexpected status code: {} for request to uri: {} with body: {}",
118 response.statusCode(), request.uri(), response.body());
120 } catch (final InterruptedException | IOException e) {
121 LOG.error("Failed to execute request: {}", request, e);
122 throw new IllegalStateException("Failed to execute request", e);
125 LOG.info("End sending sync requests");
128 private HttpRequest prepareRequest(final String payload) {
129 LOG.info("Creating request to: {} with payload: {}", destination, payload);
130 return HttpRequest.newBuilder(URI.create(destination))
131 .method("PATCH", BodyPublishers.ofString(payload, StandardCharsets.UTF_8))
132 .header("Content-Type", "application/json")
133 .header("Accept", "application/json")