X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=netconf%2Ftools%2Fnetconf-testtool%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Ftest%2Ftool%2FMain.java;h=e7c772521cabfe69b8e149bca7397b82cd93c361;hb=f46a22d9b6117b3e5da7ca40c0312ca53afcf584;hp=1488b0545d954ff4cd6ca4f0ef64dea6336e32d6;hpb=07332923b85725c03472c49a4a2b4e6ee98b74fa;p=netconf.git diff --git a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/Main.java b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/Main.java index 1488b0545d..e7c772521c 100644 --- a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/Main.java +++ b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/Main.java @@ -8,203 +8,86 @@ package org.opendaylight.netconf.test.tool; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import ch.qos.logback.classic.Level; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; +import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; import com.google.common.io.ByteStreams; import com.google.common.io.CharStreams; import com.google.common.io.Files; import java.io.File; import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; 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 net.sourceforge.argparse4j.ArgumentParsers; -import net.sourceforge.argparse4j.annotation.Arg; -import net.sourceforge.argparse4j.inf.ArgumentParser; -import net.sourceforge.argparse4j.inf.ArgumentParserException; -import org.opendaylight.controller.config.util.xml.XmlElement; -import org.opendaylight.controller.config.util.xml.XmlUtil; +import javax.xml.bind.JAXBException; +import org.apache.karaf.features.internal.model.ConfigFile; +import org.apache.karaf.features.internal.model.Feature; +import org.apache.karaf.features.internal.model.Features; +import org.apache.karaf.features.internal.model.JaxbUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; + public final class Main { private static final Logger LOG = LoggerFactory.getLogger(Main.class); - public static class Params { - - @Arg(dest = "schemas-dir") - public File schemasDir; - - @Arg(dest = "devices-count") - public int deviceCount; - - @Arg(dest = "devices-per-port") - public int devicesPerPort; - - @Arg(dest = "starting-port") - public int startingPort; - - @Arg(dest = "generate-config-connection-timeout") - public int generateConfigsTimeout; - - @Arg(dest = "generate-config-address") - public String generateConfigsAddress; - - @Arg(dest = "distro-folder") - public File distroFolder; - - @Arg(dest = "generate-configs-batch-size") - public int generateConfigBatchSize; - - @Arg(dest = "ssh") - public boolean ssh; - - @Arg(dest = "exi") - public boolean exi; - - @Arg(dest = "debug") - public boolean debug; - - @Arg(dest = "notification-file") - public File notificationFile; - - @Arg(dest = "md-sal") - public boolean mdSal; - - @Arg(dest = "initial-config-xml-file") - public File initialConfigXMLFile; - - static ArgumentParser getParser() { - final ArgumentParser parser = ArgumentParsers.newArgumentParser("netconf testool"); - - parser.description("Netconf device simulator. Detailed info can be found at https://wiki.opendaylight.org/view/OpenDaylight_Controller:Netconf:Testtool#Building_testtool"); - - parser.addArgument("--device-count") - .type(Integer.class) - .setDefault(1) - .help("Number of simulated netconf devices to spin. This is the number of actual ports open for the devices.") - .dest("devices-count"); - - parser.addArgument("--devices-per-port") - .type(Integer.class) - .setDefault(1) - .help("Amount of config files generated per port to spoof more devices then are actually running") - .dest("devices-per-port"); - - parser.addArgument("--schemas-dir") - .type(File.class) - .help("Directory containing yang schemas to describe simulated devices. Some schemas e.g. netconf monitoring and inet types are included by default") - .dest("schemas-dir"); - - parser.addArgument("--notification-file") - .type(File.class) - .help("Xml file containing notifications that should be sent to clients after create subscription is called") - .dest("notification-file"); - - parser.addArgument("--initial-config-xml-file") - .type(File.class) - .help("Xml file containing initial simulatted configuration to be returned via get-config rpc") - .dest("initial-config-xml-file"); - - parser.addArgument("--starting-port") - .type(Integer.class) - .setDefault(17830) - .help("First port for simulated device. Each other device will have previous+1 port number") - .dest("starting-port"); - - parser.addArgument("--generate-config-connection-timeout") - .type(Integer.class) - .setDefault((int)TimeUnit.MINUTES.toMillis(30)) - .help("Timeout to be generated in initial config files") - .dest("generate-config-connection-timeout"); - - parser.addArgument("--generate-config-address") - .type(String.class) - .setDefault("127.0.0.1") - .help("Address to be placed in generated configs") - .dest("generate-config-address"); - - parser.addArgument("--generate-configs-batch-size") - .type(Integer.class) - .setDefault(4000) - .help("Number of connector configs per generated file") - .dest("generate-configs-batch-size"); - - parser.addArgument("--distribution-folder") - .type(File.class) - .help("Directory where the karaf distribution for controller is located") - .dest("distro-folder"); - - parser.addArgument("--ssh") - .type(Boolean.class) - .setDefault(true) - .help("Whether to use ssh for transport or just pure tcp") - .dest("ssh"); - - parser.addArgument("--exi") - .type(Boolean.class) - .setDefault(true) - .help("Whether to use exi to transport xml content") - .dest("exi"); - - parser.addArgument("--debug") - .type(Boolean.class) - .setDefault(false) - .help("Whether to use debug log level instead of INFO") - .dest("debug"); - - parser.addArgument("--md-sal") - .type(Boolean.class) - .setDefault(false) - .help("Whether to use md-sal datastore instead of default simulated datastore.") - .dest("md-sal"); - - return parser; - } - - void validate() { - checkArgument(deviceCount > 0, "Device count has to be > 0"); - checkArgument(startingPort > 1023, "Starting port has to be > 1023"); - checkArgument(devicesPerPort > 0, "Atleast one device per port needed"); - - if(schemasDir != null) { - checkArgument(schemasDir.exists(), "Schemas dir has to exist"); - checkArgument(schemasDir.isDirectory(), "Schemas dir has to be a directory"); - checkArgument(schemasDir.canRead(), "Schemas dir has to be readable"); - } - } - } - public static void main(final String[] args) { - final Params params = parseArgs(args, Params.getParser()); + final TesttoolParameters params = TesttoolParameters.parseArgs(args, TesttoolParameters.getParser()); params.validate(); - final ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); root.setLevel(params.debug ? Level.DEBUG : Level.INFO); - final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator(); + final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator(params.threadPoolSize); try { final List openDevices = netconfDeviceSimulator.start(params); if (openDevices.size() == 0) { LOG.error("Failed to start any simulated devices, exiting..."); System.exit(1); } - if(params.distroFolder != null) { + if (params.controllerDestination != null) { + final ArrayList> allThreadsPayloads = params.getThreadsPayloads(openDevices); + final ArrayList executions = new ArrayList<>(); + for (ArrayList payloads : allThreadsPayloads) { + executions.add(new Execution(params, payloads)); + } + final ExecutorService executorService = Executors.newFixedThreadPool(params.threadAmount); + final Stopwatch time = Stopwatch.createStarted(); + List> futures = executorService.invokeAll(executions, params.timeOut, TimeUnit.SECONDS); + int threadNum = 0; + for(Future future : futures){ + threadNum++; + if (future.isCancelled()) { + LOG.info("{}. thread timed out.",threadNum); + } else { + try { + future.get(); + } catch (final ExecutionException e) { + LOG.info("{}. thread failed.", threadNum, e); + } + } + } + time.stop(); + LOG.info("Time spent with configuration of devices: {}.",time); + } + + if (params.distroFolder != null) { final ConfigGenerator configGenerator = new ConfigGenerator(params.distroFolder, openDevices); final List generated = configGenerator.generate( params.ssh, params.generateConfigBatchSize, @@ -229,19 +112,6 @@ public final class Main { } } - private static Params parseArgs(final String[] args, final ArgumentParser parser) { - final Params opt = new Params(); - try { - parser.parseArgs(args, opt); - return opt; - } catch (final ArgumentParserException e) { - parser.handleError(e); - } - - System.exit(1); - return null; - } - static class ConfigGenerator { public static final String NETCONF_CONNECTOR_XML = "/99-netconf-connector-simulated.xml"; public static final String SIM_DEVICE_SUFFIX = "-sim-device"; @@ -270,7 +140,7 @@ public final class Main { public List generate(final boolean useSsh, final int batchSize, final int generateConfigsTimeout, final String address, final int devicesPerPort) { - if(configDir.exists() == false) { + if (configDir.exists() == false) { Preconditions.checkState(configDir.mkdirs(), "Unable to create directory " + configDir); } @@ -283,7 +153,7 @@ public final class Main { Preconditions.checkState(file.delete(), "Unable to clean previous generated file %s", file); } - try(InputStream stream = Main.class.getResourceAsStream(NETCONF_CONNECTOR_XML)) { + try (InputStream stream = Main.class.getResourceAsStream(NETCONF_CONNECTOR_XML)) { checkNotNull(stream, "Cannot load %s", NETCONF_CONNECTOR_XML); String configBlueprint = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8)); @@ -299,7 +169,7 @@ public final class Main { final List generatedConfigs = Lists.newArrayList(); for (final Integer openDevice : openDevices) { - if(batchStart == null) { + if (batchStart == null) { batchStart = openDevice; } @@ -310,7 +180,7 @@ public final class Main { b.append(configContent); connectorCount++; - if(connectorCount == batchSize) { + if (connectorCount == batchSize) { b.append(after); final File to = new File(configDir, String.format(SIM_DEVICE_CFG_PREFIX + "%d-%d.xml", batchStart, openDevice)); generatedConfigs.add(to); @@ -324,7 +194,7 @@ public final class Main { } // Write remaining - if(connectorCount != 0) { + if (connectorCount != 0) { b.append(after); final File to = new File(configDir, String.format(SIM_DEVICE_CFG_PREFIX + "%d-%d.xml", batchStart, openDevices.get(openDevices.size() - 1))); generatedConfigs.add(to); @@ -340,53 +210,33 @@ public final class Main { public void updateFeatureFile(final List generated) { - // TODO karaf core contains jaxb for feature files, use that for - // modification - try { - for (final File featureFile : ncFeatureFiles) { - final Document document = XmlUtil.readXmlToDocument(Files - .toString(featureFile, Charsets.UTF_8)); - final NodeList childNodes = document.getDocumentElement().getChildNodes(); - - for (int i = 0; i < childNodes.getLength(); i++) { - final Node item = childNodes.item(i); - if (item instanceof Element == false) { - continue; - } - if (item.getLocalName().equals("feature") == false) { - continue; - } + for (final File fileFeatures : ncFeatureFiles) { + try { + final Features f = JaxbUtil.unmarshal(new FileInputStream(fileFeatures), false); - if (NETCONF_CONNECTOR_ALL_FEATURE - .equals(((Element) item).getAttribute("name"))) { - final Element ncAllFeatureDefinition = (Element) item; - // Clean previous generated files - for (final XmlElement configfile : XmlElement - .fromDomElement(ncAllFeatureDefinition) - .getChildElements("configfile")) { - ncAllFeatureDefinition.removeChild(configfile.getDomElement()); - } - for (final File file : generated) { - final Element configfile = document.createElement("configfile"); - configfile.setTextContent("file:" - + ETC_OPENDAYLIGHT_KARAF_PATH - + file.getName()); - configfile.setAttribute( - "finalname", - ETC_OPENDAYLIGHT_KARAF_PATH - + file.getName()); - ncAllFeatureDefinition.appendChild(configfile); + for (final Feature feature : f.getFeature()) { + if (NETCONF_CONNECTOR_ALL_FEATURE.equals(feature.getName())) { + //Clean all previously generated configFiles + feature.getConfigfile().clear(); + + //Create new configFiles + for (final File gen : generated) { + final ConfigFile cf = new ConfigFile(); + + final String generatedName = ETC_OPENDAYLIGHT_KARAF_PATH + gen.getName(); + + cf.setFinalname(generatedName); + cf.setLocation("file:" + generatedName); + + feature.getConfigfile().add(cf); + } } } - } - - Files.write(XmlUtil.toString(document), featureFile,Charsets.UTF_8); - LOG.info("Feature file {} updated", featureFile); + JaxbUtil.marshal(f, new FileWriter(fileFeatures)); + LOG.info("Feature file {} updated", fileFeatures); + } catch (JAXBException | IOException e) { + throw new RuntimeException(e); } - } catch (final IOException e) { - throw new RuntimeException("Unable to load features file as a resource"); - } catch (final SAXException e) { - throw new RuntimeException("Unable to parse features file"); } } @@ -433,7 +283,7 @@ public final class Main { public void changeLoadOrder() { try { - Files.write(ByteStreams.toByteArray(getClass().getResourceAsStream("/" +ORG_OPS4J_PAX_URL_MVN_CFG)), loadOrderCfgFile); + Files.write(ByteStreams.toByteArray(getClass().getResourceAsStream("/" + ORG_OPS4J_PAX_URL_MVN_CFG)), loadOrderCfgFile); LOG.info("Load order changed to prefer local bundles/features by rewriting file {}", loadOrderCfgFile); } catch (IOException e) { throw new RuntimeException("Unable to rewrite features file " + loadOrderCfgFile, e);