Merge "Fixed bug in cross-broker RPC routing"
authorEd Warnicke <eaw@cisco.com>
Mon, 16 Dec 2013 15:23:04 +0000 (15:23 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 16 Dec 2013 15:23:04 +0000 (15:23 +0000)
54 files changed:
opendaylight/commons/controller-maven-plugin/pom.xml [deleted file]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/AbstractControllerMojo.java [deleted file]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StartControllerMojo.java [deleted file]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StopControllerMojo.java [deleted file]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JavaProcess.java [deleted file]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JpsProcessMonitor.java [deleted file]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/ProcessMonitor.java [deleted file]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/VMProcessMonitor.java [deleted file]
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/yang-jmx-generator/pom.xml
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/TypeProviderWrapper.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/SimpleTypeResolver.java
opendaylight/config/yang-test/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/config/test/types/rev131127/UnionTestBuilder.java [new file with mode: 0644]
opendaylight/config/yang-test/src/main/yang/config-test-impl.yang
opendaylight/config/yang-test/src/main/yang/types/test-types.yang
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/runsanity.bat [new file with mode: 0644]
opendaylight/distribution/opendaylight/runsanity.sh [new file with mode: 0755]
opendaylight/distribution/opendaylight/src/assemble/bin.xml
opendaylight/distribution/opendaylight/src/main/resources/run.bat
opendaylight/distribution/sanitytest/pom.xml
opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/distribution/Sanity.java [new file with mode: 0644]
opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/sanitytest/internal/Activator.java [new file with mode: 0644]
opendaylight/distribution/sanitytest/src/test/java/org/opendaylight/controller/distribution/test/SanityIT.java [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java
opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-flow-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/table-types.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-node-inventory.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-table-statistics.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/port-statistics.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/statistics-types.yang
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatistics.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleUnionAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/CompositeAttributeMappingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/UnionCompositeAttributeMappingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/UnionCompositeAttributeResolvingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleUnionAttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/util/Util.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PropertiesProviderAdapterImpl.java
opendaylight/netconf/ietf-netconf-monitoring/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/netconf/monitoring/rev101004/netconf/state/schemas/LocationBuilder.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_setUnions.xml [new file with mode: 0644]
pom.xml

diff --git a/opendaylight/commons/controller-maven-plugin/pom.xml b/opendaylight/commons/controller-maven-plugin/pom.xml
deleted file mode 100644 (file)
index 1ab4e70..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <groupId>org.opendaylight.controller</groupId>
-    <artifactId>commons.opendaylight</artifactId>
-    <version>1.4.1-SNAPSHOT</version>
-    <relativePath>../../commons/opendaylight</relativePath>
-  </parent>
-
-  <artifactId>controller-maven-plugin</artifactId>
-  <version>0.1.0-SNAPSHOT</version>
-  <packaging>maven-plugin</packaging>
-
-  <name>controller-maven-plugin</name>
-  <description>Maven Plugin for controlling the launch of the controller.</description>
-  <url>http://maven.apache.org</url>
-
-  <properties>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-  </properties>
-
-  <dependencies>
-    <dependency>
-      <!-- controller mojos depend on the api module -->
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-plugin-api</artifactId>
-      <version>2.0</version>
-    </dependency>
-    <dependency>
-      <!-- controller mojos use the annotations defined in this module -->
-      <groupId>org.apache.maven.plugin-tools</groupId>
-      <artifactId>maven-plugin-annotations</artifactId>
-      <version>3.2</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <!-- needed for handling processes -->
-      <groupId>com.sun</groupId>
-      <artifactId>tools</artifactId>
-      <scope>system</scope>
-      <version>7</version>
-      <systemPath>${java.home}/../lib/tools.jar</systemPath>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.8.1</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <!-- plugin builder -->
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-plugin-plugin</artifactId>
-        <version>3.2</version>
-        <configuration>
-          <goalPrefix>controller-maven-plugin</goalPrefix>
-          <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
-        </configuration>
-        <executions>
-          <execution>
-            <id>mojo-descriptor</id>
-            <goals>
-              <goal>descriptor</goal>
-            </goals>
-          </execution>
-          <execution>
-            <id>help-goal</id>
-            <goals>
-              <goal>helpmojo</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-
-</project>
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/AbstractControllerMojo.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/AbstractControllerMojo.java
deleted file mode 100644 (file)
index 39ca71c..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (c) 2013 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.maven.plugin;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.Parameter;
-
-import org.opendaylight.controller.maven.plugin.util.JavaProcess;
-import org.opendaylight.controller.maven.plugin.util.ProcessMonitor;
-
-/**
- * Base controller mojo which handles common operations
- */
-public abstract class AbstractControllerMojo extends AbstractMojo {
-    public static final String OS_NAME = System.getProperty("os.name");
-    public static final boolean WIN = OS_NAME.toUpperCase().contains("WINDOWS");
-    public static final String JAVA_HOME = "JAVA_HOME";
-    public static final boolean skip = Boolean.getBoolean("controller.startup.skip");
-    public static final String MAIN_CLASS = "org.eclipse.equinox.launcher.Main";
-    public static final String CTRL_PROP = "opendaylight.controller";
-
-    /**
-     * The home directory where controller is installed
-     */
-    @Parameter( required = false )
-    protected File controllerHome;
-
-    /**
-     * The address on which controller is listening
-     */
-    @Parameter( defaultValue = "localhost")
-    protected String controllerHost;
-
-    /**
-     * The admin web port
-     */
-    @Parameter( defaultValue = "8080")
-    protected int controllerWebPort;
-
-    /**
-     * The openflow port
-     */
-    @Parameter( defaultValue = "6633")
-    protected int controllerOFPort;
-
-    /**
-     * Additional environment variables passed when starting the controller
-     * process.
-     */
-    @Parameter(required = false)
-    protected Properties controllerShellVariables;
-
-    /**
-     * The script name to invoke
-     */
-    @Parameter(required = false)
-    protected String controllerStartScriptName;
-
-    /**
-     * The username
-     */
-    @Parameter(required = false)
-    protected String controllerUsername;
-
-    /**
-     * The password
-     */
-    @Parameter(required = false)
-    protected String controllerPassword;
-
-    /**
-     * pidFile location
-     */
-    @Parameter(required = false)
-    protected File pidFile;
-
-    protected final ProcessMonitor procMon = ProcessMonitor.load();
-
-    public abstract void start() throws MojoExecutionException, MojoFailureException;
-
-    public void execute() throws MojoExecutionException, MojoFailureException {
-        if (skip) return;
-        validateArgs();
-        start();
-    }
-
-    protected URL getWebUrl() {
-      try {
-        return new URL("http", controllerHost, controllerWebPort, "/");
-      } catch (MalformedURLException e) {
-        throw new IllegalArgumentException(
-            "controller host:port is Malformed: " + controllerHost + " " + controllerWebPort, e);
-      }
-
-    }
-
-    protected void validateArgs() throws IllegalArgumentException {
-        // System property and environment variable override the default setting
-        String odlHome = System.getProperty("controllerHome");
-        if (odlHome != null) {
-          controllerHome = new File(odlHome);
-        }
-        if (controllerHome == null) {
-            getLog().error("controllerHome cannot be determined from controllerHome "
-                + "property or ONE_HOME env variable");
-            throw new IllegalArgumentException("controllerHome cannot be determined.");
-        }
-        if (!controllerHome.exists()) {
-            throw new IllegalArgumentException(
-                    "controllerHome does not exist: " + controllerHome);
-        }
-       if (controllerUsername == null) {
-            controllerUsername = System.getProperty("controllerUsername");
-        }
-        if (controllerPassword == null) {
-            controllerPassword= System.getProperty("controllerPassword");
-        }
-        URL u = getWebUrl();
-        getLog().info("Controller Home       : " + controllerHome);
-        getLog().info("Controller Url        : " + u);
-        getLog().info("Controller credentials: " + controllerUsername
-                + "/" + controllerPassword);
-    }
-
-    protected Process invokeScript(List<String> args, String log)
-            throws MojoFailureException, MojoExecutionException
-    {
-        ProcessBuilder pb = new ProcessBuilder();
-        List<String> cmd = new ArrayList<String>();
-        cmd.add(getScript());
-        if (args != null) {
-            for (String s : args) {
-                // on windows args containing equals symbols need to be quoted
-                if (WIN && s.contains("=") && !s.startsWith("\"")) {
-                  cmd.add("\"" + s + "\"");
-                } else {
-                  cmd.add(s);
-                }
-            }
-        }
-        pb.command(cmd);
-        pb.directory(controllerHome);
-        pb.redirectErrorStream(true);
-        pb.inheritIO();
-        Map<String,String> env = pb.environment();
-        if (controllerShellVariables != null) {
-            for (Enumeration e = controllerShellVariables.propertyNames(); e.hasMoreElements();) {
-                String n = (String) e.nextElement();
-                env.put(n, controllerShellVariables.getProperty(n));
-            }
-        }
-        String jh = env.get(JAVA_HOME);
-        if (jh == null) env.put(JAVA_HOME, System.getProperty("java.home"));
-        try {
-            getLog().info("Invoking process " + pb.command());
-            return pb.start();
-        } catch (IOException e) {
-            throw new MojoExecutionException(e.getMessage());
-        }
-    }
-
-    private String getScript() throws MojoFailureException {
-        File script = null;
-        if (controllerStartScriptName != null && !"".equals(controllerStartScriptName) ) {
-            script = new File(controllerStartScriptName);
-            if (!script.exists()) {
-                // try relative path
-                script = new File(controllerHome, controllerStartScriptName);
-            }
-            if (script.exists()) return script.getAbsolutePath();
-            throw new MojoFailureException("Script not found: " + controllerStartScriptName);
-        }
-        // try default
-        script = new File(controllerHome, "run." + (WIN ? "bat" : "sh") );
-        if (script.exists()) return script.getAbsolutePath();
-        throw new MojoFailureException("Cannot find a default script to launch.");
-    }
-
-    protected boolean canConnect() {
-        try {
-            URL url = getWebUrl();
-            HttpURLConnection con;
-            con = (HttpURLConnection) url.openConnection();
-            return (con.getResponseCode() > 0);
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    public void killControllers() {
-        getLog().info("Checking environment for stray processes.");
-        List<JavaProcess> jvms = procMon.getProcesses(MAIN_CLASS, CTRL_PROP);
-        for (JavaProcess j : jvms) {
-            getLog().info("Killing running process: " + j);
-            ProcessMonitor.kill(j.getPid());
-        }
-        // cleanup pid files
-        getLog().info("Checking left over pid file: " + pidFile);
-        if (pidFile != null && pidFile.exists()) {
-            getLog().info("Cleaning up pid file : " + pidFile);
-            pidFile.delete();
-        }
-    }
-
-    public boolean isControllerRunning() {
-        return !procMon.getProcesses(MAIN_CLASS, CTRL_PROP).isEmpty();
-    }
-
-}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StartControllerMojo.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StartControllerMojo.java
deleted file mode 100644 (file)
index 0a3bee4..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2013 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.maven.plugin;
-
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-
-
-/**
- * Starts the controller
- */
-@Mojo( name = "run", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST )
-public class StartControllerMojo extends AbstractControllerMojo {
-    public static final String REDIRECT_LOG = "controller.out";
-
-    /**
-     * The timeout value for starting the controller. Defaults to 60 secs
-     */
-    @Parameter(defaultValue = "60")
-    public int timeoutSecs = 60;
-
-    /**
-     * The startArgs for starting the controller
-     */
-    @Parameter(required = false)
-    protected List<String> startArgs = new ArrayList<String>();
-
-    /**
-     * The time to wait after successfully connecting to the controller and
-     * before returning from execution.
-     */
-    @Parameter(required = false)
-    protected int warmupTimeSecs = 10;
-
-
-    @Override
-    public void start() throws MojoExecutionException, MojoFailureException {
-        killControllers();
-        // if we can still connect to a controller, bail out
-        if (canConnect()) {
-            getLog().error("A controller is already running. Shutdown and retry.");
-            throw new MojoFailureException("Controller is already running.");
-        }
-        startArgs.add("-D" + CTRL_PROP);
-        Process process = invokeScript(startArgs, REDIRECT_LOG);
-        getLog().info("Controller starting... (waiting for open ports)");
-        try {
-            waitForListening(process);
-            getLog().info("Controller port open. Waiting for warmup: "
-                    + warmupTimeSecs);
-            Thread.sleep(warmupTimeSecs*1000);
-        } catch (Exception e) {
-            throw new MojoExecutionException(e.getMessage());
-        }
-        getLog().info("Controller started successfully.");
-    }
-
-    protected boolean waitForListening(Process process)
-            throws MalformedURLException, InterruptedException, MojoExecutionException
-    {
-        long timeElapsedMillis = 0L;
-        long sleepTimeMillis = 2000L; // 2 secs
-        long timeoutMillis = timeoutSecs * 1000;
-
-        while (timeElapsedMillis < timeoutMillis) {
-            long timeRemaining = timeoutMillis - timeElapsedMillis;
-            sleepTimeMillis *= 2;
-            long toSleep = (sleepTimeMillis > timeRemaining)
-                    ? timeRemaining : sleepTimeMillis;
-            Thread.sleep(toSleep);
-            timeElapsedMillis += toSleep;
-            if (canConnect()) {
-                return true;
-            }
-            if (!isControllerRunning()) {
-                throw new MojoExecutionException("Process seems to have exited prematurely.");
-            }
-        }
-        return false;
-    }
-}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StopControllerMojo.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StopControllerMojo.java
deleted file mode 100644 (file)
index 579778d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013 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.maven.plugin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-
-/**
- * Stop controller
- */
-@Mojo( name = "stop", defaultPhase = LifecyclePhase.POST_INTEGRATION_TEST )
-public class StopControllerMojo extends AbstractControllerMojo {
-    private static final boolean SKIP_STOP = Boolean.getBoolean("skipControllerStop");
-
-    @Override
-    public void start() throws MojoExecutionException, MojoFailureException {
-        if (SKIP_STOP) {
-            getLog().info("Controller STOP is skipped per configuration " +
-                    "(-DskipControllerStop=true).");
-            return;
-        }
-        if (canConnect()) {
-            List<String> args = new ArrayList<String>();
-            args.add("-stop");
-            Process proc = invokeScript(args, null);
-            try {
-                int status = proc.waitFor();
-                if (status == 0) {
-                    getLog().info("Controller stopped.");
-                } else {
-                    getLog().error("Error stopping controller. See stdout log for details.");
-                }
-            } catch (InterruptedException ie) {
-                throw new MojoExecutionException("Error stopping controller : " + ie.getMessage());
-            }
-        } else {
-            getLog().info("Controller not running.");
-        }
-        // cleanup for any hung processes
-        killControllers();
-    }
-
-}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JavaProcess.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JavaProcess.java
deleted file mode 100644 (file)
index 95da34f..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-
-/*
- * Copyright (c) 2013 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.maven.plugin.util;
-
-import java.util.Properties;
-
-public class JavaProcess {
-    private final int pid;
-    private final String mainClass;
-    private final Properties systemProperties = new Properties();
-
-    public JavaProcess(int id, String cls) {
-        this.pid = id;
-        this.mainClass = cls;
-    }
-
-    public void setSystemProperties(String line) {
-        if (line == null || line.length() == 0) return;
-        String[] tokens = line.split("\\s");
-        for (String t : tokens) setSystemProperty(t);
-    }
-
-    public void setSystemProperty(String line) {
-        if (line.startsWith("-D")) {
-            int x = line.indexOf('=');
-            if (x > -1) {
-                systemProperties.put(line.substring(2, x), line.substring(x+1));
-            } else {
-                systemProperties.put(line.substring(2), "");
-            }
-        }
-    }
-
-    public int getPid() {
-        return pid;
-    }
-
-    public String getMainClass() {
-        return mainClass;
-    }
-
-    public Properties getSystemProperties() {
-        return systemProperties;
-    }
-
-    @Override
-    public String toString() {
-        return "pid:" + pid + " class:" + mainClass +
-                " system-properties:" + systemProperties.toString();
-    }
-}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JpsProcessMonitor.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JpsProcessMonitor.java
deleted file mode 100644 (file)
index 8474266..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2013 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.maven.plugin.util;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Uses JPS tool to monitor java local processes
- */
-public class JpsProcessMonitor extends ProcessMonitor {
-    private final String jpsTool;
-
-    public JpsProcessMonitor() {
-        String jh = System.getProperty("java.home");
-        File jps = new File(jh + SEP + "bin" + SEP + "jps");
-        if (!jps.exists()) {
-            // try one dir above
-            jps = new File(jh + SEP + ".." + SEP + "bin" + SEP + "jps");
-            if (!jps.exists()) {
-                throw new IllegalStateException("jps tool cannot be located.");
-            }
-        }
-        jpsTool = jps.getAbsolutePath();
-    }
-
-    @Override
-    public List<JavaProcess> getProcesses() {
-        if (jpsTool == null) return super.getProcesses();
-        List<JavaProcess> jvms = new ArrayList<JavaProcess>();
-        try {
-            ProcessBuilder pb = new ProcessBuilder();
-            pb.command(new String[] { jpsTool, "-mlvV"} );
-            pb.redirectErrorStream(true);
-            Process process = pb.start();
-            BufferedReader br = new BufferedReader(
-                    new InputStreamReader(process.getInputStream()));
-            String line = null;
-            while ( (line = br.readLine()) != null) {
-                JavaProcess j = parseLine(line);
-                if (j != null) jvms.add(j);
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return jvms;
-    }
-
-    public static JavaProcess parseLine(String line) {
-        String[] tokens = line.split("\\s");
-        if (tokens.length < 2) {
-            System.out.println("Unable to parse line: " + line);
-            return null;
-        }
-        int idx = 0;
-        int pid = Integer.parseInt(tokens[idx++]);
-        String mainClass = "";
-        if (!tokens[idx].startsWith("-")) {
-            mainClass = tokens[idx++];
-        }
-        JavaProcess proc = new JavaProcess(pid, mainClass);
-        for (int i=idx; i<tokens.length; i++) {
-            if (tokens[i].startsWith("-D")) {
-                proc.setSystemProperty(tokens[i]);
-            }
-        }
-        return proc;
-    }
-
-}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/ProcessMonitor.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/ProcessMonitor.java
deleted file mode 100644 (file)
index 5c3c69f..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2013 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.maven.plugin.util;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class ProcessMonitor {
-    public static final String SEP = File.pathSeparator;
-    public static final boolean WIN =
-            System.getProperty("os.name").toLowerCase().indexOf("windows") > -1;
-
-
-
-    public void log(String msg) {
-        System.out.println("" + msg);
-    }
-
-    public List<JavaProcess> getProcesses() {
-        return Collections.emptyList();
-    }
-
-    public List<JavaProcess> getProcesses(String mainClass, String systemPropertyKey) {
-        List<JavaProcess> result = new ArrayList<JavaProcess>();
-         for (JavaProcess info : getProcesses()) {
-            if (info.getMainClass().equals(mainClass)) {
-                if (info.getSystemProperties().containsKey(systemPropertyKey)) {
-                    result.add(info);
-                }
-            }
-        }
-        return result;
-    }
-
-    public int kill(String mainClass) {
-        for (JavaProcess info : getProcesses()) {
-            if (info.getMainClass().equals(mainClass)) {
-                log("Killing process matching class: " + mainClass);
-                return kill(info.getPid());
-            }
-        }
-        return -1;
-    }
-
-    public static int kill(int pid)  {
-        String cmd = WIN ? "TASKKILL /F /PID " + pid : "kill -SIGTERM " + pid;
-        try {
-            Process p = Runtime.getRuntime().exec(cmd);
-            p.waitFor();
-            return p.exitValue();
-        } catch (Exception e) {
-            e.printStackTrace();
-            return -1;
-        }
-    }
-
-    public static ProcessMonitor load() {
-        // load the providers dynamically to allow error handling
-        ProcessMonitor pm = load("org.opendaylight.controller.maven.plugin.util.VMProcessMonitor");
-        if (pm == null) {
-            pm = load("org.opendaylight.controller.maven.plugin.util.JpsProcessMonitor");
-        }
-        return (pm == null ? new ProcessMonitor() : pm);
-    }
-
-    private static ProcessMonitor load(String clz) {
-        try {
-            Class c = Class.forName(clz);
-            return (ProcessMonitor) c.newInstance();
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    // simple driver for basic manual testing
-    public static void main(String[] args) throws Exception {
-        ProcessMonitor pm = ProcessMonitor.load();
-        System.out.println("==== " + pm);
-        for (JavaProcess info : pm.getProcesses()) {
-            System.out.println(info.toString());
-        }
-        pm.kill("Foo");
-        System.out.println("==== controller processses ");
-        for (JavaProcess info : pm.getProcesses(
-                "org.eclipse.equinox.launcher.Main", "opendaylight.controller"))
-        {
-            System.out.println(info.toString());
-            pm.kill(info.getPid());
-        }
-    }
-
-}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/VMProcessMonitor.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/VMProcessMonitor.java
deleted file mode 100644 (file)
index fdf232a..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2013 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.maven.plugin.util;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import sun.jvmstat.monitor.HostIdentifier;
-import sun.jvmstat.monitor.MonitoredHost;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.MonitoredVmUtil;
-import sun.jvmstat.monitor.VmIdentifier;
-
-public class VMProcessMonitor extends ProcessMonitor {
-
-    @Override
-    public List<JavaProcess> getProcesses() {
-        Set<Integer> activeVmPids = null;
-        List<JavaProcess> result = new ArrayList<JavaProcess>();
-        MonitoredHost monitoredHost = null;
-        MonitoredVm mvm = null;
-        try {
-            monitoredHost = MonitoredHost.getMonitoredHost(
-                    new HostIdentifier((String) null));
-            activeVmPids = monitoredHost.activeVms();
-        } catch (Exception e) {
-            throw new IllegalStateException("Error accessing VM", e);
-        }
-        for (Integer vmPid : activeVmPids) {
-            try {
-                mvm = monitoredHost.getMonitoredVm(
-                        new VmIdentifier(vmPid.toString()));
-                JavaProcess proc = new JavaProcess(vmPid,
-                        MonitoredVmUtil.mainClass(mvm, true));
-                proc.setSystemProperties(MonitoredVmUtil.jvmArgs(mvm));
-                proc.setSystemProperties(MonitoredVmUtil.jvmFlags(mvm));
-                result.add(proc);
-            } catch(Exception e2) {
-                log("Error connecting to pid: " + vmPid + " reason:"
-                    + e2.getMessage());
-                e2.printStackTrace();
-            } finally {
-                if (mvm != null) {
-                    mvm.detach();
-                }
-            }
-        }
-        return result;
-    }
-
-
-}
index 07c89166f9c397b9289ae4b7658b0354b3eb6a7a..5183165752446b8e38507d7dd3cc239394051cdb 100644 (file)
@@ -70,8 +70,6 @@
     <jacoco.version>0.5.3.201107060350</jacoco.version>
     <enforcer.version>1.3.1</enforcer.version>
     <bundle.plugin.version>2.3.7</bundle.plugin.version>
-    <install.plugin.version>2.5</install.plugin.version>
-    <enforcer.plugin.version>1.3.1</enforcer.plugin.version>
     <junit.version>4.8.1</junit.version>
     <bgpcep.version>0.3.0-SNAPSHOT</bgpcep.version>
     <yangtools.version>0.5.9-SNAPSHOT</yangtools.version>
           <includeTestSourceDirectory>true</includeTestSourceDirectory>
           <sourceDirectory>${project.basedir}</sourceDirectory>
           <includes>**\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat</includes>
-          <excludes>**\/target\/,**\/bin\/</excludes>
+          <excludes>**\/target\/,**\/bin\/,**\/target-ide\/</excludes>
         </configuration>
       </plugin>
       <plugin>
index c312cc849351587096c871c5edefe9bd25954efd..c66b11256601125e4ef84980756780fc9bc20376 100644 (file)
             <artifactId>commons-lang3</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-type-provider</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
index 764ecd38868c7b224c1c8e0065d7989f8126fa37..c43fead0fcd0f5aa7e281768e2da0020bf149918 100644 (file)
@@ -64,4 +64,8 @@ public class TypeProviderWrapper {
     public String getJMXParamForBaseType(TypeDefinition<?> baseType) {
         return typeProvider.getConstructorPropertyName(baseType);
     }
+
+    public String getJMXParamForUnionInnerType(TypeDefinition<?> unionInnerType) {
+        return typeProvider.getParamNameFromType(unionInnerType);
+    }
 }
index 3e20e4a55ad47f58e538a33594d1f5d4f0e70d32..e01063ef92e86b217bc4c737eb89b0f7c17cf283 100644 (file)
@@ -7,20 +7,26 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.attribute;
 
+import com.google.common.base.Preconditions;
 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 
 import javax.management.openmbean.ArrayType;
 import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.OpenDataException;
 import javax.management.openmbean.OpenType;
 import javax.management.openmbean.SimpleType;
+import java.util.Arrays;
+import java.util.List;
 
 public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
 
+    public static final String DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION = "valueOfArtificialUnionProperty";
+
     private final Type type;
     private final String nullableDescription, nullableDefault, nullableDefaultWrappedForCode;
     private final TypeProviderWrapper typeProviderWrapper;
@@ -47,6 +53,11 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
         this.nullableDescription = leaf.getDescription();
     }
 
+    public boolean isUnion() {
+        TypeDefinition<?> base = getBaseType(typeProviderWrapper, typeDefinition);
+        return base instanceof UnionTypeDefinition;
+    }
+
     public TypeDefinition<?> getTypeDefinition() {
         return typeDefinition;
     }
@@ -132,13 +143,70 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
             return getArrayType();
         } else if (isEnum(baseType)) {
             return getSimpleType(baseType);
-        } else if (isDerivedType(baseType)) {
+        } else if (isUnion()) {
+            return getCompositeTypeForUnion(baseTypeDefinition);
+        } else if (isDerivedType(baseType, getType())) {
             return getCompositeType(baseType, baseTypeDefinition);
         }
 
         return getSimpleType(getType());
     }
 
+    private OpenType<?> getCompositeTypeForUnion(TypeDefinition<?> baseTypeDefinition) {
+        Preconditions.checkArgument(baseTypeDefinition instanceof UnionTypeDefinition,
+                "Expected %s instance but was %s", UnionTypeDefinition.class, baseTypeDefinition);
+
+        List<TypeDefinition<?>> types = ((UnionTypeDefinition) baseTypeDefinition).getTypes();
+
+        String[] itemNames = new String[types.size()+1];
+        OpenType<?>[] itemTypes = new OpenType[itemNames.length];
+
+        addArtificialPropertyToUnionCompositeType(baseTypeDefinition, itemNames, itemTypes);
+
+        String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
+
+        int i = 1;
+        for (TypeDefinition<?> innerTypeDefinition : types) {
+
+            Type innerType = typeProviderWrapper.getType(innerTypeDefinition, innerTypeDefinition);
+
+            TypeDefinition<?> baseInnerTypeDefinition = getBaseType(typeProviderWrapper, innerTypeDefinition);
+            Type innerTypeBaseType = typeProviderWrapper.getType(baseInnerTypeDefinition, baseInnerTypeDefinition);
+
+            OpenType<?> innerCompositeType;
+
+            if(isDerivedType(innerTypeBaseType, innerType)) {
+                innerCompositeType = getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
+            } else {
+                innerCompositeType = SimpleTypeResolver.getSimpleType(innerType);
+            }
+
+            itemNames[i] = typeProviderWrapper.getJMXParamForUnionInnerType(innerTypeDefinition);
+            itemTypes[i++] = innerCompositeType;
+        }
+
+        String[] descriptions = Arrays.copyOf(itemNames, itemNames.length);
+        descriptions[0] = DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
+
+        try {
+            return new CompositeType(getUpperCaseCammelCase(), description, itemNames, descriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new RuntimeException("Unable to create " + CompositeType.class + " with inner elements "
+                    + Arrays.toString(itemTypes), e);
+        }
+    }
+
+    public static final Class<Character> TYPE_OF_ARTIFICIAL_UNION_PROPERTY = char.class;
+
+    private void addArtificialPropertyToUnionCompositeType(TypeDefinition<?> baseTypeDefinition, String[] itemNames, OpenType<?>[] itemTypes) {
+        String artificialPropertyName = typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
+        itemNames[0] = artificialPropertyName;
+
+        OpenType<?> artificialPropertyType = getArrayOpenTypeForSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName(),
+                SimpleTypeResolver.getSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName()));
+        itemTypes[0] = artificialPropertyType;
+    }
+
     private boolean isEnum(Type baseType) {
         return baseType.getFullyQualifiedName().equals(Enum.class.getName());
     }
@@ -163,12 +231,15 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
             throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
                     + itemTypes, e);
         }
-
     }
 
     private OpenType<?> getArrayType() {
         String innerTypeFullyQName = getInnerType(getType());
         SimpleType<?> innerSimpleType = SimpleTypeResolver.getSimpleType(innerTypeFullyQName);
+        return getArrayOpenTypeForSimpleType(innerTypeFullyQName, innerSimpleType);
+    }
+
+    private OpenType<?> getArrayOpenTypeForSimpleType(String innerTypeFullyQName, SimpleType<?> innerSimpleType) {
         try {
             ArrayType<Object> arrayType = isPrimitive(innerTypeFullyQName) ? new ArrayType<>(innerSimpleType, true)
                     : new ArrayType<>(1, innerSimpleType);
@@ -191,8 +262,8 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
         return type.getName().endsWith("[]");
     }
 
-    private boolean isDerivedType(Type baseType) {
-        return  baseType.equals(getType()) == false;
+    private boolean isDerivedType(Type baseType, Type currentType) {
+        return  baseType.equals(currentType) == false;
     }
 
     private static String getInnerType(Type type) {
index 87b55f3756a0e042c98c89739d91bf0f92ab5285..f4bd979faca43fa5f4bdce943ceeb389ca07b42b 100644 (file)
@@ -59,6 +59,8 @@ public class SimpleTypeResolver {
         JAVA_TYPE_TO_SIMPLE_TYPE.put(Date.class.getName(), SimpleType.DATE);
         JAVA_TYPE_TO_SIMPLE_TYPE.put(Double.class.getName(), SimpleType.DOUBLE);
         JAVA_TYPE_TO_SIMPLE_TYPE.put(double.class.getName(), SimpleType.DOUBLE);
+
+        JAVA_TYPE_TO_SIMPLE_TYPE.put(char.class.getName(), SimpleType.CHARACTER);
     }
 
 }
diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/config/test/types/rev131127/UnionTestBuilder.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/config/test/types/rev131127/UnionTestBuilder.java
new file mode 100644 (file)
index 0000000..c49319b
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127;
+
+
+/**
+**/
+public class UnionTestBuilder {
+
+    public static UnionTest getDefaultInstance(String defaultValue) {
+        try {
+            int i = Integer.valueOf(defaultValue);
+            return new UnionTest(new ExtendTwice(i));
+        } catch (NumberFormatException e) {
+            return new UnionTest(defaultValue);
+        }
+    }
+
+}
index 9ad7a44915b15bdfbce7a64cbdaf2eb02f8bba14..f7cea0a52abbb0b46edb5b431d140dc4482fe76d 100644 (file)
@@ -61,10 +61,6 @@ module config-test-impl {
                     default 127.0.0.1;
                 }
 
-                leaf ip {
-                    type inet:ip-address;
-                    // TODO defaults for union default 0:0:0:0:0:0:0:1;
-                }
             }
 
             leaf as-number {
@@ -136,6 +132,16 @@ module config-test-impl {
                 default ONE;
             }
 
+            leaf ip {
+                type inet:ip-address;
+                default 0:0:0:0:0:0:0:1;
+            }
+
+            leaf union-test-attr {
+                type tt:unionTest;
+                default 456;
+            }
+
             leaf sleep-factor {
                 type decimal64 {
                     fraction-digits 2;
index 84fbcb089d6390ba4478c24a0503442ad0bfd8d1..8c086d8aceb1d5ec21c06f398e57fcd46d8bda62 100644 (file)
@@ -23,4 +23,12 @@ module test-types {
         }
     }
 
+      typedef unionTest {
+        type union {
+          type string;
+          type uint32;
+          type extend-twice;
+        }
+      }
+
 }
index b7a4638c604874b86561f9440382f0ecf3a23d00..e519a04a57ccebfa3ee935c8c549a2f7a96491d7 100644 (file)
       </dependencies>
     </profile>
     <profile>
-      <!-- sanitytests are only enabled with this profile -->
       <id>integrationtests</id>
       <activation>
         <activeByDefault>false</activeByDefault>
         <plugins>
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-invoker-plugin</artifactId>
-            <version>1.5</version>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <version>2.8</version>
+            <executions>
+              <execution>
+                <id>copy</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+              </execution>
+            </executions>
             <configuration>
-              <debug>false</debug>
-              <projectsDirectory>../sanitytest</projectsDirectory>
-              <pomIncludes>
-                <pomInclude>pom.xml</pomInclude>
-              </pomIncludes>
-              <streamLogs>true</streamLogs>
-              <noLog>true</noLog>
-              <goals>
-                <goal>clean</goal>
-                <goal>verify</goal>
-              </goals>
-              </configuration>
-              <executions>
-                <execution>
-                  <id>integration-test</id>
-                    <goals>
-                      <goal>install</goal>
-                      <goal>run</goal>
-                    </goals>
-                </execution>
-              </executions>
-           </plugin>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.opendaylight.controller</groupId>
+                  <artifactId>sanitytest</artifactId>
+                  <version>${controller.version}</version>
+                  <type>jar</type>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </plugin>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>exec-maven-plugin</artifactId>
+            <version>1.2.1</version>
+            <executions>
+              <execution>
+                <id>sanity-test</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>exec</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <executable>${java.home}/bin/java</executable>
+              <arguments>
+                <argument>-cp</argument>
+                <argument>./target/dependency/*</argument>
+                <argument>org.opendaylight.controller.distribution.Sanity</argument>
+              </arguments>
+              <environmentVariables>
+                <JAVA_HOME>
+                  ${java.home}
+                </JAVA_HOME>
+              </environmentVariables>
+            </configuration>
+          </plugin>
         </plugins>
       </build>
-
-      <dependencies>
-        <dependency>
-         <groupId>org.opendaylight.controller</groupId>
-         <artifactId>controller-maven-plugin</artifactId>
-         <version>0.1.0-SNAPSHOT</version>
-        </dependency>
-      </dependencies>
     </profile>
   </profiles>
 
      <version>${commons.httpclient.version}</version>
     </dependency>
 
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sanitytest</artifactId>
+      <version>${controller.version}</version>
+    </dependency>
+
+
   </dependencies>
 
 
           </execution>
         </executions>
       </plugin>
-
     </plugins>
   </build>
-
 </project>
diff --git a/opendaylight/distribution/opendaylight/runsanity.bat b/opendaylight/distribution/opendaylight/runsanity.bat
new file mode 100644 (file)
index 0000000..f219828
--- /dev/null
@@ -0,0 +1,23 @@
+rem Inject the sanitytest jar as a controller plugin
+copy .\target\dependency\sanitytest*.jar .\target\distribution.opendaylight-osgipackage\opendaylight\plugins
+
+rem Store the current working directory in a variable so that we can get back to it later
+set cwd=%cd%
+
+rem Switch to the distribution folder
+cd .\target\distribution.opendaylight-osgipackage\opendaylight
+
+rem Run the controller
+cmd.exe /c run.bat
+
+rem Store the exit value of the controller in a variable
+set success=%ERRORLEVEL%
+
+rem Switch back to the directory from which this script was invoked
+cd %cwd%
+
+rem Remove the sanitytest jar from the plugins directory
+del .\target\distribution.opendaylight-osgipackage\opendaylight\plugins\sanitytest*.jar
+
+rem Exit using the exit code that we had captured earlier after running the controller
+exit /b %SUCCESS%
\ No newline at end of file
diff --git a/opendaylight/distribution/opendaylight/runsanity.sh b/opendaylight/distribution/opendaylight/runsanity.sh
new file mode 100755 (executable)
index 0000000..4ee9555
--- /dev/null
@@ -0,0 +1,24 @@
+# Inject the sanitytest jar as a controller plugin
+cp ./target/dependency/sanitytest*.jar ./target/distribution.opendaylight-osgipackage/opendaylight/plugins
+
+# Store the current working directory in a variable so that we can get back to it later
+cwd=`pwd`
+
+# Switch to the distribution folder
+cd ./target/distribution.opendaylight-osgipackage/opendaylight/
+
+# Run the controller
+./run.sh
+
+# Store the exit value of the controller in a variable
+success=`echo $?`
+
+# Switch back to the directory from which this script was invoked
+cd $cwd
+
+# Remove the sanitytest jar from the plugins directory
+rm ./target/distribution.opendaylight-osgipackage/opendaylight/plugins/sanitytest*.jar
+
+# Exit using the exit code that we had captured earlier after running the controller
+exit $success
+
index 1e8f34e5b772cd845d3361fffdf71432a2c00958..8fea1756148cee4774de9a3586c7ea1056821e81 100644 (file)
@@ -27,6 +27,7 @@
         <exclude>com.sun.jersey:jersey-json</exclude>
         <exclude>com.sun.jersey:jersey-server</exclude>
         <exclude>org.opendaylight.controller:logging.bridge</exclude>
+        <exclude>org.opendaylight.controller:sanitytest</exclude>
       </excludes>
       <outputFileNameMapping>
         ${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}
index a8e33d26328876334205d0c7f8f679024eca6332..9d6ac8d1deaecdee57ef842335389edb9931e1d3 100644 (file)
@@ -140,7 +140,7 @@ SET RUN_CMD="%JAVA_HOME%\bin\java.exe" -Dopendaylight.controller %extraJVMOpts%
 ECHO %RUN_CMD%
 
 if "%startEnabled%" NEQ "" (
-    START /B cmd /C CALL %RUN_CMD%
+    START /B cmd /C CALL %RUN_CMD% > %basedir%\logs\controller.out 2>&1
     ECHO Running controller in the background.
 ) else (
     %RUN_CMD%
index ce710d120e998b81cf3af602a434f4be5dc3f237..9d5ba5cc9596ee6b9986f905b1064bc9542f0f00 100644 (file)
 
   <artifactId>sanitytest</artifactId>
   <version>0.4.1-SNAPSHOT</version>
-  <packaging>jar</packaging>
-
-  <properties>
-    <distro.dir>${project.basedir}/../opendaylight/target/distribution.opendaylight-osgipackage/opendaylight</distro.dir>
-    <distro.script>${distro.dir}/run.bat</distro.script>
-    <!-- the address is passed to both the controller & the test to establish the connection -->
-    <sanitytest.bind.address>127.0.0.1</sanitytest.bind.address>
-    <sanitytest.timeout>300</sanitytest.timeout>
-  </properties>
-
-  <profiles>
-    <profile>
-      <id>non-windows</id>
-      <activation>
-        <os>
-          <family>!windows</family>
-        </os>
-      </activation>
-      <properties>
-        <distro.script>${distro.dir}/run.sh</distro.script>
-        <distro.pid>/tmp/opendaylight.PID</distro.pid>
-      </properties>
-    </profile>
-  </profiles>
-
+  <packaging>bundle</packaging>
   <dependencies>
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
       <scope>provided</scope>
     </dependency>
-
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.ow2.chameleon.management</groupId>
-      <artifactId>chameleon-mbeans</artifactId>
-      <scope>test</scope>
-    </dependency>
-
   </dependencies>
-
   <build>
     <plugins>
       <plugin>
-        <!-- disable the install plugin -->
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-install-plugin</artifactId>
-        <version>${install.plugin.version}</version>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>${bundle.plugin.version}</version>
+        <extensions>true</extensions>
         <configuration>
-          <skip>true</skip>
+          <instructions>
+            <Export-Package>
+              org.opendaylight.controller.sanitytest
+            </Export-Package>
+            <Import-Package>
+              javax.xml.bind.annotation,
+              org.osgi.service.component,
+              org.slf4j,
+              org.eclipse.osgi.framework.console,
+              org.osgi.framework,
+              org.eclipse.osgi.baseadaptor,
+              org.eclipse.osgi.framework.adaptor,
+              org.osgi.framework.wiring
+            </Import-Package>
+            <Bundle-Activator>
+              org.opendaylight.controller.sanitytest.internal.Activator
+            </Bundle-Activator>
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
         </configuration>
-        <executions>
-          <execution>
-            <id>default-install</id>
-            <phase>none</phase>
-          </execution>
-        </executions>
       </plugin>
-
-      <plugin>
-        <!--  ensure that the distro installation is already built -->
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-enforcer-plugin</artifactId>
-        <version>${enforcer.plugin.version}</version>
-        <executions>
-          <execution>
-            <id>enforce-files-exist</id>
-            <phase>pre-integration-test</phase>
-            <goals>
-              <goal>enforce</goal>
-            </goals>
-            <configuration>
-              <rules>
-                <requireFilesExist>
-                  <files>
-                    <file>${distro.script}</file>
-                  </files>
-                </requireFilesExist>
-              </rules>
-              <fail>true</fail>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-
-      <plugin>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>controller-maven-plugin</artifactId>
-        <version>0.1.0-SNAPSHOT</version>
-          <configuration>
-              <controllerHome>${distro.dir}</controllerHome>
-              <controllerHost>localhost</controllerHost>
-              <controllerWebPort>8080</controllerWebPort>
-              <controllerUsername>admin</controllerUsername>
-              <controllerPassword>admin</controllerPassword>
-              <controllerStartScriptName>${distro.script}</controllerStartScriptName>
-              <pidFile>${distro.pid}</pidFile>
-          </configuration>
-        <executions>
-          <execution>
-            <!-- ensure controller is started in pre-integration phase -->
-            <id>start-controller</id>
-            <phase>pre-integration-test</phase>
-            <configuration>
-              <startArgs>
-                <param>-start</param>
-                <param>-jmx</param>
-                <param>-Djava.rmi.server.hostname=${sanitytest.bind.address} </param>
-              </startArgs>
-              <warmupTimeSecs> 60 </warmupTimeSecs>
-            </configuration>
-            <goals>
-              <goal>run</goal>
-            </goals>
-          </execution>
-          <execution>
-            <!-- ensure controller is stopped in post-integration phase -->
-            <id>stop-controller</id>
-            <phase>post-integration-test</phase>
-            <goals>
-              <goal>stop</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-
-      <plugin>
-        <!--  run the test -->
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-failsafe-plugin</artifactId>
-        <version>${failsafe.version}</version>
-        <configuration>
-          <systemPropertyVariables>
-            <ctrl.home>${distro.dir}</ctrl.home>
-            <ctrl.host>${sanitytest.bind.address}</ctrl.host>
-            <ctrl.start.timeout>${sanitytest.timeout}</ctrl.start.timeout>
-          </systemPropertyVariables>
-        </configuration>
-      </plugin>
-
     </plugins>
-
-
   </build>
 </project>
diff --git a/opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/distribution/Sanity.java b/opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/distribution/Sanity.java
new file mode 100644 (file)
index 0000000..7fc25e2
--- /dev/null
@@ -0,0 +1,48 @@
+package org.opendaylight.controller.distribution;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Sanity {
+
+    static void copy(InputStream in, OutputStream out) throws IOException {
+      while (true) {
+        int c = in.read();
+        if (c == -1) break;
+        out.write((char)c);
+      }
+    }
+
+    public static void main(String[] args) throws IOException, InterruptedException {
+        String cwd = System.getProperty("user.dir");
+
+        System.out.println("Current working directory = " + cwd);
+
+        String os = System.getProperty("os.name").toLowerCase();
+        List<String> script = new ArrayList<String>();
+
+        if(os.contains("windows")){
+            script.add("cmd.exe");
+            script.add("/c");
+            script.add("runsanity.bat");
+        } else {
+            script.add("./runsanity.sh");
+        }
+
+        ProcessBuilder processBuilder = new ProcessBuilder();
+        processBuilder.inheritIO().command(script);
+        Process p = processBuilder.start();
+
+        copy(p.getInputStream(), System.out);
+
+        p.waitFor();
+
+        System.out.println("Test exited with exitValue = " + p.exitValue());
+
+        System.exit(p.exitValue());
+    }
+}
diff --git a/opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/sanitytest/internal/Activator.java b/opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/sanitytest/internal/Activator.java
new file mode 100644 (file)
index 0000000..08f0700
--- /dev/null
@@ -0,0 +1,101 @@
+package org.opendaylight.controller.sanitytest.internal;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class Activator implements BundleActivator {
+    //10 Second initial, 1 second subsequent
+    private static final int INITIAL_DELAY = 10000;
+    private static final int SUBSEQUENT_DELAY = 1000;
+    private static final int MAX_ATTEMPTS = 120;
+
+
+    private String stateToString(int state) {
+        switch (state) {
+        case Bundle.ACTIVE:
+            return "ACTIVE";
+        case Bundle.INSTALLED:
+            return "INSTALLED";
+        case Bundle.RESOLVED:
+            return "RESOLVED";
+        case Bundle.UNINSTALLED:
+            return "UNINSTALLED";
+        case Bundle.STARTING:
+            return "STARTING";
+        default:
+            return "Not CONVERTED: state value is " + state;
+        }
+    }
+
+    public void start(final BundleContext bundleContext) throws Exception {
+        Timer monitorTimer = new Timer("monitor timer", true);
+        monitorTimer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                int countup = 0;
+                boolean failed = false;
+                boolean resolved = false;
+                while (!resolved) {
+                    resolved = true;
+                    failed = false;
+                    for(Bundle bundle : bundleContext.getBundles()){
+                        /*
+                         * A bundle should be ACTIVE, unless it a fragment, in which case it should be RESOLVED
+                         */
+                        int state = bundle.getState();
+                        if ((bundle.adapt(BundleRevision.class).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+                            //fragment
+                            if (state != Bundle.RESOLVED) {
+                                System.out.println("------ Failed to activate/resolve fragment = " + bundle.getSymbolicName() + " state = " + stateToString(bundle.getState()));
+                                failed = true;
+                                if (state == Bundle.STARTING)
+                                    resolved = false;
+                            }
+                        } else {
+                            if(state != Bundle.ACTIVE) {
+                                System.out.println("------ Failed to activate/resolve bundle = " + bundle.getSymbolicName() + " state = " + stateToString(bundle.getState()));
+                                failed = true;
+                                if (state == Bundle.STARTING)
+                                    resolved = false;
+                            }
+                        }
+                    }
+                    if (!resolved) {
+                        countup++;
+                        if (countup < MAX_ATTEMPTS) {
+                            System.out.println("all bundles haven't finished starting, will repeat");
+                            try {
+                                Thread.sleep(SUBSEQUENT_DELAY);
+                            } catch (Exception e) {
+                                System.out.println("Thread.sleep interuptted.");
+                                break;
+                            }
+                        } else
+                            resolved = true;
+                    }
+                }
+
+                if(failed){
+                    System.out.flush();
+                    System.out.println("exiting with 1 as failed");
+                    System.out.close();
+                    Runtime.getRuntime().exit(1);
+                } else {
+                    System.out.flush();
+                    System.out.println("exiting with 0 as succeeded");
+                    System.out.close();
+                    Runtime.getRuntime().exit(0);
+                }
+            }
+        }, INITIAL_DELAY);
+    }
+
+    public void stop(BundleContext bundleContext) throws Exception {
+
+    }
+}
diff --git a/opendaylight/distribution/sanitytest/src/test/java/org/opendaylight/controller/distribution/test/SanityIT.java b/opendaylight/distribution/sanitytest/src/test/java/org/opendaylight/controller/distribution/test/SanityIT.java
deleted file mode 100644 (file)
index 931e88f..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2013 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.distribution.test;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.Socket;
-import java.net.URL;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-import java.util.jar.Attributes;
-import java.util.jar.JarFile;
-
-import javax.management.JMX;
-import javax.management.MBeanServerConnection;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.ow2.chameleon.management.beans.BundleMXBean;
-import org.ow2.chameleon.management.beans.OSGiPlatformMXBean;
-
-/**
- * This integration test assumes a running local controller. The test does the
- * following:
- * 1) Wait for HTTP, JMX and OF ports to open
- * 2) Establishes a JMX connection and registers a bundle notification listener
- * 3) Waits till all bundles reach expected states or the timeout period elapses
- */
-public class SanityIT {
-  private static final int OF_PORT = Integer.getInteger("ctrl.of.port", 6633);
-  private static final int HTTP_PORT = Integer.getInteger("ctrl.http.port", 8080);
-  private static final int JMX_PORT = Integer.getInteger("ctrl.jmx.port", 1088);
-  private static final int RMI_PORT = Integer.getInteger("ctrl.rmi.port", 1099);
-  private static final String CTRL_HOST = System.getProperty("ctrl.host", "127.0.0.1");
-  private static final String CTRL_HOME = System.getProperty("ctrl.home");
-  private static final long TIMEOUT_MILLIS =
-          Integer.getInteger("ctrl.start.timeout", 3*60) * 1000L;
-  private static final String JMX_URL =
-          "service:jmx:rmi:///jndi/rmi://" + CTRL_HOST + ":" + JMX_PORT + "/jmxrmi";
-
-  private static final Set<String> bundles =
-          Collections.synchronizedSet(new HashSet<String>());
-  private static final Set<String> fragments =
-          Collections.synchronizedSet(new HashSet<String>());
-
-  @BeforeClass
-  public static void loadBundles() throws IOException {
-      log("         ctrl.home: " + CTRL_HOME);
-      log("         ctrl.host: " + CTRL_HOST);
-      log("ctrl.start.timeout: " + TIMEOUT_MILLIS);
-      log("           jmx.url: " + JMX_URL);
-
-      Assert.assertNotNull(CTRL_HOME);
-      File ctrlHome = new File(CTRL_HOME);
-      Assert.assertTrue(ctrlHome.exists() && ctrlHome.isDirectory());
-      File configDir = new File(ctrlHome, "configuration");
-      Assert.assertTrue(configDir.exists() && configDir.isDirectory());
-      File configIni = new File(configDir, "config.ini");
-      Assert.assertTrue(configIni.exists());
-      Properties config = new Properties();
-      config.load(new FileInputStream(configIni));
-      processBundles(configDir, config.getProperty("osgi.bundles"));
-      processBundles(new File(ctrlHome, "plugins"));
-      log("Bundles found in installation:   " + bundles.size());
-      log("Fragments found in installation: " + fragments.size());
-  }
-
-@Test
-  public void sanityTest() throws Exception {
-    // wait for http, jmx & of ports to open
-    long startTime = System.currentTimeMillis();
-    waitForListening(OF_PORT, false, startTime);
-    waitForListening(JMX_PORT, false, startTime);
-    waitForListening(HTTP_PORT, false, startTime);
-
-    // open jmx connection
-    JMXServiceURL serviceUrl = new JMXServiceURL(JMX_URL);
-    JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceUrl, null);
-    final MBeanServerConnection conn = jmxConnector.getMBeanServerConnection();
-
-    ObjectName fmkName = new ObjectName("org.ow2.chameleon:type=framework");
-    OSGiPlatformMXBean fmkBean= JMX.newMBeanProxy(conn, fmkName,
-              OSGiPlatformMXBean.class, true);
-    conn.addNotificationListener(fmkName, new NotificationListener() {
-
-        @Override
-        public void handleNotification(Notification n, Object handback) {
-            try {
-                //log("Notification: source: " + n.getSource());
-                ObjectName bundleName = new ObjectName(
-                        "org.ow2.chameleon:type=bundle,id=" + n.getUserData());
-                BundleMXBean bundleBean = JMX.newMXBeanProxy(conn,
-                        bundleName, BundleMXBean.class, true);
-                log("Bundle state change: " + bundleBean.getSymbolicName() +
-                        " : " + stateToString(bundleBean.getState()));
-                handleBundleEvent(bundleBean);
-                // if its a system bundle, notify the main thread
-                if (bundleBean.getBundleId() == 0 &&
-                        bundleBean.getState() == Bundle.ACTIVE)
-                {
-                    synchronized(SanityIT.this) {
-                        SanityIT.this.notify();
-                    }
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-    }, null, null);
-
-    if (checkAllBundles(conn) > 0) {
-        log("Waiting for system bundle to start... (times out in: " + TIMEOUT_MILLIS + "ms)");
-        long timeElapsed = System.currentTimeMillis() - startTime;
-        synchronized(this) {
-            this.wait(TIMEOUT_MILLIS - timeElapsed);
-        }
-        log("System bundle started. Revalidating bundle states for all bundles...");
-
-        // Sometimes, the system bundle starts earlier than other bundles(?). The
-        // following loop will cover that case.
-        do {
-            Thread.sleep(2000); // 2s seems appropriate given the default timeout
-            if (checkAllBundles(conn) == 0) {
-                break;
-            }
-        } while(System.currentTimeMillis() - startTime < TIMEOUT_MILLIS);
-    }
-    try {
-        jmxConnector.close();
-    } catch (Exception ignore) {
-        // dont want the tests to fail in case we can't close jmx connection
-        ignore.printStackTrace();
-    }
-    if (bundles.size() + fragments.size() == 0) {
-        log("All bundles have reached expected state");
-    } else {
-        log("The following bundles did not reach expected state: ");
-        for (String s : bundles) log("Bundle: " + s);
-        for (String s : fragments) log("Fragment: " + s);
-
-    }
-    Assert.assertTrue(bundles.size() == 0 && fragments.size() == 0);
-  }
-
-  private static int checkAllBundles(MBeanServerConnection conn) throws Exception {
-      ObjectName allBundlesName = new ObjectName("org.ow2.chameleon:*");
-      Set<ObjectName> bundleNames = conn.queryNames(allBundlesName, null);
-      for (ObjectName bundleName : bundleNames) {
-          if ("bundle".equals(bundleName.getKeyProperty("type"))) {
-              BundleMXBean bundleBean = JMX.newMBeanProxy(conn, bundleName,
-                      BundleMXBean.class, true);
-              handleBundleEvent(bundleBean);
-          }
-      }
-      int remaining = bundles.size() + fragments.size();
-      if (remaining > 0) {
-        log("Bundles not in expected states: " + remaining + " Waiting...");
-      }
-      return remaining;
-  }
-
-  private synchronized static void handleBundleEvent(BundleMXBean bundleBean) {
-      String name = bundleBean.getSymbolicName();
-      int state = bundleBean.getState();
-      // BUG in BundleMXBeanImpl - can't get bundle headers :(
-      // String fragHost = bundleBean.getBundleHeaders().get(Constants.FRAGMENT_HOST);
-      if (bundles.contains(name) && (state == Bundle.RESOLVED || state == Bundle.ACTIVE)) {
-          bundles.remove(name);
-      } else if (fragments.contains(name) && state == Bundle.RESOLVED) {
-          fragments.remove(name);
-      }
-      //log("Bundles to be started: " + bundles.size());
-  }
-
-
-  //    reference\:file\:../lib/org.apache.felix.fileinstall-3.1.6.jar@1:start,\
-  private static void processBundles(File dir, String property) {
-      Assert.assertTrue(property == null || property.length() > 0);
-      for(String s : property.split(",")) {
-          int idx = s.indexOf("@");
-          s = s.substring(15, (idx == -1 ? s.length() : idx));
-          if (!s.endsWith(".jar")) s = s + ".jar";
-          processJar(new File(dir, s));
-      }
-  }
-
-  public static void processBundles(File dir) throws IOException {
-      if (!dir.exists()) throw new FileNotFoundException("Cannot find dir:" + dir);
-      dir.listFiles(new FileFilter() {
-
-        @Override
-        public boolean accept(File file) {
-            //p("---- " + file);
-            if (file.getName().endsWith(".jar")) {
-                return processJar(file);
-            }
-            return false;
-        }
-      });
-  }
-
-  public static boolean processJar(File file) {
-      try {
-          //log("----" + file);
-          JarFile jar = new JarFile(file, false);
-          Attributes jarAttributes = jar.getManifest().getMainAttributes();
-          String bundleName = jarAttributes.getValue(Constants.BUNDLE_SYMBOLICNAME);
-          String fragHost = jarAttributes.getValue(Constants.FRAGMENT_HOST);
-          if (bundleName == null) {
-              log("Found a non bundle file:" + file);
-              return false;
-          } else {
-              int idx = bundleName.indexOf(';');
-              if (idx > -1) {
-                  bundleName = bundleName.substring(0, idx);
-              }
-          }
-
-          if (fragHost == null) {
-              if (!bundles.add(bundleName)) {
-                  throw new IllegalStateException(
-                          "Found duplicate bundles with same symbolic name: "
-                                  + bundleName);
-              }
-          } else {
-              // fragments attaching to framework can't be detected
-              if (fragHost.contains("extension:=\"framework\"")) return false;
-              if (!fragments.add(bundleName)) {
-                  throw new IllegalStateException(
-                          "Found duplicate fragments with same symbolic name: "
-                                  + bundleName);
-              }
-          }
-      } catch (IOException e) {
-          throw new IllegalStateException("Error processing jar: " + file , e);
-      }
-      return true;
-  }
-
-    public static long waitForListening(int port, boolean isHTTP, long beginTime)
-            throws InterruptedException {
-        long timeElapsedMillis = System.currentTimeMillis() - beginTime;
-        long sleepTimeMillis = 500L; // 0.5 secs
-
-        while (timeElapsedMillis < TIMEOUT_MILLIS) {
-            long timeRemaining = TIMEOUT_MILLIS - timeElapsedMillis;
-            sleepTimeMillis *= 2; // exponential backoff
-            long toSleep = (sleepTimeMillis > timeRemaining)
-                    ? timeRemaining : sleepTimeMillis;
-            Thread.sleep(toSleep);
-            timeElapsedMillis = System.currentTimeMillis() - beginTime;
-            if (isHTTP ? connectHTTP(port) : connectTCP(port)) {
-              log("Port is open: " + port);
-              return timeElapsedMillis;
-            }
-        }
-        throw new IllegalStateException("Timeout waiting for port: " + port);
-    }
-
-    private static void log(String msg) {
-        System.out.format("[SanityIT] [%s] %s %s", new Date().toString(), msg,
-                System.lineSeparator());
-    }
-
-    public static boolean connectTCP(int port) {
-      String host = CTRL_HOST.length() == 0 ? null : CTRL_HOST;
-      try {
-        Socket sock = new Socket(host, port);
-        sock.getPort();
-        try {
-          sock.close();
-        } catch (IOException ignore) {
-          // Can't close socket. Ingore and let downstream validate health
-        }
-        return true;
-      } catch (IOException ioe) {
-        return false;
-      }
-    }
-
-    public static boolean connectHTTP(int port) {
-        String host = CTRL_HOST.length() == 0 ? "localhost" : CTRL_HOST;
-        try {
-            URL url = new URL("http", host, port, "/");
-            HttpURLConnection con;
-            con = (HttpURLConnection) url.openConnection();
-            return (con.getResponseCode() > 0);
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    private String stateToString(int state) {
-        switch (state) {
-            case Bundle.ACTIVE: return "ACTIVE";
-            case Bundle.INSTALLED: return "INSTALLED";
-            case Bundle.RESOLVED: return "RESOLVED";
-            case Bundle.UNINSTALLED: return "UNINSTALLED";
-            case Bundle.STARTING: return "STARTING";
-            case Bundle.STOPPING: return "STOPPING";
-            default: return "UNKNOWN: " + state;
-        }
-    }
-
-
-
-
-}
index f5c5620d7cccf3e023211d64629b1f77a55470c7..09585d6273a0c2cecd32e90d4f442313bf685946 100644 (file)
@@ -21,12 +21,22 @@ import org.opendaylight.controller.sal.reader.NodeDescription;
 import org.opendaylight.controller.sal.reader.NodeTableStatistics;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllNodeConnectorStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllNodeConnectorStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllNodeConnectorStatisticsOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsOutputBuilder;
@@ -292,4 +302,39 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService,
         return builder.build();
     }
 
+    @Override
+    public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> getAggregateFlowStatisticsFromFlowTableForAllFlows(
+            GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> getAggregateFlowStatisticsFromFlowTableForGivenMatch(
+            GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<GetAllFlowStatisticsFromFlowTableOutput>> getAllFlowStatisticsFromFlowTable(
+            GetAllFlowStatisticsFromFlowTableInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> getAllFlowsStatisticsFromAllFlowTables(
+            GetAllFlowsStatisticsFromAllFlowTablesInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<GetFlowStatisticsFromFlowTableOutput>> getFlowStatisticsFromFlowTable(
+            GetFlowStatisticsFromFlowTableInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
 }
index e83306db50db1155ab1d9fb7147fd71e2329cfff..2bcd40522330901eaaf08824d68680cfdb48d381 100644 (file)
@@ -12,6 +12,41 @@ module opendaylight-flow-types {
         description "Initial revision of flow service";
     }
     
+    typedef output-port-values {
+        type enumeration {
+            enum MAX {
+                value 1;
+            }
+            enum IN_PORT {
+                value 2;
+            }
+            enum TABLE {
+                value 3;
+            }
+            enum NORMAL {
+                value 4;
+            }
+            enum FLOOD {
+                value 5;
+            }
+            enum ALL {
+                value 6;
+            }
+            enum CONTROLLER {
+                value 7;
+            }
+            enum LOCAL {
+                value 8;
+            }
+            enum ANY {
+                value 9;
+            }
+            enum NONE {
+                value 10;
+            }
+
+        }
+    }
     grouping instruction-list {
         list instruction {
             key "order";
@@ -227,4 +262,4 @@ module opendaylight-flow-types {
             uses match:match;
         }
     }
-}
\ No newline at end of file
+}
index 3774f950fc63aa139b35749cfaf9e2c4ffad0af4..5e747e47221ae7557f98b9a22ec9a5caf9fbccc9 100644 (file)
@@ -11,6 +11,10 @@ module opendaylight-table-types {
         description "Initial revision of table service";
     }
 
+    typedef table-id {
+       type uint8;
+    }
+
     typedef table-ref {
         type instance-identifier;
     }
index d717e87f761ea5b8c0897d6b4fc87d4fedf89581..e55c50fb29612f2511adef62063a25b0468575cd 100644 (file)
@@ -15,7 +15,60 @@ module flow-node-inventory {
     revision "2013-08-19" {
         description "Flow Capable Node extensions to the Inventory model";
     }
-
+    
+    identity feature-capability {
+    }
+    
+    identity flow-feature-capability-flow-stats {
+        description "Flow statistics"; 
+        base feature-capability;      
+    }
+    
+    identity flow-feature-capability-table-stats {
+        description "Table statistics";
+        base feature-capability;        
+    }
+    
+    identity flow-feature-capability-port-stats {
+        description "Port statistics";
+        base feature-capability;        
+    }
+    
+    identity flow-feature-capability-stp {
+        description "802.1d spanning tree";
+        base feature-capability;        
+    }
+    
+    identity flow-feature-capability-reserved {
+        description "Reserved, must be zero";
+        base feature-capability;        
+    }
+    
+    identity flow-feature-capability-ip-reasm {
+        description "Can reassemble IP fragments";
+        base feature-capability;        
+    }
+    
+    identity flow-feature-capability-queue-stats {
+        description "Queue statistics";
+        base feature-capability;        
+    }
+    
+    identity flow-feature-capability-arp-match-ip {
+        description "Match IP addresses in ARP pkts";
+        base feature-capability;        
+    }
+    
+    identity flow-feature-capability-group-stats {
+        description "Group statistics";
+        base feature-capability;        
+    }
+    
+    identity flow-feature-capability-port-blocked {
+        description "Switch will block looping ports";
+        base feature-capability;        
+    }
+    
     grouping feature {
         leaf support-state {
             type inv:support-type;
@@ -70,7 +123,8 @@ module flow-node-inventory {
             uses meter:meter;
         }
     }
-
+    
+    
     grouping flow-node {
 
         leaf manufacturer {
@@ -122,6 +176,24 @@ module flow-node-inventory {
                 }
             }
         }
+        
+        container switch-features {
+            
+            leaf max_buffers {
+                type uint32;
+            }
+            
+            leaf max_tables {
+                type uint8;
+            }
+            
+            leaf-list capabilities {
+                type identityref {
+                    base feature-capability;
+                }
+            }
+            
+        }
     }
     
     grouping flow-node-connector {
@@ -149,9 +221,10 @@ module flow-node-inventory {
         ext:augment-identifier "flow-capable-node-connector-update-fields";
         uses flow-node-connector;
     }
-
+    
     augment "/inv:node-connector-updated" {
         ext:augment-identifier "flow-capable-node-connector-updated";
         uses flow-node-connector;
     }
+
 }
\ No newline at end of file
index 87d1559e4921ffed91ad38c8a431ec78523fd4d2..3bd37bcf3387ae4500f45d372f6a6454c949526f 100644 (file)
@@ -3,28 +3,156 @@ module opendaylight-flow-statistics {
     prefix flowstat;
 
     import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import ietf-yang-types {prefix yang; revision-date "2010-09-24";}   
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-flow-types {prefix flow-types;revision-date "2013-10-26";}
-    import sal-flow {prefix flow;}
     import opendaylight-statistics-types {prefix stat-types;revision-date "2013-09-25";}
+    import opendaylight-table-types {prefix table-types;revision-date "2013-10-26";}
+    import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
+    import flow-capable-transaction {prefix tr;}
+    import sal-flow {prefix flow;}
+    
 
     revision "2013-08-19" {
-        description "Initial revision of flow service";
+        description "Initial revision of flow statistics service";
+    }
+       
+       //Augment flow statistics data to the flow-capable-node->table->flow
+       augment "/inv:nodes/inv:node/flow-node:table/flow-node:flow" {
+        ext:augment-identifier "flow-statistics-data";
+        uses flow-statistics;
+    }
+       
+       grouping flow-statistics {
+        container flow-statistics {
+            //config "false";
+               uses flow-types:flow;
+               uses stat-types:generic-statistics;
+        }
+       }    
+       
+       typedef flow-id {
+               description "flow id";
+               type yang:counter32;
+       }
+       
+       grouping flow-and-statistics-map-list {
+               description "List of flow and statistics map";
+               list flow-and-statistics-map-list {
+                       key "flow-id";
+                       leaf flow-id {
+                               type flow-id;
+                       }
+                       uses flow-and-statistics-map;
+               }
+       }
+       
+       grouping flow-and-statistics-map{
+               description "Mapping between flow and its statistics";
+               uses flow-types:flow;
+               uses stat-types:generic-statistics;
+       }
+       
+    // RPC calls to fetch flow statistics
+    rpc get-all-flows-statistics-from-all-flow-tables {
+       description "Fetch statistics of all the flow present in all the flow tables of the switch"; 
+        input {
+            uses inv:node-context-ref;
+        }
+        output {
+            uses flow-and-statistics-map-list;
+            uses tr:transaction-aware;
+        }
+    
     }
 
-    rpc get-node-connector-statistics {
+    rpc get-all-flow-statistics-from-flow-table {
+       description "Fetch statistics of all the flow present in the specific flow table of the switch"; 
         input {
             uses inv:node-context-ref;
-            leaf node-connector {
-                type inv:node-connector-ref;
+            leaf table-id {
+               type table-types:table-id;
             }
         }
         output {
-            uses stat-types:node-connector-statistics;
+            uses flow-and-statistics-map-list;
+            uses tr:transaction-aware;
         }
     }
 
-    rpc get-flow-statistics {
+    rpc get-flow-statistics-from-flow-table {
+       description "Fetch statistics of the specific flow present in the specific flow table of the switch"; 
+        input {
+            uses inv:node-context-ref;
+            uses flow-types:flow;
+        }
+        output {
+            uses flow-and-statistics-map-list;
+            uses tr:transaction-aware;
+        }
+    }
+
+    notification flows-statistics-update {
+       description "Flows statistics sent by switch";
+               leaf moreReplies {
+            type boolean;
+        }
+        uses inv:node;
+               uses flow-and-statistics-map-list;
+               uses tr:transaction-aware;
+    }
+
+       //Models for aggregate flow statistics collection
+       augment "/inv:nodes/inv:node/flow-node:table" {
+        ext:augment-identifier "aggregate-flow-statistics-data";
+        uses aggregate-flow-statistics;
+    }
+       
+       grouping aggregate-flow-statistics {
+        container aggregate-flow-statistics {
+            //config "false";
+               uses stat-types:aggregate-flow-statistics;
+        }
+       }    
+       
+    // RPC calls to fetch flow statistics
+    rpc get-aggregate-flow-statistics-from-flow-table-for-all-flows {
+       description "Fetch aggregate statistics for all the flows present in the specific flow table of the switch"; 
+        input {
+            uses inv:node-context-ref;
+            leaf table-id {
+               type table-types:table-id;
+            }
+        }
+        output {
+               uses stat-types:aggregate-flow-statistics;
+            uses tr:transaction-aware;
+        }
+    }
+    rpc get-aggregate-flow-statistics-from-flow-table-for-given-match {
+       description "Fetch aggregate statistics for all the flow matches to the given match from the given table of the switch"; 
+        input {
+            uses inv:node-context-ref;
+            uses flow-types:flow;
+        }
+        output {
+               uses stat-types:aggregate-flow-statistics;
+            uses tr:transaction-aware;
+        }
+    }
+
+    notification aggregate-flow-statistics-update {
+       description "Aggregate flow statistics for a table, sent by switch";
+               leaf moreReplies {
+            type boolean;
+        }
+        uses inv:node;
+               uses stat-types:aggregate-flow-statistics;
+               uses tr:transaction-aware;
+    }
+       
+       //Keeping flow statistics RPC call for backward compatibility for sal-compatibility layer --START
+       rpc get-flow-statistics {
         input {
             uses inv:node-context-ref;
             uses flow-types:flow;
@@ -45,6 +173,25 @@ module opendaylight-flow-statistics {
         }
     }
 
+    notification flow-statistics-updated {
+        uses flow-types:flow-statistics;
+    }
+       
+       //Keeping flow statistics RPC call for backward compatibility for sal-compatibility layer --END
+       
+       //RPC call to fetch node connector statistics
+    rpc get-node-connector-statistics {
+        input {
+            uses inv:node-context-ref;
+            leaf node-connector {
+                type inv:node-connector-ref;
+            }
+        }
+        output {
+            uses stat-types:node-connector-statistics;
+        }
+    }
+
     rpc get-all-node-connector-statistics {
         input {
             uses inv:node-context-ref;
@@ -56,10 +203,6 @@ module opendaylight-flow-statistics {
         }
     }
 
-    notification flow-statistics-updated {
-        uses flow-types:flow-statistics;
-    }
-
     rpc get-flow-table-statistics {
         input {
             uses inv:node-context-ref;
@@ -79,6 +222,4 @@ module opendaylight-flow-statistics {
     notification node-connector-statistics-updated {
         uses stat-types:node-connector-statistics;
     }
-
-
 }
diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-table-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/flow-table-statistics.yang
new file mode 100644 (file)
index 0000000..b823354
--- /dev/null
@@ -0,0 +1,69 @@
+module opendaylight-flow-table-statistics {
+    namespace "urn:opendaylight:flow:table:statistics";
+    prefix flowtablestat;
+
+       import flow-capable-transaction {prefix tr;}
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
+    import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
+    import opendaylight-table-types {prefix table-types;revision-date "2013-10-26";}
+    import opendaylight-statistics-types {prefix stat-types;revision-date "2013-09-25";}
+    
+
+    contact
+        "Anilkumar Vishnoi
+        Email: avishnoi@in.ibm.com";
+
+    revision "2013-12-15" {
+        description "Initial revision of flow table statistics model";
+    }
+    
+    //Augment flow table statistics data to the table
+       augment "/inv:nodes/inv:node/flow-node:table" {
+        ext:augment-identifier "flow-table-statistics-data";
+        uses flow-table-statistics;
+    }
+       
+       grouping flow-table-statistics {
+        container flow-table-statistics {
+            //config "false";
+               uses stat-types:generic-table-statistics;
+        }
+       }    
+    
+    //RPC calls to fetch flow table statistics
+    grouping flow-table-and-statistics-map {
+       list flow-table-and-statistics-map {
+               key "table-id";
+               leaf table-id {
+                       type table-types:table-id;
+               }
+               uses stat-types:generic-table-statistics;
+       }
+    }
+    
+    rpc get-flow-tables-statistics {
+       description "Fetch statistics of all the flow tables present on the tarnet node";
+       input {
+               uses inv:node-context-ref;
+       }
+       output {
+               uses flow-table-and-statistics-map;
+               uses tr:transaction-aware;
+       }
+    }
+    
+    //Notification to receive table statistics update
+    
+    notification flow-table-statistics-update {
+       description "Receive flow table statistics update";
+       
+               leaf moreReplies {
+            type boolean;
+        }
+        uses inv:node;
+               uses flow-table-and-statistics-map;
+               uses tr:transaction-aware;
+    }
+}
diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/port-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/port-statistics.yang
new file mode 100644 (file)
index 0000000..0cb6a60
--- /dev/null
@@ -0,0 +1,78 @@
+module opendaylight-port-statistics {
+    namespace "urn:opendaylight:port:statistics";
+    prefix portstat;
+
+       import flow-capable-transaction {prefix tr;}
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import ietf-yang-types {prefix yang; revision-date "2010-09-24";}   
+    import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import opendaylight-statistics-types {prefix stat-types;revision-date "2013-09-25";}
+
+    contact
+        "Anilkumar Vishnoi
+        Email: avishnoi@in.ibm.com";
+
+    revision "2013-12-14" {
+        description "Initial revision of port statistics model";
+    }
+    
+    //Augment port statistics data to the flow-capable-node-connector
+       augment "/inv:nodes/inv:node/inv:node-connector" {
+        ext:augment-identifier "flow-capable-node-connector-statistics-data";
+        uses flow-capable-node-connector-statistics;
+    }
+       
+       grouping flow-capable-node-connector-statistics {
+        container flow-capable-node-connector-statistics {
+            //config "false";
+            uses stat-types:node-connector-statistics;
+        }
+       }    
+       
+    // RPC calls
+    rpc get-all-ports-statistics {
+       description "Get statistics for all the ports from the node";
+        input {
+            uses inv:node-context-ref;
+        }
+        output {
+            uses stat-types:node-connector-statistics;
+            uses tr:transaction-aware;
+        }
+    }
+    
+    rpc get-port-statistics {
+       description "Get statistics for given port from the node";
+       input {
+               uses inv:node-context-ref;
+               leaf node-connector-id {
+                       type inv:node-connector-id;
+               }
+       }
+       output {
+            uses stat-types:node-connector-statistics;
+            uses tr:transaction-aware;
+       }
+    }
+    
+    //Notification for port statistics update
+       grouping node-connector-statistics-and-port-number-map {
+               description "List of flow and statistics map";
+               list node-connector-statistics-and-port-number-map {
+                       key "node-connector-id";
+                       leaf node-connector-id {
+                               type inv:node-connector-id;
+                       }
+                       uses stat-types:node-connector-statistics;
+               }
+       }
+
+       notification port-statistics-update {
+        leaf moreReplies {
+            type boolean;
+        }
+        uses inv:node;
+               uses node-connector-statistics-and-port-number-map;
+        uses tr:transaction-aware;
+    }
+}
index d0b2e6a95931f8abdebf7f0f0c7353791a49b481..6d5bec1280ffde4cee89690032ec3b40b6fc318b 100644 (file)
@@ -60,4 +60,52 @@ module opendaylight-statistics-types {
             }
         }
     }
+    
+    grouping generic-statistics {
+       description "Generic grouping for statistics";
+        leaf packet-count {
+            type yang:counter64;
+        }
+
+        leaf byte-count {
+            type yang:counter64;
+        }
+
+        container duration {
+            leaf second {
+                type yang:counter64;
+            }
+            leaf nanosecond {
+                type yang:counter64;
+            }
+        }
+    }
+    
+    grouping generic-table-statistics {
+       description "Generic grouping holding generic statistics related to switch table";
+       leaf active-flows {
+            type yang:counter32;
+       }
+       leaf packets-looked-up {
+               type yang:counter64;
+       }
+       leaf packets-matched {
+               type yang:counter64;
+       }
+    }
+    
+    grouping aggregate-flow-statistics {
+       description "Aggregate flow statistics";
+        leaf packet-count {
+            type yang:counter64;
+        }
+
+        leaf byte-count {
+            type yang:counter64;
+        }
+        leaf flow-count {
+            type yang:counter32;
+        }
+    }
+    
 }
\ No newline at end of file
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MultipartMessageManager.java
new file mode 100644 (file)
index 0000000..11cce72
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright IBM Corporation, 2013.  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.md.statistics.manager;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
+
+/**
+ * Main responsibility of the class is to manage multipart response 
+ * for multipart request. It also handles the flow aggregate request
+ * and response mapping. 
+ * @author avishnoi@in.ibm.com
+ *
+ */
+public class MultipartMessageManager {
+
+    private static Map<TransactionId,Short> txIdTotableIdMap = new ConcurrentHashMap<TransactionId,Short>();
+    
+    public MultipartMessageManager(){}
+    
+    public Short getTableIdForTxId(TransactionId id){
+        
+        return txIdTotableIdMap.get(id);
+        
+    }
+    
+    public void setTxIdAndTableIdMapEntry(TransactionId id,Short tableId){
+        txIdTotableIdMap.put(id, tableId);
+    }
+}
index c48ac311abb33dc0ffdfe5ee1ca4c3f26595111b..a659a4088695ce392471dba4c1c81cabc72d8d81 100644 (file)
@@ -7,15 +7,24 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatistics;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeatures;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericTableStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics;
 
 public class NodeStatistics {
 
@@ -33,6 +42,18 @@ public class NodeStatistics {
     
     private MeterFeatures meterFeatures;
     
+    private final Map<Short,Map<Flow,GenericStatistics>> flowAndStatsMap= 
+            new HashMap<Short,Map<Flow,GenericStatistics>>();
+    
+    private final Map<Short,AggregateFlowStatistics> tableAndAggregateFlowStatsMap = 
+            new HashMap<Short,AggregateFlowStatistics>();
+    
+    private final Map<NodeConnectorId,NodeConnectorStatistics> nodeConnectorStats = 
+            new ConcurrentHashMap<NodeConnectorId,NodeConnectorStatistics>();
+    
+    private final Map<Short,GenericTableStatistics> flowTableAndStatisticsMap = 
+            new HashMap<Short,GenericTableStatistics>();
+    
     public NodeStatistics(){
         
     }
@@ -92,5 +113,19 @@ public class NodeStatistics {
     public void setMeterFeatures(MeterFeatures meterFeatures) {
         this.meterFeatures = meterFeatures;
     }
-    
+
+    public Map<Short,Map<Flow,GenericStatistics>> getFlowAndStatsMap() {
+        return flowAndStatsMap;
+    }
+
+    public Map<Short, GenericTableStatistics> getFlowTableAndStatisticsMap() {
+        return flowTableAndStatisticsMap;
+    }
+
+    public Map<Short, AggregateFlowStatistics> getTableAndAggregateFlowStatsMap() {
+        return tableAndAggregateFlowStatsMap;
+    }
+    public Map<NodeConnectorId, NodeConnectorStatistics> getNodeConnectorStats() {
+        return nodeConnectorStats;
+    }
 }
index f22ca00b2ab4d0dc20d551aa08d58522848923a7..b7b408211851d0ce09f8fa6fb825ca04a340e755 100644 (file)
@@ -7,9 +7,11 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 import org.eclipse.xtext.xbase.lib.Exceptions;
@@ -17,6 +19,15 @@ import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionInputBuilder;
@@ -26,11 +37,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllPortsStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllPortsStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
@@ -50,6 +65,14 @@ public class StatisticsProvider implements AutoCloseable {
     
     private OpendaylightMeterStatisticsService meterStatsService;
     
+    private OpendaylightFlowStatisticsService flowStatsService;
+    
+    private OpendaylightPortStatisticsService portStatsService;
+
+    private OpendaylightFlowTableStatisticsService flowTableStatsService;
+
+    private final MultipartMessageManager multipartMessageManager = new MultipartMessageManager();
+    
     private Thread statisticsRequesterThread;
     
     private final  InstanceIdentifier<Nodes> nodesIdentifier = InstanceIdentifier.builder(Nodes.class).toInstance();
@@ -76,6 +99,10 @@ public class StatisticsProvider implements AutoCloseable {
       this.nps = notificationService;
     }
 
+    public MultipartMessageManager getMultipartMessageManager() {
+        return multipartMessageManager;
+    }
+
     private final StatisticsUpdateCommiter updateCommiter = new StatisticsUpdateCommiter(StatisticsProvider.this);
     
     private Registration<NotificationListener> listenerRegistration;
@@ -92,7 +119,16 @@ public class StatisticsProvider implements AutoCloseable {
         
         meterStatsService = StatisticsManagerActivator.getProviderContext().
                 getRpcService(OpendaylightMeterStatisticsService.class);
+        
+        flowStatsService = StatisticsManagerActivator.getProviderContext().
+                getRpcService(OpendaylightFlowStatisticsService.class);
+
+        portStatsService = StatisticsManagerActivator.getProviderContext().
+                getRpcService(OpendaylightPortStatisticsService.class);
 
+        flowTableStatsService = StatisticsManagerActivator.getProviderContext().
+                getRpcService(OpendaylightFlowTableStatisticsService.class);
+        
         statisticsRequesterThread = new Thread( new Runnable(){
 
             @Override
@@ -124,21 +160,35 @@ public class StatisticsProvider implements AutoCloseable {
     
     private void statsRequestSender(){
         
-        //Need to call API to receive all the nodes connected to controller.
         List<Node> targetNodes = getAllConnectedNodes();
         
         if(targetNodes == null)
             return;
+        
 
         for (Node targetNode : targetNodes){
+            
+            InstanceIdentifier<Node> targetInstanceId = InstanceIdentifier.builder(Nodes.class).child(Node.class,targetNode.getKey()).toInstance();
+            NodeRef targetNodeRef = new NodeRef(targetInstanceId);
+            
+            try {
+                
+                sendAggregateFlowsStatsFromAllTablesRequest(targetNode.getKey());
+
+                sendAllFlowsStatsFromAllTablesRequest(targetNodeRef);
+
+                sendAllPortStatisticsRequest(targetNodeRef);
+                
+                sendAllFlowTablesStatisticsRequest(targetNodeRef);
+
+            }catch(Exception e){
+                spLogger.error("Exception occured while sending statistics requests : {}",e);
+            }
 
             if(targetNode.getAugmentation(FlowCapableNode.class) != null){
 
                 spLogger.info("Send request for stats collection to node : {})",targetNode.getId());
-                
-                InstanceIdentifier<Node> targetInstanceId = InstanceIdentifier.builder(Nodes.class).child(Node.class,targetNode.getKey()).toInstance();
-                NodeRef targetNodeRef = new NodeRef(targetInstanceId);
-                
+
                 try{
                   sendAllGroupStatisticsRequest(targetNodeRef);
                   Thread.sleep(1000);
@@ -149,17 +199,85 @@ public class StatisticsProvider implements AutoCloseable {
                   sendMeterConfigStatisticsRequest(targetNodeRef);
                   Thread.sleep(1000);
                 }catch(Exception e){
-                    spLogger.error("Exception occured while sending statistics request : {}", e);
+                    spLogger.error("Exception occured while sending statistics requests : {}", e);
                 }
             }
         }
     }
+
+    private void sendAllFlowTablesStatisticsRequest(NodeRef targetNodeRef) {
+        final GetFlowTablesStatisticsInputBuilder input = 
+                new GetFlowTablesStatisticsInputBuilder();
+        
+        input.setNode(targetNodeRef);
+
+        @SuppressWarnings("unused")
+        Future<RpcResult<GetFlowTablesStatisticsOutput>> response = 
+                flowTableStatsService.getFlowTablesStatistics(input.build());
+    }
+
+    private void sendAllFlowsStatsFromAllTablesRequest(NodeRef targetNode){
+        final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder input =
+                new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder();
+        
+        input.setNode(targetNode);
+        
+        @SuppressWarnings("unused")
+        Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> response = 
+                flowStatsService.getAllFlowsStatisticsFromAllFlowTables(input.build());
+        
+    }
     
+    private void sendAggregateFlowsStatsFromAllTablesRequest(NodeKey targetNodeKey) throws InterruptedException, ExecutionException{
+        
+        List<Short> tablesId = getTablesFromNode(targetNodeKey);
+        
+        if(tablesId.size() != 0){
+            for(Short id : tablesId){
+                
+                spLogger.info("Send aggregate stats request for flow table {} to node {}",id,targetNodeKey);
+                GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder input = 
+                        new GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder();
+                
+                input.setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).toInstance()));
+                input.setTableId(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId(id));
+                Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> response = 
+                        flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build());
+                
+                multipartMessageManager.setTxIdAndTableIdMapEntry(response.get().getResult().getTransactionId(), id);
+            }
+        }
+        
+        //Note: Just for testing, because i am not able to fetch table list from datastore
+        // Bug-225 is raised for investigation.
+        
+//                spLogger.info("Send aggregate stats request for flow table {} to node {}",1,targetNodeKey);
+//                GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder input = 
+//                        new GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder();
+//                
+//                input.setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).toInstance()));
+//                input.setTableId(new TableId((short)1));
+//                Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> response = 
+//                        flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build());`
+//                
+//                multipartMessageManager.setTxIdAndTableIdMapEntry(response.get().getResult().getTransactionId(), (short)1);
+    }
+
+    private void sendAllPortStatisticsRequest(NodeRef targetNode){
+        
+        final GetAllPortsStatisticsInputBuilder input = new GetAllPortsStatisticsInputBuilder();
+        
+        input.setNode(targetNode);
+
+        @SuppressWarnings("unused")
+        Future<RpcResult<GetAllPortsStatisticsOutput>> response = 
+                portStatsService.getAllPortsStatistics(input.build());
+    }
+
     private void sendAllGroupStatisticsRequest(NodeRef targetNode){
         
         final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
         
-        input.setNode(targetNode);
         input.setNode(targetNode);
 
         @SuppressWarnings("unused")
@@ -213,6 +331,20 @@ public class StatisticsProvider implements AutoCloseable {
         spLogger.info("Number of connected nodes : {}",nodes.getNode().size());
         return nodes.getNode();
     }
+    
+    private List<Short> getTablesFromNode(NodeKey nodeKey){
+        InstanceIdentifier<FlowCapableNode> nodesIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class,nodeKey).augmentation(FlowCapableNode.class).toInstance();
+        
+        FlowCapableNode node = (FlowCapableNode)dps.readConfigurationData(nodesIdentifier);
+        List<Short> tablesId = new ArrayList<Short>();
+        if(node != null && node.getTable()!=null){
+            spLogger.info("Number of tables {} supported by node {}",node.getTable().size(),nodeKey);
+            for(Table table: node.getTable()){
+                tablesId.add(table.getId());
+            }
+        }
+        return tablesId;
+    }
 
     @SuppressWarnings("deprecation")
     @Override
index 86e6114b5f67a9df25f02e8ae98677d0d842cc54..a4a7e1e6613f6ee0425bec4fded4798681e0dd35 100644 (file)
@@ -7,9 +7,39 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
+import java.util.HashMap;
+import java.util.List;
 import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowTableStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.NodeConnectorStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.aggregate.flow.statistics.AggregateFlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatisticsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
@@ -26,6 +56,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
@@ -42,13 +75,29 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterConfigStatsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.PortStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsListener,
-        OpendaylightMeterStatisticsListener {
+        OpendaylightMeterStatisticsListener, 
+        OpendaylightFlowStatisticsListener,
+        OpendaylightPortStatisticsListener,
+        OpendaylightFlowTableStatisticsListener{
     
+    public final static Logger sucLogger = LoggerFactory.getLogger(StatisticsUpdateCommiter.class);
+
     private final StatisticsProvider statisticsManager;
+    
+    private final int unaccountedFlowsCounter = 1;
 
     public StatisticsUpdateCommiter(final StatisticsProvider manager){
 
@@ -264,9 +313,360 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         it.commit();
     }
 
+    @Override
+    public void onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
+        NodeKey key = new NodeKey(notification.getId());
+        sucLogger.info("Received flow stats update : {}",notification.toString());
+        
+        for(FlowAndStatisticsMapList map: notification.getFlowAndStatisticsMapList()){
+            short tableId = map.getTableId();
+            
+            DataModificationTransaction it = this.statisticsManager.startChange();
+
+            boolean foundOriginalFlow = false;
+
+            FlowBuilder flowBuilder = new FlowBuilder();
+
+            FlowStatisticsDataBuilder flowStatisticsData = new FlowStatisticsDataBuilder();
+
+            FlowBuilder flow = new FlowBuilder();
+            flow.setContainerName(map.getContainerName());
+            flow.setBufferId(map.getBufferId());
+            flow.setCookie(map.getCookie());
+            flow.setCookieMask(map.getCookieMask());
+            flow.setFlags(map.getFlags());
+            flow.setFlowName(map.getFlowName());
+            flow.setHardTimeout(map.getHardTimeout());
+            if(map.getFlowId() != null)
+                flow.setId(new FlowId(map.getFlowId().getValue()));
+            flow.setIdleTimeout(map.getIdleTimeout());
+            flow.setInstallHw(map.isInstallHw());
+            flow.setInstructions(map.getInstructions());
+            if(map.getFlowId()!= null)
+                flow.setKey(new FlowKey(new FlowId(map.getKey().getFlowId().getValue())));
+            flow.setMatch(map.getMatch());
+            flow.setOutGroup(map.getOutGroup());
+            flow.setOutPort(map.getOutPort());
+            flow.setPriority(map.getPriority());
+            flow.setStrict(map.isStrict());
+            flow.setTableId(tableId);
+                
+            Flow flowRule = flow.build();
+                
+            FlowAndStatisticsMapListBuilder stats = new FlowAndStatisticsMapListBuilder();
+            stats.setByteCount(map.getByteCount());
+            stats.setPacketCount(map.getPacketCount());
+            stats.setDuration(map.getDuration());
+                
+            GenericStatistics flowStats = stats.build();
+                
+            //Add statistics to local cache
+            ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+            if(!cache.containsKey(notification.getId())){
+                cache.put(notification.getId(), new NodeStatistics());
+            }
+            if(!cache.get(notification.getId()).getFlowAndStatsMap().containsKey(tableId)){
+                cache.get(notification.getId()).getFlowAndStatsMap().put(tableId, new HashMap<Flow,GenericStatistics>());
+            }
+            cache.get(notification.getId()).getFlowAndStatsMap().get(tableId).put(flowRule,flowStats);
+                
+            //Augment the data to the flow node
+
+            FlowStatisticsBuilder flowStatistics = new FlowStatisticsBuilder();
+            flowStatistics.setByteCount(flowStats.getByteCount());
+            flowStatistics.setPacketCount(flowStats.getPacketCount());
+            flowStatistics.setDuration(flowStats.getDuration());
+            flowStatistics.setContainerName(map.getContainerName());
+            flowStatistics.setBufferId(map.getBufferId());
+            flowStatistics.setCookie(map.getCookie());
+            flowStatistics.setCookieMask(map.getCookieMask());
+            flowStatistics.setFlags(map.getFlags());
+            flowStatistics.setFlowName(map.getFlowName());
+            flowStatistics.setHardTimeout(map.getHardTimeout());
+            flowStatistics.setIdleTimeout(map.getIdleTimeout());
+            flowStatistics.setInstallHw(map.isInstallHw());
+            flowStatistics.setInstructions(map.getInstructions());
+            flowStatistics.setMatch(map.getMatch());
+            flowStatistics.setOutGroup(map.getOutGroup());
+            flowStatistics.setOutPort(map.getOutPort());
+            flowStatistics.setPriority(map.getPriority());
+            flowStatistics.setStrict(map.isStrict());
+            flowStatistics.setTableId(tableId);
+
+            flowStatisticsData.setFlowStatistics(flowStatistics.build());
+                
+            sucLogger.info("Flow : {}",flowRule.toString());
+            sucLogger.info("Statistics to augment : {}",flowStatistics.build().toString());
+
+            InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
+                    .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
+            
+            Table table= (Table)it.readConfigurationData(tableRef);
+
+            //TODO: Not a good way to do it, need to figure out better way.
+            //TODO: major issue in any alternate approach is that flow key is incrementally assigned 
+            //to the flows stored in data store.
+            if(table != null){
+
+                for(Flow existingFlow : table.getFlow()){
+                    sucLogger.debug("Existing flow in data store : {}",existingFlow.toString());
+                    if(flowEquals(flowRule,existingFlow)){
+                        InstanceIdentifier<Flow> flowRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
+                                .augmentation(FlowCapableNode.class)
+                                .child(Table.class, new TableKey(tableId))
+                                .child(Flow.class,existingFlow.getKey()).toInstance();
+                        flowBuilder.setKey(existingFlow.getKey());
+                        flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
+                        sucLogger.debug("Found matching flow in the datastore, augmenting statistics");
+                        foundOriginalFlow = true;
+                        it.putOperationalData(flowRef, flowBuilder.build());
+                        it.commit();
+                        break;
+                    }
+                }
+            }
+            
+            if(!foundOriginalFlow){
+                sucLogger.info("Associated original flow is not found in data store. Augmenting flow in operational data st");
+                //TODO: Temporary fix: format [ 0+tableid+0+unaccounted flow counter]
+                long flowKey = Long.getLong(new String("0"+Short.toString(tableId)+"0"+Integer.toString(this.unaccountedFlowsCounter)));
+                FlowKey newFlowKey = new FlowKey(new FlowId(flowKey));
+                InstanceIdentifier<Flow> flowRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
+                        .augmentation(FlowCapableNode.class)
+                        .child(Table.class, new TableKey(tableId))
+                        .child(Flow.class,newFlowKey).toInstance();
+                flowBuilder.setKey(newFlowKey);
+                flowBuilder.addAugmentation(FlowStatisticsData.class, flowStatisticsData.build());
+                sucLogger.debug("Flow was no present in data store, augmenting statistics as an unaccounted flow");
+                it.putOperationalData(flowRef, flowBuilder.build());
+                it.commit();
+            }
+        }
+    }
+
+    @Override
+    public void onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
+        NodeKey key = new NodeKey(notification.getId());
+        sucLogger.debug("Received aggregate flow statistics update : {}",notification.toString());
+        
+        Short tableId = this.statisticsManager.getMultipartMessageManager().getTableIdForTxId(notification.getTransactionId());
+        if(tableId != null){
+            
+            DataModificationTransaction it = this.statisticsManager.startChange();
+
+            InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
+                    .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
+
+            AggregateFlowStatisticsDataBuilder aggregateFlowStatisticsDataBuilder = new AggregateFlowStatisticsDataBuilder();
+            AggregateFlowStatisticsBuilder aggregateFlowStatisticsBuilder = new AggregateFlowStatisticsBuilder();
+            aggregateFlowStatisticsBuilder.setByteCount(notification.getByteCount());
+            aggregateFlowStatisticsBuilder.setFlowCount(notification.getFlowCount());
+            aggregateFlowStatisticsBuilder.setPacketCount(notification.getPacketCount());
+            aggregateFlowStatisticsDataBuilder.setAggregateFlowStatistics(aggregateFlowStatisticsBuilder.build());
+            
+            ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+            if(!cache.containsKey(notification.getId())){
+                cache.put(notification.getId(), new NodeStatistics());
+            }
+            cache.get(notification.getId()).getTableAndAggregateFlowStatsMap().put(tableId,aggregateFlowStatisticsBuilder.build());
+            
+            sucLogger.debug("Augment aggregate statistics: {} for table {} on Node {}",aggregateFlowStatisticsBuilder.build().toString(),tableId,key);
+
+            TableBuilder tableBuilder = new TableBuilder();
+            tableBuilder.setKey(new TableKey(tableId));
+            tableBuilder.addAugmentation(AggregateFlowStatisticsData.class, aggregateFlowStatisticsDataBuilder.build());
+            it.putOperationalData(tableRef, tableBuilder.build());
+            it.commit();
+
+        }
+    }
+
+    @Override
+    public void onPortStatisticsUpdate(PortStatisticsUpdate notification) {
+        NodeKey key = new NodeKey(notification.getId());
+        sucLogger.info("Received port stats update : {}",notification.toString());
+        
+        //Add statistics to local cache
+        ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+        if(!cache.containsKey(notification.getId())){
+            cache.put(notification.getId(), new NodeStatistics());
+        }
+
+
+        List<NodeConnectorStatisticsAndPortNumberMap> portsStats = notification.getNodeConnectorStatisticsAndPortNumberMap();
+        for(NodeConnectorStatisticsAndPortNumberMap portStats : portsStats){
+            
+            DataModificationTransaction it = this.statisticsManager.startChange();
+
+            FlowCapableNodeConnectorStatisticsBuilder statisticsBuilder 
+                                            = new FlowCapableNodeConnectorStatisticsBuilder();
+            statisticsBuilder.setBytes(portStats.getBytes());
+            statisticsBuilder.setCollisionCount(portStats.getCollisionCount());
+            statisticsBuilder.setDuration(portStats.getDuration());
+            statisticsBuilder.setPackets(portStats.getPackets());
+            statisticsBuilder.setReceiveCrcError(portStats.getReceiveCrcError());
+            statisticsBuilder.setReceiveDrops(portStats.getReceiveDrops());
+            statisticsBuilder.setReceiveErrors(portStats.getReceiveErrors());
+            statisticsBuilder.setReceiveFrameError(portStats.getReceiveFrameError());
+            statisticsBuilder.setReceiveOverRunError(portStats.getReceiveOverRunError());
+            statisticsBuilder.setTransmitDrops(portStats.getTransmitDrops());
+            statisticsBuilder.setTransmitErrors(portStats.getTransmitErrors());
+            
+            //Update data in the cache
+            cache.get(notification.getId()).getNodeConnectorStats().put(portStats.getNodeConnectorId(), statisticsBuilder.build());
+            
+            //Augment data to the node-connector
+            FlowCapableNodeConnectorStatisticsDataBuilder statisticsDataBuilder = 
+                    new FlowCapableNodeConnectorStatisticsDataBuilder();
+            
+            statisticsDataBuilder.setFlowCapableNodeConnectorStatistics(statisticsBuilder.build());
+            
+            InstanceIdentifier<NodeConnector> nodeConnectorRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key).child(NodeConnector.class, new NodeConnectorKey(portStats.getNodeConnectorId())).toInstance();
+            
+            NodeConnector nodeConnector = (NodeConnector)it.readOperationalData(nodeConnectorRef);
+            
+            if(nodeConnector != null){
+                sucLogger.debug("Augmenting port statistics {} to port {}",statisticsDataBuilder.build().toString(),nodeConnectorRef.toString());
+                NodeConnectorBuilder nodeConnectorBuilder = new NodeConnectorBuilder();
+                nodeConnectorBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, statisticsDataBuilder.build());
+                it.putOperationalData(nodeConnectorRef, nodeConnectorBuilder.build());
+                it.commit();
+            }
+        }
+    }
+
+    @Override
+    public void onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) {
+        NodeKey key = new NodeKey(notification.getId());
+        sucLogger.debug("Received flow table statistics update : {}",notification.toString());
+        
+        List<FlowTableAndStatisticsMap> flowTablesStatsList = notification.getFlowTableAndStatisticsMap();
+        for (FlowTableAndStatisticsMap ftStats : flowTablesStatsList){
+            
+            DataModificationTransaction it = this.statisticsManager.startChange();
+
+            InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
+                    .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(ftStats.getTableId().getValue())).toInstance();
+            
+            FlowTableStatisticsDataBuilder statisticsDataBuilder = new FlowTableStatisticsDataBuilder();
+            
+            FlowTableStatisticsBuilder statisticsBuilder = new FlowTableStatisticsBuilder();
+            statisticsBuilder.setActiveFlows(ftStats.getActiveFlows());
+            statisticsBuilder.setPacketsLookedUp(ftStats.getPacketsLookedUp());
+            statisticsBuilder.setPacketsMatched(ftStats.getPacketsMatched());
+            
+            statisticsDataBuilder.setFlowTableStatistics(statisticsBuilder.build());
+            
+            ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+            if(!cache.containsKey(notification.getId())){
+                cache.put(notification.getId(), new NodeStatistics());
+            }
+            cache.get(notification.getId()).getFlowTableAndStatisticsMap().put(ftStats.getTableId().getValue(),statisticsBuilder.build());
+            
+            sucLogger.debug("Augment flow table statistics: {} for table {} on Node {}",statisticsBuilder.build().toString(),ftStats.getTableId(),key);
+            
+            TableBuilder tableBuilder = new TableBuilder();
+            tableBuilder.setKey(new TableKey(ftStats.getTableId().getValue()));
+            tableBuilder.addAugmentation(FlowTableStatisticsData.class, statisticsDataBuilder.build());
+            it.putOperationalData(tableRef, tableBuilder.build());
+            it.commit();
+        }
+    }
+
+    @Override
+    public void onFlowStatisticsUpdated(FlowStatisticsUpdated notification) {
+        // TODO Auto-generated method stub
+        //TODO: Depricated, will clean it up once sal-compatibility is fixed.
+        //Sal-Compatibility code usage this notification event.
+        
+    }
+
+    @Override
+    public void onFlowTableStatisticsUpdated(FlowTableStatisticsUpdated notification) {
+        // TODO Auto-generated method stub
+        //TODO: Need to implement it yet
+        
+    }
+
+    @Override
+    public void onNodeConnectorStatisticsUpdated(NodeConnectorStatisticsUpdated notification) {
+        // TODO Auto-generated method stub
+        //TODO: Need to implement it yet
+        
+    }
+
     private NodeRef getNodeRef(NodeKey nodeKey){
         InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder(Nodes.class).child(Node.class, nodeKey);
         return new NodeRef(builder.toInstance());
     }
-
+    
+    public boolean flowEquals(Flow statsFlow, Flow storedFlow) {
+        if (statsFlow.getClass() != storedFlow.getClass()) {
+            return false;
+        }
+        if (statsFlow.getBufferId()== null) {
+            if (storedFlow.getBufferId() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getBufferId().equals(storedFlow.getBufferId())) {
+            return false;
+        }
+        if (statsFlow.getContainerName()== null) {
+            if (storedFlow.getContainerName()!= null) {
+                return false;
+            }
+        } else if(!statsFlow.getContainerName().equals(storedFlow.getContainerName())) {
+            return false;
+        }
+        if (statsFlow.getCookie()== null) {
+            if (storedFlow.getCookie()!= null) {
+                return false;
+            }
+        } else if(!statsFlow.getCookie().equals(storedFlow.getCookie())) {
+            return false;
+        }
+        if (statsFlow.getMatch()== null) {
+            if (storedFlow.getMatch() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getMatch().equals(storedFlow.getMatch())) {
+            return false;
+        }
+        if (statsFlow.getCookie()== null) {
+            if (storedFlow.getCookie()!= null) {
+                return false;
+            }
+        } else if(!statsFlow.getCookie().equals(storedFlow.getCookie())) {
+            return false;
+        }
+        if (statsFlow.getHardTimeout() == null) {
+            if (storedFlow.getHardTimeout() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getHardTimeout().equals(storedFlow.getHardTimeout() )) {
+            return false;
+        }
+        if (statsFlow.getIdleTimeout()== null) {
+            if (storedFlow.getIdleTimeout() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getIdleTimeout().equals(storedFlow.getIdleTimeout())) {
+            return false;
+        }
+        if (statsFlow.getPriority() == null) {
+            if (storedFlow.getPriority() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getPriority().equals(storedFlow.getPriority())) {
+            return false;
+        }
+        if (statsFlow.getTableId() == null) {
+            if (storedFlow.getTableId() != null) {
+                return false;
+            }
+        } else if(!statsFlow.getTableId().equals(storedFlow.getTableId())) {
+            return false;
+        }
+        return true;
+    }
 }
index 697b811d51c90c9b7cab4f05f266292d25d2a260..cf0e71e67a52ab9983b5a2599519cf9f3014118c 100644 (file)
@@ -29,12 +29,16 @@ public abstract class AttributeIfcSwitchStatement<T> {
 
         this.lastAttribute = attributeIfc;
 
+        OpenType<?> openType = attributeIfc.getOpenType();
+
         if (attributeIfc instanceof JavaAttribute) {
             try {
                 if(((JavaAttribute)attributeIfc).getTypeDefinition() instanceof BinaryTypeDefinition) {
-                    return caseJavaBinaryAttribute(attributeIfc.getOpenType());
+                    return caseJavaBinaryAttribute(openType);
+                } else if(((JavaAttribute)attributeIfc).isUnion()) {
+                    return caseJavaUnionAttribute(openType);
                 } else
-                    return caseJavaAttribute(attributeIfc.getOpenType());
+                    return caseJavaAttribute(openType);
             } catch (UnknownOpenTypeException e) {
                 throw getIllegalArgumentException(attributeIfc);
             }
@@ -42,9 +46,9 @@ public abstract class AttributeIfcSwitchStatement<T> {
         } else if (attributeIfc instanceof DependencyAttribute) {
             return caseDependencyAttribute(((DependencyAttribute) attributeIfc).getOpenType());
         } else if (attributeIfc instanceof ListAttribute) {
-            return caseListAttribute((ArrayType<?>) attributeIfc.getOpenType());
+            return caseListAttribute((ArrayType<?>) openType);
         } else if (attributeIfc instanceof ListDependenciesAttribute) {
-            return caseListDependeciesAttribute((ArrayType<?>) attributeIfc.getOpenType());
+            return caseListDependeciesAttribute((ArrayType<?>) openType);
         } else if (attributeIfc instanceof TOAttribute) {
             return caseTOAttribute(((TOAttribute) attributeIfc).getOpenType());
         }
@@ -52,6 +56,10 @@ public abstract class AttributeIfcSwitchStatement<T> {
         throw getIllegalArgumentException(attributeIfc);
     }
 
+    protected T caseJavaUnionAttribute(OpenType<?> openType) {
+        return caseJavaAttribute(openType);
+    }
+
     protected T caseJavaBinaryAttribute(OpenType<?> openType) {
         return caseJavaAttribute(openType);
     }
index a2691f241cfa9a6c273c95c653c2fa9720d03cb9..97c0f4d834ba7d7a810d9d36a08a1a74deb748e7 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
@@ -47,6 +48,12 @@ public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadin
         return new SimpleBinaryAttributeReadingStrategy(lastAttribute.getNullableDefault());
     }
 
+    @Override
+    protected AttributeReadingStrategy caseJavaUnionAttribute(OpenType<?> openType) {
+        String mappingKey = JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
+        return new SimpleUnionAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey);
+    }
+
     @Override
     public AttributeReadingStrategy caseJavaSimpleAttribute(SimpleType<?> openType) {
         return new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault());
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleUnionAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleUnionAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..2e8b459
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 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.confignetconfconnector.mapping.attributes.fromxml;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import java.util.List;
+import java.util.Map;
+
+public class SimpleUnionAttributeReadingStrategy extends SimpleAttributeReadingStrategy {
+
+    private final String key;
+
+    public SimpleUnionAttributeReadingStrategy(String nullableDefault, String key) {
+        super(nullableDefault);
+        this.key = key;
+    }
+
+    protected Object postprocessParsedValue(String textContent) {
+        char[] charArray = textContent.toCharArray();
+        List<String> chars = Lists.newArrayListWithCapacity(charArray.length);
+
+        for (char c : charArray) {
+            chars.add(Character.toString(c));
+        }
+
+        Map<String, Object> map = Maps.newHashMap();
+        map.put(key, chars);
+        return map;
+    }
+
+    @Override
+    protected Object postprocessNullableDefault(String nullableDefault) {
+        return nullableDefault == null ? null : postprocessParsedValue(nullableDefault);
+    }
+}
index 252b13bf6850c498d6c122565044359647dd5520..368e1f12a642e54dc90ac8231818619a0de96815 100644 (file)
@@ -53,17 +53,21 @@ public class CompositeAttributeMappingStrategy extends
         Map<String, Object> retVal = Maps.newHashMap();
 
         for (String jmxName : jmxToJavaNameMapping.keySet()) {
-            String innerAttrJmxName = jmxName;
-            Object innerValue = compositeData.get(innerAttrJmxName);
-
-            AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = innerStrategies
-                    .get(innerAttrJmxName);
-            Optional<?> mapAttribute = attributeMappingStrategy.mapAttribute(innerValue);
-            if (mapAttribute.isPresent())
-                retVal.put(jmxToJavaNameMapping.get(innerAttrJmxName), mapAttribute.get());
+            Optional<?> mapped = mapInnerAttribute(compositeData, jmxName, expectedType.getDescription(jmxName));
+            if(mapped.isPresent())
+                retVal.put(jmxToJavaNameMapping.get(jmxName), mapped.get());
         }
 
         return Optional.of(retVal);
     }
 
+    protected Optional<?> mapInnerAttribute(CompositeDataSupport compositeData, String jmxName, String description) {
+        Object innerValue = compositeData.get(jmxName);
+
+        AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = innerStrategies
+                .get(jmxName);
+        Optional<?> mapAttribute = attributeMappingStrategy.mapAttribute(innerValue);
+        return mapAttribute;
+    }
+
 }
index 6e5bd0d3fe8229597ab6984f37150f1833cd3525..fb385221c8877b9ffceadf53cd355f8c78197811 100644 (file)
@@ -90,6 +90,22 @@ public class ObjectMapper extends AttributeIfcSwitchStatement<AttributeMappingSt
         return new CompositeAttributeMappingStrategy(openType, innerStrategies, attributeMapping);
     }
 
+    @Override
+    protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseJavaUnionAttribute(OpenType<?> openType) {
+        Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies = Maps.newHashMap();
+
+        Map<String, String> attributeMapping = Maps.newHashMap();
+
+        CompositeType compositeType = (CompositeType) openType;
+        for (String innerAttributeKey : compositeType.keySet()) {
+
+            innerStrategies.put(innerAttributeKey, caseJavaAttribute(compositeType.getType(innerAttributeKey)));
+            attributeMapping.put(innerAttributeKey, innerAttributeKey);
+        }
+
+        return new UnionCompositeAttributeMappingStrategy(compositeType, innerStrategies, attributeMapping);
+    }
+
     private String serviceNameOfDepAttr;
     private String namespaceOfDepAttr;
 
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/UnionCompositeAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/UnionCompositeAttributeMappingStrategy.java
new file mode 100644 (file)
index 0000000..81a1e53
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 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.confignetconfconnector.mapping.attributes.mapping;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import java.util.Map;
+
+public class UnionCompositeAttributeMappingStrategy extends
+        CompositeAttributeMappingStrategy {
+
+
+    public UnionCompositeAttributeMappingStrategy(CompositeType compositeType, Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies, Map<String, String> jmxToJavaNameMapping) {
+        super(compositeType, innerStrategies, jmxToJavaNameMapping);
+    }
+
+    @Override
+    protected Optional<?> mapInnerAttribute(CompositeDataSupport compositeData, String jmxName, String description) {
+        if(description.equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION) == false)
+            return Optional.absent();
+
+        return super.mapInnerAttribute(compositeData, jmxName, description);
+    }
+}
index c477821051b08d03288d129fc29c1aaddd32eef6..e8e97f990f44cd45608fb8df92e042437351e319 100644 (file)
@@ -21,7 +21,7 @@ import javax.management.openmbean.OpenDataException;
 import javax.management.openmbean.OpenType;
 import java.util.Map;
 
-final class CompositeAttributeResolvingStrategy extends
+class CompositeAttributeResolvingStrategy extends
         AbstractAttributeResolvingStrategy<CompositeDataSupport, CompositeType> {
     private final Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerTypes;
     private final Map<String, String> yangToJavaAttrMapping;
@@ -49,6 +49,7 @@ final class CompositeAttributeResolvingStrategy extends
 
         Util.checkType(value, Map.class);
         Map<?, ?> valueMap = (Map<?, ?>) value;
+        valueMap = preprocessValueMap(valueMap);
 
         Map<String, Object> items = Maps.newHashMap();
         Map<String, OpenType<?>> openTypes = Maps.newHashMap();
@@ -82,4 +83,8 @@ final class CompositeAttributeResolvingStrategy extends
 
         return Optional.of(parsedValue);
     }
+
+    protected Map<?, ?> preprocessValueMap(Map<?, ?> valueMap) {
+        return valueMap;
+    }
 }
index f5a25112602ac6b92c6d08faa46b311dbd11533c..a3e2813fa0d383f6db78c6a2c2d52e32d03dc5e1 100644 (file)
@@ -72,13 +72,30 @@ public class ObjectResolver extends AttributeIfcSwitchStatement<AttributeResolvi
     @Override
     protected AttributeResolvingStrategy<?, ? extends OpenType<?>>  caseJavaCompositeAttribute(CompositeType openType) {
         Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap = Maps.newHashMap();
-
         Map<String, String> yangToJmxMapping = Maps.newHashMap();
+
+        fillMappingForComposite(openType, innerMap, yangToJmxMapping);
+        return new CompositeAttributeResolvingStrategy(innerMap, openType, yangToJmxMapping);
+    }
+
+    private void fillMappingForComposite(CompositeType openType, Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap, Map<String, String> yangToJmxMapping) {
         for (String innerAttributeKey : openType.keySet()) {
             innerMap.put(innerAttributeKey, caseJavaAttribute(openType.getType(innerAttributeKey)));
             yangToJmxMapping.put(innerAttributeKey, innerAttributeKey);
         }
-        return new CompositeAttributeResolvingStrategy(innerMap, openType, yangToJmxMapping);
+    }
+
+    @Override
+    protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseJavaUnionAttribute(OpenType<?> openType) {
+
+        Preconditions.checkState(openType instanceof CompositeType, "Unexpected open type, expected %s but was %s");
+        CompositeType compositeType = (CompositeType) openType;
+
+        Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap = Maps.newHashMap();
+        Map<String, String> yangToJmxMapping = Maps.newHashMap();
+        fillMappingForComposite(compositeType, innerMap, yangToJmxMapping);
+
+        return new UnionCompositeAttributeResolvingStrategy(innerMap, compositeType, yangToJmxMapping);
     }
 
     @Override
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/UnionCompositeAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/UnionCompositeAttributeResolvingStrategy.java
new file mode 100644 (file)
index 0000000..bc99ecf
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 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.confignetconfconnector.mapping.attributes.resolving;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
+
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import java.util.Map;
+
+final class UnionCompositeAttributeResolvingStrategy extends CompositeAttributeResolvingStrategy {
+
+    UnionCompositeAttributeResolvingStrategy(Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerTypes,
+                                        CompositeType openType, Map<String, String> yangToJavaAttrMapping) {
+        super(innerTypes, openType, yangToJavaAttrMapping);
+    }
+
+    protected Map<String, Object> preprocessValueMap(Map<?, ?> valueMap) {
+        CompositeType openType = getOpenType();
+
+        Preconditions.checkArgument(
+                valueMap.size() == 1 && valueMap.containsKey(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION),
+                "Unexpected structure of incoming map, expecting one element under %s, but was %s",
+                JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION, valueMap);
+
+        Map<String, Object> newMap = Maps.newHashMap();
+
+        for (String key : openType.keySet()) {
+            if (openType.getDescription(key).equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION))
+                newMap.put(key, valueMap.get(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION));
+            else
+                newMap.put(key, null);
+        }
+        return newMap;
+    }
+}
index a174e9a25160e8aa3d52ab66891c9d1314e58185..4e870f042d8cf45605546750d0f99868772fa897 100644 (file)
@@ -73,6 +73,11 @@ public class ObjectXmlWriter extends AttributeIfcSwitchStatement<AttributeWritin
         return new SimpleCompositeAttributeWritingStrategy(document, key);
     }
 
+    @Override
+    protected AttributeWritingStrategy caseJavaUnionAttribute(OpenType<?> openType) {
+        return new SimpleUnionAttributeWritingStrategy(document, key);
+    }
+
     @Override
     protected AttributeWritingStrategy caseDependencyAttribute(SimpleType<?> openType) {
         return new ObjectNameAttributeWritingStrategy(document, key);
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleUnionAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleUnionAttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..d75feb2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 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.confignetconfconnector.mapping.attributes.toxml;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.w3c.dom.Document;
+
+import java.util.List;
+import java.util.Map;
+
+public class SimpleUnionAttributeWritingStrategy extends SimpleAttributeWritingStrategy {
+
+    /**
+     * @param document
+     * @param key
+     */
+    public SimpleUnionAttributeWritingStrategy(Document document, String key) {
+        super(document, key);
+    }
+
+    protected Object preprocess(Object value) {
+        Util.checkType(value, Map.class);
+        Preconditions.checkArgument(((Map)value).size() == 1, "Unexpected number of values in %s, expected 1", value);
+        Object listOfStrings = ((Map) value).values().iterator().next();
+        Util.checkType(listOfStrings, List.class);
+
+        StringBuilder b = new StringBuilder();
+        for (Object character: (List)listOfStrings) {
+            Util.checkType(character, String.class);
+            b.append(character);
+        }
+
+        return b.toString();
+    }
+
+}
index 26719592bbbe4dd7e553534a1d9fbafe89fbc097..1c806742e9b141c7f836d9565a9f449255406b69 100644 (file)
@@ -38,7 +38,7 @@ public final class Util {
 
     public static void checkType(final Object value, final Class<?> clazz) {
         Preconditions.checkArgument(clazz.isAssignableFrom(value.getClass()), "Unexpected type " + value.getClass()
-                + " should be " + clazz);
+                + " should be " + clazz + " of " + value);
     }
 
     // TODO: add message and proper error types
index b248342a0a9c308a23714a3f82966f11456faa02..11cf1aae6a42bc184dda8288dddcafa9ba47f419 100644 (file)
@@ -144,7 +144,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
                 "ref_from_code_to_instance-from-code_1");
 
         edit("netconfMessages/editConfig_addServiceName.xml");
-         config = getConfigCandidate();
+        config = getConfigCandidate();
         assertCorrectServiceNames(config, 7, "ref_test2", "user_to_instance_from_code", "ref_dep_user",
                 "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
                 "ref_from_code_to_instance-from-code_1", "ref_dep_user_another");
@@ -199,6 +199,29 @@ public class NetconfMappingTest extends AbstractConfigTest {
         }
     }
 
+    @Test
+    public void testConfigNetconfUnionTypes() throws Exception {
+
+        createModule(INSTANCE_NAME);
+
+        edit("netconfMessages/editConfig.xml");
+        commit();
+        Element response = getConfigRunning();
+        String trimmedResponse = XmlUtil.toString(response).replaceAll("\\s", "");
+        assertContainsString(trimmedResponse, "<ipxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">0:0:0:0:0:0:0:1</ip>");
+        assertContainsString(trimmedResponse, "<union-test-attrxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">456</union-test-attr>");
+
+
+        edit("netconfMessages/editConfig_setUnions.xml");
+        commit();
+        response = getConfigRunning();
+
+        trimmedResponse = XmlUtil.toString(response).replaceAll("\\s", "");
+        assertContainsString(trimmedResponse, "<ipxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">127.1.2.3</ip>");
+        assertContainsString(trimmedResponse, "<union-test-attrxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">randomStringForUnion</union-test-attr>");
+
+    }
+
     @Test
     public void testConfigNetconf() throws Exception {
 
index 981be827b74a7714ae7316aedc7a0347d8263f4c..d9466ff00b6d6a0d1e9c034d43ad310600407dd3 100644 (file)
@@ -1,10 +1,9 @@
-/**
- * @author Tomas Olvecky
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
  *
- * 11 2013
- *
- * Copyright (c) 2013 by Cisco Systems, Inc.
- * 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.persist.impl;
 
diff --git a/opendaylight/netconf/ietf-netconf-monitoring/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/netconf/monitoring/rev101004/netconf/state/schemas/LocationBuilder.java b/opendaylight/netconf/ietf-netconf-monitoring/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/netconf/monitoring/rev101004/netconf/state/schemas/LocationBuilder.java
new file mode 100644 (file)
index 0000000..0a084b0
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema.Location;
+
+
+/**
+**/
+public class LocationBuilder {
+
+    public static Location getDefaultInstance(String defaultValue) {
+        return defaultValue.equals("NETCONF") ? new Location(Location.Enumeration.NETCONF) : new Location(new Uri(
+                defaultValue));
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_setUnions.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_setUnions.xml
new file mode 100644 (file)
index 0000000..21db4b8
--- /dev/null
@@ -0,0 +1,30 @@
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>merge</default-operation>
+        <config>
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module>
+                    <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        test-impl:impl-netconf
+                    </type>
+
+                    <name>instance-from-code</name>
+
+                    <ip xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">127.1.2.3</ip>
+                    <union-test-attr xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">randomStringForUnion</union-test-attr>
+
+                </module>
+            </modules>
+
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+            </services>
+        </config>
+    </edit-config>
+</rpc>
diff --git a/pom.xml b/pom.xml
index 6ece420d5ad01e252c431fd7a4ab38f2240dcd3c..f7f9bc2256b35c72697d4deeaef84e70930521ec 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <module>opendaylight/commons/opendaylight</module>
     <module>opendaylight/commons/parent</module>
     <module>opendaylight/commons/logback_settings</module>
-    <module>opendaylight/commons/controller-maven-plugin</module>
   </modules>
 
     <profiles>
                 <module>opendaylight/statisticsmanager/integrationtest</module>
                 <module>opendaylight/commons/integrationtest</module>
                 <module>opendaylight/containermanager/it.implementation</module>
+                <module>opendaylight/distribution/sanitytest/</module>
             </modules>
         </profile>
         <profile>