2 * Copyright (c) 2014 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
9 package org.opendaylight.controller.netconf.test.tool;
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static com.google.common.base.Preconditions.checkNotNull;
13 import static com.google.common.base.Preconditions.checkState;
15 import com.google.common.io.Files;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.InputStreamReader;
20 import java.util.List;
22 import net.sourceforge.argparse4j.ArgumentParsers;
23 import net.sourceforge.argparse4j.annotation.Arg;
24 import net.sourceforge.argparse4j.inf.ArgumentParser;
25 import net.sourceforge.argparse4j.inf.ArgumentParserException;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import com.google.common.base.Charsets;
31 import com.google.common.io.CharStreams;
33 public final class Main {
35 // TODO add logback config
37 // TODO make exi configurable
39 private static final Logger LOG = LoggerFactory.getLogger(Main.class);
43 @Arg(dest = "schemas-dir")
44 public File schemasDir;
46 @Arg(dest = "devices-count")
47 public int deviceCount;
49 @Arg(dest = "starting-port")
50 public int startingPort;
52 @Arg(dest = "generate-configs-dir")
53 public File generateConfigsDir;
55 @Arg(dest = "generate-configs-batch-size")
56 public int generateConfigBatchSize;
61 static ArgumentParser getParser() {
62 final ArgumentParser parser = ArgumentParsers.newArgumentParser("netconf testool");
63 parser.addArgument("--devices-count")
67 .help("Number of simulated netconf devices to spin")
68 .dest("devices-count");
70 parser.addArgument("--schemas-dir")
73 .help("Directory containing yang schemas to describe simulated devices")
76 parser.addArgument("--starting-port")
79 .help("First port for simulated device. Each other device will have previous+1 port number")
80 .dest("starting-port");
82 parser.addArgument("--generate-configs-batch-size")
85 .help("Number of connector configs per generated file")
86 .dest("generate-configs-batch-size");
88 parser.addArgument("--generate-configs-dir")
90 .help("Directory where initial config files for ODL distribution should be generated")
91 .dest("generate-configs-dir");
93 parser.addArgument("--ssh")
96 .help("Whether to use ssh for transport or just pure tcp")
103 checkArgument(deviceCount > 0, "Device count has to be > 0");
104 checkArgument(startingPort > 1024, "Starting port has to be > 1024");
106 checkArgument(schemasDir.exists(), "Schemas dir has to exist");
107 checkArgument(schemasDir.isDirectory(), "Schemas dir has to be a directory");
108 checkArgument(schemasDir.canRead(), "Schemas dir has to be readable");
112 public static void main(final String[] args) {
113 final Params params = parseArgs(args, Params.getParser());
116 final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator();
118 final List<Integer> openDevices = netconfDeviceSimulator.start(params);
119 if(params.generateConfigsDir != null) {
120 new ConfigGenerator(params.generateConfigsDir, openDevices).generate(params.ssh, params.generateConfigBatchSize);
122 } catch (final Exception e) {
123 LOG.error("Unhandled exception", e);
124 netconfDeviceSimulator.close();
129 synchronized (netconfDeviceSimulator) {
131 netconfDeviceSimulator.wait();
132 } catch (final InterruptedException e) {
133 throw new RuntimeException(e);
139 private static Params parseArgs(final String[] args, final ArgumentParser parser) {
140 final Params opt = new Params();
142 parser.parseArgs(args, opt);
144 } catch (final ArgumentParserException e) {
145 parser.handleError(e);
152 private static class ConfigGenerator {
153 public static final String NETCONF_CONNECTOR_XML = "/initial/99-netconf-connector.xml";
154 public static final String NETCONF_CONNECTOR_NAME = "controller-config";
155 public static final String NETCONF_CONNECTOR_PORT = "1830";
156 public static final String NETCONF_USE_SSH = "false";
157 public static final String SIM_DEVICE_SUFFIX = "-sim-device";
159 private final File directory;
160 private final List<Integer> openDevices;
162 public ConfigGenerator(final File directory, final List<Integer> openDevices) {
163 this.directory = directory;
164 this.openDevices = openDevices;
167 public void generate(final boolean useSsh, final int batchSize) {
168 if(directory.exists() == false) {
169 checkState(directory.mkdirs(), "Unable to create folder %s" + directory);
172 try(InputStream stream = Main.class.getResourceAsStream(NETCONF_CONNECTOR_XML)) {
173 checkNotNull(stream, "Cannot load %s", NETCONF_CONNECTOR_XML);
174 String configBlueprint = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
176 // TODO make address configurable
177 checkState(configBlueprint.contains(NETCONF_CONNECTOR_NAME));
178 checkState(configBlueprint.contains(NETCONF_CONNECTOR_PORT));
179 checkState(configBlueprint.contains(NETCONF_USE_SSH));
180 configBlueprint = configBlueprint.replace(NETCONF_CONNECTOR_NAME, "%s");
181 configBlueprint = configBlueprint.replace(NETCONF_CONNECTOR_PORT, "%s");
182 configBlueprint = configBlueprint.replace(NETCONF_USE_SSH, "%s");
184 final String before = configBlueprint.substring(0, configBlueprint.indexOf("<module>"));
185 final String middleBlueprint = configBlueprint.substring(configBlueprint.indexOf("<module>"), configBlueprint.indexOf("</module>") + "</module>".length());
186 final String after = configBlueprint.substring(configBlueprint.indexOf("</module>") + "</module>".length());
188 int connectorCount = 0;
189 Integer batchStart = null;
190 StringBuilder b = new StringBuilder();
193 for (final Integer openDevice : openDevices) {
194 if(batchStart == null) {
195 batchStart = openDevice;
198 final String name = String.valueOf(openDevice) + SIM_DEVICE_SUFFIX;
199 final String configContent = String.format(middleBlueprint, name, String.valueOf(openDevice), String.valueOf(!useSsh));
200 b.append(configContent);
202 if(connectorCount == batchSize) {
204 Files.write(b.toString(), new File(directory, String.format("simulated-devices_%d-%d.xml", batchStart, openDevice)), Charsets.UTF_8);
206 b = new StringBuilder();
213 if(connectorCount != 0) {
215 Files.write(b.toString(), new File(directory, String.format("simulated-devices_%d-%d.xml", batchStart, openDevices.get(openDevices.size() - 1))), Charsets.UTF_8);
218 LOG.info("Config files generated in {}", directory);
219 } catch (final IOException e) {
220 throw new RuntimeException("Unable to generate config files", e);