From: Ed Warnicke Date: Fri, 1 Aug 2014 02:31:30 +0000 (+0000) Subject: Merge "Fixed for bug 1197" X-Git-Tag: release/helium~383 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=c46e223995956f1f759c551163c212947c1e2fb7;hp=092446676c34fc456e02a8f3c206f79edeb42b2b Merge "Fixed for bug 1197" --- diff --git a/features/adsal/pom.xml b/features/adsal/pom.xml new file mode 100644 index 0000000000..0ccb17a664 --- /dev/null +++ b/features/adsal/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.2-SNAPSHOT + ../../opendaylight/commons/opendaylight + + features-adsal + ${sal.version} + pom + Features :: AD-SAL Features + AD-SAL Features POM + + features.xml + + + + org.opendaylight.controller + base-features + ${project.parent.version} + features + xml + runtime + + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + diff --git a/features/adsal/src/main/resources/features.xml b/features/adsal/src/main/resources/features.xml new file mode 100644 index 0000000000..f955315164 --- /dev/null +++ b/features/adsal/src/main/resources/features.xml @@ -0,0 +1,47 @@ + + + + odl-adsal-core + odl-adsal-networkconfiguration + odl-adsal-connection + odl-adsal-clustering + odl-adsal-configuration + + + base-felix-dm + base-dummy-console + odl-adsal-thirdparty + mvn:org.apache.commons/commons-lang3/${commons.lang3.version} + + mvn:org.opendaylight.controller/sal/${sal.version} + mvn:org.opendaylight.controller/sal.implementation/${sal.implementation.version} + + + mvn:org.opendaylight.controller/sal.networkconfiguration/${sal.networkconfiguration.version} + mvn:org.opendaylight.controller/sal.networkconfiguration.implementation/${sal.networkconfiguration.version} + + + odl-adsal-core + mvn:org.opendaylight.controller/sal.connection/${sal.connection.version} + mvn:org.opendaylight.controller/sal.connection.implementation/${sal.connection.version} + + + transaction + base-felix-dm + base-eclipselink-persistence + odl-adsal-core + mvn:org.opendaylight.controller/clustering.services/${clustering.services.version} + mvn:org.opendaylight.controller/clustering.services-implementation/${clustering.services_implementation.version} + mvn:org.opendaylight.controller/clustering.stub/${clustering.stub.version} + + + odl-adsal-core + odl-adsal-clustering + mvn:org.opendaylight.controller/configuration/${configuration.version} + mvn:org.opendaylight.controller/configuration.implementation/${configuration.implementation.version} + + + mvn:org.opendaylight.controller/logging.bridge/${logging.bridge.version} + + diff --git a/features/base/src/main/resources/features.xml b/features/base/src/main/resources/features.xml index 60286175c1..b9107b9f62 100644 --- a/features/base/src/main/resources/features.xml +++ b/features/base/src/main/resources/features.xml @@ -79,6 +79,8 @@ mvn:eclipselink/javax.persistence/2.0.4.v201112161009 mvn:eclipselink/javax.resource/1.5.0.v200906010428 + mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/2.5.0 + mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0 http diff --git a/features/config-netty/pom.xml b/features/config-netty/pom.xml new file mode 100644 index 0000000000..98b97d1d95 --- /dev/null +++ b/features/config-netty/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + org.opendaylight.controller + config-subsystem + 0.2.5-SNAPSHOT + ../../opendaylight/config/ + + config-netty-features + + pom + + + features.xml + + + + + org.opendaylight.controller + config-persister-features + ${config.version} + features + xml + runtime + + + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + diff --git a/features/config-netty/src/main/resources/features.xml b/features/config-netty/src/main/resources/features.xml new file mode 100644 index 0000000000..3121ca01a2 --- /dev/null +++ b/features/config-netty/src/main/resources/features.xml @@ -0,0 +1,16 @@ + + + + mvn:org.opendaylight.controller/config-persister-features/${config.version}/xml/features + + odl-config-netty-config-api + mvn:org.opendaylight.controller/netty-event-executor-config/${project.version} + mvn:org.opendaylight.controller/netty-threadgroup-config/${project.version} + mvn:org.opendaylight.controller/netty-timer-config/${project.version} + mvn:org.opendaylight.controller/threadpool-config-api/${project.version} + mvn:org.opendaylight.controller/threadpool-config-impl/${project.version} + odl-config-startup + + \ No newline at end of file diff --git a/features/config-persister/pom.xml b/features/config-persister/pom.xml new file mode 100644 index 0000000000..969d0c8841 --- /dev/null +++ b/features/config-persister/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + org.opendaylight.controller + config-subsystem + 0.2.5-SNAPSHOT + ../../opendaylight/config/ + + config-persister-features + + pom + + + features.xml + + + + + org.opendaylight.yangtools + features-yangtools + ${yangtools.version} + features + xml + runtime + + + org.opendaylight.controller + netconf-features + ${netconf.version} + features + xml + runtime + + + org.opendaylight.controller + config-features + ${config.version} + features + xml + runtime + + + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + diff --git a/features/config-persister/src/main/resources/features.xml b/features/config-persister/src/main/resources/features.xml new file mode 100644 index 0000000000..2273a4a309 --- /dev/null +++ b/features/config-persister/src/main/resources/features.xml @@ -0,0 +1,32 @@ + + + + mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features + mvn:org.opendaylight.controller/netconf-features/${netconf.version}/xml/features + mvn:org.opendaylight.controller/config-features/${config.version}/xml/features + + odl-config-netconf-connector + odl-config-persister + odl-netconf-impl + + + odl-netconf-api + odl-config-api + yangtools-binding-generator + mvn:org.opendaylight.controller/config-persister-api/${project.version} + mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version} + mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version} + mvn:org.opendaylight.controller/config-persister-impl/${project.version} + + mvn:org.opendaylight.controller/netconf-util/${netconf.version} + mvn:org.opendaylight.controller/netconf-mapping-api/${netconf.version} + + mvn:com.google.guava/guava/${guava.version} + mvn:commons-io/commons-io/${commons.io.version} + mvn:org.apache.commons/commons-lang3/${commons.lang3.version} + mvn:org.eclipse.persistence/org.eclipse.persistence.core/${eclipse.persistence.version} + mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/${eclipse.persistence.version} + + \ No newline at end of file diff --git a/opendaylight/config/feature/pom.xml b/features/config/pom.xml similarity index 85% rename from opendaylight/config/feature/pom.xml rename to features/config/pom.xml index aaf33ccc0f..7e5dd6472b 100644 --- a/opendaylight/config/feature/pom.xml +++ b/features/config/pom.xml @@ -5,6 +5,7 @@ org.opendaylight.controller config-subsystem 0.2.5-SNAPSHOT + ../../opendaylight/config/ config-features @@ -14,7 +15,16 @@ features.xml - + + + org.opendaylight.yangtools + features-yangtools + ${yangtools.version} + features + xml + runtime + + diff --git a/features/config/src/main/resources/features.xml b/features/config/src/main/resources/features.xml new file mode 100644 index 0000000000..de5b198173 --- /dev/null +++ b/features/config/src/main/resources/features.xml @@ -0,0 +1,49 @@ + + + + mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features + + + yangtools-concepts + yangtools-binding + yangtools-binding-generator + odl-mdsal-commons + odl-config-api + mvn:org.opendaylight.controller/config-util/${project.version} + mvn:org.opendaylight.controller/yang-jmx-generator/${project.version} + mvn:org.opendaylight.controller/shutdown-api/${project.version} + mvn:org.opendaylight.controller/shutdown-impl/${project.version} + mvn:org.osgi/org.osgi.core/${osgi.core.version} + mvn:com.google.guava/guava/${guava.version} + mvn:org.javassist/javassist/${javassist.version} + + + odl-config-core + mvn:org.opendaylight.controller/config-manager/${project.version} + + + + mvn:org.opendaylight.controller/config-api/${project.version} + + + yangtools-concepts + yangtools-binding + + + + mvn:org.opendaylight.controller/netty-config-api/${project.version} + + + mvn:io.netty/netty-transport/${netty.version} + mvn:io.netty/netty-common/${netty.version} + mvn:io.netty/netty-buffer/${netty.version} + + odl-config-api + + + mvn:org.opendaylight.controller/netconf-config-dispatcher/${project.version} + + + \ No newline at end of file diff --git a/features/extras/pom.xml b/features/extras/pom.xml new file mode 100644 index 0000000000..4563190b9f --- /dev/null +++ b/features/extras/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.2-SNAPSHOT + ../../opendaylight/commons/opendaylight + + extras-features + kar + ${project.artifactId} + Base Features POM + + features.xml + 3.9.2.Final + + + + + true + src/main/resources + + + + + org.apache.karaf.tooling + karaf-maven-plugin + ${karaf.version} + true + + + features-create-kar + + features-create-kar + + + ${project.build.directory}/classes/${features.file} + + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + diff --git a/features/extras/src/main/resources/features.xml b/features/extras/src/main/resources/features.xml new file mode 100644 index 0000000000..3be66d9a6e --- /dev/null +++ b/features/extras/src/main/resources/features.xml @@ -0,0 +1,34 @@ + + + + + mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version} + + + + mvn:org.scala-lang/scala-library/${scala.version}.${scala.micro.version} + mvn:org.scala-lang/scala-reflect/${scala.version}.${scala.micro.version} + + + + odl-extras-scala + mvn:com.typesafe/config/${typesafe.config.version} + mvn:com.typesafe.akka/akka-actor_${scala.version}/${akka.version} + mvn:com.typesafe.akka/akka-slf4j_${scala.version}/${akka.version} + mvn:com.typesafe.akka/akka-osgi_${scala.version}/${akka.version} + + + + odl-extras-akka-system + wrap:mvn:org.uncommons.maths/uncommons-maths/${uncommons.maths.version} + mvn:com.google.protobuf/protobuf-java/${protobuf.version} + wrap:mvn:io.netty/netty/${netty3.version} + mvn:com.typesafe.akka/akka-remote_${scala.version}/${akka.version} + mvn:com.typesafe.akka/akka-cluster_${scala.version}/${akka.version} + + + + wrap:mvn:org.iq80.leveldb/leveldb/${leveldb.version} + wrap:mvn:org.fusesource.leveldbjni/leveldbjni-all/${leveldbjni.version} + + diff --git a/opendaylight/md-sal/feature/pom.xml b/features/mdsal/pom.xml similarity index 97% rename from opendaylight/md-sal/feature/pom.xml rename to features/mdsal/pom.xml index c08c3e5606..2983c5efab 100644 --- a/opendaylight/md-sal/feature/pom.xml +++ b/features/mdsal/pom.xml @@ -5,6 +5,7 @@ org.opendaylight.controller sal-parent 1.1-SNAPSHOT + ../../opendaylight/md-sal mdsal-features diff --git a/opendaylight/md-sal/feature/src/main/resources/features.xml b/features/mdsal/src/main/resources/features.xml similarity index 56% rename from opendaylight/md-sal/feature/src/main/resources/features.xml rename to features/mdsal/src/main/resources/features.xml index 16b4574037..7d393bc64c 100644 --- a/opendaylight/md-sal/feature/src/main/resources/features.xml +++ b/features/mdsal/src/main/resources/features.xml @@ -9,20 +9,20 @@ odl-mdsal-restconf - yangtools-concepts - yangtools-binding + yangtools-data-binding mvn:org.opendaylight.controller/sal-common/${project.version} mvn:org.opendaylight.controller/sal-common-api/${project.version} mvn:org.opendaylight.controller/sal-common-impl/${project.version} mvn:org.opendaylight.controller/sal-common-util/${project.version} - wrap:mvn:com.google.guava/guava/${guava.version} - wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version} yangtools-concepts yangtools-binding odl-mdsal-commons - odl-config-subsystem + odl-config-core + odl-config-manager + odl-config-api + odl-config-persister mvn:org.opendaylight.controller/sal-core-api/${project.version} mvn:org.opendaylight.controller/sal-core-spi/${project.version} mvn:org.opendaylight.controller/sal-broker-impl/${project.version} @@ -31,6 +31,7 @@ mvn:org.opendaylight.controller/sal-binding-broker-impl/${project.version} mvn:org.opendaylight.controller/sal-binding-util/${project.version} mvn:org.opendaylight.controller/sal-connector-api/${project.version} + mvn:org.opendaylight.controller/sal-inmemory-datastore/${project.version} odl-mdsal-broker @@ -46,4 +47,32 @@ wrap:mvn:io.netty/netty-handler/${netty.version} wrap:mvn:io.netty/netty-transport/${netty.version} + + mvn:org.opendaylight.controller.model/model-flow-base/${project.version} + mvn:org.opendaylight.controller.model/model-flow-management/${project.version} + mvn:org.opendaylight.controller.model/model-flow-service/${project.version} + mvn:org.opendaylight.controller.model/model-flow-statistics/${project.version} + mvn:org.opendaylight.controller.model/model-inventory/${project.version} + mvn:org.opendaylight.controller.model/model-topology/${project.version} + + + yangtools-concepts + yangtools-binding + odl-mdsal-broker + odl-mdsal-all + mvn:org.opendaylight.controller.samples/sample-toaster/${project.version} + mvn:org.opendaylight.controller.samples/sample-toaster-consumer/${project.version} + mvn:org.opendaylight.controller.samples/sample-toaster-provider/${project.version} + + + mvn:org.opendaylight.controller/sal-netconf-connector/${project.version} + mvn:org.opendaylight.controller/sal-restconf-broker/${project.version} + mvn:org.opendaylight.controller/sal-remote/${project.version} + mvn:org.opendaylight.controller.md/topology-manager/${project.version} + mvn:org.opendaylight.controller.md/topology-lldp-discovery/${project.version} + mvn:org.opendaylight.controller.md/statistics-manager/${project.version} + mvn:org.opendaylight.controller.md/inventory-manager/${project.version} + mvn:org.opendaylight.controller.md/forwardingrules-manager/${project.version} + + diff --git a/features/netconf/pom.xml b/features/netconf/pom.xml new file mode 100644 index 0000000000..90c088eaba --- /dev/null +++ b/features/netconf/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + org.opendaylight.controller + netconf-subsystem + 0.2.5-SNAPSHOT + ../../opendaylight/netconf + + netconf-features + + pom + + + features.xml + + + + + org.opendaylight.controller + config-features + ${config.version} + features + xml + runtime + + + org.opendaylight.controller + features-odl-protocol-framework + ${protocol-framework.version} + features + xml + runtime + + + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + diff --git a/features/netconf/src/main/resources/features.xml b/features/netconf/src/main/resources/features.xml new file mode 100644 index 0000000000..50a537b50a --- /dev/null +++ b/features/netconf/src/main/resources/features.xml @@ -0,0 +1,59 @@ + + + + mvn:org.opendaylight.controller/features-odl-protocol-framework/${protocol-framework.version}/xml/features + mvn:org.opendaylight.controller/config-features/${config.version}/xml/features + + + mvn:org.opendaylight.controller/netconf-api/${project.version} + mvn:org.opendaylight.controller/ietf-netconf-monitoring/${project.version} + mvn:org.opendaylight.controller/ietf-netconf-monitoring-extension/${project.version} + odl-protocol-framework + mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf-inet-types.version} + mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf-yang-types.version} + + + odl-netconf-api + mvn:org.opendaylight.controller/netconf-mapping-api/${project.version} + + + odl-netconf-mapping-api + mvn:org.opendaylight.controller/netconf-util/${project.version} + + + odl-config-manager + mvn:org.opendaylight.controller/config-netconf-connector/${project.version} + odl-netconf-api + odl-netconf-mapping-api + odl-netconf-util + + + + mvn:org.opendaylight.controller/netconf-impl/${project.version} + odl-netconf-api + odl-netconf-mapping-api + odl-netconf-util + odl-netconf-netty-util + + + mvn:org.opendaylight.controller/netconf-netty-util/${project.version} + odl-netconf-api + odl-netconf-mapping-api + odl-netconf-util + mvn:org.opendaylight.controller.thirdparty/ganymed/${ganymed.version} + mvn:org.openexi/nagasena/${exi.nagasena.version} + mvn:io.netty/netty-codec/${netty.version} + mvn:io.netty/netty-handler/${netty.version} + mvn:io.netty/netty-common/${netty.version} + mvn:io.netty/netty-buffer/${netty.version} + mvn:io.netty/netty-transport/${netty.version} + + + mvn:org.opendaylight.controller/netconf-client/${project.version} + mvn:org.opendaylight.controller/netconf-monitoring/${project.version} + mvn:org.opendaylight.controller/netconf-tcp/${project.version} + + + \ No newline at end of file diff --git a/features/nsf/pom.xml b/features/nsf/pom.xml new file mode 100644 index 0000000000..224aef1dac --- /dev/null +++ b/features/nsf/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.2-SNAPSHOT + ../../opendaylight/commons/opendaylight + + features-nsf + pom + OpenDaylight :: Features :: Network Service Functions + Feature for Network Service Functions + + features.xml + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + diff --git a/features/nsf/src/main/resources/features.xml b/features/nsf/src/main/resources/features.xml new file mode 100644 index 0000000000..fb61f33fb3 --- /dev/null +++ b/features/nsf/src/main/resources/features.xml @@ -0,0 +1,73 @@ + + + + odl-adsal-all + odl-nsf-managers + odl-adsal-northbound + + + + + base-all + odl-adsal-all + mvn:org.opendaylight.controller/usermanager/${usermanager.version} + mvn:org.opendaylight.controller/usermanager.implementation/${usermanager.version} + + mvn:org.opendaylight.controller/appauth/${appauth.version} + + mvn:org.opendaylight.controller/connectionmanager/${connectionmanager.version} + mvn:org.opendaylight.controller/connectionmanager.implementation/${connectionmanager.version} + + mvn:org.opendaylight.controller/containermanager/${containermanager.version} + mvn:org.opendaylight.controller/containermanager.implementation/${containermanager.version} + + mvn:org.opendaylight.controller/statisticsmanager/${statisticsmanager.version} + mvn:org.opendaylight.controller/statisticsmanager.implementation/${statisticsmanager.implementation.version} + + mvn:org.opendaylight.controller/switchmanager/${switchmanager.api.version} + mvn:org.opendaylight.controller/switchmanager.implementation/${switchmanager.implementation.version} + + mvn:org.opendaylight.controller/forwardingrulesmanager/${forwardingrulesmanager.version} + mvn:org.opendaylight.controller/forwardingrulesmanager.implementation/${forwardingrulesmanager.implementation.version} + + mvn:org.opendaylight.controller/topologymanager/${topologymanager.version} + + mvn:org.opendaylight.controller/networkconfig.neutron/${networkconfig.neutron.version} + mvn:org.opendaylight.controller/networkconfig.neutron.implementation/${networkconfig.neutron.implementation.version} + + mvn:org.opendaylight.controller/hosttracker/${hosttracker.api.version} + mvn:org.opendaylight.controller/hosttracker.implementation/${hosttracker.implementation.version} + + mvn:org.opendaylight.controller/forwarding.staticrouting + + mvn:org.opendaylight.controller.thirdparty/net.sf.jung2/2.0.1 + mvn:org.opendaylight.controller/routing.dijkstra_implementation + + + + base-all + odl-nsf-managers + mvn:org.ow2.asm/asm-all/${asm.version} + + mvn:org.opendaylight.controller/bundlescanner/${bundlescanner.api.version} + mvn:org.opendaylight.controller/bundlescanner.implementation/${bundlescanner.implementation.version} + mvn:org.opendaylight.controller/commons.northbound/${northbound.commons.version} + mvn:org.opendaylight.controller/flowprogrammer.northbound/${flowprogrammer.northbound.version} + mvn:org.opendaylight.controller/hosttracker.northbound/${hosttracker.northbound.version} + mvn:org.opendaylight.controller/networkconfig.bridgedomain.northbound/${networkconfig.bridgedomain.northbound.version} + mvn:org.opendaylight.controller/networkconfig.neutron.northbound/${networkconfig.neutron.northbound.version} + mvn:org.opendaylight.controller/forwarding.staticrouting.northbound/${forwarding.staticrouting.northbound.version} + mvn:org.opendaylight.controller/statistics.northbound/${statistics.northbound.version} + mvn:org.opendaylight.controller/subnets.northbound/${subnets.northbound.version} + mvn:org.opendaylight.controller/switchmanager.northbound/${switchmanager.northbound.version} + mvn:org.opendaylight.controller/topology.northbound/${topology.northbound.version} + mvn:org.opendaylight.controller/usermanager.northbound/${usermanager.northbound.version} + + \ No newline at end of file diff --git a/features/pom.xml b/features/pom.xml new file mode 100644 index 0000000000..f69190cebd --- /dev/null +++ b/features/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.2-SNAPSHOT + ../opendaylight/commons/opendaylight + + features-controller + pom + + 3.0 + + + base + controller + adsal + nsf + extras + config + config-persister + config-netty + mdsal + netconf + protocol-framework + + diff --git a/features/protocol-framework/pom.xml b/features/protocol-framework/pom.xml new file mode 100644 index 0000000000..045ac2dffe --- /dev/null +++ b/features/protocol-framework/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.2-SNAPSHOT + ../../opendaylight/commons/opendaylight + + features-odl-protocol-framework + ${protocol-framework.version} + pom + + + features.xml + + + + + org.opendaylight.controller + config-features + ${config.version} + features + xml + runtime + + + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + diff --git a/features/protocol-framework/src/main/resources/features.xml b/features/protocol-framework/src/main/resources/features.xml new file mode 100644 index 0000000000..d2560f5cb0 --- /dev/null +++ b/features/protocol-framework/src/main/resources/features.xml @@ -0,0 +1,12 @@ + + + + mvn:org.opendaylight.controller/config-features/${config.version}/xml/features + + mvn:org.opendaylight.controller/protocol-framework/${protocol-framework.version} + odl-config-api + odl-config-netty-config-api + + \ No newline at end of file diff --git a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java index fe456f3f8e..4efcada2f8 100644 --- a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java +++ b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java @@ -695,6 +695,8 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA dot1q.setVid(vlan); dot1q.setEtherType(EtherTypes.ARP.shortValue()); dot1q.setPayload(arp); + dot1q.setCfi((byte)0); + dot1q.setPcp((byte)0); ethernet.setEtherType(EtherTypes.VLANTAGGED.shortValue()); ethernet.setPayload(dot1q); } diff --git a/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/jaxb/Context.java b/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/jaxb/Context.java index dbe0745725..cec780c9ec 100644 --- a/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/jaxb/Context.java +++ b/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/jaxb/Context.java @@ -69,9 +69,10 @@ public class Context { initialized = true; } - public List findMatchingFilters(String pathInfo) { + public List findMatchingFilters(String path) { + logger.trace("findMatchingFilters({})", path); checkState(initialized, "Not initialized"); - return urlMatcher.findMatchingFilters(pathInfo); + return urlMatcher.findMatchingFilters(path); } @XmlAttribute(name = "path") diff --git a/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/FilterProcessor.java b/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/FilterProcessor.java index dc3e9dcd49..ae9d79a63d 100644 --- a/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/FilterProcessor.java +++ b/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/FilterProcessor.java @@ -37,14 +37,14 @@ public class FilterProcessor { throws IOException, ServletException { String contextPath = request.getContext().getPath(); - String pathInfo = request.getPathInfo(); + String path = request.getDecodedRequestURI(); Optional maybeContext = host.findContext(contextPath); - logger.trace("Processing context {} path {}, found {}", contextPath, pathInfo, maybeContext); + logger.trace("Processing context {} path {}, found {}", contextPath, path, maybeContext); if (maybeContext.isPresent()) { // process filters Context context = maybeContext.get(); - List matchingFilters = context.findMatchingFilters(pathInfo); + List matchingFilters = context.findMatchingFilters(path); FilterChain fromLast = nextValveFilterChain; ListIterator it = matchingFilters.listIterator(matchingFilters.size()); final boolean trace = logger.isTraceEnabled(); diff --git a/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/UrlMatcher.java b/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/UrlMatcher.java index 9535fb1f70..210326f5d1 100644 --- a/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/UrlMatcher.java +++ b/opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/UrlMatcher.java @@ -62,31 +62,31 @@ public class UrlMatcher { /** * Find filters matching path * - * @param pathInfo as returned by request.getPathInfo() + * @param path relative and decoded path to resource * @return list of matching filters */ - public List findMatchingFilters(String pathInfo) { - checkNotNull(pathInfo); + public List findMatchingFilters(String path) { + checkNotNull(path); TreeMap sortedMap = new TreeMap<>(); // add matching prefixes for (Entry> prefixEntry : prefixMap.entrySet()) { - if (pathInfo.startsWith(prefixEntry.getKey())) { + if (path.startsWith(prefixEntry.getKey())) { put(sortedMap, prefixEntry.getValue()); } } // add matching suffixes for (Entry> suffixEntry : suffixMap.entrySet()) { - if (pathInfo.endsWith(suffixEntry.getKey())) { + if (path.endsWith(suffixEntry.getKey())) { put(sortedMap, suffixEntry.getValue()); } } // add exact match - Entry exactMatch = exactMatchMap.get(pathInfo); + Entry exactMatch = exactMatchMap.get(path); if (exactMatch != null) { put(sortedMap, exactMatch); } ArrayList filters = new ArrayList<>(sortedMap.values()); - logger.trace("Matching filters for path {} are {}", pathInfo, filters); + logger.trace("Matching filters for path {} are {}", path, filters); return filters; } diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index de8caa0e67..be88e4a505 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -18,7 +18,7 @@ - 2.3.2 + 2.3.4 1.0.0 0.4.2-SNAPSHOT 0.0.1-SNAPSHOT @@ -43,7 +43,6 @@ 7.0.32.v201211201952 7.0.32.v201211201952 0.0.3-SNAPSHOT - 1.7 7.0.32.v201211201952 7.0.32.v201211081135 1.2.2 @@ -63,6 +62,7 @@ 2.3.2 0.1.2-SNAPSHOT 0.5.2-SNAPSHOT + 1.4 0.2.5-SNAPSHOT 0.4.3-SNAPSHOT 0.4.3-SNAPSHOT @@ -91,6 +91,7 @@ 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT 0.6.0-SNAPSHOT + 1.1-SNAPSHOT 0.5.2-SNAPSHOT 0.5.2-SNAPSHOT 0.4.2-SNAPSHOT @@ -112,10 +113,13 @@ 1.0.0-SNAPSHOT 3.0.0 3.0.1 + 0.7 + 1.8 1.0.0 1.0.9 0.4.2-SNAPSHOT 3.0.5 + 1.9.4 1.1-SNAPSHOT 0.2.5-SNAPSHOT 0.0.3-SNAPSHOT @@ -129,7 +133,10 @@ 1.4.2-SNAPSHOT 2013.08.27.4-SNAPSHOT 0.0.2-SNAPSHOT + 1.1.6 + 1.1.6 1.0-alpha-2 + 2.5.0 0.5.0-SNAPSHOT 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT @@ -143,14 +150,22 @@ 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT - 2.11 + 2.10 + 4 0.4.2-SNAPSHOT + 1.2.4 dav:http://nexus.opendaylight.org/content/sites/site ${user.name}-private-view https://sonar.opendaylight.org/ jacoco java + org.openflow.openflowj,net.sf.jung2,org.opendaylight.controller.protobuff.messages + 1.0.0 + 1.2.1 + 3.1.4.RELEASE + 3.1.3.RELEASE + 3.1.3.RELEASE org.openflow.openflowj,net.sf.jung2 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT @@ -165,6 +180,8 @@ 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT + 1.2.0 + 1.2.2 0.4.2-SNAPSHOT 0.0.2-SNAPSHOT 0.4.2-SNAPSHOT @@ -1218,6 +1235,11 @@ sal-rest-connector ${mdsal.version} + + org.opendaylight.controller + sal-rest-connector-config + ${mdsal.version} + org.opendaylight.controller sal-rest-docgen @@ -1228,6 +1250,11 @@ sal-restconf-broker ${mdsal.version} + + org.opendaylight.controller + sal-test-model + ${mdsal.version} + @@ -1477,7 +1504,7 @@ org.opendaylight.controller.thirdparty ganymed - 1.1-SNAPSHOT + ${ganymed.version} @@ -2059,7 +2086,7 @@ true ${project.basedir} **\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat - **\/target\/,**\/bin\/,**\/target-ide\/,**\/${jmxGeneratorPath}\/,**\/${salGeneratorPath}\/,**\/xtend-gen\/ + **\/target\/,**\/bin\/,**\/target-ide\/,**\/${jmxGeneratorPath}\/,**\/${salGeneratorPath}\/,**\/xtend-gen\/,**\/protobuff\/ diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java index 580a53be94..12b771df80 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java @@ -32,14 +32,14 @@ public final class ReconnectImmediatelyStrategyFactoryModule extends org.openday @Override protected void customValidation(){ - JmxAttributeValidationException.checkNotNull(getTimeout(), "value is not set.", timeoutJmxAttribute); - JmxAttributeValidationException.checkCondition(getTimeout() >= 0, "value " + getTimeout() + " is less than 0", - timeoutJmxAttribute); + JmxAttributeValidationException.checkNotNull(getReconnectTimeout(), "value is not set.", reconnectTimeoutJmxAttribute); + JmxAttributeValidationException.checkCondition(getReconnectTimeout() >= 0, "value " + getReconnectTimeout() + " is less than 0", + reconnectTimeoutJmxAttribute); } @Override public java.lang.AutoCloseable createInstance() { - return new ReconnectImmediatelyStrategyFactoryCloseable(getExecutorDependency(), getTimeout()); + return new ReconnectImmediatelyStrategyFactoryCloseable(getReconnectExecutorDependency(), getReconnectTimeout()); } private static final class ReconnectImmediatelyStrategyFactoryCloseable implements ReconnectStrategyFactory, AutoCloseable { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java index b8849c7a1d..0b4a7baf6f 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java @@ -49,7 +49,7 @@ public final class TimedReconnectStrategyFactoryModule extends org.opendaylight. @Override public java.lang.AutoCloseable createInstance() { - return new TimedReconnectStrategyFactoryCloseable(getExecutorDependency(), + return new TimedReconnectStrategyFactoryCloseable(getTimedReconnectExecutorDependency(), getConnectTime(), getMinSleep(), getSleepFactor().doubleValue(), getMaxSleep(), getMaxAttempts(), getDeadline()); } diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java index fef2c71969..a62bd7da06 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java @@ -8,9 +8,11 @@ package org.opendaylight.protocol.framework; import com.google.common.base.Preconditions; + import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; +import io.netty.buffer.PooledByteBufAllocator; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; @@ -25,9 +27,11 @@ import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GlobalEventExecutor; import io.netty.util.concurrent.Promise; + import java.io.Closeable; import java.net.InetSocketAddress; import java.net.SocketAddress; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -94,8 +98,8 @@ public abstract class AbstractDispatcher, L extends * * @return ChannelFuture representing the binding process */ - protected ChannelFuture createServer(SocketAddress address, Class channelClass, - final ChannelPipelineInitializer initializer) { + protected ChannelFuture createServer(final SocketAddress address, final Class channelClass, + final ChannelPipelineInitializer initializer) { final ServerBootstrap b = new ServerBootstrap(); b.childHandler(new ChannelInitializer() { @@ -110,6 +114,7 @@ public abstract class AbstractDispatcher, L extends // makes no sense for LocalServer and produces warning b.childOption(ChannelOption.SO_KEEPALIVE, true); } + b.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); customizeBootstrap(b); if (b.group() == null) { @@ -151,9 +156,8 @@ public abstract class AbstractDispatcher, L extends protected Future createClient(final InetSocketAddress address, final ReconnectStrategy strategy, final PipelineInitializer initializer) { final Bootstrap b = new Bootstrap(); final ProtocolSessionPromise p = new ProtocolSessionPromise(executor, address, strategy, b); - b.group(this.workerGroup).channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE, true).handler( + b.option(ChannelOption.SO_KEEPALIVE, true).handler( new ChannelInitializer() { - @Override protected void initChannel(final SocketChannel ch) { initializer.initializeChannel(ch, p); @@ -162,6 +166,18 @@ public abstract class AbstractDispatcher, L extends customizeBootstrap(b); + if (b.group() == null) { + b.group(workerGroup); + } + + // There is no way to detect if this was already set by + // customizeBootstrap() + try { + b.channel(NioSocketChannel.class); + } catch (IllegalStateException e) { + LOG.trace("Not overriding channelFactory on bootstrap {}", b, e); + } + p.connect(); LOG.debug("Client created."); return p; diff --git a/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang b/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang index 1856369178..cd84d4a95e 100644 --- a/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang +++ b/opendaylight/commons/protocol-framework/src/main/yang/odl-protocol-framework-cfg.yang @@ -77,12 +77,12 @@ module protocol-framework { case reconnect-immediately-strategy-factory { when "/config:modules/config:module/config:type = 'reconnect-immediately-strategy-factory'"; - leaf timeout { + leaf reconnect-timeout { mandatory true; type int32; } - container executor { + container reconnect-executor { uses config:service-ref { refine type { mandatory true; @@ -138,7 +138,7 @@ module protocol-framework { units "milliseconds"; } - container executor { + container timed-reconnect-executor { uses config:service-ref { refine type { mandatory true; diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java index 9beadc4dbb..cfdf3bff28 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java @@ -78,7 +78,7 @@ public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest { final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy( transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), ReconnectImmediatelyStrategyFactoryModuleMXBean.class); - mxBean.setTimeout(200); + mxBean.setReconnectTimeout(200); final CommitStatus status = transaction.commit(); assertBeanCount(1, FACTORY_NAME); assertStatus(status, 0, 1, 1); @@ -99,8 +99,8 @@ public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest { final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME); final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, ReconnectImmediatelyStrategyFactoryModuleMXBean.class); - mxBean.setTimeout(timeout); - mxBean.setExecutor(GlobalEventExecutorUtil.create(transaction)); + mxBean.setReconnectTimeout(timeout); + mxBean.setReconnectExecutor(GlobalEventExecutorUtil.create(transaction)); return nameCreated; } diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java index a8cdff7119..1c068a98e7 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java @@ -7,6 +7,13 @@ */ package org.opendaylight.controller.config.yang.protocol.framework; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.math.BigDecimal; +import javax.management.InstanceAlreadyExistsException; +import javax.management.ObjectName; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.ConflictingVersionException; @@ -17,14 +24,6 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory; -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; -import java.math.BigDecimal; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - public class TimedReconnectStrategyModuleTest extends AbstractConfigTest { private static final String INSTANCE_NAME = "timed-reconect-stategy-facotry-impl"; @@ -158,7 +157,7 @@ public class TimedReconnectStrategyModuleTest extends AbstractConfigTest { mxBean.setMaxSleep(maxSleep); mxBean.setMinSleep(minSleep); mxBean.setSleepFactor(sleepFactor); - mxBean.setExecutor(GlobalEventExecutorUtil.create(transaction)); + mxBean.setTimedReconnectExecutor(GlobalEventExecutorUtil.create(transaction)); return nameCreated; } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ServiceReferenceMXBean.java similarity index 87% rename from opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java rename to opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ServiceReferenceMXBean.java index 759541dc26..7ecf758bda 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ServiceReferenceMXBean.java @@ -5,7 +5,7 @@ * 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.config.manager.impl.jmx; +package org.opendaylight.controller.config.api.jmx; import javax.management.ObjectName; diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java index 335acc81fe..07bd63b7c7 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/DynamicWritableWrapper.java @@ -53,12 +53,12 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { private final ReadOnlyAtomicBoolean configBeanModificationDisabled; public DynamicWritableWrapper(Module module, - ModuleIdentifier moduleIdentifier, - TransactionIdentifier transactionIdentifier, - ReadOnlyAtomicBoolean configBeanModificationDisabled, - MBeanServer internalServer, MBeanServer configMBeanServer) { + ModuleIdentifier moduleIdentifier, + TransactionIdentifier transactionIdentifier, + ReadOnlyAtomicBoolean configBeanModificationDisabled, + MBeanServer internalServer, MBeanServer configMBeanServer) { super(module, true, moduleIdentifier, ObjectNameUtil - .createTransactionModuleON(transactionIdentifier.getName(), moduleIdentifier), getOperations(moduleIdentifier), + .createTransactionModuleON(transactionIdentifier.getName(), moduleIdentifier), getOperations(moduleIdentifier), internalServer, configMBeanServer); this.configBeanModificationDisabled = configBeanModificationDisabled; } @@ -67,22 +67,19 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { ModuleIdentifier moduleIdentifier) { Method validationMethod; try { - validationMethod = DynamicWritableWrapper.class.getMethod( - "validate", new Class[0]); + validationMethod = DynamicWritableWrapper.class.getMethod("validate"); } catch (NoSuchMethodException e) { - throw new IllegalStateException("No such method exception on " - + moduleIdentifier, e); + throw new IllegalStateException("No such method exception on " + moduleIdentifier, e); } - return new MBeanOperationInfo[] { new MBeanOperationInfo("Validation", - validationMethod) }; + return new MBeanOperationInfo[]{new MBeanOperationInfo("Validation", validationMethod)}; } @Override public synchronized void setAttribute(Attribute attribute) - throws AttributeNotFoundException, InvalidAttributeValueException, - MBeanException, ReflectionException { - if (configBeanModificationDisabled.get() == true) + throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { + if (configBeanModificationDisabled.get() == true) { throw new IllegalStateException("Operation is not allowed now"); + } if (attribute.getName().equals("Attribute")) { setAttribute((Attribute) attribute.getValue()); @@ -92,7 +89,7 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { try { if (attribute.getValue() instanceof ObjectName) { attribute = fixDependencyAttribute(attribute); - } else if(attribute.getValue() instanceof ObjectName[]) { + } else if (attribute.getValue() instanceof ObjectName[]) { attribute = fixDependencyListAttribute(attribute); } @@ -104,24 +101,19 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { } private Attribute fixDependencyListAttribute(Attribute attribute) { - AttributeHolder attributeHolder = attributeHolderMap - .get(attribute.getName()); + AttributeHolder attributeHolder = attributeHolderMap.get(attribute.getName()); if (attributeHolder.getRequireInterfaceOrNull() != null) { - attribute = new Attribute(attribute.getName(), - fixObjectNames((ObjectName[]) attribute.getValue())); + attribute = new Attribute(attribute.getName(), fixObjectNames((ObjectName[]) attribute.getValue())); } return attribute; } private Attribute fixDependencyAttribute(Attribute attribute) { - AttributeHolder attributeHolder = attributeHolderMap - .get(attribute.getName()); + AttributeHolder attributeHolder = attributeHolderMap.get(attribute.getName()); if (attributeHolder.getRequireInterfaceOrNull() != null) { - attribute = new Attribute(attribute.getName(), - fixObjectName((ObjectName) attribute.getValue())); + attribute = new Attribute(attribute.getName(), fixObjectName((ObjectName) attribute.getValue())); } else { - attribute = new Attribute(attribute.getName(), - attribute.getValue()); + attribute = new Attribute(attribute.getName(), attribute.getValue()); } return attribute; } @@ -145,8 +137,7 @@ public class DynamicWritableWrapper extends AbstractDynamicWrapper { setAttribute(attribute); result.add(attribute); } catch (Exception e) { - logger.warn("Setting attribute {} failed on {}", - attribute.getName(), moduleIdentifier, e); + logger.warn("Setting attribute {} failed on {}", attribute.getName(), moduleIdentifier, e); throw new IllegalArgumentException( "Setting attribute failed - " + attribute.getName() + " on " + moduleIdentifier, e); diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java index dedeeed789..ba6676b927 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.config.manager.impl.jmx; import javax.management.ObjectName; +import org.opendaylight.controller.config.api.jmx.ServiceReferenceMXBean; public class ServiceReferenceMXBeanImpl implements ServiceReferenceMXBean { private ObjectName currentImplementation; diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTracker.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTracker.java index c1ebba7881..eff267ad13 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTracker.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTracker.java @@ -7,6 +7,13 @@ */ package org.opendaylight.controller.config.manager.impl.osgi; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleEvent; @@ -15,74 +22,114 @@ import org.osgi.util.tracker.BundleTrackerCustomizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + /** * - * Extensible bundle tracker. Takes several BundleTrackerCustomizers and propagates bundle events to all of them. - * Primary customizer + * Extensible bundle tracker. Takes several BundleTrackerCustomizers and + * propagates bundle events to all of them. + * + * Primary customizer may return tracking object, + * which will be passed to it during invocation of + * {@link BundleTrackerCustomizer#removedBundle(Bundle, BundleEvent, Future)} + * + * + * This extender modifies behaviour to not leak platform thread + * in {@link BundleTrackerCustomizer#addingBundle(Bundle, BundleEvent)} + * but deliver this event from its own single threaded executor. + * + * If bundle is removed before event for adding bundle was executed, + * that event is cancelled. If addingBundle event is currently in progress + * or was already executed, platform thread is block untill addingBundle + * finishes so bundle could be removed correctly in platform thread. + * + * + * Method {@link BundleTrackerCustomizer#removedBundle(Bundle, BundleEvent, Object)} + * is never invoked on registered trackers. * * @param */ -public final class ExtensibleBundleTracker extends BundleTracker { +public final class ExtensibleBundleTracker extends BundleTracker> { + private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder() + .setNameFormat("config-bundle-tracker-%d") + .build(); + private final ExecutorService eventExecutor; private final BundleTrackerCustomizer primaryTracker; private final BundleTrackerCustomizer[] additionalTrackers; - private static final Logger logger = LoggerFactory.getLogger(ExtensibleBundleTracker.class); + private static final Logger LOG = LoggerFactory.getLogger(ExtensibleBundleTracker.class); - public ExtensibleBundleTracker(BundleContext context, BundleTrackerCustomizer primaryBundleTrackerCustomizer, - BundleTrackerCustomizer... additionalBundleTrackerCustomizers) { + public ExtensibleBundleTracker(final BundleContext context, final BundleTrackerCustomizer primaryBundleTrackerCustomizer, + final BundleTrackerCustomizer... additionalBundleTrackerCustomizers) { this(context, Bundle.ACTIVE, primaryBundleTrackerCustomizer, additionalBundleTrackerCustomizers); } - public ExtensibleBundleTracker(BundleContext context, int bundleState, - BundleTrackerCustomizer primaryBundleTrackerCustomizer, - BundleTrackerCustomizer... additionalBundleTrackerCustomizers) { + public ExtensibleBundleTracker(final BundleContext context, final int bundleState, + final BundleTrackerCustomizer primaryBundleTrackerCustomizer, + final BundleTrackerCustomizer... additionalBundleTrackerCustomizers) { super(context, bundleState, null); this.primaryTracker = primaryBundleTrackerCustomizer; this.additionalTrackers = additionalBundleTrackerCustomizers; - logger.trace("Registered as extender with context {} and bundle state {}", context, bundleState); + eventExecutor = Executors.newSingleThreadExecutor(THREAD_FACTORY); + LOG.trace("Registered as extender with context {} and bundle state {}", context, bundleState); } @Override - public T addingBundle(final Bundle bundle, final BundleEvent event) { - T primaryTrackerRetVal = primaryTracker.addingBundle(bundle, event); - - forEachAdditionalBundle(new BundleStrategy() { + public Future addingBundle(final Bundle bundle, final BundleEvent event) { + LOG.trace("Submiting AddingBundle for bundle {} and event {} to be processed asynchronously",bundle,event); + Future future = eventExecutor.submit(new Callable() { @Override - public void execute(BundleTrackerCustomizer tracker) { - tracker.addingBundle(bundle, event); + public T call() throws Exception { + try { + T primaryTrackerRetVal = primaryTracker.addingBundle(bundle, event); + + forEachAdditionalBundle(new BundleStrategy() { + @Override + public void execute(final BundleTrackerCustomizer tracker) { + tracker.addingBundle(bundle, event); + } + }); + LOG.trace("AddingBundle for {} and event {} finished successfully",bundle,event); + return primaryTrackerRetVal; + } catch (Exception e) { + LOG.error("Failed to add bundle {}",e); + throw e; + } } }); - - return primaryTrackerRetVal; + return future; } @Override - public void modifiedBundle(final Bundle bundle, final BundleEvent event, final T object) { - primaryTracker.modifiedBundle(bundle, event, object); - - forEachAdditionalBundle(new BundleStrategy() { - @Override - public void execute(BundleTrackerCustomizer tracker) { - tracker.modifiedBundle(bundle, event, null); - } - }); + public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Future object) { + // Intentionally NOOP } @Override - public void removedBundle(final Bundle bundle, final BundleEvent event, final T object) { - primaryTracker.removedBundle(bundle, event, object); - - forEachAdditionalBundle(new BundleStrategy() { - @Override - public void execute(BundleTrackerCustomizer tracker) { - tracker.removedBundle(bundle, event, null); - } - }); + public void removedBundle(final Bundle bundle, final BundleEvent event, final Future object) { + if(!object.isDone() && object.cancel(false)) { + // We canceled adding event before it was processed + // so it is safe to return + LOG.trace("Adding Bundle event for {} was cancelled. No additional work required.",bundle); + return; + } + try { + LOG.trace("Invoking removedBundle event for {}",bundle); + primaryTracker.removedBundle(bundle, event, object.get()); + forEachAdditionalBundle(new BundleStrategy() { + @Override + public void execute(final BundleTrackerCustomizer tracker) { + tracker.removedBundle(bundle, event, null); + } + }); + LOG.trace("Removed bundle event for {} finished successfully.",bundle); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Addition of bundle failed, ", e); + } } - private void forEachAdditionalBundle(BundleStrategy lambda) { + private void forEachAdditionalBundle(final BundleStrategy lambda) { for (BundleTrackerCustomizer trac : additionalTrackers) { lambda.execute(trac); } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java index 3e7b65e1bd..8c132c93b2 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java @@ -13,7 +13,7 @@ import org.junit.Test; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.AbstractConfigTest.RecordingBundleContextServiceRegistrationHandler.RegistrationHolder; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; -import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBean; +import org.opendaylight.controller.config.api.jmx.ServiceReferenceMXBean; import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory; import org.opendaylight.controller.config.manager.testingservices.parallelapsp.test.AbstractParallelAPSPTest; import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory; diff --git a/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/pom.xml b/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/pom.xml index 6ddb1306c5..ae041f4585 100644 --- a/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/pom.xml +++ b/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/pom.xml @@ -20,6 +20,7 @@ org.opendaylight.controller config-api + ${config.version} diff --git a/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/src/main/yang/__module-name__-impl.yang b/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/src/main/yang/__module-name__-impl.yang index 8c1dab1495..639610f3d5 100644 --- a/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/src/main/yang/__module-name__-impl.yang +++ b/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/src/main/yang/__module-name__-impl.yang @@ -1,4 +1,3 @@ -// vi: set smarttab et sw=4 tabstop=4: module ${module-name}-${module-implementation-name} { yang-version 1; diff --git a/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/src/main/yang/__module-name__.yang b/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/src/main/yang/__module-name__.yang index 2afc91e8e3..f77df5a22d 100644 --- a/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/src/main/yang/__module-name__.yang +++ b/opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/src/main/yang/__module-name__.yang @@ -1,4 +1,3 @@ -// vi: set smarttab et sw=4 tabstop=4: module ${module-name} { yang-version 1; diff --git a/opendaylight/config/config-util/pom.xml b/opendaylight/config/config-util/pom.xml index b6e2efcd45..7429f4d574 100644 --- a/opendaylight/config/config-util/pom.xml +++ b/opendaylight/config/config-util/pom.xml @@ -8,7 +8,7 @@ .. config-util - jar + bundle ${project.artifactId} @@ -42,6 +42,15 @@ 1 + + org.apache.felix + maven-bundle-plugin + + + org.opendaylight.controller.config.util + + + diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java index 549ff9ffcf..559993f264 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; +import org.opendaylight.controller.config.api.jmx.ServiceReferenceMXBean; public class ConfigRegistryJMXClient implements ConfigRegistryClient { private final ConfigRegistryMXBean configRegistryMXBeanProxy; @@ -65,10 +66,27 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient { configMBeanServer); } + /** + * Usage of this method indicates error as config JMX uses solely MXBeans. + * Use {@link #newMXBeanProxy(javax.management.ObjectName, Class)} + * or {@link JMX#newMBeanProxy(javax.management.MBeanServerConnection, javax.management.ObjectName, Class)} + * This method will be removed soon. + */ + @Deprecated public T newMBeanProxy(ObjectName on, Class clazz) { + on = translateServiceRefIfPossible(on, clazz, configMBeanServer); return JMX.newMBeanProxy(configMBeanServer, on, clazz); } + static ObjectName translateServiceRefIfPossible(ObjectName on, Class clazz, MBeanServer configMBeanServer) { + if (ObjectNameUtil.isServiceReference(on) && clazz.equals(ServiceReferenceMXBean.class) == false) { + ServiceReferenceMXBean proxy = JMX.newMXBeanProxy(configMBeanServer, on, ServiceReferenceMXBean.class); + on = proxy.getCurrentImplementation(); + } + return on; + } + + public T newMXBeanProxy(ObjectName on, Class clazz) { return JMX.newMXBeanProxy(configMBeanServer, on, clazz); } @@ -211,5 +229,4 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient { public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException { configRegistryMXBeanProxy.checkServiceReferenceExists(objectName); } - } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java index 4f02db5a38..f5381424de 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionClient.java @@ -41,4 +41,14 @@ public interface ConfigTransactionClient extends void destroyModule(String moduleName, String instanceName) throws InstanceNotFoundException; void setAttribute(ObjectName on, String jmxName, Attribute attribute); + + /* + * Get the attribute named jmxName from the Object with ObjectName on + * + * @param on - ObjectName of the Object from which the attribute should be read + * @param jmxName - name of the attribute to be read + * + * @return Attribute of Object on with attribute name jmxName + */ + Attribute getAttribute(ObjectName on, String jmxName); } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java index 4adc0d9364..bc18851553 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java @@ -7,12 +7,8 @@ */ package org.opendaylight.controller.config.util; -import org.opendaylight.controller.config.api.ConflictingVersionException; -import org.opendaylight.controller.config.api.ValidationException; -import org.opendaylight.controller.config.api.jmx.CommitStatus; -import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean; -import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean; -import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import java.util.Map; +import java.util.Set; import javax.management.Attribute; import javax.management.InstanceAlreadyExistsException; @@ -22,8 +18,13 @@ import javax.management.JMX; import javax.management.MBeanException; import javax.management.MBeanServer; import javax.management.ObjectName; -import java.util.Map; -import java.util.Set; + +import org.opendaylight.controller.config.api.ConflictingVersionException; +import org.opendaylight.controller.config.api.ValidationException; +import org.opendaylight.controller.config.api.jmx.CommitStatus; +import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean; +import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean; +import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; public class ConfigTransactionJMXClient implements ConfigTransactionClient { private final ConfigRegistryMXBean configRegistryMXBeanProxy; @@ -44,9 +45,21 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { } public T newMXBeanProxy(ObjectName on, Class clazz) { + // if on is without transaction, add it. Reason is that when using getters on MXBeans the transaction name is stripped + on = ObjectNameUtil.withTransactionName(on, getTransactionName()); + // if this is service reference and user requests for implementation, look it up + on = ConfigRegistryJMXClient.translateServiceRefIfPossible(on, clazz, configMBeanServer); + on = ObjectNameUtil.withTransactionName(on, getTransactionName()); return JMX.newMXBeanProxy(configMBeanServer, on, clazz); } + /** + * Usage of this method indicates error as config JMX uses solely MXBeans. + * Use {@link #newMXBeanProxy(javax.management.ObjectName, Class)} + * or {@link JMX#newMBeanProxy(javax.management.MBeanServerConnection, javax.management.ObjectName, Class)} + * This method will be removed soon. + */ + @Deprecated public T newMBeanProxy(ObjectName on, Class clazz) { return JMX.newMBeanProxy(configMBeanServer, on, clazz); } @@ -259,6 +272,20 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient { } } + @Override + public Attribute getAttribute(ObjectName on, String attrName) { + if (ObjectNameUtil.getTransactionName(on) == null) + throw new IllegalArgumentException("Not in transaction instance " + + on + ", no transaction name present"); + + try { + return new Attribute(attrName, configMBeanServer.getAttribute(on,attrName)); + } catch (JMException e) { + throw new IllegalStateException("Unable to get attribute " + + attrName + " for " + on, e); + } + } + @Override public Set getAvailableModuleFactoryQNames() { return configTransactionControllerMXBeanProxy.getAvailableModuleFactoryQNames(); diff --git a/opendaylight/config/feature/src/main/resources/features.xml b/opendaylight/config/feature/src/main/resources/features.xml deleted file mode 100644 index 81972c3661..0000000000 --- a/opendaylight/config/feature/src/main/resources/features.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - odl-config-subsystem - - - - yangtools-concepts - yangtools-binding - yangtools-binding-generator - odl-mdsal-commons - mvn:org.opendaylight.controller/config-api/${project.version} - mvn:org.opendaylight.controller/config-manager/${project.version} - mvn:org.opendaylight.controller/yang-jmx-generator/${project.version} - mvn:org.opendaylight.controller/config-persister-api/${project.version} - mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version} - mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version} - mvn:org.opendaylight.controller/shutdown-api/${project.version} - mvn:org.opendaylight.controller/shutdown-impl/${project.version} - mvn:org.osgi/org.osgi.core/${osgi.core.version} - wrap:mvn:com.google.guava/guava/${guava.version} - mvn:org.javassist/javassist/${javassist.version} - - \ No newline at end of file diff --git a/opendaylight/config/pom.xml b/opendaylight/config/pom.xml index 76fbd7f6e5..66bb01f051 100644 --- a/opendaylight/config/pom.xml +++ b/opendaylight/config/pom.xml @@ -1,5 +1,4 @@ - 4.0.0 @@ -40,7 +39,6 @@ shutdown-impl netconf-config-dispatcher config-module-archetype - feature diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java index 3dfa6e2bc7..5036399828 100644 --- a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java @@ -10,15 +10,20 @@ package org.opendaylight.controller.config.threadpool.util; import java.io.Closeable; import java.io.IOException; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.opendaylight.controller.config.threadpool.ThreadPool; +import com.google.common.base.Optional; + /** * Implementation of {@link ThreadPool} using flexible number of threads wraps * {@link ExecutorService}. @@ -28,12 +33,33 @@ public class FlexibleThreadPoolWrapper implements ThreadPool, Closeable { public FlexibleThreadPoolWrapper(int minThreadCount, int maxThreadCount, long keepAlive, TimeUnit timeUnit, ThreadFactory threadFactory) { + this(minThreadCount, maxThreadCount, keepAlive, timeUnit, threadFactory, getQueue(Optional.absent())); + } + + public FlexibleThreadPoolWrapper(int minThreadCount, int maxThreadCount, long keepAlive, TimeUnit timeUnit, + ThreadFactory threadFactory, Optional queueCapacity) { + this(minThreadCount, maxThreadCount, keepAlive, timeUnit, threadFactory, getQueue(queueCapacity)); + } + + private FlexibleThreadPoolWrapper(int minThreadCount, int maxThreadCount, long keepAlive, TimeUnit timeUnit, + ThreadFactory threadFactory, BlockingQueue queue) { executor = new ThreadPoolExecutor(minThreadCount, maxThreadCount, keepAlive, timeUnit, - new SynchronousQueue(), threadFactory); + queue, threadFactory, new FlexibleRejectionHandler()); executor.prestartAllCoreThreads(); } + /** + * Overriding the queue: + * ThreadPoolExecutor would not create new threads if the queue is not full, thus adding + * occurs in RejectedExecutionHandler. + * This impl saturates threadpool first, then queue. When both are full caller will get blocked. + */ + private static ForwardingBlockingQueue getQueue(Optional capacity) { + final BlockingQueue delegate = capacity.isPresent() ? new LinkedBlockingQueue(capacity.get()) : new LinkedBlockingQueue(); + return new ForwardingBlockingQueue(delegate); + } + @Override public ExecutorService getExecutor() { return Executors.unconfigurableExecutorService(executor); @@ -77,4 +103,37 @@ public class FlexibleThreadPoolWrapper implements ThreadPool, Closeable { executor.shutdown(); } + /** + * if the max threads are met, then it will raise a rejectedExecution. We then push to the queue. + */ + private static class FlexibleRejectionHandler implements RejectedExecutionHandler { + @Override + public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { + try { + executor.getQueue().put(r); + } catch (InterruptedException e) { + throw new RejectedExecutionException("Interrupted while waiting on the queue", e); + } + } + } + + private static class ForwardingBlockingQueue extends com.google.common.util.concurrent.ForwardingBlockingQueue { + private final BlockingQueue delegate; + + public ForwardingBlockingQueue(BlockingQueue delegate) { + this.delegate = delegate; + } + + @Override + protected BlockingQueue delegate() { + return delegate; + } + + @Override + public boolean offer(final Runnable r) { + // ThreadPoolExecutor will spawn a new thread after core size is reached only + // if the queue.offer returns false. + return false; + } + } } diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/flexible/FlexibleThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/flexible/FlexibleThreadPoolModule.java index 94639d43c0..d6abe168fb 100644 --- a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/flexible/FlexibleThreadPoolModule.java +++ b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/flexible/FlexibleThreadPoolModule.java @@ -17,6 +17,7 @@ */ package org.opendaylight.controller.config.yang.threadpool.impl.flexible; +import com.google.common.base.Optional; import java.util.concurrent.TimeUnit; import org.opendaylight.controller.config.api.JmxAttributeValidationException; @@ -50,11 +51,15 @@ public final class FlexibleThreadPoolModule extends org.opendaylight.controller. JmxAttributeValidationException.checkNotNull(getMaxThreadCount(), maxThreadCountJmxAttribute); JmxAttributeValidationException.checkCondition(getMaxThreadCount() > 0, "must be greater than zero", maxThreadCountJmxAttribute); + + if(getQueueCapacity() != null) { + JmxAttributeValidationException.checkCondition(getQueueCapacity() > 0, "Queue capacity cannot be < 1", queueCapacityJmxAttribute); + } } @Override public java.lang.AutoCloseable createInstance() { return new FlexibleThreadPoolWrapper(getMinThreadCount(), getMaxThreadCount(), getKeepAliveMillis(), - TimeUnit.MILLISECONDS, getThreadFactoryDependency()); + TimeUnit.MILLISECONDS, getThreadFactoryDependency(), Optional.fromNullable(getQueueCapacity())); } } diff --git a/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl-flexible.yang b/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl-flexible.yang index be275ef487..c124f6388f 100644 --- a/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl-flexible.yang +++ b/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl-flexible.yang @@ -46,6 +46,12 @@ module threadpool-impl-flexible { type uint32; } + leaf queueCapacity { + type uint16; + mandatory false; + description "Capacity of queue that holds waiting tasks"; + } + container threadFactory { uses config:service-ref { refine type { diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java index 6eda364af0..33546b1e2a 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java @@ -286,7 +286,7 @@ public class AbsModuleGeneratedObjectFactory { format("private final %s oldModule;\n", abstractFQN.getTypeName())+ format("private final %s oldInstance;\n", AutoCloseable.class.getCanonicalName())+ format("private %s instance;\n", AutoCloseable.class.getCanonicalName())+ - format("private final %s dependencyResolver;\n", DependencyResolver.class.getCanonicalName())+ + format("protected final %s dependencyResolver;\n", DependencyResolver.class.getCanonicalName())+ format("private final %s identifier;\n", ModuleIdentifier.class.getCanonicalName())+ "@Override\n"+ format("public %s getIdentifier() {\n", ModuleIdentifier.class.getCanonicalName())+ diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java index 0fd9720f79..864ebdf954 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java @@ -7,12 +7,40 @@ */ package org.opendaylight.controller.config.yangjmxgenerator.plugin; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.matchers.JUnitMatchers.containsString; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.io.Files; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.io.FileUtils; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; @@ -46,35 +74,6 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.fail; -import static org.junit.matchers.JUnitMatchers.containsString; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; - //TODO: refactor public class JMXGeneratorTest extends AbstractGeneratorTest { @@ -85,7 +84,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest { File generatedResourcesDir; private static final List expectedModuleFileNames = ServiceInterfaceEntryTest - .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]"); + .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, FromGrouping.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]"); private static final List expectedBGPNames = ServiceInterfaceEntryTest .toFileNames("[AbstractBgpListenerImplModule.java, " + "AbstractBgpListenerImplModuleFactory.java, " + @@ -108,7 +107,7 @@ public class JMXGeneratorTest extends AbstractGeneratorTest { "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " + "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java]"); private static final List expectedAllFileNames = ServiceInterfaceEntryTest - .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]"); + .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, FromGrouping.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]"); private static final List expectedGenerateMBEsListNames = ServiceInterfaceEntryTest .toFileNames("[AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java]"); @@ -506,8 +505,9 @@ public class JMXGeneratorTest extends AbstractGeneratorTest { + ".threads.java", visitor.packageName); assertEquals("AsyncEventBusModuleMXBean", visitor.type); - assertEquals("Incorrenct number of generated methods", 2, + assertEquals("Incorrenct number of generated methods", 4, visitor.methods.size()); + } private void assertAbstractDynamicThreadPoolModule(MbeASTVisitor visitor) { diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ConfigConstants.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ConfigConstants.java index ae06400195..775fa9fc20 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ConfigConstants.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ConfigConstants.java @@ -7,11 +7,6 @@ */ package org.opendaylight.controller.config.yangjmxgenerator; -import java.net.URI; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - import org.opendaylight.yangtools.yang.common.QName; public class ConfigConstants { @@ -33,33 +28,14 @@ public class ConfigConstants { public static final QName RPC_CONTEXT_REF_GROUPING_LEAF = createRpcXQName("context-instance"); public static final QName RPC_CONTEXT_INSTANCE_EXTENSION_QNAME = createRpcXQName("rpc-context-instance"); - public static QName createConfigQName(String localName) { - return createQName(CONFIG_NAMESPACE, "2013-04-05", localName); + public static QName createConfigQName(final String localName) { + // FIXME: pre-construct QNameModule + return QName.create(CONFIG_NAMESPACE, "2013-04-05", localName); } - public static QName createRpcXQName(String localName) { - return createQName("urn:ietf:params:xml:ns:yang:rpc-context", + public static QName createRpcXQName(final String localName) { + // FIXME: pre-construct QNameModule + return QName.create("urn:ietf:params:xml:ns:yang:rpc-context", "2013-06-17", localName); } - - /** - * - * @param uri - * @param revisionDate - * in format yyyy-MM-dd - * @param localName - * @return - */ - private static QName createQName(String uri, String revisionDate, - String localName) { - SimpleDateFormat revisionFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date revision; - try { - revision = revisionFormat.parse(revisionDate); - } catch (ParseException e) { - throw new RuntimeException(e); - } - return new QName(URI.create(uri), revision, localName); - } - } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryBuilder.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryBuilder.java index 89f3a4a519..e9f0ac8176 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryBuilder.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryBuilder.java @@ -18,6 +18,7 @@ import com.google.common.base.Optional; import com.google.common.collect.Collections2; import com.google.common.collect.Maps; import com.google.common.collect.Sets; + import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -26,7 +27,9 @@ import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; + import javax.annotation.Nullable; + import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute; @@ -35,6 +38,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribu import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.ServiceRef; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; @@ -64,27 +68,27 @@ final class ModuleMXBeanEntryBuilder { private TypeProviderWrapper typeProviderWrapper; private String packageName; - public ModuleMXBeanEntryBuilder setModule(Module module) { + public ModuleMXBeanEntryBuilder setModule(final Module module) { this.currentModule = module; return this; } - public ModuleMXBeanEntryBuilder setqNamesToSIEs(Map qNamesToSIEs) { + public ModuleMXBeanEntryBuilder setqNamesToSIEs(final Map qNamesToSIEs) { this.qNamesToSIEs = qNamesToSIEs; return this; } - public ModuleMXBeanEntryBuilder setSchemaContext(SchemaContext schemaContext) { + public ModuleMXBeanEntryBuilder setSchemaContext(final SchemaContext schemaContext) { this.schemaContext = schemaContext; return this; } - public ModuleMXBeanEntryBuilder setTypeProviderWrapper(TypeProviderWrapper typeProviderWrapper) { + public ModuleMXBeanEntryBuilder setTypeProviderWrapper(final TypeProviderWrapper typeProviderWrapper) { this.typeProviderWrapper = typeProviderWrapper; return this; } - public ModuleMXBeanEntryBuilder setPackageName(String packageName) { + public ModuleMXBeanEntryBuilder setPackageName(final String packageName) { this.packageName = packageName; return this; } @@ -127,7 +131,7 @@ final class ModuleMXBeanEntryBuilder { Map result = new HashMap<>(); for (AugmentationSchema augmentation : currentModule.getAugmentations()) { - Set childNodes = augmentation.getChildNodes(); + Collection childNodes = augmentation.getChildNodes(); if (areAllChildrenChoiceCaseNodes(childNodes)) { for (ChoiceCaseNode childCase : castChildNodesToChoiceCases(childNodes)) { // TODO refactor, extract to standalone builder class @@ -147,7 +151,7 @@ final class ModuleMXBeanEntryBuilder { return result; } - private static void cleanUpNulls(Map result) { + private static void cleanUpNulls(final Map result) { for (Map.Entry entry : result.entrySet()) { ModuleMXBeanEntry module = entry.getValue(); if (module.getAttributes() == null) { @@ -160,14 +164,14 @@ final class ModuleMXBeanEntryBuilder { } } - private static void checkUnaugumentedIdentities(Map unaugmentedModuleIdentities) { + private static void checkUnaugumentedIdentities(final Map unaugmentedModuleIdentities) { if (unaugmentedModuleIdentities.size() > 0) { logger.warn("Augmentation not found for all currentModule identities: {}", unaugmentedModuleIdentities.keySet()); } } - private static void checkAttributeNamesUniqueness(Map uniqueGeneratedClassesNames, Map result) { + private static void checkAttributeNamesUniqueness(final Map uniqueGeneratedClassesNames, final Map result) { for (Map.Entry entry : result.entrySet()) { checkUniqueRuntimeBeanAttributesName(entry.getValue(), uniqueGeneratedClassesNames); @@ -212,29 +216,30 @@ final class ModuleMXBeanEntryBuilder { return moduleIdentities; } - private Collection castChildNodesToChoiceCases(Set childNodes) { + private Collection castChildNodesToChoiceCases(final Collection childNodes) { return Collections2.transform(childNodes, new Function() { @Nullable @Override - public ChoiceCaseNode apply(@Nullable DataSchemaNode input) { + public ChoiceCaseNode apply(@Nullable final DataSchemaNode input) { return (ChoiceCaseNode) input; } }); } - private boolean areAllChildrenChoiceCaseNodes(Set childNodes) { + private boolean areAllChildrenChoiceCaseNodes(final Iterable childNodes) { for (DataSchemaNode childNode : childNodes) { - if (childNode instanceof ChoiceCaseNode == false) + if (childNode instanceof ChoiceCaseNode == false) { return false; + } } return true; } - private void processChoiceCaseNode(Map result, - Map uniqueGeneratedClassesNames, String configModulePrefix, - Map moduleIdentities, - Map unaugmentedModuleIdentities, AugmentationSchema augmentation, - DataSchemaNode when) { + private void processChoiceCaseNode(final Map result, + final Map uniqueGeneratedClassesNames, final String configModulePrefix, + final Map moduleIdentities, + final Map unaugmentedModuleIdentities, final AugmentationSchema augmentation, + final DataSchemaNode when) { ChoiceCaseNode choiceCaseNode = (ChoiceCaseNode) when; if (choiceCaseNode.getConstraints() == null || choiceCaseNode.getConstraints().getWhenCondition() == null) { @@ -301,12 +306,12 @@ final class ModuleMXBeanEntryBuilder { } checkState(Objects.equals(nullableDummyContainerName, moduleMXBeanEntry.getNullableDummyContainerName()), "Mismatch in module " + moduleMXBeanEntry.toString() + " - dummy container must be present/missing in" + - " both state and configuration"); + " both state and configuration"); } else { ModuleMXBeanEntry.ModuleMXBeanEntryInitial initial = new ModuleMXBeanEntry.ModuleMXBeanEntryInitialBuilder() - .setIdSchemaNode(moduleIdentity).setPackageName(packageName).setJavaNamePrefix(javaNamePrefix) - .setNamespace(currentModule.getNamespace().toString()).setqName(ModuleUtil.getQName(currentModule)) - .build(); + .setIdSchemaNode(moduleIdentity).setPackageName(packageName).setJavaNamePrefix(javaNamePrefix) + .setNamespace(currentModule.getNamespace().toString()).setqName(ModuleUtil.getQName(currentModule)) + .build(); // construct ModuleMXBeanEntry ModuleMXBeanEntry moduleMXBeanEntry = new ModuleMXBeanEntry(initial, yangToAttributes, providedServices, @@ -319,8 +324,8 @@ final class ModuleMXBeanEntryBuilder { } } - private void checkUniqueRuntimeBeansGeneratedClasses(Map uniqueGeneratedClassesNames, - DataSchemaNode when, Collection runtimeBeans) { + private void checkUniqueRuntimeBeansGeneratedClasses(final Map uniqueGeneratedClassesNames, + final DataSchemaNode when, final Collection runtimeBeans) { for (RuntimeBeanEntry runtimeBean : runtimeBeans) { final String javaNameOfRuntimeMXBean = runtimeBean.getJavaNameOfRuntimeMXBean(); if (uniqueGeneratedClassesNames.containsKey(javaNameOfRuntimeMXBean)) { @@ -331,8 +336,8 @@ final class ModuleMXBeanEntryBuilder { } } - private static void checkUniqueRuntimeBeanAttributesName(ModuleMXBeanEntry mxBeanEntry, - Map uniqueGeneratedClassesNames) { + private static void checkUniqueRuntimeBeanAttributesName(final ModuleMXBeanEntry mxBeanEntry, + final Map uniqueGeneratedClassesNames) { for (RuntimeBeanEntry runtimeBeanEntry : mxBeanEntry.getRuntimeBeans()) { for (String runtimeAttName : runtimeBeanEntry.getYangPropertiesToTypesMap().keySet()) { if (mxBeanEntry.getAttributes().keySet().contains(runtimeAttName)) { @@ -344,8 +349,8 @@ final class ModuleMXBeanEntryBuilder { } } - private void checkUniqueAttributesWithGeneratedClass(Map uniqueGeneratedClassNames, - QName parentQName, Map yangToAttributes) { + private void checkUniqueAttributesWithGeneratedClass(final Map uniqueGeneratedClassNames, + final QName parentQName, final Map yangToAttributes) { for (Map.Entry attr : yangToAttributes.entrySet()) { if (attr.getValue() instanceof TOAttribute) { checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName, (TOAttribute) attr.getValue()); @@ -357,7 +362,7 @@ final class ModuleMXBeanEntryBuilder { } } - private void checkUniqueTOAttr(Map uniqueGeneratedClassNames, QName parentQName, TOAttribute attr) { + private void checkUniqueTOAttr(final Map uniqueGeneratedClassNames, final QName parentQName, final TOAttribute attr) { final String upperCaseCamelCase = attr.getUpperCaseCammelCase(); if (uniqueGeneratedClassNames.containsKey(upperCaseCamelCase)) { QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCamelCase); @@ -367,9 +372,9 @@ final class ModuleMXBeanEntryBuilder { } } - private Collection fillRuntimeBeans(DataNodeContainer dataNodeContainer, Module currentModule, - TypeProviderWrapper typeProviderWrapper, String packageName, String moduleLocalNameFromXPath, - String javaNamePrefix) { + private Collection fillRuntimeBeans(final DataNodeContainer dataNodeContainer, final Module currentModule, + final TypeProviderWrapper typeProviderWrapper, final String packageName, final String moduleLocalNameFromXPath, + final String javaNamePrefix) { return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName, dataNodeContainer, moduleLocalNameFromXPath, typeProviderWrapper, javaNamePrefix, currentModule).values(); @@ -383,8 +388,8 @@ final class ModuleMXBeanEntryBuilder { * @param choiceCaseNode state or configuration case statement * @return either choiceCaseNode or its only child container */ - private HAS_CHILDREN_AND_QNAME getDataNodeContainer(ChoiceCaseNode choiceCaseNode) { - Set childNodes = choiceCaseNode.getChildNodes(); + private HAS_CHILDREN_AND_QNAME getDataNodeContainer(final ChoiceCaseNode choiceCaseNode) { + Collection childNodes = choiceCaseNode.getChildNodes(); if (childNodes.size() == 1) { DataSchemaNode onlyChild = childNodes.iterator().next(); if (onlyChild instanceof ContainerSchemaNode) { @@ -398,12 +403,11 @@ final class ModuleMXBeanEntryBuilder { return (HAS_CHILDREN_AND_QNAME) choiceCaseNode; } - private Map fillConfiguration(DataNodeContainer dataNodeContainer, Module currentModule, - TypeProviderWrapper typeProviderWrapper, Map qNamesToSIEs, - SchemaContext schemaContext, String packageName) { + private Map fillConfiguration(final DataNodeContainer dataNodeContainer, final Module currentModule, + final TypeProviderWrapper typeProviderWrapper, final Map qNamesToSIEs, + final SchemaContext schemaContext, final String packageName) { Map yangToAttributes = new HashMap<>(); - Set childNodes = dataNodeContainer.getChildNodes(); - for (DataSchemaNode attrNode : childNodes) { + for (DataSchemaNode attrNode : dataNodeContainer.getChildNodes()) { AttributeIfc attributeValue = getAttributeValue(attrNode, currentModule, qNamesToSIEs, typeProviderWrapper, schemaContext, packageName); yangToAttributes.put(attributeValue.getAttributeYangName(), attributeValue); @@ -411,8 +415,8 @@ final class ModuleMXBeanEntryBuilder { return yangToAttributes; } - private Map findProvidedServices(IdentitySchemaNode moduleIdentity, Module currentModule, - Map qNamesToSIEs, SchemaContext schemaContext) { + private Map findProvidedServices(final IdentitySchemaNode moduleIdentity, final Module currentModule, + final Map qNamesToSIEs, final SchemaContext schemaContext) { Map result = new HashMap<>(); for (UnknownSchemaNode unknownNode : moduleIdentity.getUnknownSchemaNodes()) { if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME.equals(unknownNode.getNodeType())) { @@ -425,9 +429,9 @@ final class ModuleMXBeanEntryBuilder { return result; } - private AttributeIfc getAttributeValue(DataSchemaNode attrNode, Module currentModule, - Map qNamesToSIEs, TypeProviderWrapper typeProviderWrapper, - SchemaContext schemaContext, String packageName) { + private AttributeIfc getAttributeValue(final DataSchemaNode attrNode, final Module currentModule, + final Map qNamesToSIEs, final TypeProviderWrapper typeProviderWrapper, + final SchemaContext schemaContext, final String packageName) { if (attrNode instanceof LeafSchemaNode) { // simple type @@ -460,10 +464,10 @@ final class ModuleMXBeanEntryBuilder { } } - private Optional extractDependency(DataNodeContainer dataNodeContainer, - DataSchemaNode attrNode, Module currentModule, Map qNamesToSIEs, - SchemaContext schemaContext) { - if (dataNodeContainer.getUses().size() == 1 && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) { + private Optional extractDependency(final DataNodeContainer dataNodeContainer, + final DataSchemaNode attrNode, final Module currentModule, final Map qNamesToSIEs, + final SchemaContext schemaContext) { + if (isDependencyContainer(dataNodeContainer)) { // reference UsesNode usesNode = dataNodeContainer.getUses().iterator().next(); checkState(usesNode.getRefines().size() == 1, "Unexpected 'refine' child node size of " + dataNodeContainer); @@ -490,7 +494,19 @@ final class ModuleMXBeanEntryBuilder { return Optional.absent(); } - private int getChildNodeSizeWithoutUses(DataNodeContainer csn) { + private boolean isDependencyContainer(final DataNodeContainer dataNodeContainer) { + if(dataNodeContainer.getUses().size() != 1) { + return false; + } + UsesNode onlyUses = dataNodeContainer.getUses().iterator().next(); + if(onlyUses.getGroupingPath().getLastComponent().equals(ServiceRef.QNAME) == false) { + return false; + } + + return getChildNodeSizeWithoutUses(dataNodeContainer) == 0; + } + + private int getChildNodeSizeWithoutUses(final DataNodeContainer csn) { int result = 0; for (DataSchemaNode dsn : csn.getChildNodes()) { if (dsn.isAddedByUses() == false) { @@ -500,8 +516,8 @@ final class ModuleMXBeanEntryBuilder { return result; } - private ServiceInterfaceEntry findSIE(String prefixAndIdentityLocalName, Module currentModule, - Map qNamesToSIEs, SchemaContext schemaContext) { + private ServiceInterfaceEntry findSIE(final String prefixAndIdentityLocalName, final Module currentModule, + final Map qNamesToSIEs, final SchemaContext schemaContext) { Matcher m = PREFIX_COLON_LOCAL_NAME.matcher(prefixAndIdentityLocalName); Module foundModule; @@ -518,13 +534,13 @@ final class ModuleMXBeanEntryBuilder { foundModule = currentModule; // no prefix => SIE is in currentModule localSIName = prefixAndIdentityLocalName; } - QName siQName = new QName(foundModule.getNamespace(), foundModule.getRevision(), localSIName); + QName siQName = QName.create(foundModule.getNamespace(), foundModule.getRevision(), localSIName); ServiceInterfaceEntry sie = qNamesToSIEs.get(siQName); checkState(sie != null, "Cannot find referenced Service Interface by " + prefixAndIdentityLocalName); return sie; } - private ModuleImport findModuleImport(Module module, String prefix) { + private ModuleImport findModuleImport(final Module module, final String prefix) { for (ModuleImport moduleImport : module.getImports()) { if (moduleImport.getPrefix().equals(prefix)) { return moduleImport; @@ -534,13 +550,13 @@ final class ModuleMXBeanEntryBuilder { } @VisibleForTesting - static Matcher getWhenConditionMatcher(String prefix, RevisionAwareXPath whenConstraint) { + static Matcher getWhenConditionMatcher(final String prefix, final RevisionAwareXPath whenConstraint) { String xpathRegex = MODULE_CONDITION_XPATH_TEMPLATE.replace(MAGIC_STRING, prefix); Pattern pattern = Pattern.compile(xpathRegex); return pattern.matcher(whenConstraint.toString()); } - String getConfigModulePrefixFromImport(Module currentModule) { + String getConfigModulePrefixFromImport(final Module currentModule) { for (ModuleImport currentImport : currentModule.getImports()) { if (currentImport.getModuleName().equals(ConfigConstants.CONFIG_MODULE)) { return currentImport.getPrefix(); diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleUtil.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleUtil.java index 5fea8fd078..ccd701d1fb 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleUtil.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleUtil.java @@ -12,7 +12,7 @@ import org.opendaylight.yangtools.yang.model.api.Module; public class ModuleUtil { - public static QName getQName(Module currentModule){ - return new QName(currentModule.getNamespace(), currentModule.getRevision(), currentModule.getName()); + public static QName getQName(final Module currentModule) { + return QName.create(currentModule.getNamespace(), currentModule.getRevision(), currentModule.getName()); } } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java index c941d1504d..67f624175b 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/RuntimeBeanEntry.java @@ -13,6 +13,7 @@ import static com.google.common.base.Preconditions.checkState; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.collect.Lists; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -25,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; + import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute; import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute; @@ -65,11 +67,11 @@ public class RuntimeBeanEntry { private final Set rpcs; @VisibleForTesting - RuntimeBeanEntry(String packageName, - DataNodeContainer nodeForReporting, String yangName, - String javaNamePrefix, boolean isRoot, - Optional keyYangName, List attributes, - List children, Set rpcs) { + RuntimeBeanEntry(final String packageName, + final DataNodeContainer nodeForReporting, final String yangName, + final String javaNamePrefix, final boolean isRoot, + final Optional keyYangName, final List attributes, + final List children, final Set rpcs) { checkArgument(isRoot == false || keyYangName.isPresent() == false, "Root RuntimeBeanEntry must not have key " + "set"); @@ -86,7 +88,7 @@ public class RuntimeBeanEntry { for (AttributeIfc a : attributes) { checkState(map.containsKey(a.getAttributeYangName()) == false, "Attribute already defined: " + a.getAttributeYangName() - + " in " + nodeForReporting); + + " in " + nodeForReporting); map.put(a.getAttributeYangName(), a); } @@ -110,9 +112,9 @@ public class RuntimeBeanEntry { * not contain special configuration for it. */ public static Map extractClassNameToRuntimeBeanMap( - String packageName, DataNodeContainer container, - String moduleYangName, TypeProviderWrapper typeProviderWrapper, - String javaNamePrefix, Module currentModule) { + final String packageName, final DataNodeContainer container, + final String moduleYangName, final TypeProviderWrapper typeProviderWrapper, + final String javaNamePrefix, final Module currentModule) { Map> identitiesToRpcs = getIdentitiesToRpcs(currentModule); @@ -151,7 +153,7 @@ public class RuntimeBeanEntry { } private static Map> getIdentitiesToRpcs( - Module currentModule) { + final Module currentModule) { // currently only looks for local identities (found in currentModule) Map> result = new HashMap<>(); for (IdentitySchemaNode identity : currentModule.getIdentities()) { @@ -164,14 +166,16 @@ public class RuntimeBeanEntry { if (input != null) { for (UsesNode uses : input.getUses()) { - if (uses.getGroupingPath().getPath().size() != 1) + if (uses.getGroupingPath().getPath().size() != 1) { continue; + } // check grouping path QName qname = uses.getGroupingPath().getPath().get(0); if (false == qname - .equals(ConfigConstants.RPC_CONTEXT_REF_GROUPING_QNAME)) + .equals(ConfigConstants.RPC_CONTEXT_REF_GROUPING_QNAME)) { continue; + } for (SchemaNode refinedNode : uses.getRefines().values()) { @@ -181,7 +185,7 @@ public class RuntimeBeanEntry { .equals(unknownSchemaNode.getNodeType())) { String localIdentityName = unknownSchemaNode .getNodeParameter(); - QName identityQName = new QName( + QName identityQName = QName.create( currentModule.getNamespace(), currentModule.getRevision(), localIdentityName); @@ -208,9 +212,9 @@ public class RuntimeBeanEntry { * in subtree. */ private static AttributesRpcsAndRuntimeBeans extractSubtree( - String packageName, DataNodeContainer subtree, - TypeProviderWrapper typeProviderWrapper, Module currentModule, - Map> identitiesToRpcs) { + final String packageName, final DataNodeContainer subtree, + final TypeProviderWrapper typeProviderWrapper, final Module currentModule, + final Map> identitiesToRpcs) { List attributes = Lists.newArrayList(); // List javaAttributes = new ArrayList<>(); @@ -258,7 +262,7 @@ public class RuntimeBeanEntry { if (ConfigConstants.RPC_CONTEXT_INSTANCE_EXTENSION_QNAME .equals(unknownSchemaNode.getNodeType())) { String localIdentityName = unknownSchemaNode.getNodeParameter(); - QName identityQName = new QName(currentModule.getNamespace(), + QName identityQName = QName.create(currentModule.getNamespace(), currentModule.getRevision(), localIdentityName); Set rpcDefinitions = identitiesToRpcs .get(identityQName); @@ -290,8 +294,8 @@ public class RuntimeBeanEntry { for (DataSchemaNode childNode : sortAttributes(rpcDefinition.getInput() .getChildNodes())) { if (childNode.isAddedByUses() == false) { // skip - // refined - // context-instance + // refined + // context-instance checkArgument(childNode instanceof LeafSchemaNode, "Unexpected type of rpc input type. " + "Currently only leafs and empty output nodes are supported, got " + childNode); JavaAttribute javaAttribute = new JavaAttribute( @@ -310,8 +314,8 @@ public class RuntimeBeanEntry { attributes, rpcs); } - private static AttributeIfc getReturnTypeAttribute(DataSchemaNode child, TypeProviderWrapper typeProviderWrapper, - String packageName) { + private static AttributeIfc getReturnTypeAttribute(final DataSchemaNode child, final TypeProviderWrapper typeProviderWrapper, + final String packageName) { if (child instanceof LeafSchemaNode) { LeafSchemaNode leaf = (LeafSchemaNode) child; return new JavaAttribute(leaf, typeProviderWrapper); @@ -328,10 +332,10 @@ public class RuntimeBeanEntry { } } - private static Collection sortAttributes(Set childNodes) { + private static Collection sortAttributes(final Collection childNodes) { final TreeSet dataSchemaNodes = new TreeSet<>(new Comparator() { @Override - public int compare(DataSchemaNode o1, DataSchemaNode o2) { + public int compare(final DataSchemaNode o1, final DataSchemaNode o2) { return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName()); } }); @@ -339,20 +343,21 @@ public class RuntimeBeanEntry { return dataSchemaNodes; } - private static boolean isInnerStateBean(DataSchemaNode child) { + private static boolean isInnerStateBean(final DataSchemaNode child) { for (UnknownSchemaNode unknownSchemaNode : child .getUnknownSchemaNodes()) { if (unknownSchemaNode.getNodeType().equals( - ConfigConstants.INNER_STATE_BEAN_EXTENSION_QNAME)) + ConfigConstants.INNER_STATE_BEAN_EXTENSION_QNAME)) { return true; + } } return false; } - private static RuntimeBeanEntry createHierarchical(String packageName, - ListSchemaNode listSchemaNode, - TypeProviderWrapper typeProviderWrapper, Module currentModule, - Map> identitiesToRpcs) { + private static RuntimeBeanEntry createHierarchical(final String packageName, + final ListSchemaNode listSchemaNode, + final TypeProviderWrapper typeProviderWrapper, final Module currentModule, + final Map> identitiesToRpcs) { // supported are numeric types, strings, enums // get all attributes @@ -387,10 +392,10 @@ public class RuntimeBeanEntry { return rbFromAttributes; } - private static RuntimeBeanEntry createRoot(String packageName, - DataNodeContainer nodeForReporting, String attributeYangName, - List attributes, String javaNamePrefix, - List children, Set rpcs) { + private static RuntimeBeanEntry createRoot(final String packageName, + final DataNodeContainer nodeForReporting, final String attributeYangName, + final List attributes, final String javaNamePrefix, + final List children, final Set rpcs) { return new RuntimeBeanEntry(packageName, nodeForReporting, attributeYangName, javaNamePrefix, true, Optional. absent(), attributes, children, rpcs); @@ -442,8 +447,8 @@ public class RuntimeBeanEntry { private final Set rpcs; public AttributesRpcsAndRuntimeBeans( - List runtimeBeanEntries, - List attributes, Set rpcs) { + final List runtimeBeanEntries, + final List attributes, final Set rpcs) { this.runtimeBeanEntries = runtimeBeanEntries; this.attributes = attributes; this.rpcs = rpcs; @@ -472,8 +477,8 @@ public class RuntimeBeanEntry { private final AttributeIfc returnType; private final String yangName; - Rpc(AttributeIfc returnType, String name, String yangName, - List parameters) { + Rpc(final AttributeIfc returnType, final String name, final String yangName, + final List parameters) { this.returnType = returnType; this.name = name; this.parameters = parameters; @@ -503,12 +508,12 @@ public class RuntimeBeanEntry { return getJavaNameOfRuntimeMXBean(javaNamePrefix); } - public String getFullyQualifiedName(String typeName) { + public String getFullyQualifiedName(final String typeName) { return FullyQualifiedNameHelper.getFullyQualifiedName(packageName, typeName); } - private static String getJavaNameOfRuntimeMXBean(String javaNamePrefix) { + private static String getJavaNameOfRuntimeMXBean(final String javaNamePrefix) { return javaNamePrefix + MXBEAN_SUFFIX; } diff --git a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java index dd44246867..fab273c600 100644 --- a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java +++ b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ModuleMXBeanEntryTest.java @@ -7,7 +7,35 @@ */ package org.opendaylight.controller.config.yangjmxgenerator; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + import com.google.common.collect.Sets; + +import java.net.URI; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; + +import javax.management.openmbean.ArrayType; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.SimpleType; + import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc; @@ -25,32 +53,6 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath; -import javax.management.openmbean.ArrayType; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.SimpleType; -import java.net.URI; -import java.net.URISyntaxException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; - public class ModuleMXBeanEntryTest extends AbstractYangTest { public static final String PACKAGE_NAME = "pack2"; @@ -95,7 +97,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { PACKAGE_NAME,identitiesToSIs)); Map namesToMBEs = ModuleMXBeanEntry .create(jmxImplModule, modulesToSIEs, context, new TypeProviderWrapper(new TypeProviderImpl(context)) - , PACKAGE_NAME); + , PACKAGE_NAME); Map attributes = namesToMBEs.get("impl-netconf") .getAttributes(); @@ -120,7 +122,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { assertThat(threadFactoryAttribute.getType().getName(), is("ObjectName")); } - private void assertCorrectAttributesSize(Map namesToMBEs, Map attributes) { + private void assertCorrectAttributesSize(final Map namesToMBEs, final Map attributes) { assertEquals(14, attributes.size()); assertEquals(1, namesToMBEs.get("impl-netconf").getRuntimeBeans().size()); assertEquals(2, namesToMBEs.get("impl-netconf").getRuntimeBeans().iterator().next().getAttributes().size()); @@ -131,10 +133,11 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { } protected RuntimeBeanEntry findFirstByYangName( - Collection runtimeBeans, String yangName) { + final Collection runtimeBeans, final String yangName) { for (RuntimeBeanEntry rb : runtimeBeans) { - if (yangName.equals(rb.getYangName())) + if (yangName.equals(rb.getYangName())) { return rb; + } } throw new IllegalArgumentException("Yang name not found:" + yangName + " in " + runtimeBeans); @@ -150,7 +153,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { "/config:modules/config:module/config:type=\"threadpool-dynamic\""); } - private void assertMatches(String prefix, String input) { + private void assertMatches(final String prefix, final String input) { RevisionAwareXPath whenConstraint = mock(RevisionAwareXPath.class); doReturn(input).when(whenConstraint).toString(); Matcher output = ModuleMXBeanEntryBuilder.getWhenConditionMatcher(prefix, @@ -181,7 +184,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { is((Type) Types.typeForClass(Long.class))); } // check dependency on thread factory - QName threadfactoryQName = new QName(THREADS_NAMESPACE, + QName threadfactoryQName = QName.create(THREADS_NAMESPACE, THREADS_REVISION_DATE, "threadfactory"); ServiceInterfaceEntry threadFactorySIEntry = modulesToSIEs .get(threadfactoryQName); @@ -192,7 +195,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { DataSchemaNode mockedDataSchemaNode = mock(DataSchemaNode.class); doReturn(Collections.emptyList()).when(mockedDataSchemaNode) - .getUnknownSchemaNodes(); + .getUnknownSchemaNodes(); doReturn(threadfactoryQName).when(mockedDataSchemaNode).getQName(); AttributeIfc expectedDependencyAttribute = new DependencyAttribute( mockedDataSchemaNode, threadFactorySIEntry, @@ -200,7 +203,7 @@ public class ModuleMXBeanEntryTest extends AbstractYangTest { assertThat(actualThreadFactory, is(expectedDependencyAttribute)); assertThat( dynamicThreadPool - .getFullyQualifiedName("DynamicThreadPoolModuleMXBean"), + .getFullyQualifiedName("DynamicThreadPoolModuleMXBean"), is(PACKAGE_NAME + ".DynamicThreadPoolModuleMXBean")); assertThat(dynamicThreadPool.getNullableDescription(), is("threadpool-dynamic description")); diff --git a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ServiceInterfaceEntryTest.java b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ServiceInterfaceEntryTest.java index eed8695103..f22edbf948 100644 --- a/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ServiceInterfaceEntryTest.java +++ b/opendaylight/config/yang-jmx-generator/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/ServiceInterfaceEntryTest.java @@ -7,7 +7,12 @@ */ package org.opendaylight.controller.config.yangjmxgenerator; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + import com.google.common.collect.Sets; + import java.net.URI; import java.net.URISyntaxException; import java.text.ParseException; @@ -20,13 +25,11 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; + import org.hamcrest.CoreMatchers; import org.junit.Test; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; public class ServiceInterfaceEntryTest extends AbstractYangTest { public static final String PACKAGE_NAME = "packages.sis"; @@ -53,15 +56,15 @@ public class ServiceInterfaceEntryTest extends AbstractYangTest { } } - public static final QName EVENTBUS_QNAME = new QName(THREADS_NAMESPACE, + public static final QName EVENTBUS_QNAME = QName.create(THREADS_NAMESPACE, THREADS_REVISION_DATE, "eventbus"); - public static final QName THREADFACTORY_QNAME = new QName( + public static final QName THREADFACTORY_QNAME = QName.create( THREADS_NAMESPACE, THREADS_REVISION_DATE, "threadfactory"); - public static final QName THREADPOOL_QNAME = new QName(THREADS_NAMESPACE, + public static final QName THREADPOOL_QNAME = QName.create(THREADS_NAMESPACE, THREADS_REVISION_DATE, "threadpool"); - public static final QName SCHEDULED_THREADPOOL_QNAME = new QName( + public static final QName SCHEDULED_THREADPOOL_QNAME = QName.create( THREADS_NAMESPACE, THREADS_REVISION_DATE, "scheduled-threadpool"); - public static final QName SCHEDULED_EXECUTOR_SERVICE_QNAME = new QName( + public static final QName SCHEDULED_EXECUTOR_SERVICE_QNAME = QName.create( THREADS_NAMESPACE, THREADS_REVISION_DATE, "scheduled-executor-service"); public static final String SCHEDULED_THREADPOOL_INTERFACE_NAME = "ScheduledThreadPoolServiceInterface"; @@ -133,9 +136,10 @@ public class ServiceInterfaceEntryTest extends AbstractYangTest { + SCHEDULED_THREADPOOL_INTERFACE_NAME)); } - static String trimInnerSpacesOrNull(String input) { - if (input == null) + static String trimInnerSpacesOrNull(final String input) { + if (input == null) { return null; + } return input.replaceAll("\\s{2,}", " "); } } diff --git a/opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang b/opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang index e189ef7d66..a6d2feaf04 100644 --- a/opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang +++ b/opendaylight/config/yang-jmx-generator/src/test/resources/test-config-threads-java.yang @@ -56,6 +56,12 @@ module config-threads-java { } } + grouping async-eventbus-config-attrs { + leaf cfg-attr { + type string; + } + } + augment "/config:modules/config:module/config:configuration" { case async-eventbus { when "/config:modules/config:module/config:type = 'async-eventbus'"; @@ -66,6 +72,10 @@ module config-threads-java { } } } + + container from-grouping { + uses async-eventbus-config-attrs; + } } } augment "/config:modules/config:module/config:state" { diff --git a/opendaylight/config/yang-test/.gitignore b/opendaylight/config/yang-test/.gitignore deleted file mode 100644 index 14393541b4..0000000000 --- a/opendaylight/config/yang-test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -src/main/java/org/opendaylight/controller/config/yang/test/impl/* diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/.gitignore b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/.gitignore new file mode 100644 index 0000000000..27d1535693 --- /dev/null +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/.gitignore @@ -0,0 +1 @@ +*.java diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java deleted file mode 100644 index 6046665f45..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.opendaylight.controller.config.yang.test.impl; -public class DepTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule { - public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { - super(identifier, dependencyResolver); - } - - public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.test.impl.DepTestImplModule oldModule, java.lang.AutoCloseable oldInstance) { - super(identifier, dependencyResolver, oldModule, oldInstance); - } - - @Override - public void customValidation() { - // add custom validation form module attributes here. - } - - @Override - public java.lang.AutoCloseable createInstance() { - return new AutoCloseable() { - @Override - public void close() throws Exception { - } - }; - - } - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java deleted file mode 100644 index 026dd9aca2..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java +++ /dev/null @@ -1,6 +0,0 @@ - - -package org.opendaylight.controller.config.yang.test.impl; -public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory { - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java deleted file mode 100644 index bda3548892..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.opendaylight.controller.config.yang.test.impl; -public class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule { - public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { - super(identifier, dependencyResolver); - } - - public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.test.impl.IdentityTestModule oldModule, java.lang.AutoCloseable oldInstance) { - super(identifier, dependencyResolver, oldModule, oldInstance); - } - - @Override - public void customValidation() { - // add custom validation form module attributes here. - } - - @Override - public java.lang.AutoCloseable createInstance() { - org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(getClass()); - logger.info("Afi: {}", getAfi()); - logger.info("Afi class: {}", getAfiIdentity()); - - for (Identities identities : getIdentities()) { - logger.info("Identities Afi class: {}", identities.resolveAfi()); - logger.info("Identities Safi class: {}", identities.resolveSafi()); - - } - logger.info("IdentityContainer Afi class: {}", getIdentitiesContainer().resolveAfi()); - - return new AutoCloseable() { - @Override - public void close() throws Exception { - } - }; - - } - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java deleted file mode 100644 index 3a4348d376..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java +++ /dev/null @@ -1,6 +0,0 @@ - - -package org.opendaylight.controller.config.yang.test.impl; -public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory { - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleStub.txt b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleStub.txt new file mode 100644 index 0000000000..80c1e54a15 --- /dev/null +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleStub.txt @@ -0,0 +1,5 @@ + return new AutoCloseable() { + @Override + public void close() throws Exception { + } + }; diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java deleted file mode 100644 index ab43dea5e4..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.opendaylight.controller.config.yang.test.impl; -public class NetconfTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule { - public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { - super(identifier, dependencyResolver); - } - - public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModule oldModule, java.lang.AutoCloseable oldInstance) { - super(identifier, dependencyResolver, oldModule, oldInstance); - } - - @Override - public void customValidation() { - // add custom validation form module attributes here. - } - - @Override - public java.lang.AutoCloseable createInstance() { -return NetconfTestImplModuleUtil.registerRuntimeBeans(this); - - } - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java deleted file mode 100644 index 587089b10f..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java +++ /dev/null @@ -1,6 +0,0 @@ - - -package org.opendaylight.controller.config.yang.test.impl; -public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory { - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleStub.txt b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleStub.txt index 6515412f24..dbb6fe6d67 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleStub.txt +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleStub.txt @@ -1 +1 @@ -return NetconfTestImplModuleUtil.registerRuntimeBeans(this); +return org.opendaylight.controller.config.yang.test.util.NetconfTestImplModuleUtil.registerRuntimeBeans(this); diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java deleted file mode 100644 index 2880b46d1f..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.opendaylight.controller.config.yang.test.impl; -public class TestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule { - public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { - super(identifier, dependencyResolver); - } - - public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.test.impl.TestImplModule oldModule, java.lang.AutoCloseable oldInstance) { - super(identifier, dependencyResolver, oldModule, oldInstance); - } - - @Override - public void customValidation() { - // add custom validation form module attributes here. - } - - @Override - public java.lang.AutoCloseable createInstance() { - return new AutoCloseable() { - @Override - public void close() throws Exception { - } - }; - - } - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java deleted file mode 100644 index de9ac2fef3..0000000000 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java +++ /dev/null @@ -1,6 +0,0 @@ - - -package org.opendaylight.controller.config.yang.test.impl; -public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory { - -} diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/util/NetconfTestImplModuleUtil.java similarity index 69% rename from opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java rename to opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/util/NetconfTestImplModuleUtil.java index 1d5cda036f..5e37f5afcf 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/util/NetconfTestImplModuleUtil.java @@ -1,13 +1,34 @@ -package org.opendaylight.controller.config.yang.test.impl; +/* + * Copyright (c) 2014 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 + */ -import com.google.common.collect.Lists; +package org.opendaylight.controller.config.yang.test.util; +import com.google.common.collect.Lists; import java.util.List; +import org.opendaylight.controller.config.yang.test.impl.Asdf; +import org.opendaylight.controller.config.yang.test.impl.Deep2; +import org.opendaylight.controller.config.yang.test.impl.Deep3; +import org.opendaylight.controller.config.yang.test.impl.Deep4; +import org.opendaylight.controller.config.yang.test.impl.InnerInnerRunningDataRuntimeMXBean; +import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataAdditionalRuntimeMXBean; +import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataRuntimeMXBean; +import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataRuntimeRegistration; +import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModule; +import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplRuntimeMXBean; +import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplRuntimeRegistration; +import org.opendaylight.controller.config.yang.test.impl.NotStateBean; +import org.opendaylight.controller.config.yang.test.impl.RetValContainer; +import org.opendaylight.controller.config.yang.test.impl.RetValList; public class NetconfTestImplModuleUtil { - static NetconfTestImplRuntimeRegistration registerRuntimeBeans(final NetconfTestImplModule module) { + public static NetconfTestImplRuntimeRegistration registerRuntimeBeans(final NetconfTestImplModule module) { NetconfTestImplRuntimeRegistration reg = module.getRootRuntimeBeanRegistratorWrapper().register(new NetconfTestImplRuntimeMXBean() { @Override diff --git a/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang b/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang index 4b006bc72e..e7aa64d7a6 100644 --- a/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang +++ b/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang @@ -41,6 +41,12 @@ module config-test-impl { config:java-name-prefix IdentityTest; } + identity multiple-dependencies { + base config:module-type; + config:provided-service test:testing; + config:java-name-prefix MultipleDependencies; + } + augment "/config:modules/config:module/config:configuration" { case impl-identity-test { when "/config:modules/config:module/config:type = 'impl-identity-test'"; @@ -444,6 +450,24 @@ module config-test-impl { } } + + augment "/config:modules/config:module/config:configuration" { + case multiple-dependencies { + when "/config:modules/config:module/config:type = 'multiple-dependencies'"; + container multiple-dependencies { + list testing-deps { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity test:testing; + } + } + } + } + } + } + + identity test-rpc; identity inner-test-rpc; identity inner-inner-test-rpc; diff --git a/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleTest.java b/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleTest.java new file mode 100644 index 0000000000..2df15d0dc1 --- /dev/null +++ b/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/MultipleDependenciesModuleTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014 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.config.yang.test.impl; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.getInstanceName; +import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.getTransactionName; + +import java.util.List; +import javax.management.ObjectName; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; +import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; +import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; + +public class MultipleDependenciesModuleTest extends AbstractConfigTest { + private static final MultipleDependenciesModuleFactory factory = new MultipleDependenciesModuleFactory(); + + @Before + public void setUp() throws Exception { + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory)); + } + + @Test + public void testMultipleDependencies() throws Exception { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + ObjectName d1 = transaction.createModule(factory.getImplementationName(), "d1"); + ObjectName d2 = transaction.createModule(factory.getImplementationName(), "d2"); + + assertEquals(transaction.getTransactionName(), getTransactionName(d1)); + + ObjectName parent = transaction.createModule(factory.getImplementationName(), "parent"); + MultipleDependenciesModuleMXBean multipleDependenciesModuleMXBean = transaction.newMXBeanProxy(parent, MultipleDependenciesModuleMXBean.class); + multipleDependenciesModuleMXBean.setTestingDeps(asList(d1, d2)); + List found = multipleDependenciesModuleMXBean.getTestingDeps(); + ObjectName d1WithoutTxName = found.get(0); + assertEquals(getInstanceName(d1), getInstanceName(d1WithoutTxName)); + // check that transaction name gets stripped automatically from attribute. + // d1,2 contained tx name, found doesn't + assertNull(getTransactionName(d1WithoutTxName)); + transaction.commit(); + } +} diff --git a/opendaylight/distribution/opendaylight-karaf/pom.xml b/opendaylight/distribution/opendaylight-karaf/pom.xml index 8a23a6b5e6..977fab1334 100644 --- a/opendaylight/distribution/opendaylight-karaf/pom.xml +++ b/opendaylight/distribution/opendaylight-karaf/pom.xml @@ -22,6 +22,12 @@ ${karaf.version} kar + + org.opendaylight.controller + base-features + ${project.version} + kar + org.opendaylight.controller karaf.branding @@ -41,35 +47,48 @@ org.opendaylight.controller base-features + ${project.parent.version} + features + xml + runtime + + + + org.opendaylight.controller + extras-features ${project.version} kar runtime org.opendaylight.controller - config-features + config-netty-features ${config.version} features xml runtime - + org.opendaylight.controller - base-features - ${project.version} + features-adsal + ${sal.version} features xml runtime - --> - + + org.opendaylight.controller mdsal-features @@ -78,14 +97,6 @@ xml runtime - - org.opendaylight.yangtools - features-yangtools - ${yangtools.version} - features - xml - runtime - @@ -233,6 +244,25 @@ + + org.apache.maven.plugins + maven-antrun-plugin + + + prepare-package + + run + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml deleted file mode 100644 index 7853b8681b..0000000000 --- a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - prefix:remote-zeromq-rpc-server - remoter - 5666 - - prefix:dom-broker-osgi-registry - dom-broker - - - - - - - - - - urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28 - urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28 - urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28 - urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-cfg&revision=2013-10-28 - - - diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance new file mode 100755 index 0000000000..7288042bab --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance @@ -0,0 +1,349 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +DIRNAME=`dirname "$0"` +PROGNAME=`basename "$0"` + +# +# Sourcing environment settings for karaf similar to tomcats setenv +# +KARAF_SCRIPT="instance" +export KARAF_SCRIPT +if [ -f "$DIRNAME/setenv" ]; then + . "$DIRNAME/setenv" +fi + +# +# Check/Set up some easily accessible MIN/MAX params for JVM mem usage +# +if [ "x$JAVA_MIN_MEM" = "x" ]; then + JAVA_MIN_MEM=128M + export JAVA_MIN_MEM +fi +if [ "x$JAVA_MAX_MEM" = "x" ]; then + JAVA_MAX_MEM=512M + export JAVA_MAX_MEM +fi + +warn() { + echo "${PROGNAME}: $*" +} + +die() { + warn "$*" + exit 1 +} + +detectOS() { + # OS specific support (must be 'true' or 'false'). + cygwin=false; + darwin=false; + aix=false; + os400=false; + case "`uname`" in + CYGWIN*) + cygwin=true + ;; + Darwin*) + darwin=true + ;; + AIX*) + aix=true + ;; + OS400*) + os400=true + ;; + esac + # For AIX, set an environment variable + if $aix; then + export LDR_CNTRL=MAXDATA=0xB0000000@DSA + echo $LDR_CNTRL + fi +} + +unlimitFD() { + # Use the maximum available, or set MAX_FD != -1 to use that + if [ "x$MAX_FD" = "x" ]; then + MAX_FD="maximum" + fi + + # Increase the maximum file descriptors if we can + if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then + if [ $? -eq 0 ]; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then + # use the system max + MAX_FD="$MAX_FD_LIMIT" + fi + + ulimit -n $MAX_FD > /dev/null + # echo "ulimit -n" `ulimit -n` + if [ $? -ne 0 ]; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT" + fi + fi + fi +} + +locateHome() { + if [ "x$KARAF_HOME" != "x" ]; then + warn "Ignoring predefined value for KARAF_HOME" + fi + + # In POSIX shells, CDPATH may cause cd to write to stdout + (unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + KARAF_HOME=`cd "$DIRNAME/.."; pwd` + if [ ! -d "$KARAF_HOME" ]; then + die "KARAF_HOME is not valid: $KARAF_HOME" + fi +} + +locateBase() { + if [ "x$KARAF_BASE" != "x" ]; then + if [ ! -d "$KARAF_BASE" ]; then + die "KARAF_BASE is not valid: $KARAF_BASE" + fi + else + KARAF_BASE=$KARAF_HOME + fi +} + +locateData() { + if [ "x$KARAF_DATA" != "x" ]; then + if [ ! -d "$KARAF_DATA" ]; then + die "KARAF_DATA is not valid: $KARAF_DATA" + fi + else + KARAF_DATA=$KARAF_BASE/data + fi +} + +locateEtc() { + if [ "x$KARAF_ETC" != "x" ]; then + if [ ! -d "$KARAF_ETC" ]; then + die "KARAF_ETC is not valid: $KARAF_ETC" + fi + else + KARAF_ETC=$KARAF_BASE/etc + fi +} + +setupNativePath() { + # Support for loading native libraries + LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$KARAF_BASE/lib:$KARAF_HOME/lib" + + # For Cygwin, set PATH from LD_LIBRARY_PATH + if $cygwin; then + LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"` + PATH="$PATH;$LD_LIBRARY_PATH" + export PATH + fi + export LD_LIBRARY_PATH +} + +pathCanonical() { + local dst="${1}" + while [ -h "${dst}" ] ; do + ls=`ls -ld "${dst}"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + dst="$link" + else + dst="`dirname "${dst}"`/$link" + fi + done + local bas=`basename "${dst}"` + local dir=`dirname "${dst}"` + if [ "$bas" != "$dir" ]; then + dst="`pathCanonical "$dir"`/$bas" + fi + echo "${dst}" | sed -e 's#//#/#g' -e 's#/./#/#g' -e 's#/[^/]*/../#/#g' +} + +locateJava() { + # Setup the Java Virtual Machine + if $cygwin ; then + [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"` + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + fi + + if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then + JAVA_HOME="$(/usr/libexec/java_home)" + fi + if [ "x$JAVA" = "x" ] && [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi + if [ "x$JAVA" = "x" ]; then + if [ "x$JAVA_HOME" != "x" ]; then + if [ ! -d "$JAVA_HOME" ]; then + die "JAVA_HOME is not valid: $JAVA_HOME" + fi + JAVA="$JAVA_HOME/bin/java" + else + warn "JAVA_HOME not set; results may vary" + JAVA=`type java` + JAVA=`expr "$JAVA" : '.*is \(.*\)$'` + if [ "x$JAVA" = "x" ]; then + die "java command not found" + fi + fi + fi + if [ "x$JAVA_HOME" = "x" ]; then + JAVA_HOME="$(dirname $(dirname $(pathCanonical "$JAVA")))" + fi +} + +detectJVM() { + #echo "`$JAVA -version`" + # This service should call `java -version`, + # read stdout, and look for hints + if $JAVA -version 2>&1 | grep "^IBM" ; then + JVM_VENDOR="IBM" + # on OS/400, java -version does not contain IBM explicitly + elif $os400; then + JVM_VENDOR="IBM" + else + JVM_VENDOR="SUN" + fi + # echo "JVM vendor is $JVM_VENDOR" +} + +setupDebugOptions() { + if [ "x$JAVA_OPTS" = "x" ]; then + JAVA_OPTS="$DEFAULT_JAVA_OPTS" + fi + export JAVA_OPTS + + # Set Debug options if enabled + if [ "x$KARAF_DEBUG" != "x" ]; then + # Use the defaults if JAVA_DEBUG_OPTS was not set + if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then + JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS" + fi + + JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS" + warn "Enabling Java debug options: $JAVA_DEBUG_OPTS" + fi +} + +setupDefaults() { + DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM " + + #Set the JVM_VENDOR specific JVM flags + if [ "$JVM_VENDOR" = "SUN" ]; then + # + # Check some easily accessible MIN/MAX params for JVM mem usage + # + if [ "x$JAVA_PERM_MEM" != "x" ]; then + DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:PermSize=$JAVA_PERM_MEM" + fi + if [ "x$JAVA_MAX_PERM_MEM" != "x" ]; then + DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:MaxPermSize=$JAVA_MAX_PERM_MEM" + fi + DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote" + elif [ "$JVM_VENDOR" = "IBM" ]; then + if $os400; then + DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS" + elif $aix; then + DEFAULT_JAVA_OPTS="-Xverify:none -Xdump:heap -Xlp $DEFAULT_JAVA_OPTS" + else + DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS" + fi + fi + + # Add the jars in the lib dir + for file in "$KARAF_HOME"/lib/*.jar + do + if [ -z "$CLASSPATH" ]; then + CLASSPATH="$file" + else + CLASSPATH="$CLASSPATH:$file" + fi + done + DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005" + + ## + ## TODO: Move to conf/profiler/yourkit.{sh|cmd} + ## + # Uncomment to enable YourKit profiling + #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent" +} + +init() { + # Determine if there is special OS handling we must perform + detectOS + + # Unlimit the number of file descriptors if possible + unlimitFD + + # Locate the Karaf home directory + locateHome + + # Locate the Karaf base directory + locateBase + + # Locate the Karaf data directory + locateData + + # Locate the Karaf etc directory + locateEtc + + # Setup the native library path + setupNativePath + + # Locate the Java VM to execute + locateJava + + # Determine the JVM vendor + detectJVM + + # Setup default options + setupDefaults + + # Install debug options + setupDebugOptions + +} + +run() { + + CLASSPATH="${KARAF_HOME}/system/org/apache/karaf/instance/org.apache.karaf.instance.command/3.0.1/org.apache.karaf.instance.command-3.0.1.jar:${KARAF_HOME}/system/org/apache/karaf/instance/org.apache.karaf.instance.core/3.0.1/org.apache.karaf.instance.core-3.0.1.jar:${KARAF_HOME}/system/org/apache/karaf/shell/org.apache.karaf.shell.console/3.0.1/org.apache.karaf.shell.console-3.0.1.jar:${KARAF_HOME}/system/org/apache/karaf/shell/org.apache.karaf.shell.table/3.0.1/org.apache.karaf.shell.table-3.0.1.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.api/1.0.0/org.apache.aries.blueprint.api-1.0.0.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.core/1.4.0/org.apache.aries.blueprint.core-1.4.0.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.cm/1.0.3/org.apache.aries.blueprint.cm-1.0.3.jar:${KARAF_HOME}/system/org/ops4j/pax/logging/pax-logging-api/1.7.2/pax-logging-api-1.7.2.jar:${KARAF_HOME}/system/org/apache/felix/org.apache.felix.framework/4.2.1/org.apache.felix.framework-4.2.1.jar:${KARAF_HOME}/system/jline/jline/2.11/jline-2.11.jar:$CLASSPATH" + + if $cygwin; then + KARAF_HOME=`cygpath --path --windows "$KARAF_HOME"` + KARAF_BASE=`cygpath --path --windows "$KARAF_BASE"` + KARAF_DATA=`cygpath --path --windows "$KARAF_DATA"` + KARAF_ETC=`cygpath --path --windows "$KARAF_ETC"` + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + fi + + exec "$JAVA" $JAVA_OPTS -Dkaraf.instances="${KARAF_HOME}/instances" -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Dkaraf.etc="$KARAF_ETC" -Djava.io.tmpdir="$KARAF_DATA/tmp" -Djava.util.logging.config.file="$KARAF_BASE/etc/java.util.logging.properties" $KARAF_OPTS $OPTS -classpath "$CLASSPATH" org.apache.karaf.instance.main.Execute "$@" +} + +main() { + init + run "$@" +} + +main "$@" + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance.bat b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance.bat new file mode 100644 index 0000000000..49c2c0fb4e --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance.bat @@ -0,0 +1,151 @@ +@echo off +rem +rem +rem Licensed to the Apache Software Foundation (ASF) under one or more +rem contributor license agreements. See the NOTICE file distributed with +rem this work for additional information regarding copyright ownership. +rem The ASF licenses this file to You under the Apache License, Version 2.0 +rem (the "License"); you may not use this file except in compliance with +rem the License. You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. +rem + +if not "%ECHO%" == "" echo %ECHO% + +setlocal +set DIRNAME=%~dp0% +set PROGNAME=%~nx0% +set ARGS=%* + +rem Sourcing environment settings for karaf similar to tomcats setenv +SET KARAF_SCRIPT="instance.bat" +if exist "%DIRNAME%setenv.bat" ( + call "%DIRNAME%setenv.bat" +) + +rem Check console window title. Set to Karaf by default +if not "%KARAF_TITLE%" == "" ( + title %KARAF_TITLE% +) else ( + title Karaf +) + +rem Check/Set up some easily accessible MIN/MAX params for JVM mem usage +if "%JAVA_MIN_MEM%" == "" ( + set JAVA_MIN_MEM=128M +) +if "%JAVA_MAX_MEM%" == "" ( + set JAVA_MAX_MEM=512M +) + +goto BEGIN + +:warn + echo %PROGNAME%: %* +goto :EOF + +:BEGIN + +rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +if not "%KARAF_HOME%" == "" ( + call :warn Ignoring predefined value for KARAF_HOME +) +set KARAF_HOME=%DIRNAME%.. +if not exist "%KARAF_HOME%" ( + call :warn KARAF_HOME is not valid: "%KARAF_HOME%" + goto END +) + +if not "%KARAF_BASE%" == "" ( + if not exist "%KARAF_BASE%" ( + call :warn KARAF_BASE is not valid: "%KARAF_BASE%" + goto END + ) +) +if "%KARAF_BASE%" == "" ( + set "KARAF_BASE=%KARAF_HOME%" +) + +if not "%KARAF_DATA%" == "" ( + if not exist "%KARAF_DATA%" ( + call :warn KARAF_DATA is not valid: "%KARAF_DATA%" + goto END + ) +) +if "%KARAF_DATA%" == "" ( + set "KARAF_DATA=%KARAF_BASE%\data" +) + +if not "%KARAF_ETC%" == "" ( + if not exist "%KARAF_ETC%" ( + call :warn KARAF_ETC is not valid: "%KARAF_ETC%" + goto END + ) +) +if "%KARAF_ETC%" == "" ( + set "KARAF_ETC=%KARAF_BASE%\etc" +) + +set DEFAULT_JAVA_OPTS= +set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 + +rem Support for loading native libraries +set PATH=%PATH%;%KARAF_BASE%\lib;%KARAF_HOME%\lib + +rem Setup the Java Virtual Machine +if not "%JAVA%" == "" goto :Check_JAVA_END + set JAVA=java + if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary + if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java + if not exist "%JAVA_HOME%" ( + call :warn JAVA_HOME is not valid: "%JAVA_HOME%" + goto END + ) +:Check_JAVA_END + +if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS% + +if "%KARAF_DEBUG%" == "" goto :KARAF_DEBUG_END + rem Use the defaults if JAVA_DEBUG_OPTS was not set + if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS% + + set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%" + call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS% +:KARAF_DEBUG_END + +rem Setup the classpath +pushd "%KARAF_HOME%\lib" +for %%G in (karaf*.jar) do call:APPEND_TO_CLASSPATH %%G +popd +goto CLASSPATH_END + +: APPEND_TO_CLASSPATH +set filename=%~1 +set suffix=%filename:~-4% +if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%KARAF_HOME%\lib\%filename% +goto :EOF + +:CLASSPATH_END + +set CLASSPATH=%KARAF_HOME%\system\org\apache\karaf\instance\org.apache.karaf.instance.command\3.0.1\org.apache.karaf.instance.command-3.0.1.jar;%KARAF_HOME%\system\org\apache\karaf\instance\org.apache.karaf.instance.core\3.0.1\org.apache.karaf.instance.core-3.0.1.jar;%KARAF_HOME%\system\org\apache\karaf\shell\org.apache.karaf.shell.console\3.0.1\org.apache.karaf.shell.console-3.0.1.jar;%KARAF_HOME%\system\org\apache\karaf\shell\org.apache.karaf.shell.table\3.0.1\org.apache.karaf.shell.table-3.0.1.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.api\1.0.0\org.apache.aries.blueprint.api-1.0.0.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.core\1.4.0\org.apache.aries.blueprint.core-1.4.0.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.cm\1.0.3\org.apache.aries.blueprint.cm-1.0.3.jar;%KARAF_HOME%\system\org\ops4j\pax\logging\pax-logging-api\1.7.2\pax-logging-api-1.7.2.jar;%KARAF_HOME%\system\org\apache\felix\org.apache.felix.framework\4.2.1\org.apache.felix.framework-4.2.1.jar;%KARAF_HOME%\system\jline\jline\2.11\jline-2.11.jar;%CLASSPATH% + +:EXECUTE + if "%SHIFT%" == "true" SET ARGS=%2 %3 %4 %5 %6 %7 %8 + if not "%SHIFT%" == "true" SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8 + rem Execute the Java Virtual Machine + "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dkaraf.instances="%KARAF_HOME%\instances" -Dkaraf.home="%KARAF_HOME%" -Dkaraf.base="%KARAF_BASE%" -Dkaraf.etc="%KARAF_ETC%" -Djava.io.tmpdir="%KARAF_DATA%\tmp" -Djava.util.logging.config.file="%KARAF_BASE%\etc\java.util.logging.properties" %KARAF_OPTS% org.apache.karaf.instance.main.Execute %ARGS% + +rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +:END + +endlocal + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf new file mode 100755 index 0000000000..cad052a8ce --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf @@ -0,0 +1,418 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +DIRNAME=`dirname $0` +PROGNAME=`basename $0` + +# +# Sourcing environment settings for karaf similar to tomcats setenv +# +KARAF_SCRIPT="karaf" +export KARAF_SCRIPT +if [ -f "$DIRNAME/setenv" ]; then + . "$DIRNAME/setenv" +fi + +# +# Set up some easily accessible MIN/MAX params for JVM mem usage +# +if [ "x$JAVA_MIN_MEM" = "x" ]; then + JAVA_MIN_MEM=128M + export JAVA_MIN_MEM +fi +if [ "x$JAVA_MAX_MEM" = "x" ]; then + JAVA_MAX_MEM=512M + export JAVA_MAX_MEM +fi + +# +# Check the mode that initiated the script +# +if [ "x$1" != "x" ]; then + MODE=$1 +fi + +warn() { + echo "${PROGNAME}: $*" +} + +die() { + warn "$*" + exit 1 +} + +detectOS() { + # OS specific support (must be 'true' or 'false'). + cygwin=false; + darwin=false; + aix=false; + os400=false; + case "`uname`" in + CYGWIN*) + cygwin=true + ;; + Darwin*) + darwin=true + ;; + AIX*) + aix=true + ;; + OS400*) + os400=true + ;; + esac + # For AIX, set an environment variable + if $aix; then + export LDR_CNTRL=MAXDATA=0xB0000000@DSA + echo $LDR_CNTRL + fi +} + +unlimitFD() { + # Use the maximum available, or set MAX_FD != -1 to use that + if [ "x$MAX_FD" = "x" ]; then + MAX_FD="maximum" + fi + + # Increase the maximum file descriptors if we can + if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then + if [ $? -eq 0 ]; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then + # use the system max + MAX_FD="$MAX_FD_LIMIT" + fi + + ulimit -n $MAX_FD > /dev/null + # echo "ulimit -n" `ulimit -n` + if [ $? -ne 0 ]; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT" + fi + fi + fi +} + +locateHome() { + if [ "x$KARAF_HOME" != "x" ]; then + warn "Ignoring predefined value for KARAF_HOME" + fi + + # In POSIX shells, CDPATH may cause cd to write to stdout + (unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + KARAF_HOME=`cd "$DIRNAME/.."; pwd` + if [ ! -d "$KARAF_HOME" ]; then + die "KARAF_HOME is not valid: $KARAF_HOME" + fi +} + +locateBase() { + if [ "x$KARAF_BASE" != "x" ]; then + if [ ! -d "$KARAF_BASE" ]; then + die "KARAF_BASE is not valid: $KARAF_BASE" + fi + else + KARAF_BASE=$KARAF_HOME + fi +} + +locateData() { + if [ "x$KARAF_DATA" != "x" ]; then + if [ ! -d "$KARAF_DATA" ]; then + die "KARAF_DATA is not valid: $KARAF_DATA" + fi + else + KARAF_DATA=$KARAF_BASE/data + fi +} + +locateEtc() { + if [ "x$KARAF_ETC" != "x" ]; then + if [ ! -d "$KARAF_ETC" ]; then + die "KARAF_ETC is not valid: $KARAF_ETC" + fi + else + KARAF_ETC=$KARAF_BASE/etc + fi +} + +setupNativePath() { + # Support for loading native libraries + LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$KARAF_BASE/lib:$KARAF_HOME/lib" + + # For Cygwin, set PATH from LD_LIBRARY_PATH + if $cygwin; then + LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"` + PATH="$PATH;$LD_LIBRARY_PATH" + export PATH + fi + export LD_LIBRARY_PATH +} + +pathCanonical() { + local dst="${1}" + while [ -h "${dst}" ] ; do + ls=`ls -ld "${dst}"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + dst="$link" + else + dst="`dirname "${dst}"`/$link" + fi + done + local bas=`basename "${dst}"` + local dir=`dirname "${dst}"` + if [ "$bas" != "$dir" ]; then + dst="`pathCanonical "$dir"`/$bas" + fi + echo "${dst}" | sed -e 's#//#/#g' -e 's#/./#/#g' -e 's#/[^/]*/../#/#g' +} + +locateJava() { + # Setup the Java Virtual Machine + if $cygwin ; then + [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"` + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + fi + + if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then + JAVA_HOME="$(/usr/libexec/java_home)" + fi + if [ "x$JAVA" = "x" ] && [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi + if [ "x$JAVA" = "x" ]; then + if [ "x$JAVA_HOME" != "x" ]; then + if [ ! -d "$JAVA_HOME" ]; then + die "JAVA_HOME is not valid: $JAVA_HOME" + fi + JAVA="$JAVA_HOME/bin/java" + else + warn "JAVA_HOME not set; results may vary" + JAVA=`type java` + JAVA=`expr "$JAVA" : '.*is \(.*\)$'` + if [ "x$JAVA" = "x" ]; then + die "java command not found" + fi + fi + fi + if [ "x$JAVA_HOME" = "x" ]; then + JAVA_HOME="$(dirname $(dirname $(pathCanonical "$JAVA")))" + fi +} + +detectJVM() { + #echo "`$JAVA -version`" + # This service should call `java -version`, + # read stdout, and look for hints + if $JAVA -version 2>&1 | grep "^IBM" ; then + JVM_VENDOR="IBM" + # on OS/400, java -version does not contain IBM explicitly + elif $os400; then + JVM_VENDOR="IBM" + else + JVM_VENDOR="SUN" + fi + # echo "JVM vendor is $JVM_VENDOR" +} + +checkJvmVersion() { + # echo "`$JAVA -version`" + VERSION=`$JAVA -version 2>&1 | egrep '"([0-9].[0-9]\..*[0-9])"' | awk '{print substr($3,2,length($3)-2)}' | awk '{print substr($1, 3, 3)}' | sed -e 's;\.;;g'` + # echo $VERSION + if [ "$VERSION" -lt "60" ]; then + echo "JVM must be greater than 1.6" + exit 1; + fi +} + +setupDebugOptions() { + if [ "x$JAVA_OPTS" = "x" ]; then + JAVA_OPTS="$DEFAULT_JAVA_OPTS" + fi + export JAVA_OPTS + + # Set Debug options if enabled + if [ "x$KARAF_DEBUG" != "x" ]; then + # Ignore DEBUG in case of stop or client mode + if [ "x$MODE" = "xstop" ]; then + return + fi + if [ "x$MODE" = "xclient" ]; then + return + fi + # Use the defaults if JAVA_DEBUG_OPTS was not set + if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then + JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS" + fi + + JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS" + warn "Enabling Java debug options: $JAVA_DEBUG_OPTS" + fi +} + +setupDefaults() { + DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass " + + #Set the JVM_VENDOR specific JVM flags + if [ "$JVM_VENDOR" = "SUN" ]; then + # + # Check some easily accessible MIN/MAX params for JVM mem usage + # + if [ "x$JAVA_PERM_MEM" != "x" ]; then + DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:PermSize=$JAVA_PERM_MEM" + fi + if [ "x$JAVA_MAX_PERM_MEM" != "x" ]; then + DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:MaxPermSize=$JAVA_MAX_PERM_MEM" + fi + DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote" + elif [ "$JVM_VENDOR" = "IBM" ]; then + if $os400; then + DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS" + elif $aix; then + DEFAULT_JAVA_OPTS="-Xverify:none -Xdump:heap -Xlp $DEFAULT_JAVA_OPTS" + else + DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS" + fi + fi + + # Add the jars in the lib dir + for file in "$KARAF_HOME"/lib/karaf*.jar + do + if [ -z "$CLASSPATH" ]; then + CLASSPATH="$file" + else + CLASSPATH="$CLASSPATH:$file" + fi + done + DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005" + + ## + ## TODO: Move to conf/profiler/yourkit.{sh|cmd} + ## + # Uncomment to enable YourKit profiling + #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent" +} + +init() { + # Determine if there is special OS handling we must perform + detectOS + + # Unlimit the number of file descriptors if possible + unlimitFD + + # Locate the Karaf home directory + locateHome + + # Locate the Karaf base directory + locateBase + + # Locate the Karaf data directory + locateData + + # Locate the Karaf etc directory + locateEtc + + # Setup the native library path + setupNativePath + + # Locate the Java VM to execute + locateJava + + # Determine the JVM vendor + detectJVM + + # Determine the JVM version >= 1.6 + checkJvmVersion + + # Setup default options + setupDefaults + + # Install debug options + setupDebugOptions + +} + +run() { + OPTS="-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=true" + MAIN=org.apache.karaf.main.Main + while [ "$1" != "" ]; do + case $1 in + 'clean') + rm -Rf "$KARAF_DATA" + shift + ;; + 'debug') + if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then + JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS" + fi + JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS" + shift + ;; + 'status') + MAIN=org.apache.karaf.main.Status + shift + ;; + 'stop') + MAIN=org.apache.karaf.main.Stop + shift + ;; + 'console') + shift + ;; + 'server') + OPTS="-Dkaraf.startLocalConsole=false -Dkaraf.startRemoteShell=true" + shift + ;; + 'client') + OPTS="-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=false" + shift + ;; + *) + break + ;; + esac + done + + JAVA_ENDORSED_DIRS="${JAVA_HOME}/jre/lib/endorsed:${JAVA_HOME}/lib/endorsed:${KARAF_HOME}/lib/endorsed" + JAVA_EXT_DIRS="${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext:${KARAF_HOME}/lib/ext" + if $cygwin; then + KARAF_HOME=`cygpath --path --windows "$KARAF_HOME"` + KARAF_BASE=`cygpath --path --windows "$KARAF_BASE"` + KARAF_DATA=`cygpath --path --windows "$KARAF_DATA"` + KARAF_ETC=`cygpath --path --windows "$KARAF_ETC"` + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"` + JAVA_EXT_DIRS=`cygpath --path --windows "$JAVA_EXT_DIRS"` + fi + cd "$KARAF_BASE" + + exec "$JAVA" $JAVA_OPTS -Djava.endorsed.dirs="${JAVA_ENDORSED_DIRS}" -Djava.ext.dirs="${JAVA_EXT_DIRS}" -Dkaraf.instances="${KARAF_HOME}/instances" -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Dkaraf.data="$KARAF_DATA" -Dkaraf.etc="$KARAF_ETC" -Djava.io.tmpdir="$KARAF_DATA/tmp" -Djava.util.logging.config.file="$KARAF_BASE/etc/java.util.logging.properties" $KARAF_OPTS $OPTS -classpath "$CLASSPATH" $MAIN "$@" +} + +main() { + init + run "$@" +} + +main "$@" diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf.bat b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf.bat new file mode 100644 index 0000000000..a45087730f --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf.bat @@ -0,0 +1,336 @@ +@echo off +rem +rem +rem Licensed to the Apache Software Foundation (ASF) under one or more +rem contributor license agreements. See the NOTICE file distributed with +rem this work for additional information regarding copyright ownership. +rem The ASF licenses this file to You under the Apache License, Version 2.0 +rem (the "License"); you may not use this file except in compliance with +rem the License. You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, software +rem distributed under the License is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem See the License for the specific language governing permissions and +rem limitations under the License. +rem + +if not "%ECHO%" == "" echo %ECHO% + +setlocal +set DIRNAME=%~dp0% +set PROGNAME=%~nx0% +set ARGS=%* + +rem Sourcing environment settings for karaf similar to tomcats setenv +SET KARAF_SCRIPT="karaf.bat" +if exist "%DIRNAME%setenv.bat" ( + call "%DIRNAME%setenv.bat" +) + +rem Check console window title. Set to Karaf by default +if not "%KARAF_TITLE%" == "" ( + title %KARAF_TITLE% +) else ( + title Karaf +) + +rem Check/Set up some easily accessible MIN/MAX params for JVM mem usage +if "%JAVA_MIN_MEM%" == "" ( + set JAVA_MIN_MEM=128M +) +if "%JAVA_MAX_MEM%" == "" ( + set JAVA_MAX_MEM=512M +) + +goto BEGIN + +:warn + echo %PROGNAME%: %* +goto :EOF + +:BEGIN + +rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +if not "%KARAF_HOME%" == "" ( + call :warn Ignoring predefined value for KARAF_HOME +) +set KARAF_HOME=%DIRNAME%.. +if not exist "%KARAF_HOME%" ( + call :warn KARAF_HOME is not valid: "%KARAF_HOME%" + goto END +) + +if not "%KARAF_BASE%" == "" ( + if not exist "%KARAF_BASE%" ( + call :warn KARAF_BASE is not valid: "%KARAF_BASE%" + goto END + ) +) +if "%KARAF_BASE%" == "" ( + set "KARAF_BASE=%KARAF_HOME%" +) + +if not "%KARAF_DATA%" == "" ( + if not exist "%KARAF_DATA%" ( + call :warn KARAF_DATA is not valid: "%KARAF_DATA%" + goto END + ) +) +if "%KARAF_DATA%" == "" ( + set "KARAF_DATA=%KARAF_BASE%\data" +) + +if not "%KARAF_ETC%" == "" ( + if not exist "%KARAF_ETC%" ( + call :warn KARAF_ETC is not valid: "%KARAF_ETC%" + goto END + ) +) +if "%KARAF_ETC%" == "" ( + set "KARAF_ETC=%KARAF_BASE%\etc" +) + +set LOCAL_CLASSPATH=%CLASSPATH% +set JAVA_MODE=-server +if not exist "%JAVA_HOME%\bin\server\jvm.dll" ( + if not exist "%JAVA_HOME%\jre\bin\server\jvm.dll" ( + echo WARNING: Running karaf on a Java HotSpot Client VM because server-mode is not available. + echo Install Java Developer Kit to fix this. + echo For more details see http://java.sun.com/products/hotspot/whitepaper.html#client + set JAVA_MODE=-client + ) +) +set DEFAULT_JAVA_OPTS=%JAVA_MODE% -Xms%JAVA_MIN_MEM% -Xmx%JAVA_MAX_MEM% -Dderby.system.home="%KARAF_DATA%\derby" -Dderby.storage.fileSyncTransactionLog=true -Dcom.sun.management.jmxremote -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass + +rem Check some easily accessible MIN/MAX params for JVM mem usage +if not "%JAVA_PERM_MEM%" == "" ( + set DEFAULT_JAVA_OPTS=%DEFAULT_JAVA_OPTS% -XX:PermSize=%JAVA_PERM_MEM% +) +if not "%JAVA_MAX_PERM_MEM%" == "" ( + set DEFAULT_JAVA_OPTS=%DEFAULT_JAVA_OPTS% -XX:MaxPermSize=%JAVA_MAX_PERM_MEM% +) + +set CLASSPATH=%LOCAL_CLASSPATH%;%KARAF_BASE%\conf +set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 + +if "%LOCAL_CLASSPATH%" == "" goto :KARAF_CLASSPATH_EMPTY + set CLASSPATH=%LOCAL_CLASSPATH%;%KARAF_BASE%\conf + goto :KARAF_CLASSPATH_END +:KARAF_CLASSPATH_EMPTY + set CLASSPATH=%KARAF_BASE%\conf +:KARAF_CLASSPATH_END + +rem Setup Karaf Home +if exist "%KARAF_HOME%\conf\karaf-rc.cmd" call %KARAF_HOME%\conf\karaf-rc.cmd +if exist "%HOME%\karaf-rc.cmd" call %HOME%\karaf-rc.cmd + +rem Support for loading native libraries +set PATH=%PATH%;%KARAF_BASE%\lib;%KARAF_HOME%\lib + +rem Setup the Java Virtual Machine +if not "%JAVA%" == "" goto :Check_JAVA_END + if not "%JAVA_HOME%" == "" goto :TryJDKEnd + call :warn JAVA_HOME not set; results may vary +:TryJRE + start /w regedit /e __reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment" + if not exist __reg1.txt goto :TryJDK + type __reg1.txt | find "CurrentVersion" > __reg2.txt + if errorlevel 1 goto :TryJDK + for /f "tokens=2 delims==" %%x in (__reg2.txt) do set JavaTemp=%%~x + if errorlevel 1 goto :TryJDK + set JavaTemp=%JavaTemp%## + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp:##=% + del __reg1.txt + del __reg2.txt + start /w regedit /e __reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\%JavaTemp%" + if not exist __reg1.txt goto :TryJDK + type __reg1.txt | find "JavaHome" > __reg2.txt + if errorlevel 1 goto :TryJDK + for /f "tokens=2 delims==" %%x in (__reg2.txt) do set JAVA_HOME=%%~x + if errorlevel 1 goto :TryJDK + del __reg1.txt + del __reg2.txt + goto TryJDKEnd +:TryJDK + start /w regedit /e __reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit" + if not exist __reg1.txt ( + goto TryRegJRE + ) + type __reg1.txt | find "CurrentVersion" > __reg2.txt + if errorlevel 1 ( + goto TryRegJRE + ) + for /f "tokens=2 delims==" %%x in (__reg2.txt) do set JavaTemp=%%~x + if errorlevel 1 ( + goto TryRegJRE + ) + set JavaTemp=%JavaTemp%## + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp: ##=##% + set JavaTemp=%JavaTemp:##=% + del __reg1.txt + del __reg2.txt + start /w regedit /e __reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\%JavaTemp%" + if not exist __reg1.txt ( + goto TryRegJRE + ) + type __reg1.txt | find "JavaHome" > __reg2.txt + if errorlevel 1 ( + goto TryRegJRE + ) + for /f "tokens=2 delims==" %%x in (__reg2.txt) do set JAVA_HOME=%%~x + if errorlevel 1 ( + goto TryRegJRE + ) + del __reg1.txt + del __reg2.txt +:TryRegJRE + rem try getting the JAVA_HOME from registry + FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKLM\Software\JavaSoft\Java Runtime Environment" /v CurrentVersion`) DO ( + set JAVA_VERSION=%%A + ) + FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKLM\Software\JavaSoft\Java Runtime Environment\%JAVA_VERSION%" /v JavaHome`) DO ( + set JAVA_HOME=%%A %%B + ) + if not exist "%JAVA_HOME%" ( + goto TryRegJDK + ) + goto TryJDKEnd +:TryRegJDK + rem try getting the JAVA_HOME from registry + FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKLM\Software\JavaSoft\Java Development Kit" /v CurrentVersion`) DO ( + set JAVA_VERSION=%%A + ) + FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKLM\Software\JavaSoft\Java Development Kit\%JAVA_VERSION%" /v JavaHome`) DO ( + set JAVA_HOME=%%A %%B + ) + if not exist "%JAVA_HOME%" ( + call :warn Unable to retrieve JAVA_HOME from Registry + ) + goto TryJDKEnd +:TryJDKEnd + if not exist "%JAVA_HOME%" ( + call :warn JAVA_HOME is not valid: "%JAVA_HOME%" + goto END + ) + set JAVA=%JAVA_HOME%\bin\java +:Check_JAVA_END + +if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS% + +if "%KARAF_DEBUG%" == "" goto :KARAF_DEBUG_END + if "%1" == "stop" goto :KARAF_DEBUG_END + if "%1" == "client" goto :KARAF_DEBUG_END + rem Use the defaults if JAVA_DEBUG_OPTS was not set + if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS% + + set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%" + call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS% +:KARAF_DEBUG_END + +if "%KARAF_PROFILER%" == "" goto :KARAF_PROFILER_END + set KARAF_PROFILER_SCRIPT=%KARAF_HOME%\conf\profiler\%KARAF_PROFILER%.cmd + + if exist "%KARAF_PROFILER_SCRIPT%" goto :KARAF_PROFILER_END + call :warn Missing configuration for profiler '%KARAF_PROFILER%': %KARAF_PROFILER_SCRIPT% + goto END +:KARAF_PROFILER_END + +rem Setup the classpath +pushd "%KARAF_HOME%\lib" +for %%G in (karaf*.jar) do call:APPEND_TO_CLASSPATH %%G +popd +goto CLASSPATH_END + +: APPEND_TO_CLASSPATH +set filename=%~1 +set suffix=%filename:~-4% +if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%KARAF_HOME%\lib\%filename% +goto :EOF + +:CLASSPATH_END + +rem Execute the JVM or the load the profiler +if "%KARAF_PROFILER%" == "" goto :RUN + rem Execute the profiler if it has been configured + call :warn Loading profiler script: %KARAF_PROFILER_SCRIPT% + call %KARAF_PROFILER_SCRIPT% + +:RUN + SET OPTS=-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=true + SET MAIN=org.apache.karaf.main.Main + SET SHIFT=false + +:RUN_LOOP + if "%1" == "stop" goto :EXECUTE_STOP + if "%1" == "status" goto :EXECUTE_STATUS + if "%1" == "console" goto :EXECUTE_CONSOLE + if "%1" == "server" goto :EXECUTE_SERVER + if "%1" == "client" goto :EXECUTE_CLIENT + if "%1" == "clean" goto :EXECUTE_CLEAN + if "%1" == "debug" goto :EXECUTE_DEBUG + goto :EXECUTE + +:EXECUTE_STOP + SET MAIN=org.apache.karaf.main.Stop + shift + goto :RUN_LOOP + +:EXECUTE_STATUS + SET MAIN=org.apache.karaf.main.Status + shift + goto :RUN_LOOP + +:EXECUTE_CONSOLE + shift + goto :RUN_LOOP + +:EXECUTE_SERVER + SET OPTS=-Dkaraf.startLocalConsole=false -Dkaraf.startRemoteShell=true + shift + goto :RUN_LOOP + +:EXECUTE_CLIENT + SET OPTS=-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=false + shift + goto :RUN_LOOP + +:EXECUTE_CLEAN + rmdir /S /Q "%KARAF_DATA%" + shift + goto :RUN_LOOP + +:EXECUTE_DEBUG + if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS% + set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%" + shift + goto :RUN_LOOP + +:EXECUTE + SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8 + rem Execute the Java Virtual Machine + cd "%KARAF_BASE%" + "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Djava.endorsed.dirs="%JAVA_HOME%\jre\lib\endorsed;%JAVA_HOME%\lib\endorsed;%KARAF_HOME%\lib\endorsed" -Djava.ext.dirs="%JAVA_HOME%\jre\lib\ext;%JAVA_HOME%\lib\ext;%KARAF_HOME%\lib\ext" -Dkaraf.instances="%KARAF_HOME%\instances" -Dkaraf.home="%KARAF_HOME%" -Dkaraf.base="%KARAF_BASE%" -Dkaraf.etc="%KARAF_ETC%" -Djava.io.tmpdir="%KARAF_DATA%\tmp" -Dkaraf.data="%KARAF_DATA%" -Djava.util.logging.config.file="%KARAF_BASE%\etc\java.util.logging.properties" %KARAF_OPTS% %MAIN% %ARGS% + +rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +:END + +endlocal + +if not "%PAUSE%" == "" pause + +:END_NO_PAUSE + diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index ef3b5f4fd9..541c1300f3 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -732,6 +732,27 @@ + + org.apache.maven.plugins + maven-dependency-plugin + 2.8 + + + unpack-provided-configs + + unpack-dependencies + + generate-resources + + ${project.build.directory}/configuration + sal-rest-connector-config + **\/*.xml + true + false + + + + maven-assembly-plugin 2.3 @@ -842,6 +863,10 @@ org.opendaylight.controller config-manager + + org.opendaylight.controller + config-util + org.opendaylight.controller config-netconf-connector @@ -1005,6 +1030,10 @@ org.opendaylight.controller sal-rest-connector + + org.opendaylight.controller + sal-rest-connector-config + org.opendaylight.controller sal-rest-docgen @@ -1060,10 +1089,6 @@ org.opendaylight.controller.model model-flow-base - - org.opendaylight.controller.model - model-flow-management - org.opendaylight.controller.model model-flow-service @@ -1285,6 +1310,20 @@ package + + unpack-provided-configs + + unpack-dependencies + + generate-resources + + ${project.build.directory}/configuration + sal-rest-connector-config + **\/*.xml + true + false + + diff --git a/opendaylight/distribution/opendaylight/src/assemble/bin.xml b/opendaylight/distribution/opendaylight/src/assemble/bin.xml index 0ff4c9a83c..e5fc98a863 100644 --- a/opendaylight/distribution/opendaylight/src/assemble/bin.xml +++ b/opendaylight/distribution/opendaylight/src/assemble/bin.xml @@ -75,6 +75,13 @@ opendaylight/ + + ${project.build.directory}/configuration/initial + /opendaylight/configuration/initial + + **/META-INF/** + + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini index f05afbb346..b2fc3cb386 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini @@ -113,8 +113,8 @@ org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true ovsdb.listenPort=6640 # ovsdb creates Openflow nodes/bridges. This configuration configures the bridge's Openflow version. -# default Openflow version = 1.0, we also support 1.3. -# ovsdb.of.version=1.3 +# default Openflow version = 1.3, we also support 1.0. +ovsdb.of.version=1.3 # TLS configuration # To enable TLS, set secureChannelEnabled=true and specify the location of controller Java KeyStore and TrustStore files. @@ -149,3 +149,6 @@ hosttracker.keyscheme=IP lisp.mappingOverwrite = true # Enable the Solicit-Map-Request (SMR) mechanism lisp.smr = false + +#RESTConf websocket listen port (default is 8181) +restconf.websocket.port=8181 diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/cors-config.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/cors-config.xml index 00abf6cf33..c148b83a7a 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/cors-config.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/cors-config.xml @@ -7,48 +7,61 @@ --> - - - CorsFilter - org.apache.catalina.filters.CorsFilter - - cors.allowed.origins - * - - - cors.allowed.methods - GET,POST,HEAD,OPTIONS,PUT,DELETE - - - cors.allowed.headers - Content-Type,X-Requested-With,accept,authorization, - origin,Origin,Access-Control-Request-Method,Access-Control-Request-Headers - - - - cors.exposed.headers - Access-Control-Allow-Origin,Access-Control-Allow-Credentials - - - cors.support.credentials - true - - - cors.preflight.maxage - 10 - - + + + CorsFilter + org.apache.catalina.filters.CorsFilter + + cors.allowed.origins + * + + + cors.allowed.methods + GET,POST,HEAD,OPTIONS,PUT,DELETE + + + cors.allowed.headers + Content-Type,X-Requested-With,accept,authorization, + origin,Origin,Access-Control-Request-Method,Access-Control-Request-Headers + + + + cors.exposed.headers + Access-Control-Allow-Origin,Access-Control-Allow-Credentials + + + cors.support.credentials + true + + + cors.preflight.maxage + 10 + + + + + + CorsFilter + + + + + CorsFilter + /* + + + + + + CorsFilter + + + + + CorsFilter + /* + + - - - CorsFilter - - - - - CorsFilter - /* - - diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml index 7b1df98247..f25b7d91bd 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml @@ -35,6 +35,10 @@ binding:binding-data-broker binding-data-broker + + binding:binding-async-data-broker + binding-data-broker + @@ -47,15 +51,36 @@ + + + + + prefix:inmemory-operational-datastore-provider + operational-store-service + + dom:schema-service + yang-schema-service + + + operational-dom-store-spi:operational-dom-datastore operational-store-service + + + @@ -113,6 +147,17 @@ + + @@ -122,6 +167,29 @@ /modules/module[type='schema-service-singleton'][name='yang-schema-service'] + + + + + + + + config-dom-store-spi:config-dom-datastore diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml index 8fedbe4d4c..f81a332ab6 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml @@ -12,7 +12,7 @@ - + prefix:netconf-client-dispatcher global-netconf-dispatcher @@ -30,24 +30,25 @@ - + prefix:threadfactory-naming global-netconf-processing-executor-threadfactory remote-connector-processing-executor - - + + prefix:threadpool-flexible global-netconf-processing-executor 1 4 600000 + prefix:threadfactory global-netconf-processing-executor-threadfactory - + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml index d1a5dcc416..94a3702fdb 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml @@ -86,6 +86,10 @@ + + + + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/functions.sh b/opendaylight/distribution/opendaylight/src/main/resources/functions.sh new file mode 100644 index 0000000000..21dd4c16ba --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/functions.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Function harvestHelp searches in run.sh part for line starting with "##". +# Next lines starting with "#" will be printed without first char # (=help content). +# Help content has to end with "##" on new line. +# Example: +##foo +# Foo is world wide used synnonym for bar. +## +function harvestHelp() { + key="$1" + if [ -z "${key}" ]; then + key='HELP' + fi + echo + sed -rn "/^##${key}$/,/^##/ p" $0 | sed -r '1 d; $ d; s/^#/ /' + grep "##${key}" $0 > /dev/null +} diff --git a/opendaylight/distribution/opendaylight/src/main/resources/run.bat b/opendaylight/distribution/opendaylight/src/main/resources/run.bat index 72ccd02707..ce13e33968 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/run.bat +++ b/opendaylight/distribution/opendaylight/src/main/resources/run.bat @@ -14,6 +14,7 @@ SET jvmMaxMemory= SET extraJVMOpts= SET consoleOpts=-console -consoleLog SET PID= +SET JAVA_H=%JAVA_HOME%\bin\jps.exe :LOOP IF "%~1" NEQ "" ( @@ -61,7 +62,7 @@ IF "%~1" NEQ "" ( GOTO :LOOP ) IF "!CARG!"=="-status" ( - for /F "TOKENS=1" %%G in ('%JAVA_HOME%\bin\jps.exe -lvV ^| find /I "opendaylight"') do ( + for /F "TOKENS=1" %%G in ('""!JAVA_H!" -lvV ^| find /I "opendaylight""') do ( set PID=%%G ) if "!PID!" NEQ "" ( @@ -72,7 +73,7 @@ IF "%~1" NEQ "" ( GOTO :EOF ) IF "!CARG!"=="-stop" ( - for /F "TOKENS=1" %%G in ('%JAVA_HOME%\bin\jps.exe -lvV ^| find /I "opendaylight"') do ( + for /F "TOKENS=1" %%G in ('""!JAVA_H!" -lvV ^| find /I "opendaylight""') do ( set PID=%%G ) if "!PID!" NEQ "" ( @@ -89,18 +90,23 @@ IF "%~1" NEQ "" ( GOTO :LOOP ) IF "!CARG:~0,2!"=="-D" ( - SET extraJVMOpts=%extraJVMOpts% !CARG! + SET extraJVMOpts=!extraJVMOpts! !CARG! SHIFT GOTO :LOOP ) IF "!CARG:~0,2!"=="-X" ( - SET extraJVMOpts=%extraJVMOpts% !CARG! + SET extraJVMOpts=!extraJVMOpts! !CARG! SHIFT GOTO :LOOP ) IF "!CARG!"=="-help" ( - ECHO "Usage: %0 [-jmx] [-jmxport ] [-debug] [-debugsuspend] [-debugport ] [-start] [-consoleport ]] [-stop] [-status] [-console] [-help] []" - ECHO Note: Enclose any JVM or System properties within double quotes. + SHIFT + SET CARG=%2 + IF "!CARG!" NEQ "" ( + CALL:!CARG! + ) ELSE ( + CALL:helper + ) GOTO :EOF ) @@ -110,28 +116,24 @@ IF "%~1" NEQ "" ( IF "%debugEnabled%" NEQ "" ( REM ECHO "DEBUG enabled" - SET extraJVMOpts=%extraJVMOpts% -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=%debugport% + SET extraJVMOpts=!extraJVMOpts! -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=%debugport% ) + IF "%debugSuspended%" NEQ "" ( REM ECHO "DEBUG enabled suspended" - SET extraJVMOpts=%extraJVMOpts% -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%debugport% + SET extraJVMOpts=!extraJVMOpts! -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%debugport% ) IF "%jvmMaxMemory%"=="" ( SET jvmMaxMemory=-Xmx1G - ECHO ***************************************************************** - ECHO JVM maximum memory was not defined. Setting maximum memory to 1G. - ECHO To define the maximum memory, specify the -Xmx setting on the - ECHO command line. - ECHO e.g. run.bat -Xmx1G - ECHO *****************************************************************" + ECHO Setting maximum memory to 1G. ) -SET extraJVMOpts=%extraJVMOpts% %jvmMaxMemory% +SET extraJVMOpts=!extraJVMOpts! %jvmMaxMemory% IF "%jmxEnabled%" NEQ "" ( REM ECHO "JMX enabled " - SET extraJVMOpts=%extraJVMOpts% -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=%jmxport% -Dcom.sun.management.jmxremote + SET extraJVMOpts=!extraJVMOpts! -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=%jmxport% -Dcom.sun.management.jmxremote ) IF "%startEnabled%" NEQ "" ( REM ECHO "START enabled " @@ -139,7 +141,7 @@ IF "%startEnabled%" NEQ "" ( ) REM Check if controller is already running -for /F "TOKENS=1" %%G in ('%JAVA_HOME%\bin\jps.exe -lvV ^| find /I "opendaylight"') do ( +for /F "TOKENS=1" %%G in ('""!JAVA_H!" -lvV ^| find /I "opendaylight""') do ( SET PID=%%G ) if "!PID!" NEQ "" ( @@ -154,16 +156,125 @@ SET cp="%basedir%lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar;%basedir%lib\or REM Now set framework classpath SET fwcp="file:\%basedir%lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar,file:\%basedir%lib\org.eclipse.virgo.kernel.equinox.extensions-3.6.0.RELEASE.jar,file:\%basedir%lib\org.eclipse.equinox.launcher-1.3.0.v20120522-1813.jar" -SET RUN_CMD="%JAVA_HOME%\bin\java.exe" -Dopendaylight.controller %extraJVMOpts% -Djava.io.tmpdir="%basedir%work\tmp" -Djava.awt.headless=true -Dosgi.install.area=%basedir% -Dosgi.configuration.area="%basedir%configuration" -Dosgi.frameworkClassPath=%fwcp% -Dosgi.framework="file:\%basedir%lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar" -classpath %cp% org.eclipse.equinox.launcher.Main %consoleOpts% +SET RUN_CMD="%JAVA_HOME%\bin\java.exe" -Dopendaylight.controller !extraJVMOpts! -Djava.io.tmpdir="%basedir%work\tmp" -Djava.awt.headless=true -Dosgi.install.area=%basedir% -Dosgi.configuration.area="%basedir%configuration" -Dosgi.frameworkClassPath=%fwcp% -Dosgi.framework="file:\%basedir%lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar" -classpath %cp% org.eclipse.equinox.launcher.Main %consoleOpts% -ECHO %RUN_CMD% +ECHO !RUN_CMD! if "%startEnabled%" NEQ "" ( - START /B cmd /C CALL %RUN_CMD% > %basedir%\logs\controller.out 2>&1 + START /B cmd /C CALL !RUN_CMD! > %basedir%\logs\controller.out 2>&1 ECHO Running controller in the background. + EXIT /B 1 ) else ( - %RUN_CMD% + !RUN_CMD! EXIT /B %ERRORLEVEL% ) +:helper +echo. For more information on a specific command, type -help command-name. +echo. +echo jmx ^[-jmx^] +echo jmxport ^[-jmxport ^^] - DEFAULT is 1088 +echo debug ^[-debug^] +echo debugsuspend ^[-debugsuspend^] +echo debugport ^[-debugport ^^] - DEFAULT is 8000 +echo start ^[-start ^[^^]^] - DEFAULT port is 2400 +echo stop ^[-stop^] +echo status ^[-status^] +echo console ^[-console^] +echo agentpath ^[-agentpath:^^] +exit/B 1 + +:debugsuspend +ECHO. +ECHO. debugsuspend ^[-debugsuspend^] +ECHO. +ECHO. This command sets suspend on true in runjdwp in extra JVM options. If its true, VMStartEvent has a suspendPolicy of SUSPEND_ALL. If its false, VMStartEvent has a suspendPolicy of SUSPEND_NONE. +ECHO. +EXIT /B 1 + +:debugport +ECHO. +ECHO. debugport ^[-debugport ^^] - DEFAULT is 8000 +ECHO. +ECHO. Set address for settings in runjdwp in extra JVM options. +ECHO. The address is transport address for the connection. +ECHO. The address has to be in the range ^[1024,65535^]. If the option was not call, port will be set to default value. +ECHO. +EXIT /B 1 + +:jmxport +ECHO. +ECHO. jmxport ^[-jmxport ^^] - DEFAULT is 1088 +ECHO. +ECHO. Set jmx port for com.sun.management.jmxremote.port in JMX support. Port has to be in the range ^[1024,65535^]. If this option was not call, port will be set to default value. +ECHO. +EXIT /B 1 + +:debug +ECHO. +ECHO. debug [-debug] +ECHO. +ECHO. Run ODL controller with -Xdebug and -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=^$^{debugport^} +ECHO. +ECHO. -Xdebug enables debugging capabilities in the JVM which are used by the Java Virtual Machine Tools Interface (JVMTI). JVMTI is a low-level debugging interface used by debuggers and profiling tools. +ECHO. +ECHO. -Xrunjdwp option loads the JPDA reference implementation of JDWP. This library resides in the target VM and uses JVMDI and JNI to interact with it. It uses a transport and the JDWP protocol to communicate with a separate debugger application. +ECHO. +ECHO. settings for -Xrunjdwp: +ECHO. transport - name of the transport to use in connecting to debugger application +ECHO. server - if 'y', listen for a debugger application to attach; otherwise, attach to the debugger application at the specified address +ECHO. - if 'y' and no address is specified, choose a transport address at which to listen for a debugger application, and print the address to the standard output stream +ECHO. suspend - if 'y', VMStartEvent has a suspend Policy of SUSPEND_ALL +ECHO. - if 'n', VMStartEvent has a suspend policy of SUSPEND_NONE +ECHO. address - transport address for the connection +ECHO. - if server=n, attempt to attach to debugger application at this address +ECHO. - if server=y, listen for a connection at this address +ECHO. +EXIT /B 1 + +:jmx +ECHO. +ECHO. jmx [-jmx] +ECHO. +ECHO. Add JMX support. With settings for extra JVM options: -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=^$^{jmxport^} -Dcom.sun.management.jmxremote +ECHO. jmxport can by set with option -jmxport ^. Default num for the option is 1088. +ECHO. +EXIT /B 1 + +:stop +ECHO. +ECHO. stop ^[-stop^] +ECHO. +ECHO. If a controller is running, the command stop controller. Pid will be clean. +ECHO. +EXIT /B 1 + +:status +ECHO. +ECHO. status ^[-status^] +ECHO. +ECHO. Find out whether a controller is running and print it. +ECHO. +EXIT /B 1 + +:start +ECHO. +ECHO. start ^[-start ^[^^]^] +ECHO. +ECHO. If controller is not running, the command with argument^(for set port, where controller has start^) will start new controller on a port. The port has to be in the range ^[1024,65535^]. If this option was not call, port will be set to default value. Pid will be create. +EXIT /B 1 + +:console +ECHO. +ECHO. console [-console] +ECHO. Default option. +EXIT /B 1 + +:agentpath +ECHO. +ECHO. agentpath ^[-agentpath:^^] +ECHO. +ECHO. Agentpath option passes path to agent to jvm in order to load native agent library, e.g. yourkit profiler agent. +EXIT /B 1 + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/run.sh b/opendaylight/distribution/opendaylight/src/main/resources/run.sh index 1e903d0650..13be2336b6 100755 --- a/opendaylight/distribution/opendaylight/src/main/resources/run.sh +++ b/opendaylight/distribution/opendaylight/src/main/resources/run.sh @@ -1,5 +1,20 @@ #!/bin/bash +##HELP +# For more information on a specific command, type -help command-name. +# +# jmx [-jmx] +# jmxport [-jmxport ] - DEFAULT is 1088 +# debug [-debug] +# debugsuspend [-debugsuspend] +# debugport [-debugport ] - DEFAULT is 8000 +# start [-start []] - DEFAULT port is 2400 +# stop [-stop] +# status [-status] +# console [-console] +# agentpath [-agentpath:] +## + platform='unknown' unamestr=`uname` if [[ "$unamestr" == 'Linux' ]]; then @@ -58,11 +73,6 @@ else datadir=${ODL_DATADIR} fi -function usage { - echo "Usage: $0 [-jmx] [-jmxport ] [-debug] [-debugsuspend] [-debugport ] [-start []] [-stop] [-status] [-console] [-help] [-agentpath:] []" - exit 1 -} - if [ -z ${TMP} ]; then pidfile="/tmp/opendaylight.PID" else @@ -82,13 +92,15 @@ stopdaemon=0 statusdaemon=0 consolestart=1 dohelp=0 -jvmMaxMemory="" +jvmMaxMemory="-Xmx1G" extraJVMOpts="" agentPath="" unknown_option=0 +helper="" while true ; do case "$1" in -debug) debug=1; shift ;; + -help) dohelp=1; shift; helper=$1; break ;; -jmx) startjmx=1; shift ;; -debugsuspend) debugsuspend=1; shift ;; -debugport) shift; debugportread="$1"; if [[ "${debugportread}" =~ ^[0-9]+$ ]] ; then debugport=${debugportread}; shift; else echo "-debugport expects a number but was not found"; exit -1; fi;; @@ -97,37 +109,39 @@ while true ; do -stop) stopdaemon=1; shift ;; -status) statusdaemon=1; shift ;; -console) shift ;; - -help) dohelp=1; shift;; -Xmx*) jvmMaxMemory="$1"; shift;; -D*) extraJVMOpts="${extraJVMOpts} $1"; shift;; -X*) extraJVMOpts="${extraJVMOpts} $1"; shift;; -agentpath:*) agentPath="$1"; shift;; "") break ;; - *) echo "Unknown option $1"; unknown_option=1; shift ;; + *) echo "Unknown option $1"; unknown_option=1; break ;; esac done -# Unknown Options and help + + if [ "${unknown_option}" -eq 1 ]; then - usage + echo "Use -help for more information." + exit 1 fi -if [ "${dohelp}" -eq 1 ]; then - usage -fi -if [ "${jvmMaxMemory}" == "" ]; then - jvmMaxMemory="-Xmx1G" - echo "*****************************************************************" - echo "JVM maximum memory was not defined. Setting maximum memory to 1G." - echo "To define the maximum memory, specify the -Xmx setting on the" - echo "command line. " - echo " e.g. ./run.sh -Xmx1G" - echo "*****************************************************************" +if [ "${dohelp}" -eq 1 ]; then + . ${basedir}/functions.sh + harvestHelp ${helper} + echo -e '\nFor other information type -help.\n' + exit 1 fi extraJVMOpts="${extraJVMOpts} ${jvmMaxMemory}" +##debugport +#debugport [-debugport ] - DEFAULT is 8000 +# +# Set address for settings in runjdwp in extra JVM options. +# The address is transport address for the connection. +# The address has to be in the range [1024,65535]. If this option was not call, port will be set to default value. +## # Validate debug port if [[ "${debugport}" -lt 1024 ]] || [[ "${debugport}" -gt 65535 ]]; then echo "Debug Port not in the range [1024,65535] ${debugport}" @@ -140,19 +154,51 @@ if [[ "${daemonport}" -lt 1024 ]] || [[ "${daemonport}" -gt 65535 ]]; then exit -1 fi +##jmxport +#jmxport [-jmxport ] - DEFAULT is 1088 +# +# Set jmx port for com.sun.management.jmxremote.port in JMX support. Port has to be in the range [1024,65535]. If this option was not call, port will be set to default value. +## # Validate jmx port if [[ "${jmxport}" -lt 1024 ]] || [[ "${jmxport}" -gt 65535 ]]; then echo "JMX Port not in the range [1024,65535] value is ${jmxport}" exit -1 fi +##debug +#debug [-debug] +# +#Run ODL controller with -Xdebug and -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=\${debugport} +#-Xdebug enables debugging capabilities in the JVM which are used by the Java Virtual Machine Tools Interface (JVMTI). JVMTI is a low-level debugging interface used by debuggers and profiling tools. +#-Xrunjdwp option loads the JPDA reference implementation of JDWP. This library resides in the target VM and uses JVMDI and JNI to interact with it. It uses a transport and the JDWP protocol to +#communicate with a separate debugger application. +#settings for -Xrunjdwp: +# transport - name of the transport to use in connecting to debugger application +# server - if “y”, listen for a debugger application to attach; otherwise, attach to the debugger application at the specified address +# - if “y” and no address is specified, choose a transport address at which to listen for a debugger application, and print the address to the standard output stream +# suspend - if “y”, VMStartEvent has a suspend Policy of SUSPEND_ALL +# - if “n”, VMStartEvent has a suspend policy of SUSPEND_NONE +# address - transport address for the connection +# - if server=n, attempt to attach to debugger application at this address +# - if server=y, listen for a connection at this address +## +##debugsuspend +#debugsuspend [-debugsuspend] +# +#This command sets suspend on true in runjdwp in extra JVM options. If its true, VMStartEvent has a suspendPolicy of SUSPEND_ALL. If its false, VMStartEvent has a suspendPolicy of SUSPEND_NONE. +## # Debug options if [ "${debugsuspend}" -eq 1 ]; then extraJVMOpts="${extraJVMOpts} -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=${debugport}" elif [ "${debug}" -eq 1 ]; then extraJVMOpts="${extraJVMOpts} -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debugport}" fi - +##jmx +#jmx [-jmx] +# +#Add JMX support. With settings for extra JVM options: -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=\${jmxport} -Dcom.sun.management.jmxremote +#jmxport can by set with command -jmxport . Default num for the option is 1088. +## # Add JMX support if [ "${startjmx}" -eq 1 ]; then extraJVMOpts="${extraJVMOpts} -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=${jmxport} -Dcom.sun.management.jmxremote" @@ -182,6 +228,11 @@ FWCLASSPATH=${FWCLASSPATH},file:${basedir}/lib/org.eclipse.equinox.launcher-1.3. cd $basedir +##stop +#stop [-stop] +# +#If a controller is running, the command stop controller. Pid will be clean. +## if [ "${stopdaemon}" -eq 1 ]; then if [ -e "${pidfile}" ]; then daemonpid=`cat "${pidfile}"` @@ -195,6 +246,11 @@ if [ "${stopdaemon}" -eq 1 ]; then fi fi +##status +#status [-status] +# +#Find out whether a controller is running and print it. +## if [ "${statusdaemon}" -eq 1 ]; then if [ -e "${pidfile}" ]; then daemonpid=`cat "${pidfile}"` @@ -219,6 +275,22 @@ bdir=`echo "${basedir}" | sed 's/ /\\ /g'` confarea=`echo "${datadir}" | sed 's/ /\\ /g'` fwclasspath=`echo "${FWCLASSPATH}" | sed 's/ /\\ /g'` +##start +#start [-start []] +# +# If controller is not running, the command with argument(for set port, where controller has start) will start new controller on a port. The port has to be in the range [1024,65535]. If this option was not call, port will be set to default value. Pid will be create. +## +##console +#console [-console] +# +# Default option. +## +##agentpath +#agentpath [-agentpath:] +# +# Agentpath option passes path to agent to jvm in order to load native agent library, e.g. yourkit profiler agent. +## +echo "JVM maximum memory was set to ${jvmMaxMemory}." if [ "${startdaemon}" -eq 1 ]; then if [ -e "${pidfile}" ]; then echo "Another instance of controller running, check with $0 -status" diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java index c89cfc1b9e..e2b6642501 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java @@ -867,6 +867,7 @@ public class FlowConfig extends ConfigurationObject implements Serializable { } continue; } + sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { if (!NetUtils.isIPAddressValid(sstr.group(1))) { @@ -875,7 +876,57 @@ public class FlowConfig extends ConfigurationObject implements Serializable { } continue; } - } + + sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.FLOOD_ALL.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp); + if (sstr.matches()) { + continue; + } + + // If execution reached here, it means there is an Action + // which is not recognized by the controller. Return error + + return new Status(StatusCode.BADREQUEST, String.format("%s is an UnSupported Action", actiongrp)); + } } catch (NumberFormatException e) { return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage())); } diff --git a/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java b/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java index 685ccdb7c4..3c367b9af4 100644 --- a/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java +++ b/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java @@ -760,9 +760,9 @@ public class frmTest { actions.add(ActionType.SET_NW_SRC.toString() + "=1.1.1.1"); actions.add(ActionType.SET_NW_DST.toString() + "=2.2.2.2"); actions.add(ActionType.CONTROLLER.toString()); - actions.add(ActionType.SET_NW_TOS.toString() + "1"); - actions.add(ActionType.SET_TP_SRC.toString() + "60"); - actions.add(ActionType.SET_TP_DST.toString() + "8080"); + actions.add(ActionType.SET_NW_TOS.toString() + "=1"); + actions.add(ActionType.SET_TP_SRC.toString() + "=60"); + actions.add(ActionType.SET_TP_DST.toString() + "=8080"); actions.add(ActionType.SET_NEXT_HOP.toString() + "=1.1.1.1"); return actions; diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java index be3add1042..0653eeb2a6 100644 --- a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java @@ -7,8 +7,6 @@ */ package org.opendaylight.controller.md.frm.compatibility; -import java.util.Collections; - import org.opendaylight.controller.forwardingrulesmanager.FlowConfig; import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager; import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener; @@ -17,7 +15,6 @@ import org.opendaylight.controller.md.sal.common.api.data.DataModification; import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider; import org.opendaylight.controller.sal.common.util.Arguments; -import org.opendaylight.controller.sal.common.util.Rpcs; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey; import org.opendaylight.yangtools.concepts.Registration; @@ -26,8 +23,8 @@ import org.opendaylight.yangtools.yang.binding.Identifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import com.google.common.base.Objects; import com.google.common.base.Preconditions; @@ -41,7 +38,7 @@ public class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHa private DataProviderService dataService; private IForwardingRulesManager manager; - public Registration, DataObject>> init() { + public Registration init() { return this.dataService.registerCommitHandler(FRMRuntimeDataProvider.FLOWS_PATH, this); } @@ -89,7 +86,7 @@ public class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHa this.manager.removeStaticFlow(flow.getName(), flow.getNode()); this.manager.addStaticFlow(flow); } - return Rpcs. getRpcResult(true, null, Collections. emptySet()); + return RpcResultBuilder. success().build(); } public RpcResult rollback(final FlowCommitTransaction transaction) { diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java index 36045cabf4..1b648dc98c 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java @@ -103,7 +103,8 @@ public class FromSalConversionsUtils { private static NodeConnectorId inPortMatch(Match sourceMatch) { MatchField inPort = sourceMatch.getField(MatchType.IN_PORT); if(inPort != null && inPort.getValue() != null && (inPort.getValue() instanceof NodeConnector)) { - return new NodeConnectorId(((NodeConnector) inPort.getValue()).getNodeConnectorIdAsString()); + NodeConnector port = (NodeConnector)inPort.getValue(); + return (NodeConnectorId)MDFlowMapping.toUri(port); } return null; } @@ -203,9 +204,11 @@ public class FromSalConversionsUtils { MatchField vlan = sourceMatch.getField(MatchType.DL_VLAN); if (vlan != null && vlan.getValue() != null) { VlanIdBuilder vlanIDBuilder = new VlanIdBuilder(); + short vid = (short)vlan.getValue(); + boolean present = (vid != MatchType.DL_VLAN_NONE); vlanIDBuilder.setVlanId(new VlanId((NetUtils - .getUnsignedShort((short) vlan.getValue())))); - vlanIDBuilder.setVlanIdPresent(true); + .getUnsignedShort(vid)))); + vlanIDBuilder.setVlanIdPresent(present); vlanMatchBuild.setVlanId(vlanIDBuilder.build()); } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java index 5959d23366..e2c1386775 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java @@ -7,9 +7,12 @@ */ package org.opendaylight.controller.sal.compatibility; +import com.google.common.collect.Iterables; + import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -733,26 +736,45 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI } private boolean isKnownNodeConnector(final InstanceIdentifier nodeConnectorIdentifier) { - final List path = nodeConnectorIdentifier.getPath(); - if (path.size() >= 3) { - final PathArgument nodePath = path.get(1); - final PathArgument nodeConnectorPath = path.get(2); - final List nodeConnectors = nodeToNodeConnectorsMap.get(nodePath); - if (nodeConnectors != null) { - return nodeConnectors.contains(nodeConnectorPath); - } + final Iterator it = nodeConnectorIdentifier.getPathArguments().iterator(); + + if (!it.hasNext()) { + return false; } - return false; + it.next(); + + if (!it.hasNext()) { + return false; + } + final PathArgument nodePath = it.next(); + + if (!it.hasNext()) { + return false; + } + final PathArgument nodeConnectorPath = it.next(); + + final List nodeConnectors = nodeToNodeConnectorsMap.get(nodePath); + return nodeConnectors == null ? false : + nodeConnectors.contains(nodeConnectorPath); } private boolean recordNodeConnector(final InstanceIdentifier nodeConnectorIdentifier) { - final List path = nodeConnectorIdentifier.getPath(); - if (path.size() < 3) { + final Iterator it = nodeConnectorIdentifier.getPathArguments().iterator(); + + if (!it.hasNext()) { return false; } + it.next(); - final PathArgument nodePath = path.get(1); - final PathArgument nodeConnectorPath = path.get(2); + if (!it.hasNext()) { + return false; + } + final PathArgument nodePath = it.next(); + + if (!it.hasNext()) { + return false; + } + final PathArgument nodeConnectorPath = it.next(); synchronized (this) { List nodeConnectors = this.nodeToNodeConnectorsMap.get(nodePath); @@ -766,6 +788,6 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI } private List removeNodeConnectors(final InstanceIdentifier nodeIdentifier) { - return this.nodeToNodeConnectorsMap.remove(nodeIdentifier.getPath().get(1)); + return this.nodeToNodeConnectorsMap.remove(Iterables.get(nodeIdentifier.getPathArguments(), 1)); } } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java index a700c86b9c..02964c6d55 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java @@ -11,6 +11,7 @@ import java.math.BigInteger; import java.util.Date; import java.util.HashSet; import java.util.List; + import org.opendaylight.controller.sal.common.util.Arguments; import org.opendaylight.controller.sal.core.AdvertisedBandwidth; import org.opendaylight.controller.sal.core.Bandwidth; @@ -61,6 +62,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; import com.google.common.base.Preconditions; @@ -94,13 +96,14 @@ public final class NodeMapping { /** * @param adNodeId - * @return + * @return nodeId as long */ - private static Long openflowFullNodeIdToLong(String adNodeId) { + @VisibleForTesting + public static Long openflowFullNodeIdToLong(String adNodeId) { if (adNodeId == null) { return null; } - return Long.valueOf(adNodeId.replaceFirst("^.*:", "")); + return new BigInteger(adNodeId.replaceFirst("^.*:", "")).longValue(); } public static NodeId toNodeId(final InstanceIdentifier id) { diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java index 7bbf7f10e0..58cfb20650 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java @@ -430,13 +430,17 @@ public class ToSalConversionsUtils { if (vlanMatch != null) { VlanId vlanId = vlanMatch.getVlanId(); if (vlanId != null) { - org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanIdInner = vlanId - .getVlanId(); - if (vlanIdInner != null) { - Integer vlanValue = vlanIdInner.getValue(); - if (vlanValue != null) { - target.setField(DL_VLAN, vlanValue.shortValue()); + if (Boolean.TRUE.equals(vlanId.isVlanIdPresent())) { + org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanIdInner = vlanId + .getVlanId(); + if (vlanIdInner != null) { + Integer vlanValue = vlanIdInner.getValue(); + if (vlanValue != null) { + target.setField(DL_VLAN, vlanValue.shortValue()); + } } + } else { + target.setField(DL_VLAN, MatchType.DL_VLAN_NONE); } } VlanPcp vlanPcp = vlanMatch.getVlanPcp(); diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java index 01d75acfe6..56c7afb253 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java @@ -10,7 +10,6 @@ package org.opendaylight.controller.sal.compatibility.adsal; import java.math.BigInteger; import org.opendaylight.controller.sal.binding.api.NotificationProviderService; -import org.opendaylight.controller.sal.common.util.Rpcs; import org.opendaylight.controller.sal.compatibility.InventoryMapping; import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils; import org.opendaylight.controller.sal.flowprogrammer.Flow; @@ -32,6 +31,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103. import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,7 +70,8 @@ public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListen AddFlowOutputBuilder builder = new AddFlowOutputBuilder(); builder.setTransactionId(new TransactionId(BigInteger.valueOf(status.getRequestId()))); AddFlowOutput rpcResultType = builder.build(); - return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null)); + return Futures.immediateFuture(RpcResultBuilder.status(status.isSuccess()) + .withResult(rpcResultType).build()); } @Override @@ -84,7 +85,8 @@ public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListen RemoveFlowOutputBuilder builder = new RemoveFlowOutputBuilder(); builder.setTransactionId(new TransactionId(BigInteger.valueOf(status.getRequestId()))); RemoveFlowOutput rpcResultType = builder.build(); - return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null)); + return Futures.immediateFuture(RpcResultBuilder.status(status.isSuccess()) + .withResult(rpcResultType).build()); } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java index c5cbecabed..e63cb54b86 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.concurrent.Future; import org.opendaylight.controller.sal.binding.api.NotificationProviderService; -import org.opendaylight.controller.sal.common.util.Rpcs; import org.opendaylight.controller.sal.compatibility.FromSalConversionsUtils; import org.opendaylight.controller.sal.compatibility.InventoryMapping; import org.opendaylight.controller.sal.compatibility.NodeMapping; @@ -60,6 +59,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.n import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -107,7 +107,8 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService, LOG.error(e.getMessage()); } - return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null)); + return Futures.immediateFuture(RpcResultBuilder. + status(rpcResultBool).withResult(rpcResultType).build()); } /** @@ -133,7 +134,8 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService, LOG.error(e.getMessage()); } - return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null)); + return Futures.immediateFuture(RpcResultBuilder. + status(rpcResultBool).withResult(rpcResultType).build()); } @Override @@ -154,7 +156,8 @@ public class FlowStatisticsAdapter implements OpendaylightFlowStatisticsService, LOG.error(e.getMessage()); } - return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null)); + return Futures.immediateFuture(RpcResultBuilder. + status(rpcResultBool).withResult(rpcResultType).build()); } @Override diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java index 8a23ebc933..cef7ae7a42 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java @@ -174,6 +174,18 @@ public class NodeMappingTest { Assert.assertEquals("openflow:1", observedNodeConnectorId); } + /** + * Test method for + * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#openflowFullNodeIdToLong(String)} + * . + * @throws ConstructionException + */ + @Test + public void testOpenflowFullNodeIdToLong() throws ConstructionException { + Assert.assertEquals(42L, NodeMapping.openflowFullNodeIdToLong("42").longValue()); + Assert.assertEquals(0xCC4E241C4A000000L, NodeMapping.openflowFullNodeIdToLong("14721743935839928320").longValue()); + } + /** * @param nodeId * @param portId diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java index 5d5a409445..e9f56f6a03 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 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, @@ -41,6 +41,11 @@ import org.opendaylight.controller.sal.action.SetVlanPcp; import org.opendaylight.controller.sal.action.SwPath; import org.opendaylight.controller.sal.compatibility.MDFlowMapping; import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.Node.NodeIDType; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchType; @@ -79,11 +84,11 @@ import com.google.common.net.InetAddresses; public class TestFromSalConversionsUtils { private enum MtchType { - other, ipv4, ipv6, arp, sctp, tcp, udp + other, untagged, ipv4, ipv6, arp, sctp, tcp, udp } @Test - public void testFromSalConversion() { + public void testFromSalConversion() throws ConstructionException { Flow salFlow = prepareSalFlowCommon(); NodeFlow odNodeFlow = MDFlowMapping.flowAdded(salFlow); @@ -93,6 +98,9 @@ public class TestFromSalConversionsUtils { odNodeFlow = MDFlowMapping.flowAdded(prepareSalMatch(salFlow, MtchType.other)); checkOdMatch(odNodeFlow.getMatch(), MtchType.other); + odNodeFlow = MDFlowMapping.flowAdded(prepareSalMatch(salFlow, MtchType.untagged)); + checkOdMatch(odNodeFlow.getMatch(), MtchType.untagged); + odNodeFlow = MDFlowMapping.flowAdded(prepareSalMatch(salFlow, MtchType.arp)); checkOdMatch(odNodeFlow.getMatch(), MtchType.arp); @@ -160,15 +168,26 @@ public class TestFromSalConversionsUtils { assertNotNull("Ipv6 wasn't found", ipv6Found); break; case other: + assertEquals("Incoming port is wrong.", "openflow:12345:10", match.getInPort().getValue()); assertEquals("Source MAC address is wrong.", "ff:ee:dd:cc:bb:aa", match.getEthernetMatch() .getEthernetSource().getAddress().getValue()); assertEquals("Destinatio MAC address is wrong.", "ff:ee:dd:cc:bb:aa", match.getEthernetMatch() .getEthernetDestination().getAddress().getValue()); + assertEquals("Vlan ID is not present.", Boolean.TRUE, match.getVlanMatch().getVlanId().isVlanIdPresent()); assertEquals("Vlan ID is wrong.", (Integer) 0xfff, match.getVlanMatch().getVlanId().getVlanId().getValue()); assertEquals("Vlan ID priority is wrong.", (short) 0x7, (short) match.getVlanMatch().getVlanPcp() .getValue()); assertEquals("DCSP is wrong.", (short) 0x3f, (short) match.getIpMatch().getIpDscp().getValue()); break; + case untagged: + assertEquals("Source MAC address is wrong.", "ff:ee:dd:cc:bb:aa", match.getEthernetMatch() + .getEthernetSource().getAddress().getValue()); + assertEquals("Destinatio MAC address is wrong.", "ff:ee:dd:cc:bb:aa", match.getEthernetMatch() + .getEthernetDestination().getAddress().getValue()); + assertEquals("Vlan ID is present.", Boolean.FALSE, match.getVlanMatch().getVlanId().isVlanIdPresent()); + assertEquals("Vlan ID is wrong.", Integer.valueOf(0), match.getVlanMatch().getVlanId().getVlanId().getValue()); + assertEquals("DCSP is wrong.", (short) 0x3f, (short) match.getIpMatch().getIpDscp().getValue()); + break; case sctp: boolean sctpFound = false; assertEquals("Wrong protocol", CRUDP, match.getIpMatch().getIpProtocol().byteValue()); @@ -223,30 +242,29 @@ public class TestFromSalConversionsUtils { private void checkOdActions( List actions) { - checkOdAction(actions, FloodActionCase.class, false); - checkOdAction(actions, FloodAllActionCase.class, false); - checkOdAction(actions, HwPathActionCase.class, false); - checkOdAction(actions, LoopbackActionCase.class, false); - checkOdAction(actions, PopVlanActionCase.class, false); - checkOdAction(actions, PushVlanActionCase.class, true); - checkOdAction(actions, SetDlDstActionCase.class, true); - checkOdAction(actions, SetDlSrcActionCase.class, true); - checkOdAction(actions, SetDlTypeActionCase.class, true); - checkOdAction(actions, SetNwTosActionCase.class, true); - checkOdAction(actions, SetNwDstActionCase.class, true); - checkOdAction(actions, SetNwSrcActionCase.class, true); - checkOdAction(actions, SetNextHopActionCase.class, true); - checkOdAction(actions, SetTpDstActionCase.class, true); - checkOdAction(actions, SetTpSrcActionCase.class, true); - checkOdAction(actions, SetVlanCfiActionCase.class, true); - checkOdAction(actions, SetVlanIdActionCase.class, true); - checkOdAction(actions, SetVlanPcpActionCase.class, true); - checkOdAction(actions, SwPathActionCase.class, false); + checkOdAction(actions, FloodActionCase.class); + checkOdAction(actions, FloodAllActionCase.class); + checkOdAction(actions, HwPathActionCase.class); + checkOdAction(actions, LoopbackActionCase.class); + checkOdAction(actions, PopVlanActionCase.class); + checkOdAction(actions, PushVlanActionCase.class); + checkOdAction(actions, SetDlDstActionCase.class); + checkOdAction(actions, SetDlSrcActionCase.class); + checkOdAction(actions, SetDlTypeActionCase.class); + checkOdAction(actions, SetNwTosActionCase.class); + checkOdAction(actions, SetNwDstActionCase.class); + checkOdAction(actions, SetNwSrcActionCase.class); + checkOdAction(actions, SetNextHopActionCase.class); + checkOdAction(actions, SetTpDstActionCase.class); + checkOdAction(actions, SetTpSrcActionCase.class); + checkOdAction(actions, SetVlanCfiActionCase.class); + checkOdAction(actions, SetVlanIdActionCase.class); + checkOdAction(actions, SetVlanPcpActionCase.class); + checkOdAction(actions, SwPathActionCase.class); } private void checkOdAction( - List actions, Class cl, - boolean b) { + List actions, Class cl) { int numOfFoundActions = 0; for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action action : actions) { org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action innerAction = action @@ -334,7 +352,7 @@ public class TestFromSalConversionsUtils { return salFlow; } - private Flow prepareSalMatch(Flow salFlow, MtchType mt) { + private Flow prepareSalMatch(Flow salFlow, MtchType mt) throws ConstructionException { Match salMatch = new Match(); switch (mt) { case arp: @@ -355,12 +373,21 @@ public class TestFromSalConversionsUtils { salMatch.setField(MatchType.NW_DST, InetAddresses.forString("2001:0db8:85a3:0000:0000:8a2e:0370:7336")); break; case other: + Node node = new Node(NodeIDType.OPENFLOW, 12345L); + NodeConnector port = new NodeConnector(NodeConnectorIDType.OPENFLOW, Short.valueOf((short)10), node); + salMatch.setField(MatchType.IN_PORT, port); salMatch.setField(MatchType.DL_SRC, new byte[]{(byte )0xff,(byte )0xee,(byte )0xdd,(byte )0xcc,(byte )0xbb,(byte )0xaa}); salMatch.setField(MatchType.DL_DST, new byte[]{(byte )0xff,(byte )0xee,(byte )0xdd,(byte )0xcc,(byte )0xbb,(byte )0xaa}); salMatch.setField(MatchType.DL_VLAN, (short) 0xfff); salMatch.setField(MatchType.DL_VLAN_PR, (byte) 0x7); salMatch.setField(MatchType.NW_TOS, (byte) 0x3f); break; + case untagged: + salMatch.setField(MatchType.DL_SRC, new byte[]{(byte )0xff,(byte )0xee,(byte )0xdd,(byte )0xcc,(byte )0xbb,(byte )0xaa}); + salMatch.setField(MatchType.DL_DST, new byte[]{(byte )0xff,(byte )0xee,(byte )0xdd,(byte )0xcc,(byte )0xbb,(byte )0xaa}); + salMatch.setField(MatchType.DL_VLAN, MatchType.DL_VLAN_NONE); + salMatch.setField(MatchType.NW_TOS, (byte) 0x3f); + break; case sctp: salMatch.setField(MatchType.NW_PROTO, CRUDP); salMatch.setField(MatchType.TP_SRC, (short) 0xffff); diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java index 0157bc0c64..7601a7d9cf 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 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, @@ -50,6 +50,7 @@ import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.Node.NodeIDType; import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp; @@ -118,6 +119,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp; @@ -151,7 +153,7 @@ public class TestToSalConversionsUtils { // prefix: // od|Od = Open Daylight private enum MtchType { - other, ipv4, ipv6, arp, sctp, tcp, udp + other, untagged, ipv4, ipv6, arp, sctp, tcp, udp } @Test @@ -164,6 +166,9 @@ public class TestToSalConversionsUtils { Flow salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.other), node); checkSalMatch(salFlow.getMatch(), MtchType.other); + salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.untagged), node); + checkSalMatch(salFlow.getMatch(), MtchType.untagged); + salFlow = ToSalConversionsUtils.toFlow(prepareOdFlow(odNodeFlowBuilder, MtchType.ipv4), node); checkSalMatch(salFlow.getMatch(), MtchType.ipv4); @@ -196,7 +201,7 @@ public class TestToSalConversionsUtils { Assert.assertEquals("OF|1@OF|00:00:00:00:00:00:00:2a", nodeConnector.toString()); } - private void checkSalMatch(org.opendaylight.controller.sal.match.Match match, MtchType mt) { + private void checkSalMatch(org.opendaylight.controller.sal.match.Match match, MtchType mt) throws ConstructionException { switch (mt) { case other: /*assertNotNull("DL_DST isn't equal.", "3C:A9:F4:00:E0:C8", @@ -204,12 +209,21 @@ public class TestToSalConversionsUtils { assertEquals("DL_SRC isn't equal.", "24:77:03:7C:C5:F1", new String((byte[]) match.getField(MatchType.DL_SRC).getValue())); */ + Node node = new Node(NodeIDType.OPENFLOW, 12L); + NodeConnector port = new NodeConnector(NodeConnectorIDType.OPENFLOW, Short.valueOf((short)345), node); + assertEquals("IN_PORT isn't equal.", port, match.getField(MatchType.IN_PORT).getValue()); assertEquals("DL_TYPE isn't equal.", (short) 0xffff, (short) match.getField(MatchType.DL_TYPE).getValue()); assertEquals("NW_TOS isn't equal.", (byte) 0x33, (byte) match.getField(MatchType.NW_TOS).getValue()); assertEquals("NW_PROTO isn't equal.", (byte) 0x3f, (byte) match.getField(MatchType.NW_PROTO).getValue()); assertEquals("DL_VLAN isn't equal.", (short) 0xfff, (short) match.getField(MatchType.DL_VLAN).getValue()); assertEquals("DL_VLAN_PR isn't equal.", (byte) 0x7, (byte) match.getField(MatchType.DL_VLAN_PR).getValue()); break; + case untagged: + assertEquals("DL_TYPE isn't equal.", (short) 0xffff, (short) match.getField(MatchType.DL_TYPE).getValue()); + assertEquals("NW_TOS isn't equal.", (byte) 0x33, (byte) match.getField(MatchType.NW_TOS).getValue()); + assertEquals("NW_PROTO isn't equal.", (byte) 0x3f, (byte) match.getField(MatchType.NW_PROTO).getValue()); + assertEquals("DL_VLAN isn't equal.", MatchType.DL_VLAN_NONE, (short) match.getField(MatchType.DL_VLAN).getValue()); + break; case arp: /* assertEquals("DL_SRC isn't equal.", "22:44:66:88:AA:CC", @@ -578,10 +592,16 @@ public class TestToSalConversionsUtils { MatchBuilder odMatchBuilder = new MatchBuilder(); switch (mt) { case other: + odMatchBuilder.setInPort(new NodeConnectorId("openflow:12:345")); odMatchBuilder.setEthernetMatch(prepEthernetMatch()); odMatchBuilder.setIpMatch(prepIpMatch()); odMatchBuilder.setVlanMatch(prepVlanMatch()); break; + case untagged: + odMatchBuilder.setEthernetMatch(prepEthernetMatch()); + odMatchBuilder.setIpMatch(prepIpMatch()); + odMatchBuilder.setVlanMatch(prepVlanNoneMatch()); + break; case ipv4: odMatchBuilder.setLayer3Match(prepLayer3MatchIpv4()); break; @@ -664,11 +684,20 @@ public class TestToSalConversionsUtils { VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(); VlanIdBuilder vlanIdBuilder = new VlanIdBuilder().setVlanId(new VlanId(0xfff)); - vlanMatchBuilder.setVlanId(vlanIdBuilder.build()); + vlanMatchBuilder.setVlanId(vlanIdBuilder.setVlanIdPresent(true).build()); vlanMatchBuilder.setVlanPcp(new VlanPcp((short) 0x7)); return vlanMatchBuilder.build(); + } + + private VlanMatch prepVlanNoneMatch() { + VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(); + VlanIdBuilder vlanIdBuilder = new VlanIdBuilder(). + setVlanIdPresent(false); + vlanMatchBuilder.setVlanId(vlanIdBuilder.build()); + + return vlanMatchBuilder.build(); } private IpMatch prepIpMatch() { diff --git a/opendaylight/md-sal/forwardingrules-manager/pom.xml b/opendaylight/md-sal/forwardingrules-manager/pom.xml index b3096e6478..ed5e192193 100644 --- a/opendaylight/md-sal/forwardingrules-manager/pom.xml +++ b/opendaylight/md-sal/forwardingrules-manager/pom.xml @@ -15,10 +15,6 @@ junit junit - - org.opendaylight.controller - flow-management-compatibility - org.opendaylight.controller sal-binding-api diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java index 6ed61e3024..9724d31f9a 100644 --- a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java +++ b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java @@ -15,7 +15,7 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus; 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.yangtools.concepts.Registration; +import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,7 +30,7 @@ class FlowCapableInventoryProvider implements AutoCloseable, Runnable { private final BlockingQueue queue = new LinkedBlockingDeque<>(QUEUE_DEPTH); private final NotificationProviderService notificationService; private final DataProviderService dataService; - private Registration listenerRegistration; + private ListenerRegistration listenerRegistration; private Thread thread; FlowCapableInventoryProvider(final DataProviderService dataService, final NotificationProviderService notificationService) { diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/flow/types/port/rev130925/PortNumberBuilder.java b/opendaylight/md-sal/model/model-flow-base/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/flow/types/port/rev130925/PortNumberBuilder.java new file mode 100644 index 0000000000..ff78a7478d --- /dev/null +++ b/opendaylight/md-sal/model/model-flow-base/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/flow/types/port/rev130925/PortNumberBuilder.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014 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.flow.types.port.rev130925; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.CommonPort.PortNumber; + + +public class PortNumberBuilder { + + public static PortNumber getDefaultInstance(java.lang.String defaultValue) { + try { + long uint32 = Long.parseLong(defaultValue); + return new PortNumber(uint32); + } catch(NumberFormatException e){ + return new PortNumber(defaultValue); + } + } + +} diff --git a/opendaylight/md-sal/model/model-flow-management/pom.xml b/opendaylight/md-sal/model/model-flow-management/pom.xml deleted file mode 100644 index 64f115816d..0000000000 --- a/opendaylight/md-sal/model/model-flow-management/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - 4.0.0 - - - org.opendaylight.controller.model - model-parent - 1.1-SNAPSHOT - - model-flow-management - bundle - - - - ${project.groupId} - model-flow-base - ${project.version} - - - ${project.groupId} - model-inventory - ${project.version} - - - org.opendaylight.yangtools.model - opendaylight-l2-types - - - - scm:git:ssh://git.opendaylight.org:29418/controller.git - scm:git:ssh://git.opendaylight.org:29418/controller.git - HEAD - https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL - - diff --git a/opendaylight/md-sal/model/model-flow-management/src/main/yang/flow-management.yang b/opendaylight/md-sal/model/model-flow-management/src/main/yang/flow-management.yang deleted file mode 100644 index b8579bcf9c..0000000000 --- a/opendaylight/md-sal/model/model-flow-management/src/main/yang/flow-management.yang +++ /dev/null @@ -1,30 +0,0 @@ -module flow-management { - namespace "urn:opendaylight:flow:config"; - prefix flow-cfg; - - import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} - import opendaylight-flow-types {prefix flow;} - - revision "2013-08-19" { - description "Initial revision of flow service"; - } - - - grouping flow-entry { - leaf node { - type inv:node-ref; - } - uses flow:flow; - } - - container flows { - list flow { - key "node id"; - - leaf id { - type uint32; - } - uses flow-entry; - } - } -} diff --git a/opendaylight/md-sal/model/model-flow-management/src/main/yang/group-management.yang b/opendaylight/md-sal/model/model-flow-management/src/main/yang/group-management.yang deleted file mode 100644 index 814c7e4767..0000000000 --- a/opendaylight/md-sal/model/model-flow-management/src/main/yang/group-management.yang +++ /dev/null @@ -1,30 +0,0 @@ -module group-management { - namespace "urn:opendaylight:group:config"; - prefix group-cfg; - - import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} - import opendaylight-group-types {prefix group;} - - revision "2013-10-24" { - description "Initial revision of group service"; - } - - grouping group-entry { - leaf node { - type inv:node-ref; - } - uses group:group; - } - - container groups { - list group { - key "id node"; - - leaf id { - type uint32; - } - - uses group-entry; - } - } -} diff --git a/opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-management.yang b/opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-management.yang deleted file mode 100644 index 6d86c50314..0000000000 --- a/opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-management.yang +++ /dev/null @@ -1,30 +0,0 @@ -module meter-management { - namespace "urn:opendaylight:meter:config"; - prefix meter-cfg; - - import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} - import opendaylight-meter-types {prefix meter;} - - revision "2013-10-24" { - description "Initial revision of meter service"; - } - - grouping meter-entry { - leaf node { - type inv:node-ref; - } - uses meter:meter; - } - - container meters { - list meter { - key "id node"; - - leaf id { - type uint32; - } - - uses meter-entry; - } - } -} diff --git a/opendaylight/md-sal/model/model-flow-management/src/main/yang/port-management.yang b/opendaylight/md-sal/model/model-flow-management/src/main/yang/port-management.yang deleted file mode 100644 index 77483de148..0000000000 --- a/opendaylight/md-sal/model/model-flow-management/src/main/yang/port-management.yang +++ /dev/null @@ -1,30 +0,0 @@ -module port-management { - namespace "urn:opendaylight:port:config"; - prefix port-cfg; - - import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} - import opendaylight-port-types {prefix port;} - - revision "2013-10-24" { - description "Initial revision of port service"; - } - - grouping port-entry { - leaf node { - type inv:node-ref; - } - uses port:port-mod; - } - - container ports { - list port { - key "id node"; - - leaf id { - type uint32; - } - - uses port-entry; - } - } -} diff --git a/opendaylight/md-sal/model/model-flow-management/src/main/yang/queue-management.yang b/opendaylight/md-sal/model/model-flow-management/src/main/yang/queue-management.yang deleted file mode 100644 index c8a7fbbaa3..0000000000 --- a/opendaylight/md-sal/model/model-flow-management/src/main/yang/queue-management.yang +++ /dev/null @@ -1,33 +0,0 @@ -module queue-management { - namespace "urn:opendaylight:queue:config"; - prefix queue-cfg; - - import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} - - import opendaylight-queue-types {prefix queue; revision-date "2013-09-25";} - - - revision "2013-10-24" { - description "Initial revision of queue service"; - } - - grouping queue-entry { - leaf node { - type inv:node-connector-ref; - - } - uses queue:queue-config-request; - } - - container queues { - list queue { - key "id node"; - - leaf id { - type uint32; - } - - uses queue-entry; - } - } -} diff --git a/opendaylight/md-sal/model/model-flow-management/src/main/yang/table-management.yang b/opendaylight/md-sal/model/model-flow-management/src/main/yang/table-management.yang deleted file mode 100644 index 06edb04a0a..0000000000 --- a/opendaylight/md-sal/model/model-flow-management/src/main/yang/table-management.yang +++ /dev/null @@ -1,32 +0,0 @@ -module table-management { - namespace "urn:opendaylight:table:config"; - prefix table-cfg; - - import opendaylight-inventory {prefix inv;revision-date "2013-08-19";} - import opendaylight-table-types {prefix table;} - - revision "2013-10-24" { - description "Initial revision of table service"; - } - - grouping table-entry { - - leaf node { - type inv:node-ref; - } - - uses table:table-features; - } - - container tables { - list table { - key "id node"; - - leaf id { - type uint32; - } - - uses table-entry; - } - } -} diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/node-errors.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/node-errors.yang index a8eec26936..69db856b73 100644 --- a/opendaylight/md-sal/model/model-flow-service/src/main/yang/node-errors.yang +++ b/opendaylight/md-sal/model/model-flow-service/src/main/yang/node-errors.yang @@ -73,7 +73,6 @@ module node-error { uses tr:transaction-metadata; uses flow:base-node-error-notification; uses flow:node-error-reference; - uses flow:node-error-reference; } notification group-mod-error-notification { diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-flow-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-flow-statistics.yang index e0df924a0e..f7a0652e45 100644 --- a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-flow-statistics.yang +++ b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-flow-statistics.yang @@ -25,7 +25,6 @@ module opendaylight-flow-statistics { grouping flow-statistics { container flow-statistics { //config "false"; - uses flow-types:flow; uses stat-types:generic-statistics; } } diff --git a/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory.yang b/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory.yang index 396206e28e..64d212e9bc 100644 --- a/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory.yang +++ b/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory.yang @@ -9,8 +9,8 @@ module opendaylight-inventory { revision "2013-08-19" { description "Initial revision of Inventory model"; } - - + + typedef support-type { type enumeration { enum native; @@ -21,43 +21,79 @@ module opendaylight-inventory { typedef node-id { type inet:uri; + description "Identifier for a particular node. For example: + + myprotocol: + + myprotocol:12 + + It is a good practice to always lead with a scoping identifier. + In the example above the scoping was 'myprotocol'. In your app you + could use 'myapp' etc."; } typedef node-connector-id { type inet:uri; + description "Identifier for a particular node-connector. For example: + + myprotocol: + myprotocol:3 + + It is a good practice to always lead with a scoping identifier. + In the example above the scoping was 'myprotocol'. In your app you + could use 'myapp' etc."; + } + //YANG does not have a statement which limits the scope of an instance-identifier to a particular subtree, + //which is why we are using a type capture and not an instance-identifier to define a node-ref and a node-connector-ref. typedef node-ref { type instance-identifier; + description "A reference that points to an opendaylight-light:nodes/node in the data tree."; } typedef node-connector-ref { type instance-identifier; + description "A reference that points to an opendaylight-list:nodes/node/{node-id}/node-connector in the data tree."; } identity node-context { - description "Identity used to mark node context"; + description "A node-context is a classifier for node elements which allows an RPC to provide a service on behalf of a particular element in the data tree."; } identity node-connector-context { - description "Identity used to mark node connector context"; + description "A node-connector-context is a classifier for node-connector elements which allows an RPC to provide a service on behalf of a particular element in the data tree."; } + //We are defining a base identity here because there are limitations with yang enums. Yang doesn't allow you to extend enumeratations. + //Therefore by defining a base identity we allow other yang files to extend this identity to define additional "enumerations". By + //using node-type as their base they are able to pass their object to fields that accept "node-types" while uniquely describing their + //type of node, such as "router-node" or "switch-node" etc. + //See https://wiki.opendaylight.org/view/YANG_Tools:YANG_to_Java_Mapping#Identity for more information. identity node-type { - description "Base identity for node types"; + description "A base identity definition which represents a generic node type and can be extended in other yang files."; } identity node-connector-type { - description "Base identity for node connectors type"; + description "A base identity definition which represents a generic node connector type and can be extended in other yang files."; } grouping node { + + description "Describes the contents of a generic node - + essentially an ID and a list of node-connectors. + Acts as an augmentation point where other yang files + can add additional information."; + leaf id { type node-id; + description "The unique identifier for the node."; } list "node-connector" { key "id"; + + description "A list of node connectors that belong this node."; ext:context-instance "node-connector-context"; uses node-connector; @@ -65,55 +101,117 @@ module opendaylight-inventory { } grouping node-connector { + + description "Describes a generic node connector which consists of an ID. + Acts as an augmentation point where other yang files can + add additional information."; + leaf id { type node-connector-id; + description "The unique identifier for the node-connector."; } } grouping node-context-ref { - description - "Helper grouping which contains a reference to node context."; + description + "A helper grouping which contains a reference to a node classified with a node-context. This allows RPCs in other yang files to refine their input to a particular node instance."; + leaf node { ext:context-reference "node-context"; type node-ref; + description "A reference to a particular node."; } } /** Base structure **/ container nodes { + + description "The root container of all nodes."; + list node { key "id"; ext:context-instance "node-context"; - - uses node; + description "A list of nodes (as defined by the 'grouping node')."; + uses node; //this refers to the 'grouping node' defined above. } } + //The following notifications should really be replaced by direct writes to the data tree with data change listeners listening to those changes. + //Notifications should be reserved for one time events which do not require persistence to the data tree. notification node-updated { + + status deprecated; + + description "A notification sent by someone who realized there was a modification to a node, but did not modify the data tree. + Describes that something on the node has been updated (including addition of a new node), but is for + whatever reason is not modifying the data tree. + + Deprecated: If a process determines that a node was updated, then that + logic should update the node using the DataBroker directly. Listeners interested + update changes should register a data change listener for notifications on removals."; + leaf node-ref { ext:context-reference "node-context"; + description "A reference to the node which changed."; + type node-ref; } uses node; } notification node-connector-updated { + + status deprecated; + + description "A notification sent by someone who realized there was a modification to a node-connector, but did not modify the data tree. + Describes that something on the node-connector has been updated (including addition of a new node-connector), but is for + whatever reason is not modifying the data tree. + + Deprecated: If a process determines that a node-connector was updated, then that + logic should update the node-connector using the DataBroker directly. Listeners interested + update changes should register a data change listener for notifications on removals."; + leaf node-connector-ref { ext:context-reference "node-connector-context"; type node-connector-ref; + description "A reference to the node-connector which changed."; } uses node-connector; } notification node-removed { + + status deprecated; + + description "A notification sent by someone who realized there was a node was removed, but did not modify the data tree. + Describes that a node has been removed but is for + whatever reason is not modifying the data tree. + + Deprecated: If a process determines that a node was removed, then that + logic should remove the node from the DataBroker directly. Listeners interested + in changes should register a data change listener for notifications on removals."; + leaf node-ref { + description "A reference to the node that was removed."; ext:context-reference "node-context"; type node-ref; } } notification node-connector-removed { + + status deprecated; + + description "A notification sent by someone who realized there was a node-connector was removed, but did not modify the data tree. + Describes that a node-connector has been removed but is for + whatever reason is not modifying the data tree. + + Deprecated: If a process determines that a node-connector was removed, then that + logic should remove the node-connector from the DataBroker directly. Listeners interested + in changes should register a data change listener for notifications on removals."; + leaf node-connector-ref { + description "A reference to the node-connector that was removed."; ext:context-reference "node-connector-context"; type node-connector-ref; } diff --git a/opendaylight/md-sal/model/pom.xml b/opendaylight/md-sal/model/pom.xml index 12b5f76625..5e6a86745c 100644 --- a/opendaylight/md-sal/model/pom.xml +++ b/opendaylight/md-sal/model/pom.xml @@ -17,7 +17,6 @@ model-flow-base model-flow-service model-flow-statistics - model-flow-management model-topology diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 24dcfad02b..3f02765aff 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -43,6 +43,7 @@ sal-connector-api sal-rest-connector + sal-rest-connector-config sal-netconf-connector inventory-manager @@ -57,15 +58,22 @@ sal-rest-docgen + sal-akka-raft + sal-inmemory-datastore sal-protocolbuffer-encoding - - feature + + sal-distributed-datastore + + + sal-test-model + + sal-remoterpc-connector diff --git a/opendaylight/md-sal/sal-akka-raft/README-FIRST b/opendaylight/md-sal/sal-akka-raft/README-FIRST new file mode 100644 index 0000000000..d0be2cbcbb --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/README-FIRST @@ -0,0 +1,28 @@ +Instructions on generating the protocol buffer Java source files + +These instructions are developers who are planning to generate the protocolbuffer java source files. + +1. We are using protocol buffer version 2.5.0 - you need to install the exact same version on your box. +The download link is https://code.google.com/p/protobuf/downloads/list. Download .tar/zip based on +your OS. + +2. Once downloaded the tar/zip and extracted follow the README instructions to compile protoc on your +machine + +3. Create your .proto (IDL) file in resources folder. Give appropriate package name so that the source + get generation in proper packages. For more information check + https://developers.google.com/protocol-buffers/docs/javatutorial + + For detailed information https://developers.google.com/protocol-buffers/docs/reference/java-generated + +4. To generate the java source files execute in sal-protocolbuffer-encoding directory + just run.sh in sal-protocolbuffer-encoding or execute the following command + + protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto + +5. Run mvn clean install & build the .jar + +6. !!!WARNING!!! - never edit the generated sources files of protocol buffer + +7. !!!NOTE!!! if you are planning to add new .proto file option java_package should begin with + org.opendaylight.controller.protobuff.messages to properly exclude from sonar. diff --git a/opendaylight/md-sal/sal-akka-raft/pom.xml b/opendaylight/md-sal/sal-akka-raft/pom.xml new file mode 100644 index 0000000000..3dcc546426 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/pom.xml @@ -0,0 +1,150 @@ + + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.1-SNAPSHOT + + sal-akka-raft + bundle + + + + com.google.protobuf + protobuf-java + 2.5.0 + + + com.google.guava + guava + + + + com.typesafe.akka + akka-actor_${scala.version} + + + + com.typesafe.akka + akka-cluster_${scala.version} + + + + com.typesafe.akka + akka-persistence-experimental_${scala.version} + + + + com.typesafe.akka + akka-remote_${scala.version} + + + + com.typesafe.akka + akka-testkit_${scala.version} + + + + org.osgi + org.osgi.core + + + + org.scala-lang + scala-library + + + + + junit + junit + test + + + org.mockito + mockito-all + test + + + + org.slf4j + slf4j-simple + ${slf4j.version} + test + + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.groupId}.${project.artifactId} + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + + org.jacoco + jacoco-maven-plugin + + + org.opendaylight.controller.* + + false + + + + pre-test + + prepare-agent + + + + post-test + + report + + test + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + **/protobuff/**/* + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture:Clustering + + diff --git a/opendaylight/md-sal/sal-akka-raft/run.sh b/opendaylight/md-sal/sal-akka-raft/run.sh new file mode 100755 index 0000000000..7c588f0922 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/run.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +##################################################################################################### +#Instructions on generating the protocol buffer Java source files +# +#These instructions are developers who are planning to generate the protocolbuffer java source files. +# +#1. We are using protocol buffer version 2.5.0 - you need to install the exact same version on your box. +#The download link is https://code.google.com/p/protobuf/downloads/list. Download .tar/zip based on +#your OS. +# +#2. Once downloaded the tar/zip and extracted follow the README instructions to compile protoc on your +#machine +# +#3. Create your .proto (IDL) file in resources folder. Give appropriate package name so that the source +# get generation in proper packages. For more information check +# https://developers.google.com/protocol-buffers/docs/javatutorial +# +# For detailed information https://developers.google.com/protocol-buffers/docs/reference/java-generated +# +#4. To generate the java source files execute in sal-protocolbuffer-encoding execute ./run.sh i.e. this script +# or run command +# protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto +# +#5. Run mvn clean install & build the .jar +# +#6 !!!WARNING!!!! never edit the source files generated +# +#7. !!!NOTE!!! if you are planning to add new .proto file option java_package should begin with +# org.opendaylight.controller.protobuff.messages to properly exclude from sonar. +######################################################################################################## + +protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto + +protoc --proto_path=src/main/resources --proto_path=src/test/resources --java_out=src/test/java src/test/resources/*.proto + +echo "Done generating Java source files." + +#to remove trailing spaces in the code files +find src/main/java -type f -name '*.java' -exec sed --in-place 's/[[:space:]]\+$//' {} \+ + +find src/test/java -type f -name '*.java' -exec sed --in-place 's/[[:space:]]\+$//' {} \+ diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ClientActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ClientActor.java new file mode 100644 index 0000000000..2560f16588 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ClientActor.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014 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.cluster.example; + +import akka.actor.ActorRef; +import akka.actor.Props; +import akka.actor.UntypedActor; +import akka.event.Logging; +import akka.event.LoggingAdapter; +import akka.japi.Creator; +import org.opendaylight.controller.cluster.example.messages.KeyValue; +import org.opendaylight.controller.cluster.example.messages.KeyValueSaved; + +public class ClientActor extends UntypedActor { + protected final LoggingAdapter LOG = + Logging.getLogger(getContext().system(), this); + + private final ActorRef target; + + public ClientActor(ActorRef target){ + this.target = target; + } + + public static Props props(final ActorRef target){ + return Props.create(new Creator(){ + + @Override public ClientActor create() throws Exception { + return new ClientActor(target); + } + }); + } + + @Override public void onReceive(Object message) throws Exception { + if(message instanceof KeyValue) { + target.tell(message, getSelf()); + } else if(message instanceof KeyValueSaved){ + LOG.info("KeyValue saved"); + } + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java new file mode 100644 index 0000000000..641ec0582c --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014 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.cluster.example; + +import akka.actor.ActorRef; +import akka.actor.Props; +import akka.japi.Creator; +import org.opendaylight.controller.cluster.example.messages.KeyValue; +import org.opendaylight.controller.cluster.example.messages.KeyValueSaved; +import org.opendaylight.controller.cluster.example.messages.PrintRole; +import org.opendaylight.controller.cluster.example.messages.PrintState; +import org.opendaylight.controller.cluster.raft.RaftActor; +import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; + +import java.util.HashMap; +import java.util.Map; + +/** + * A sample actor showing how the RaftActor is to be extended + */ +public class ExampleActor extends RaftActor { + + private final Map state = new HashMap(); + + private long persistIdentifier = 1; + + + public ExampleActor(String id, Map peerAddresses) { + super(id, peerAddresses); + } + + public static Props props(final String id, final Map peerAddresses){ + return Props.create(new Creator(){ + + @Override public ExampleActor create() throws Exception { + return new ExampleActor(id, peerAddresses); + } + }); + } + + @Override public void onReceiveCommand(Object message){ + if(message instanceof KeyValue){ + if(isLeader()) { + String persistId = Long.toString(persistIdentifier++); + persistData(getSender(), persistId, (Payload) message); + } else { + if(getLeader() != null) { + getLeader().forward(message, getContext()); + } + } + + } else if (message instanceof PrintState) { + LOG.debug("State of the node:"+getId() + " has = "+state.size() + " entries"); + + } else if (message instanceof PrintRole) { + LOG.debug(getId() + " = " + getRaftState()); + } else { + super.onReceiveCommand(message); + } + } + + @Override protected void applyState(ActorRef clientActor, String identifier, + Object data) { + if(data instanceof KeyValue){ + KeyValue kv = (KeyValue) data; + state.put(kv.getKey(), kv.getValue()); + if(clientActor != null) { + clientActor.tell(new KeyValueSaved(), getSelf()); + } + } + } + + @Override protected Object createSnapshot() { + return state; + } + + @Override protected void applySnapshot(Object snapshot) { + state.clear(); + state.putAll((HashMap) snapshot); + } + + @Override public void onReceiveRecover(Object message) { + super.onReceiveRecover(message); + } + + @Override public String persistenceId() { + return getId(); + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/LogGenerator.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/LogGenerator.java new file mode 100644 index 0000000000..fbe1447c72 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/LogGenerator.java @@ -0,0 +1,67 @@ +package org.opendaylight.controller.cluster.example; + +import akka.actor.ActorRef; +import org.opendaylight.controller.cluster.example.messages.KeyValue; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +/** + * Created by kramesha on 7/16/14. + */ +public class LogGenerator { + private Map clientToLoggingThread = new HashMap(); + + public void startLoggingForClient(ActorRef client) { + LoggingThread lt = new LoggingThread(client); + clientToLoggingThread.put(client, lt); + Thread t = new Thread(lt); + t.start(); + } + + public void stopLoggingForClient(ActorRef client) { + clientToLoggingThread.get(client).stopLogging(); + clientToLoggingThread.remove(client); + } + + public class LoggingThread implements Runnable { + + private ActorRef clientActor; + private volatile boolean stopLogging = false; + + public LoggingThread(ActorRef clientActor) { + this.clientActor = clientActor; + } + + public void run() { + Random r = new Random(); + while (true) { + if (stopLogging) { + System.out.println("Logging stopped for client:" + clientActor.path()); + break; + } + String key = clientActor.path().name(); + int random = r.nextInt(100); + clientActor.tell(new KeyValue(key+"-key-" + random, "value-" + random), null); + try { + Thread.sleep((random%10) * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void stopLogging() { + stopLogging = true; + } + + public void startLogging() { + stopLogging = false; + } + + + } + + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/Main.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/Main.java new file mode 100644 index 0000000000..a148ed4009 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/Main.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014 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.cluster.example; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.PoisonPill; +import org.opendaylight.controller.cluster.example.messages.KeyValue; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Main { + private static final ActorSystem actorSystem = ActorSystem.create(); + // Create three example actors + private static Map allPeers = new HashMap<>(); + + static { + allPeers.put("example-1", "akka://default/user/example-1"); + allPeers.put("example-2", "akka://default/user/example-2"); + allPeers.put("example-3", "akka://default/user/example-3"); + } + + public static void main(String[] args) throws Exception{ + ActorRef example1Actor = + actorSystem.actorOf(ExampleActor.props("example-1", + withoutPeer("example-1")), "example-1"); + + ActorRef example2Actor = + actorSystem.actorOf(ExampleActor.props("example-2", + withoutPeer("example-2")), "example-2"); + + ActorRef example3Actor = + actorSystem.actorOf(ExampleActor.props("example-3", + withoutPeer("example-3")), "example-3"); + + + List examples = Arrays.asList(example1Actor, example2Actor, example3Actor); + + ActorRef clientActor = actorSystem.actorOf(ClientActor.props(example1Actor)); + BufferedReader br = + new BufferedReader(new InputStreamReader(System.in)); + + System.out.println("Usage :"); + System.out.println("s <1-3> to start a peer"); + System.out.println("k <1-3> to kill a peer"); + + while(true) { + System.out.print("Enter command (0 to exit):"); + try { + String s = br.readLine(); + String[] split = s.split(" "); + if(split.length > 1) { + String command = split[0]; + String actor = split[1]; + + if ("k".equals(command)) { + int i = Integer.parseInt(actor); + examples.get(i - 1) + .tell(PoisonPill.getInstance(), null); + continue; + } else if ("s".equals(command)) { + int i = Integer.parseInt(actor); + String actorName = "example-" + i; + examples.add(i - 1, + actorSystem.actorOf(ExampleActor.props(actorName, + withoutPeer(actorName)), actorName)); + System.out.println("Created actor : " + actorName); + continue; + } + } + + int i = Integer.parseInt(s); + if(i == 0){ + System.exit(0); + } + clientActor.tell(new KeyValue("key " + i, "value " + i), null); + } catch (NumberFormatException nfe) { + System.err.println("Invalid Format!"); + } + } + } + + private static Map withoutPeer(String peerId) { + Map without = new HashMap<>(allPeers); + without.remove(peerId); + return without; + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java new file mode 100644 index 0000000000..c2d0b3a6b7 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java @@ -0,0 +1,251 @@ +package org.opendaylight.controller.cluster.example; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import org.opendaylight.controller.cluster.example.messages.PrintRole; +import org.opendaylight.controller.cluster.example.messages.PrintState; +import org.opendaylight.controller.cluster.raft.client.messages.AddRaftPeer; +import org.opendaylight.controller.cluster.raft.client.messages.RemoveRaftPeer; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This is a test driver for testing akka-raft implementation + * Its uses ExampleActors and threads to push content(key-vals) to these actors + * Each ExampleActor can have one or more ClientActors. Each ClientActor spawns + * a thread and starts push logs to the actor its assignged to. + */ +public class TestDriver { + + private static final ActorSystem actorSystem = ActorSystem.create(); + private static Map allPeers = new HashMap<>(); + private static Map clientActorRefs = new HashMap(); + private static Map actorRefs = new HashMap(); + private static LogGenerator logGenerator = new LogGenerator();; + + /** + * Create nodes, add clients and start logging. + * Commands + * bye + * createNodes:{num} + * addNodes:{num} + * stopNode:{nodeName} + * addClients:{num} + * addClientsToNode:{nodeName, num} + * startLogging + * stopLogging + * startLoggingForClient:{nodeName} + * stopLoggingForClient:{nodeName} + * printNodes + * printState + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + TestDriver td = new TestDriver(); + + System.out.println("Enter command (type bye to exit):"); + + + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + while(true) { + String command = br.readLine(); + if (command.startsWith("bye")) { + System.exit(0); + + } else if (command.startsWith("createNodes")) { + String[] arr = command.split(":"); + int n = Integer.parseInt(arr[1]); + td.createNodes(n); + + } else if (command.startsWith("addNodes")) { + String[] arr = command.split(":"); + int n = Integer.parseInt(arr[1]); + td.addNodes(n); + + } else if (command.startsWith("addClients")) { + String[] arr = command.split(":"); + int n = Integer.parseInt(arr[1]); + td.addClients(n); + + } else if (command.startsWith("addClientsToNode")) { + String[] arr = command.split(":"); + String nodeName = arr[1]; + int n = Integer.parseInt(arr[1]); + td.addClientsToNode(nodeName, n); + + } else if (command.startsWith("stopNode")) { + String[] arr = command.split(":"); + td.stopNode(arr[1]); + + } else if (command.startsWith("startLogging")) { + td.startAllLogging(); + + } else if (command.startsWith("startLoggingForClient")) { + String[] arr = command.split(":"); + td.startLoggingForClient(clientActorRefs.get(arr[1])); + + } else if (command.startsWith("stopLogging")) { + td.stopAllLogging(); + + } else if (command.startsWith("stopLoggingForClient")) { + String[] arr = command.split(":"); + td.stopLoggingForClient(clientActorRefs.get(arr[1])); + + } else if (command.startsWith("printState")) { + td.printState(); + } else if (command.startsWith("printNodes")) { + td.printNodes(); + } + + } + } + + public void createNodes(int num) { + for (int i=0; i < num; i++) { + int rand = getUnusedRandom(num); + allPeers.put("example-"+rand, "akka://default/user/example-"+rand); + } + + for (String s : allPeers.keySet()) { + ActorRef exampleActor = actorSystem.actorOf( + ExampleActor.props(s, withoutPeer(s)), s); + actorRefs.put(s, exampleActor); + System.out.println("Created node:"+s); + + } + } + + // add new nodes , pass in the count + public void addNodes(int num) { + Map newPeers = new HashMap<>(); + for (int i=0; i < num; i++) { + int rand = getUnusedRandom(num); + newPeers.put("example-"+rand, "akka://default/user/example-"+rand); + allPeers.put("example-"+rand, "akka://default/user/example-"+rand); + + } + Map newActorRefs = new HashMap(num); + for (Map.Entry entry : newPeers.entrySet()) { + ActorRef exampleActor = actorSystem.actorOf( + ExampleActor.props(entry.getKey(), withoutPeer(entry.getKey())), entry.getKey()); + newActorRefs.put(entry.getKey(), exampleActor); + + //now also add these new nodes as peers from the previous nodes + for (ActorRef actor : actorRefs.values()) { + actor.tell(new AddRaftPeer(entry.getKey(), entry.getValue()), null); + } + + System.out.println("Added node:" + entry); + } + + actorRefs.putAll(newActorRefs); + } + + + // add num clients to all nodes in the system + public void addClients(int num) { + for(Map.Entry actorRefEntry : actorRefs.entrySet()) { + for (int i=0; i < num; i++) { + String clientName = "client-" + i + "-" + actorRefEntry.getKey(); + ActorRef clientActor = actorSystem.actorOf( + ClientActor.props(actorRefEntry.getValue()), clientName); + clientActorRefs.put(clientName, clientActor); + System.out.println("Created client-node:" + clientName); + } + } + } + + // add num clients to a node + public void addClientsToNode(String actorName, int num) { + ActorRef actorRef = actorRefs.get(actorName); + for (int i=0; i < num; i++) { + String clientName = "client-" + i + "-" + actorRef; + clientActorRefs.put(clientName, + actorSystem.actorOf(ClientActor.props(actorRef), clientName)); + System.out.println("Added client-node:" + clientName); + } + } + + public void stopNode(String actorName) { + ActorRef actorRef = actorRefs.get(actorName); + String clientName = "client-"+actorName; + if(clientActorRefs.containsKey(clientName)) { + actorSystem.stop(clientActorRefs.get(clientName)); + clientActorRefs.remove(clientName); + } + actorSystem.stop(actorRef); + actorRefs.remove(actorName); + + for (ActorRef actor : actorRefs.values()) { + actor.tell(new RemoveRaftPeer(actorName), null); + } + + allPeers.remove(actorName); + + } + + public void startAllLogging() { + if(!clientActorRefs.isEmpty()) { + for(Map.Entry client : clientActorRefs.entrySet()) { + logGenerator.startLoggingForClient(client.getValue()); + System.out.println("Started logging for client:"+client.getKey()); + } + } else { + System.out.println("There are no clients for any nodes. First create clients using commands- addClients: or addClientsToNode::"); + } + + } + + public void startLoggingForClient(ActorRef client) { + logGenerator.startLoggingForClient(client); + } + + public void stopAllLogging() { + for(Map.Entry client : clientActorRefs.entrySet()) { + logGenerator.stopLoggingForClient(client.getValue()); + } + } + + public void stopLoggingForClient(ActorRef client) { + logGenerator.stopLoggingForClient(client); + } + + public void printState() { + for (ActorRef ref : actorRefs.values()) { + ref.tell(new PrintState(), null); + } + } + + public void printNodes() { + for (ActorRef ref : actorRefs.values()) { + ref.tell(new PrintRole(), null); + } + } + + public ActorRef getLeader() { + return null; + } + + private int getUnusedRandom(int num) { + int rand = -1; + do { + rand = (new Random()).nextInt(num * num); + } while (allPeers.keySet().contains("example-"+rand)); + + return rand; + } + + private static Map withoutPeer(String peerId) { + Map without = new ConcurrentHashMap<>(allPeers); + without.remove(peerId); + + return without; + } +} + diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java new file mode 100644 index 0000000000..560d5fc194 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValue.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 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.cluster.example.messages; + +import com.google.protobuf.GeneratedMessage; +import org.opendaylight.controller.cluster.example.protobuff.messages.KeyValueMessages; +import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; +import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class KeyValue extends Payload implements Serializable { + private String key; + private String value; + + public KeyValue() { + } + + public KeyValue(String key, String value){ + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + public void setKey(String key) { + this.key = key; + } + + public void setValue(String value) { + this.value = value; + } + + @Override public String toString() { + return "KeyValue{" + + "key='" + key + '\'' + + ", value='" + value + '\'' + + '}'; + } + + // override this method to return the protobuff related extension fields and their values + @Override public Map encode() { + Map map = new HashMap<>(); + map.put(KeyValueMessages.key, getKey()); + map.put(KeyValueMessages.value, getValue()); + return map; + } + + // override this method to assign the values from protobuff + @Override public Payload decode( + AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload payloadProtoBuff) { + String key = payloadProtoBuff.getExtension(KeyValueMessages.key); + String value = payloadProtoBuff.getExtension(KeyValueMessages.value); + this.setKey(key); + this.setValue(value); + return this; + } + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValueSaved.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValueSaved.java new file mode 100644 index 0000000000..9b2a2e9e3b --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/KeyValueSaved.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014 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.cluster.example.messages; + +import java.io.Serializable; + +public class KeyValueSaved implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/PrintRole.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/PrintRole.java new file mode 100644 index 0000000000..a5105f041a --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/PrintRole.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014 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.cluster.example.messages; + +import java.io.Serializable; + +public class PrintRole implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/PrintState.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/PrintState.java new file mode 100644 index 0000000000..20ed142d76 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/messages/PrintState.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014 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.cluster.example.messages; + +import java.io.Serializable; + +public class PrintState implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/protobuff/messages/KeyValueMessages.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/protobuff/messages/KeyValueMessages.java new file mode 100644 index 0000000000..c3d4bbfd2b --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/protobuff/messages/KeyValueMessages.java @@ -0,0 +1,73 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: KeyValueMessages.proto + +package org.opendaylight.controller.cluster.example.protobuff.messages; + +public final class KeyValueMessages { + private KeyValueMessages() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registry.add(org.opendaylight.controller.cluster.example.protobuff.messages.KeyValueMessages.key); + registry.add(org.opendaylight.controller.cluster.example.protobuff.messages.KeyValueMessages.value); + } + public static final int KEY_FIELD_NUMBER = 2; + /** + * extend .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload { ... } + */ + public static final + com.google.protobuf.GeneratedMessage.GeneratedExtension< + org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, + java.lang.String> key = com.google.protobuf.GeneratedMessage + .newFileScopedGeneratedExtension( + java.lang.String.class, + null); + public static final int VALUE_FIELD_NUMBER = 3; + /** + * extend .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload { ... } + */ + public static final + com.google.protobuf.GeneratedMessage.GeneratedExtension< + org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload, + java.lang.String> value = com.google.protobuf.GeneratedMessage + .newFileScopedGeneratedExtension( + java.lang.String.class, + null); + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\026KeyValueMessages.proto\022(org.opendaylig" + + "ht.controller.cluster.raft\032\033AppendEntrie" + + "sMessages.proto:_\n\003key\022R.org.opendayligh" + + "t.controller.cluster.raft.AppendEntries." + + "ReplicatedLogEntry.Payload\030\002 \001(\t:a\n\005valu" + + "e\022R.org.opendaylight.controller.cluster." + + "raft.AppendEntries.ReplicatedLogEntry.Pa" + + "yload\030\003 \001(\tBT\n>org.opendaylight.controll" + + "er.cluster.example.protobuff.messagesB\020K" + + "eyValueMessagesH\001" + }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors( + com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + key.internalInit(descriptor.getExtensions().get(0)); + value.internalInit(descriptor.getExtensions().get(1)); + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.getDescriptor(), + }, assigner); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ClientRequestTracker.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ClientRequestTracker.java new file mode 100644 index 0000000000..4972b348ff --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ClientRequestTracker.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import akka.actor.ActorRef; + +public interface ClientRequestTracker { + /** + * The client actor who is waiting for a response + * + * @return + */ + ActorRef getClientActor(); + + /** + * + * @return + */ + String getIdentifier(); + + /** + * The index of the log entry which needs to be replicated + * + * @return + */ + long getIndex(); + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ClientRequestTrackerImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ClientRequestTrackerImpl.java new file mode 100644 index 0000000000..15de6d01a7 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ClientRequestTrackerImpl.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import akka.actor.ActorRef; + +public class ClientRequestTrackerImpl implements ClientRequestTracker { + + private final ActorRef clientActor; + private final String identifier; + private final long logIndex; + + public ClientRequestTrackerImpl(ActorRef clientActor, String identifier, + long logIndex) { + + this.clientActor = clientActor; + + this.identifier = identifier; + + this.logIndex = logIndex; + } + + @Override public ActorRef getClientActor() { + return clientActor; + } + + @Override public long getIndex() { + return logIndex; + } + + public String getIdentifier() { + return identifier; + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTerm.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTerm.java new file mode 100644 index 0000000000..9f0d02edb9 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTerm.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +/** + * ElectionTerm contains information about a RaftActors election term. + *

+ * This information includes the last known current term of the RaftActor + * and which peer was voted for by the RaftActor in that term + *

+ * This class ensures that election term information is persisted + */ +public interface ElectionTerm { + /** + * latest term server has seen (initialized to 0 + * on first boot, increases monotonically) + */ + long getCurrentTerm(); + + /** + * candidateId that received vote in current + * term (or null if none) + */ + String getVotedFor(); + + /** + * To be called mainly when we are recovering in-memory election state from + * persistent storage + * + * @param currentTerm + * @param votedFor + */ + void update(long currentTerm, String votedFor); + + /** + * To be called when we need to update the current term either because we + * received a message from someone with a more up-to-date term or because we + * just voted for someone + *

+ * This information needs to be persisted so that on recovery the replica + * can start itself in the right term and know if it has already voted in + * that term or not + * + * @param currentTerm + * @param votedFor + */ + void updateAndPersist(long currentTerm, String votedFor); +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformation.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformation.java new file mode 100644 index 0000000000..f3de983538 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformation.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * The state of the followers log as known by the Leader + */ +public interface FollowerLogInformation { + + /** + * Increment the value of the nextIndex + * @return + */ + public long incrNextIndex(); + + /** + * Decrement the value of the nextIndex + * @return + */ + public long decrNextIndex(); + + /** + * + * @param nextIndex + */ + void setNextIndex(long nextIndex); + + /** + * Increment the value of the matchIndex + * @return + */ + public long incrMatchIndex(); + + public void setMatchIndex(long matchIndex); + + /** + * The identifier of the follower + * This could simply be the url of the remote actor + */ + public String getId(); + + /** + * for each server, index of the next log entry + * to send to that server (initialized to leader + * last log index + 1) + */ + public AtomicLong getNextIndex(); + + /** + * for each server, index of highest log entry + * known to be replicated on server + * (initialized to 0, increases monotonically) + */ + public AtomicLong getMatchIndex(); + + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java new file mode 100644 index 0000000000..94f9a53a85 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import java.util.concurrent.atomic.AtomicLong; + +public class FollowerLogInformationImpl implements FollowerLogInformation{ + + private final String id; + + private final AtomicLong nextIndex; + + private final AtomicLong matchIndex; + + public FollowerLogInformationImpl(String id, AtomicLong nextIndex, + AtomicLong matchIndex) { + this.id = id; + this.nextIndex = nextIndex; + this.matchIndex = matchIndex; + } + + public long incrNextIndex(){ + return nextIndex.incrementAndGet(); + } + + @Override public long decrNextIndex() { + return nextIndex.decrementAndGet(); + } + + @Override public void setNextIndex(long nextIndex) { + this.nextIndex.set(nextIndex); + } + + public long incrMatchIndex(){ + return matchIndex.incrementAndGet(); + } + + @Override public void setMatchIndex(long matchIndex) { + this.matchIndex.set(matchIndex); + } + + public String getId() { + return id; + } + + public AtomicLong getNextIndex() { + return nextIndex; + } + + public AtomicLong getMatchIndex() { + return matchIndex; + } + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java new file mode 100644 index 0000000000..b8e9653bc5 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import akka.actor.ActorRef; +import akka.actor.ActorSelection; +import akka.event.Logging; +import akka.event.LoggingAdapter; +import akka.japi.Procedure; +import akka.persistence.RecoveryCompleted; +import akka.persistence.SaveSnapshotFailure; +import akka.persistence.SaveSnapshotSuccess; +import akka.persistence.SnapshotOffer; +import akka.persistence.SnapshotSelectionCriteria; +import akka.persistence.UntypedPersistentActor; +import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot; +import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; +import org.opendaylight.controller.cluster.raft.base.messages.Replicate; +import org.opendaylight.controller.cluster.raft.behaviors.Candidate; +import org.opendaylight.controller.cluster.raft.behaviors.Follower; +import org.opendaylight.controller.cluster.raft.behaviors.Leader; +import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior; +import org.opendaylight.controller.cluster.raft.client.messages.AddRaftPeer; +import org.opendaylight.controller.cluster.raft.client.messages.FindLeader; +import org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply; +import org.opendaylight.controller.cluster.raft.client.messages.RemoveRaftPeer; +import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * RaftActor encapsulates a state machine that needs to be kept synchronized + * in a cluster. It implements the RAFT algorithm as described in the paper + * + * In Search of an Understandable Consensus Algorithm + *

+ * RaftActor has 3 states and each state has a certain behavior associated + * with it. A Raft actor can behave as, + *

    + *
  • A Leader
  • + *
  • A Follower (or)
  • + *
  • A Candidate
  • + *
+ *

+ *

+ * A RaftActor MUST be a Leader in order to accept requests from clients to + * change the state of it's encapsulated state machine. Once a RaftActor becomes + * a Leader it is also responsible for ensuring that all followers ultimately + * have the same log and therefore the same state machine as itself. + *

+ *

+ * The current behavior of a RaftActor determines how election for leadership + * is initiated and how peer RaftActors react to request for votes. + *

+ *

+ * Each RaftActor also needs to know the current election term. It uses this + * information for a couple of things. One is to simply figure out who it + * voted for in the last election. Another is to figure out if the message + * it received to update it's state is stale. + *

+ *

+ * The RaftActor uses akka-persistence to store it's replicated log. + * Furthermore through it's behaviors a Raft Actor determines + *

+ *

    + *
  • when a log entry should be persisted
  • + *
  • when a log entry should be applied to the state machine (and)
  • + *
  • when a snapshot should be saved
  • + *
+ */ +public abstract class RaftActor extends UntypedPersistentActor { + protected final LoggingAdapter LOG = + Logging.getLogger(getContext().system(), this); + + /** + * The current state determines the current behavior of a RaftActor + * A Raft Actor always starts off in the Follower State + */ + private RaftActorBehavior currentBehavior; + + /** + * This context should NOT be passed directly to any other actor it is + * only to be consumed by the RaftActorBehaviors + */ + private RaftActorContext context; + + /** + * The in-memory journal + */ + private ReplicatedLogImpl replicatedLog = new ReplicatedLogImpl(); + + + public RaftActor(String id, Map peerAddresses) { + context = new RaftActorContextImpl(this.getSelf(), + this.getContext(), + id, new ElectionTermImpl(), + -1, -1, replicatedLog, peerAddresses, LOG); + } + + @Override public void onReceiveRecover(Object message) { + if (message instanceof SnapshotOffer) { + SnapshotOffer offer = (SnapshotOffer) message; + Snapshot snapshot = (Snapshot) offer.snapshot(); + + // Create a replicated log with the snapshot information + // The replicated log can be used later on to retrieve this snapshot + // when we need to install it on a peer + replicatedLog = new ReplicatedLogImpl(snapshot); + + // Apply the snapshot to the actors state + applySnapshot(snapshot.getState()); + + } else if (message instanceof ReplicatedLogEntry) { + replicatedLog.append((ReplicatedLogEntry) message); + } else if (message instanceof DeleteEntries) { + replicatedLog.removeFrom(((DeleteEntries) message).getFromIndex()); + } else if (message instanceof UpdateElectionTerm) { + context.getTermInformation().update(((UpdateElectionTerm) message).getCurrentTerm(), ((UpdateElectionTerm) message).getVotedFor()); + } else if (message instanceof RecoveryCompleted) { + LOG.debug( + "Last index in log : " + replicatedLog.lastIndex()); + currentBehavior = switchBehavior(RaftState.Follower); + } + } + + @Override public void onReceiveCommand(Object message) { + if (message instanceof ApplyState){ + ApplyState applyState = (ApplyState) message; + + LOG.debug("Applying state for log index {} data {}", + applyState.getReplicatedLogEntry().getIndex(), + applyState.getReplicatedLogEntry().getData()); + + applyState(applyState.getClientActor(), applyState.getIdentifier(), + applyState.getReplicatedLogEntry().getData()); + + } else if(message instanceof ApplySnapshot ) { + applySnapshot(((ApplySnapshot) message).getSnapshot()); + + } else if (message instanceof FindLeader) { + getSender().tell( + new FindLeaderReply( + context.getPeerAddress(currentBehavior.getLeaderId())), + getSelf() + ); + + } else if (message instanceof SaveSnapshotSuccess) { + SaveSnapshotSuccess success = (SaveSnapshotSuccess) message; + + // TODO: Not sure if we want to be this aggressive with trimming stuff + trimPersistentData(success.metadata().sequenceNr()); + + } else if (message instanceof SaveSnapshotFailure) { + + // TODO: Handle failure in saving the snapshot + + } else if (message instanceof FindLeader){ + + getSender().tell(new FindLeaderReply( + context.getPeerAddress(currentBehavior.getLeaderId())), + getSelf()); + + } else if (message instanceof AddRaftPeer){ + + // FIXME : Do not add raft peers like this. + // When adding a new Peer we have to ensure that the a majority of + // the peers know about the new Peer. Doing it this way may cause + // a situation where multiple Leaders may emerge + AddRaftPeer arp = (AddRaftPeer)message; + context.addToPeers(arp.getName(), arp.getAddress()); + + } else if (message instanceof RemoveRaftPeer){ + + RemoveRaftPeer rrp = (RemoveRaftPeer)message; + context.removePeer(rrp.getName()); + + } else { + + RaftState state = + currentBehavior.handleMessage(getSender(), message); + currentBehavior = switchBehavior(state); + } + } + + + + /** + * When a derived RaftActor needs to persist something it must call + * persistData. + * + * @param clientActor + * @param identifier + * @param data + */ + protected void persistData(ActorRef clientActor, String identifier, + Payload data) { + + ReplicatedLogEntry replicatedLogEntry = new ReplicatedLogImplEntry( + context.getReplicatedLog().lastIndex() + 1, + context.getTermInformation().getCurrentTerm(), data); + + LOG.debug("Persist data {}", replicatedLogEntry); + + replicatedLog + .appendAndPersist(clientActor, identifier, replicatedLogEntry); + } + + protected String getId() { + return context.getId(); + } + + /** + * Derived actors can call the isLeader method to check if the current + * RaftActor is the Leader or not + * + * @return true it this RaftActor is a Leader false otherwise + */ + protected boolean isLeader() { + return context.getId().equals(currentBehavior.getLeaderId()); + } + + /** + * Derived actor can call getLeader if they need a reference to the Leader. + * This would be useful for example in forwarding a request to an actor + * which is the leader + * + * @return A reference to the leader if known, null otherwise + */ + protected ActorSelection getLeader(){ + String leaderId = currentBehavior.getLeaderId(); + if (leaderId == null) { + return null; + } + String peerAddress = context.getPeerAddress(leaderId); + LOG.debug("getLeader leaderId = " + leaderId + " peerAddress = " + + peerAddress); + return context.actorSelection(peerAddress); + } + + protected RaftState getRaftState() { + return currentBehavior.state(); + } + + /** + * setPeerAddress sets the address of a known peer at a later time. + *

+ * This is to account for situations where a we know that a peer + * exists but we do not know an address up-front. This may also be used in + * situations where a known peer starts off in a different location and we + * need to change it's address + *

+ * Note that if the peerId does not match the list of peers passed to + * this actor during construction an IllegalStateException will be thrown. + * + * @param peerId + * @param peerAddress + */ + protected void setPeerAddress(String peerId, String peerAddress){ + context.setPeerAddress(peerId, peerAddress); + } + + + + /** + * The applyState method will be called by the RaftActor when some data + * needs to be applied to the actor's state + * + * @param clientActor A reference to the client who sent this message. This + * is the same reference that was passed to persistData + * by the derived actor. clientActor may be null when + * the RaftActor is behaving as a follower or during + * recovery. + * @param identifier The identifier of the persisted data. This is also + * the same identifier that was passed to persistData by + * the derived actor. identifier may be null when + * the RaftActor is behaving as a follower or during + * recovery + * @param data A piece of data that was persisted by the persistData call. + * This should NEVER be null. + */ + protected abstract void applyState(ActorRef clientActor, String identifier, + Object data); + + /** + * This method will be called by the RaftActor when a snapshot needs to be + * created. The derived actor should respond with its current state. + *

+ * During recovery the state that is returned by the derived actor will + * be passed back to it by calling the applySnapshot method + * + * @return The current state of the actor + */ + protected abstract Object createSnapshot(); + + /** + * This method will be called by the RaftActor during recovery to + * reconstruct the state of the actor. + *

+ * This method may also be called at any other point during normal + * operations when the derived actor is out of sync with it's peers + * and the only way to bring it in sync is by applying a snapshot + * + * @param snapshot A snapshot of the state of the actor + */ + protected abstract void applySnapshot(Object snapshot); + + private RaftActorBehavior switchBehavior(RaftState state) { + if (currentBehavior != null) { + if (currentBehavior.state() == state) { + return currentBehavior; + } + LOG.info("Switching from state " + currentBehavior.state() + " to " + + state); + + try { + currentBehavior.close(); + } catch (Exception e) { + LOG.error(e, + "Failed to close behavior : " + currentBehavior.state()); + } + + } else { + LOG.info("Switching behavior to " + state); + } + RaftActorBehavior behavior = null; + if (state == RaftState.Candidate) { + behavior = new Candidate(context); + } else if (state == RaftState.Follower) { + behavior = new Follower(context); + } else { + behavior = new Leader(context); + } + return behavior; + } + + private void trimPersistentData(long sequenceNumber) { + // Trim snapshots + // FIXME : Not sure how exactly the SnapshotSelectionCriteria is applied + // For now guessing that it is ANDed. + deleteSnapshots(new SnapshotSelectionCriteria( + sequenceNumber - 100000, 43200000)); + + // Trim journal + deleteMessages(sequenceNumber); + } + + + private class ReplicatedLogImpl implements ReplicatedLog { + private final List journal; + private final Object snapshot; + private long snapshotIndex = -1; + private long snapshotTerm = -1; + + public ReplicatedLogImpl(Snapshot snapshot) { + this.snapshot = snapshot.getState(); + this.snapshotIndex = snapshot.getLastAppliedIndex(); + this.snapshotTerm = snapshot.getLastAppliedTerm(); + + this.journal = new ArrayList<>(snapshot.getUnAppliedEntries()); + } + + public ReplicatedLogImpl() { + this.snapshot = null; + this.journal = new ArrayList<>(); + } + + @Override public ReplicatedLogEntry get(long index) { + int adjustedIndex = adjustedIndex(index); + + if (adjustedIndex < 0 || adjustedIndex >= journal.size()) { + return null; + } + + return journal.get(adjustedIndex); + } + + @Override public ReplicatedLogEntry last() { + if (journal.size() == 0) { + return null; + } + return get(journal.size() - 1); + } + + @Override public long lastIndex() { + if (journal.size() == 0) { + return -1; + } + + return last().getIndex(); + } + + @Override public long lastTerm() { + if (journal.size() == 0) { + return -1; + } + + return last().getTerm(); + } + + + @Override public void removeFrom(long index) { + int adjustedIndex = adjustedIndex(index); + + if (adjustedIndex < 0 || adjustedIndex >= journal.size()) { + return; + } + + journal.subList(adjustedIndex , journal.size()).clear(); + } + + + @Override public void removeFromAndPersist(long index) { + int adjustedIndex = adjustedIndex(index); + + if (adjustedIndex < 0 || adjustedIndex >= journal.size()) { + return; + } + + // FIXME: Maybe this should be done after the command is saved + journal.subList(adjustedIndex , journal.size()).clear(); + + persist(new DeleteEntries(adjustedIndex), new Procedure(){ + + @Override public void apply(DeleteEntries param) + throws Exception { + //FIXME : Doing nothing for now + } + }); + + + } + + @Override public void append( + final ReplicatedLogEntry replicatedLogEntry) { + journal.add(replicatedLogEntry); + } + + @Override public List getFrom(long index) { + int adjustedIndex = adjustedIndex(index); + + List entries = new ArrayList<>(100); + if (adjustedIndex < 0 || adjustedIndex >= journal.size()) { + return entries; + } + + + for (int i = adjustedIndex; + i < journal.size(); i++) { + entries.add(journal.get(i)); + } + return entries; + } + + @Override public void appendAndPersist( + final ReplicatedLogEntry replicatedLogEntry) { + appendAndPersist(null, null, replicatedLogEntry); + } + + public void appendAndPersist(final ActorRef clientActor, + final String identifier, + final ReplicatedLogEntry replicatedLogEntry) { + context.getLogger().debug( + "Append log entry and persist {} ", replicatedLogEntry); + // FIXME : By adding the replicated log entry to the in-memory journal we are not truly ensuring durability of the logs + journal.add(replicatedLogEntry); + + // When persisting events with persist it is guaranteed that the + // persistent actor will not receive further commands between the + // persist call and the execution(s) of the associated event + // handler. This also holds for multiple persist calls in context + // of a single command. + persist(replicatedLogEntry, + new Procedure() { + public void apply(ReplicatedLogEntry evt) throws Exception { + // FIXME : Tentatively create a snapshot every hundred thousand entries. To be tuned. + if (size() > 100000) { + ReplicatedLogEntry lastAppliedEntry = + get(context.getLastApplied()); + long lastAppliedIndex = -1; + long lastAppliedTerm = -1; + if (lastAppliedEntry != null) { + lastAppliedIndex = lastAppliedEntry.getIndex(); + lastAppliedTerm = lastAppliedEntry.getTerm(); + } + + saveSnapshot(Snapshot.create(createSnapshot(), + getFrom(context.getLastApplied() + 1), + lastIndex(), lastTerm(), lastAppliedIndex, + lastAppliedTerm)); + } + // Send message for replication + if (clientActor != null) { + currentBehavior.handleMessage(getSelf(), + new Replicate(clientActor, identifier, + replicatedLogEntry) + ); + } + } + } + ); + } + + @Override public long size() { + return journal.size() + snapshotIndex + 1; + } + + @Override public boolean isPresent(long index) { + int adjustedIndex = adjustedIndex(index); + + if (adjustedIndex < 0 || adjustedIndex >= journal.size()) { + return false; + } + return true; + } + + @Override public boolean isInSnapshot(long index) { + return index <= snapshotIndex; + } + + @Override public Object getSnapshot() { + return snapshot; + } + + @Override public long getSnapshotIndex() { + return snapshotIndex; + } + + @Override public long getSnapshotTerm() { + return snapshotTerm; + } + + private int adjustedIndex(long index) { + if(snapshotIndex < 0){ + return (int) index; + } + return (int) (index - snapshotIndex); + } + } + + + + + private static class DeleteEntries implements Serializable { + private final int fromIndex; + + + public DeleteEntries(int fromIndex) { + this.fromIndex = fromIndex; + } + + public int getFromIndex() { + return fromIndex; + } + } + + + private static class Snapshot implements Serializable { + private final Object state; + private final List unAppliedEntries; + private final long lastIndex; + private final long lastTerm; + private final long lastAppliedIndex; + private final long lastAppliedTerm; + + private Snapshot(Object state, + List unAppliedEntries, long lastIndex, + long lastTerm, long lastAppliedIndex, long lastAppliedTerm) { + this.state = state; + this.unAppliedEntries = unAppliedEntries; + this.lastIndex = lastIndex; + this.lastTerm = lastTerm; + this.lastAppliedIndex = lastAppliedIndex; + this.lastAppliedTerm = lastAppliedTerm; + } + + + public static Snapshot create(Object state, + List entries, long lastIndex, long lastTerm, + long lastAppliedIndex, long lastAppliedTerm) { + return new Snapshot(state, entries, lastIndex, lastTerm, + lastAppliedIndex, lastAppliedTerm); + } + + public Object getState() { + return state; + } + + public List getUnAppliedEntries() { + return unAppliedEntries; + } + + public long getLastTerm() { + return lastTerm; + } + + public long getLastAppliedIndex() { + return lastAppliedIndex; + } + + public long getLastAppliedTerm() { + return lastAppliedTerm; + } + } + + private class ElectionTermImpl implements ElectionTerm { + /** + * Identifier of the actor whose election term information this is + */ + private long currentTerm = 0; + private String votedFor = null; + + public long getCurrentTerm() { + return currentTerm; + } + + public String getVotedFor() { + return votedFor; + } + + @Override public void update(long currentTerm, String votedFor) { + LOG.info("Set currentTerm={}, votedFor={}", currentTerm, votedFor); + + this.currentTerm = currentTerm; + this.votedFor = votedFor; + } + + @Override + public void updateAndPersist(long currentTerm, String votedFor){ + update(currentTerm, votedFor); + // FIXME : Maybe first persist then update the state + persist(new UpdateElectionTerm(this.currentTerm, this.votedFor), new Procedure(){ + + @Override public void apply(UpdateElectionTerm param) + throws Exception { + + } + }); + } + } + + private static class UpdateElectionTerm implements Serializable { + private final long currentTerm; + private final String votedFor; + + public UpdateElectionTerm(long currentTerm, String votedFor) { + this.currentTerm = currentTerm; + this.votedFor = votedFor; + } + + public long getCurrentTerm() { + return currentTerm; + } + + public String getVotedFor() { + return votedFor; + } + } + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java new file mode 100644 index 0000000000..ae9431a43a --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import akka.actor.ActorRef; +import akka.actor.ActorSelection; +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.event.LoggingAdapter; + +import java.util.Map; + +/** + * The RaftActorContext contains that portion of the RaftActors state that + * needs to be shared with it's behaviors. A RaftActorContext should NEVER be + * used in any actor context outside the RaftActor that constructed it. + */ +public interface RaftActorContext { + /** + * Create a new local actor + * @param props + * @return + */ + ActorRef actorOf(Props props); + + /** + * Create a actor selection + * @param path + * @return + */ + ActorSelection actorSelection(String path); + + /** + * Get the identifier for the RaftActor. This identifier represents the + * name of the actor whose common state is being shared. For example the + * id could be 'inventory' + * @return the identifier + */ + String getId(); + + /** + * A reference to the RaftActor itself. This could be used to send messages + * to the RaftActor + * @return + */ + ActorRef getActor(); + + /** + * Get the ElectionTerm information + * @return + */ + ElectionTerm getTermInformation(); + + /** + * index of highest log entry known to be + * committed (initialized to 0, increases + * monotonically) + * @return + */ + long getCommitIndex(); + + + /** + * + */ + void setCommitIndex(long commitIndex); + + /** + * index of highest log entry applied to state + * machine (initialized to 0, increases + * monotonically) + * @return + */ + long getLastApplied(); + + + /** + * + */ + void setLastApplied(long lastApplied); + + /** + * @return A representation of the log + */ + ReplicatedLog getReplicatedLog(); + + /** + * @return The ActorSystem associated with this context + */ + ActorSystem getActorSystem(); + + /** + * Get the logger to be used for logging messages + * + * @return + */ + LoggingAdapter getLogger(); + + /** + * Get a mapping of peerId's to their addresses + * + * @return + * + */ + Map getPeerAddresses(); + + /** + * Get the address of the peer as a String. This is the same format in + * which a consumer would provide the address + * + * @param peerId + * @return The address of the peer or null if the address has not yet been + * resolved + */ + String getPeerAddress(String peerId); + + /** + * Add to actor peers + * @param name + * @param address + */ + void addToPeers(String name, String address); + + /** + * + * @param name + */ + public void removePeer(String name); + + /** + * Given a peerId return the corresponding actor + *

+ * + * + * @param peerId + * @return The actorSelection corresponding to the peer or null if the + * address has not yet been resolved + */ + ActorSelection getPeerActorSelection(String peerId); + + /** + * Set Peer Address can be called at a later time to change the address of + * a known peer. + * + *

+ * Throws an IllegalStateException if the peer is unknown + * + * @param peerId + * @param peerAddress + */ + void setPeerAddress(String peerId, String peerAddress); +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java new file mode 100644 index 0000000000..833c8a9e8a --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import akka.actor.ActorRef; +import akka.actor.ActorSelection; +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.actor.UntypedActorContext; +import akka.event.LoggingAdapter; + +import java.util.Map; + +import static com.google.common.base.Preconditions.checkState; + +public class RaftActorContextImpl implements RaftActorContext{ + + private final ActorRef actor; + + private final UntypedActorContext context; + + private final String id; + + private final ElectionTerm termInformation; + + private long commitIndex; + + private long lastApplied; + + private final ReplicatedLog replicatedLog; + + private final Map peerAddresses; + + private final LoggingAdapter LOG; + + public RaftActorContextImpl(ActorRef actor, UntypedActorContext context, + String id, + ElectionTerm termInformation, long commitIndex, + long lastApplied, ReplicatedLog replicatedLog, Map peerAddresses, LoggingAdapter logger) { + this.actor = actor; + this.context = context; + this.id = id; + this.termInformation = termInformation; + this.commitIndex = commitIndex; + this.lastApplied = lastApplied; + this.replicatedLog = replicatedLog; + this.peerAddresses = peerAddresses; + this.LOG = logger; + } + + public ActorRef actorOf(Props props){ + return context.actorOf(props); + } + + public ActorSelection actorSelection(String path){ + return context.actorSelection(path); + } + + public String getId() { + return id; + } + + public ActorRef getActor() { + return actor; + } + + public ElectionTerm getTermInformation() { + return termInformation; + } + + public long getCommitIndex() { + return commitIndex; + } + + @Override public void setCommitIndex(long commitIndex) { + this.commitIndex = commitIndex; + } + + public long getLastApplied() { + return lastApplied; + } + + @Override public void setLastApplied(long lastApplied) { + this.lastApplied = lastApplied; + } + + @Override public ReplicatedLog getReplicatedLog() { + return replicatedLog; + } + + @Override public ActorSystem getActorSystem() { + return context.system(); + } + + @Override public LoggingAdapter getLogger() { + return this.LOG; + } + + @Override public Map getPeerAddresses() { + return peerAddresses; + } + + @Override public String getPeerAddress(String peerId) { + return peerAddresses.get(peerId); + } + + @Override public void addToPeers(String name, String address) { + peerAddresses.put(name, address); + } + + @Override public void removePeer(String name) { + peerAddresses.remove(name); + } + + @Override public ActorSelection getPeerActorSelection(String peerId) { + String peerAddress = getPeerAddress(peerId); + if(peerAddress != null){ + return actorSelection(peerAddress); + } + return null; + } + + @Override public void setPeerAddress(String peerId, String peerAddress) { + LOG.info("Peer address for peer {} set to {}", peerId, peerAddress); + checkState(peerAddresses.containsKey(peerId), peerId + " is unknown"); + + peerAddresses.put(peerId, peerAddress); + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftState.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftState.java new file mode 100644 index 0000000000..65114eb659 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftState.java @@ -0,0 +1,7 @@ +package org.opendaylight.controller.cluster.raft; + +public enum RaftState { + Candidate, + Follower, + Leader +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java new file mode 100644 index 0000000000..b7c8955aad --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import java.util.List; + +/** + * Represents the ReplicatedLog that needs to be kept in sync by the RaftActor + */ +public interface ReplicatedLog { + /** + * Get a replicated log entry at the specified index + * + * @param index the index of the log entry + * @return the ReplicatedLogEntry at index. null if index less than 0 or + * greater than the size of the in-memory journal. + */ + ReplicatedLogEntry get(long index); + + + /** + * Get the last replicated log entry + * + * @return + */ + ReplicatedLogEntry last(); + + /** + * + * @return + */ + long lastIndex(); + + /** + * + * @return + */ + long lastTerm(); + + /** + * To be called when we need to remove entries from the in-memory log. + * This method will remove all entries >= index. This method should be used + * during recovery to appropriately trim the log based on persisted + * information + * + * @param index the index of the log entry + */ + void removeFrom(long index); + + + /** + * To be called when we need to remove entries from the in-memory log and we + * need that information persisted to disk. This method will remove all + * entries >= index. + *

+ * The persisted information would then be used during recovery to properly + * reconstruct the state of the in-memory replicated log + * + * @param index the index of the log entry + */ + void removeFromAndPersist(long index); + + /** + * Append an entry to the log + * @param replicatedLogEntry + */ + void append(ReplicatedLogEntry replicatedLogEntry); + + /** + * + * @param replicatedLogEntry + */ + void appendAndPersist(final ReplicatedLogEntry replicatedLogEntry); + + /** + * + * @param index the index of the log entry + */ + List getFrom(long index); + + + /** + * + * @return + */ + long size(); + + /** + * Checks if the entry at the specified index is present or not + * + * @param index the index of the log entry + * @return true if the entry is present in the in-memory journal + */ + boolean isPresent(long index); + + /** + * Checks if the entry is present in a snapshot + * + * @param index the index of the log entry + * @return true if the entry is in the snapshot. false if the entry is not + * in the snapshot even if the entry may be present in the replicated log + */ + boolean isInSnapshot(long index); + + /** + * Get the snapshot + * + * @return an object representing the snapshot if it exists. null otherwise + */ + Object getSnapshot(); + + /** + * Get the index of the snapshot + * + * @return the index from which the snapshot was created. -1 otherwise. + */ + long getSnapshotIndex(); + + /** + * Get the term of the snapshot + * + * @return the term of the index from which the snapshot was created. -1 + * otherwise + */ + long getSnapshotTerm(); +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java new file mode 100644 index 0000000000..f501c4d37f --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; + +/** + * Represents one entry in the replicated log + */ +public interface ReplicatedLogEntry { + /** + * The data stored in that entry + * + * @return + */ + Payload getData(); + + /** + * The term stored in that entry + * + * @return + */ + long getTerm(); + + /** + * The index of the entry + * + * @return + */ + long getIndex(); +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java new file mode 100644 index 0000000000..fc2ec5cff9 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; + +import java.io.Serializable; + +public class ReplicatedLogImplEntry implements ReplicatedLogEntry, + Serializable { + + private final long index; + private final long term; + private final Payload payload; + + public ReplicatedLogImplEntry(long index, long term, Payload payload) { + + this.index = index; + this.term = term; + this.payload = payload; + } + + @Override public Payload getData() { + return payload; + } + + @Override public long getTerm() { + return term; + } + + @Override public long getIndex() { + return index; + } + + @Override public String toString() { + return "Entry{" + + "index=" + index + + ", term=" + term + + '}'; + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/SerializationUtils.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/SerializationUtils.java new file mode 100644 index 0000000000..374e0fa9ba --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/SerializationUtils.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014 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.cluster.raft; + +import org.opendaylight.controller.cluster.raft.messages.AppendEntries; + +public class SerializationUtils { + + public static Object fromSerializable(Object serializable){ + if(serializable.getClass().equals(AppendEntries.SERIALIZABLE_CLASS)){ + return AppendEntries.fromSerializable(serializable); + } + return serializable; + } + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplySnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplySnapshot.java new file mode 100644 index 0000000000..9739fb2f1b --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplySnapshot.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import java.io.Serializable; + +public class ApplySnapshot implements Serializable { + private final Object snapshot; + + public ApplySnapshot(Object snapshot) { + this.snapshot = snapshot; + } + + public Object getSnapshot() { + return snapshot; + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplyState.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplyState.java new file mode 100644 index 0000000000..b904335be3 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplyState.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import akka.actor.ActorRef; +import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry; + +import java.io.Serializable; + +public class ApplyState implements Serializable { + private final ActorRef clientActor; + private final String identifier; + private final ReplicatedLogEntry replicatedLogEntry; + + public ApplyState(ActorRef clientActor, String identifier, + ReplicatedLogEntry replicatedLogEntry) { + this.clientActor = clientActor; + this.identifier = identifier; + this.replicatedLogEntry = replicatedLogEntry; + } + + public ActorRef getClientActor() { + return clientActor; + } + + public String getIdentifier() { + return identifier; + } + + public ReplicatedLogEntry getReplicatedLogEntry() { + return replicatedLogEntry; + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CommitEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CommitEntry.java new file mode 100644 index 0000000000..07e376fca3 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CommitEntry.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import java.io.Serializable; + +/** + * Message sent to commit an entry to the log + */ +public class CommitEntry implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ElectionTimeout.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ElectionTimeout.java new file mode 100644 index 0000000000..a844849f15 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ElectionTimeout.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import java.io.Serializable; + +public class ElectionTimeout implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/PersistEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/PersistEntry.java new file mode 100644 index 0000000000..6a62817e90 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/PersistEntry.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import java.io.Serializable; + +/** + * Message sent to Persist an entry into the transaction journal + */ +public class PersistEntry implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/Replicate.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/Replicate.java new file mode 100644 index 0000000000..9bc737a0e3 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/Replicate.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import akka.actor.ActorRef; +import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry; + +import java.io.Serializable; + +public class Replicate implements Serializable { + private final ActorRef clientActor; + private final String identifier; + private final ReplicatedLogEntry replicatedLogEntry; + + public Replicate(ActorRef clientActor, String identifier, + ReplicatedLogEntry replicatedLogEntry) { + + this.clientActor = clientActor; + this.identifier = identifier; + this.replicatedLogEntry = replicatedLogEntry; + } + + public ActorRef getClientActor() { + return clientActor; + } + + public String getIdentifier() { + return identifier; + } + + public ReplicatedLogEntry getReplicatedLogEntry() { + return replicatedLogEntry; + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SaveSnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SaveSnapshot.java new file mode 100644 index 0000000000..861f5ee715 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SaveSnapshot.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import java.io.Serializable; + +/** + * This message is sent by a RaftActor to itself so that a subclass can process + * it and use it to save it's state + */ +public class SaveSnapshot implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendHeartBeat.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendHeartBeat.java new file mode 100644 index 0000000000..3c8c845f5d --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendHeartBeat.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import java.io.Serializable; + +/** + * This messages is sent to the Leader to prompt it to send a heartbeat + * to it's followers. + * + * Typically the Leader to itself on a schedule + */ +public class SendHeartBeat implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendInstallSnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendInstallSnapshot.java new file mode 100644 index 0000000000..6c3313f316 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendInstallSnapshot.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014 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.cluster.raft.base.messages; + +import java.io.Serializable; + +public class SendInstallSnapshot implements Serializable { +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java new file mode 100644 index 0000000000..f7281bb8e3 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2014 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.cluster.raft.behaviors; + +import akka.actor.ActorRef; +import akka.actor.Cancellable; +import org.opendaylight.controller.cluster.raft.ClientRequestTracker; +import org.opendaylight.controller.cluster.raft.RaftActorContext; +import org.opendaylight.controller.cluster.raft.RaftState; +import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry; +import org.opendaylight.controller.cluster.raft.SerializationUtils; +import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; +import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout; +import org.opendaylight.controller.cluster.raft.messages.AppendEntries; +import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply; +import org.opendaylight.controller.cluster.raft.messages.RequestVote; +import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply; +import scala.concurrent.duration.FiniteDuration; + +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Abstract class that represents the behavior of a RaftActor + *

+ * All Servers: + *