From: Ed Warnicke Date: Wed, 27 Aug 2014 21:09:18 +0000 (-0500) Subject: Initial clustering feature X-Git-Tag: release/helium~141^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=2cfa8aed573b09cfc6ab6ba9edc02476635b0896 Initial clustering feature Besides the clustering feature changes a couple of other changes had to be made to the distributed data store and remote rpc modules to make the solution work with karaf 1. The akka.conf in sal-clustering-config has now been changed so that it works in a single node cluster out of the box. Specifically the hostnames have been set to 127.0.0.1 and the member role has been set to member-1 2. The distributed-data-store and the remote-rpcconnector now load akka configuration from the configuration/initial folder. The positive thing about this is that even in a multi-node cluster one does not need to pass the location of akka.conf on the command line. The negative thing about this is that you cannot change the location from which the akka configuration can be picked up. Though this should be ok because we specifically pick modules.conf and module-shards.conf from the configuration/initial folder as well. 3. The Protobuf bundle has now been wrapped and a Dynamic Import has been added to it so that it can deserialized specific protocol buffer messages 4. The RestConfProvider was not written to shutdown correctly. While this is not normally an issue it does become an issue when the clustering feature is loaded for the first time because in that case the RestConfProvider may need to be shutdown by the config sub-system Change-Id: I1701ae8e9508c82779483963fb73b6af91095d7d Signed-off-by: Ed Warnicke Signed-off-by: Moiz Raja --- diff --git a/features/akka/pom.xml b/features/akka/pom.xml new file mode 100644 index 0000000000..f1f3017c20 --- /dev/null +++ b/features/akka/pom.xml @@ -0,0 +1,264 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.2-SNAPSHOT + ../../opendaylight/commons/opendaylight + + features-akka + org.opendaylight.controller + jar + + features.xml + + 1.0.0-SNAPSHOT + 1.4.2-SNAPSHOT + 3.0.1 + 0.6.2-SNAPSHOT + 1.4.2-SNAPSHOT + 2.16 + + + + + + + + + org.scala-lang + scala-library + ${scala.version}.${scala.micro.version} + + + org.scala-lang + scala-reflect + ${scala.version}.${scala.micro.version} + + + com.typesafe + config + ${typesafe.config.version} + + + com.typesafe.akka + akka-actor_${scala.version} + ${akka.version} + + + com.typesafe.akka + akka-slf4j_${scala.version} + ${akka.version} + + + com.typesafe.akka + akka-osgi_${scala.version} + ${akka.version} + + + org.uncommons.maths + uncommons-maths + ${uncommons.maths.version} + + + jfree + jcommon + + + jfree + jfreechart + + + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + io.netty + netty + 3.8.0.Final + + + com.typesafe.akka + akka-remote_${scala.version} + ${akka.version} + + + com.typesafe.akka + akka-cluster_${scala.version} + ${akka.version} + + + org.iq80.leveldb + leveldb + ${leveldb.version} + + + org.fusesource.leveldbjni + leveldbjni-all + ${leveldbjni.version} + + + + + org.opendaylight.yangtools + features-test + ${feature.test.version} + test + + + + org.opendaylight.controller + opendaylight-karaf-empty + ${karaf.empty.version} + zip + + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + generate-resources + + resources + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.version} + + + org.opendaylight.controller + opendaylight-karaf-empty + ${karaf.empty.version} + + + org.opendaylight.yangtools:features-test + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary + + diff --git a/features/akka/src/main/resources/features.xml b/features/akka/src/main/resources/features.xml new file mode 100644 index 0000000000..182ff766e6 --- /dev/null +++ b/features/akka/src/main/resources/features.xml @@ -0,0 +1,117 @@ + + + + + + + + + odl-akka-scala + odl-akka-system + odl-akka-clustering + odl-akka-leveldb + odl-akka-persistence + + + + mvn:org.scala-lang/scala-library/${scala.version}.${scala.micro.version} + mvn:org.scala-lang/scala-reflect/${scala.version}.${scala.micro.version} + + + odl-akka-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-akka-system + wrap:mvn:org.uncommons.maths/uncommons-maths/${uncommons.maths.version} + mvn:com.google.protobuf/protobuf-java/${protobuf.version} + mvn:io.netty/netty/3.8.0.Final + 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} + mvn:org.fusesource.leveldbjni/leveldbjni-all/${leveldbjni.version} + + + odl-akka-leveldb + odl-akka-system + mvn:com.typesafe.akka/akka-persistence-experimental_${scala.version}/${akka.version} + wrap:mvn:com.google.protobuf/protobuf-java/${protobuf.version}$overwrite=merge&DynamicImport-Package=org.opendaylight.controller.protobuff.messages.*;org.opendaylight.controller.cluster.raft.protobuff.client.messages.* + + + + diff --git a/features/mdsal/pom.xml b/features/mdsal/pom.xml index c6856c89fb..38fe92fa82 100644 --- a/features/mdsal/pom.xml +++ b/features/mdsal/pom.xml @@ -40,6 +40,13 @@ features xml + + org.opendaylight.controller + features-akka + ${commons.opendaylight.version} + features + xml + org.opendaylight.controller sal-core-api @@ -97,6 +104,30 @@ xml config + + org.opendaylight.controller + sal-distributed-datastore + + + org.opendaylight.controller + sal-remoterpc-connector + + + org.opendaylight.controller + sal-clustering-commons + + + org.opendaylight.controller + sal-akka-raft + ${mdsal.version} + + + org.opendaylight.controller + sal-clustering-config + ${mdsal.version} + xml + config + org.opendaylight.controller sal-netconf-connector diff --git a/features/mdsal/src/main/resources/features.xml b/features/mdsal/src/main/resources/features.xml index 408be621f5..ae73c71ee4 100644 --- a/features/mdsal/src/main/resources/features.xml +++ b/features/mdsal/src/main/resources/features.xml @@ -7,11 +7,13 @@ mvn:org.opendaylight.controller/features-config/${config.version}/xml/features mvn:org.opendaylight.controller/features-config-persister/${config.version}/xml/features mvn:org.opendaylight.controller/features-config-netty/${config.version}/xml/features + mvn:org.opendaylight.controller/features-akka/${commons.opendaylight.version}/xml/features odl-mdsal-broker odl-mdsal-netconf-connector odl-restconf odl-mdsal-xsql + odl-mdsal-clustering odl-toaster @@ -87,4 +89,33 @@ mvn:com.sun.jersey/jersey-servlet/${jersey.version} wrap:mvn:org.json/json/${org.json.version} + + odl-mdsal-broker + odl-akka-system + odl-akka-persistence + mvn:org.opendaylight.controller/sal-clustering-commons/${project.version} + mvn:org.opendaylight.controller/sal-akka-raft/${project.version} + mvn:com.codahale.metrics/metrics-core/3.0.1 + + + odl-mdsal-broker + odl-mdsal-clustering-commons + odl-akka-clustering + mvn:org.opendaylight.controller/sal-distributed-datastore/${project.version} + + + odl-mdsal-broker + odl-mdsal-clustering-commons + odl-akka-clustering + odl-akka-leveldb + mvn:org.opendaylight.controller/sal-remoterpc-connector/${project.version} + + + odl-mdsal-remoterpc-connector + odl-mdsal-distributed-datastore + mvn:org.opendaylight.controller/sal-clustering-config/${project.version}/xml/config + mvn:org.opendaylight.controller/sal-clustering-config/${project.version}/xml/akkaconf + mvn:org.opendaylight.controller/sal-clustering-config/${project.version}/xml/moduleshardconf + mvn:org.opendaylight.controller/sal-clustering-config/${project.version}/xml/moduleconf + diff --git a/features/pom.xml b/features/pom.xml index 039060b4ae..01156cf02a 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -26,5 +26,6 @@ netconf protocol-framework adsal-compatibility + akka \ No newline at end of file diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 2bc099d24c..b05170ddc8 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -68,6 +68,7 @@ 1.4 0.2.5-SNAPSHOT etc/opendaylight/karaf + 05-clustering.xml 00-netty.xml 01-mdsal.xml 04-xsql.xml @@ -199,7 +200,7 @@ 1.0.0-SNAPSHOT 0.4.2-SNAPSHOT 1.2.0 - 1.2.2 + 1.2.2a 0.4.2-SNAPSHOT 0.0.2-SNAPSHOT 0.4.2-SNAPSHOT diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index 7f9f56f6cd..fcb452f422 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -1066,10 +1066,6 @@ org.opendaylight.controller sal-restconf-broker - - org.opendaylight.controller - sal-remoterpc-connector - @@ -1316,10 +1312,6 @@ jeromq 0.3.1 - - org.opendaylight.controller - sal-distributed-datastore - org.opendaylight.controller sal-clustering-config diff --git a/opendaylight/md-sal/sal-akka-raft/pom.xml b/opendaylight/md-sal/sal-akka-raft/pom.xml index 325005b239..98c81c267f 100644 --- a/opendaylight/md-sal/sal-akka-raft/pom.xml +++ b/opendaylight/md-sal/sal-akka-raft/pom.xml @@ -97,9 +97,8 @@ ${project.groupId}.${project.artifactId} - - - + org.opendaylight.cluster.raft + * diff --git a/opendaylight/md-sal/sal-clustering-commons/pom.xml b/opendaylight/md-sal/sal-clustering-commons/pom.xml index b8980cd0be..a3619ec4d2 100644 --- a/opendaylight/md-sal/sal-clustering-commons/pom.xml +++ b/opendaylight/md-sal/sal-clustering-commons/pom.xml @@ -209,6 +209,7 @@ + org.jacoco @@ -238,7 +239,18 @@ - + + org.apache.felix + maven-bundle-plugin + true + + + ${project.groupId}.${project.artifactId} + org.opendaylight.controller.cluster.*,org.opendaylight.common.actor,org.opendaylight.common.reporting,org.opendaylight.controller.protobuff.*,org.opendaylight.controller.xml.* + * + + + + - diff --git a/opendaylight/md-sal/sal-clustering-config/pom.xml b/opendaylight/md-sal/sal-clustering-config/pom.xml index 31b658d1d7..91c0b5caa1 100644 --- a/opendaylight/md-sal/sal-clustering-config/pom.xml +++ b/opendaylight/md-sal/sal-clustering-config/pom.xml @@ -36,6 +36,21 @@ xml config + + ${project.build.directory}/classes/initial/akka.conf + xml + akkaconf + + + ${project.build.directory}/classes/initial/module-shards.conf + xml + moduleshardconf + + + ${project.build.directory}/classes/initial/modules.conf + xml + moduleconf + diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf index 05322137aa..5a2116b50f 100644 --- a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf +++ b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf @@ -21,7 +21,7 @@ odl-cluster-data { remote { log-remote-lifecycle-events = off netty.tcp { - hostname = "" + hostname = "127.0.0.1" port = 2550 maximum-frame-size = 419430400 send-buffer-size = 52428800 @@ -30,9 +30,14 @@ odl-cluster-data { } cluster { - seed-nodes = ["akka.tcp://opendaylight-cluster-data@:2550"] + seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"] auto-down-unreachable-after = 10s + + roles = [ + "member-1" + ] + } } } @@ -51,13 +56,13 @@ odl-cluster-rpc { remote { log-remote-lifecycle-events = off netty.tcp { - hostname = "" + hostname = "127.0.0.1" port = 2551 } } cluster { - seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@:2551"] + seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@127.0.0.1:2551"] auto-down-unreachable-after = 10s } diff --git a/opendaylight/md-sal/sal-distributed-datastore/pom.xml b/opendaylight/md-sal/sal-distributed-datastore/pom.xml index dd5a7f2979..82998226b6 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/pom.xml +++ b/opendaylight/md-sal/sal-distributed-datastore/pom.xml @@ -45,6 +45,11 @@ akka-slf4j_${scala.version} + + com.typesafe.akka + akka-osgi_${scala.version} + + @@ -178,6 +183,7 @@ !*snappy;!org.jboss.*;!com.jcraft.*;!*jetty*;!sun.security.*;* + diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ActorSystemFactory.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ActorSystemFactory.java index 15c0548761..b326d61fc6 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ActorSystemFactory.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ActorSystemFactory.java @@ -10,24 +10,55 @@ package org.opendaylight.controller.cluster.datastore; import akka.actor.ActorSystem; import akka.actor.Props; -import com.google.common.base.Function; +import akka.osgi.BundleDelegatingClassLoader; +import com.google.common.base.Preconditions; +import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; +import org.osgi.framework.BundleContext; -import javax.annotation.Nullable; +import java.io.File; public class ActorSystemFactory { - private static final ActorSystem actorSystem = (new Function(){ - - @Nullable @Override public ActorSystem apply(@Nullable Void aVoid) { - ActorSystem system = - ActorSystem.create("opendaylight-cluster-data", ConfigFactory - .load().getConfig("odl-cluster-data")); - system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor"); - return system; - } - }).apply(null); + + public static final String AKKA_CONF_PATH = "./configuration/initial/akka.conf"; + public static final String ACTOR_SYSTEM_NAME = "opendaylight-cluster-data"; + public static final String CONFIGURATION_NAME = "odl-cluster-data"; + + private static volatile ActorSystem actorSystem = null; public static final ActorSystem getInstance(){ return actorSystem; } + + /** + * This method should be called only once during initialization + * + * @param bundleContext + */ + public static final ActorSystem createInstance(final BundleContext bundleContext) { + if(actorSystem == null) { + // Create an OSGi bundle classloader for actor system + BundleDelegatingClassLoader classLoader = new BundleDelegatingClassLoader(bundleContext.getBundle(), + Thread.currentThread().getContextClassLoader()); + synchronized (ActorSystemFactory.class) { + // Double check + + if (actorSystem == null) { + ActorSystem system = ActorSystem.create(ACTOR_SYSTEM_NAME, + ConfigFactory.load(readAkkaConfiguration()).getConfig(CONFIGURATION_NAME), classLoader); + system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor"); + actorSystem = system; + } + } + } + + return actorSystem; + } + + + private static final Config readAkkaConfiguration(){ + File defaultConfigFile = new File(AKKA_CONF_PATH); + Preconditions.checkState(defaultConfigFile.exists(), "akka.conf is missing"); + return ConfigFactory.parseFile(defaultConfigFile); + } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java index 65a39a60e6..72b593f010 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java @@ -12,12 +12,13 @@ import akka.actor.ActorSystem; import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory; import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.osgi.framework.BundleContext; public class DistributedDataStoreFactory { public static DistributedDataStore createInstance(String name, SchemaService schemaService, - DistributedDataStoreProperties dataStoreProperties) { + DistributedDataStoreProperties dataStoreProperties, BundleContext bundleContext) { - ActorSystem actorSystem = ActorSystemFactory.getInstance(); + ActorSystem actorSystem = ActorSystemFactory.createInstance(bundleContext); Configuration config = new ConfigurationImpl("module-shards.conf", "modules.conf"); final DistributedDataStore dataStore = new DistributedDataStore(actorSystem, name, new ClusterWrapperImpl(actorSystem), diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java index 43a9faa3e4..fbb457178f 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java @@ -14,6 +14,7 @@ import akka.actor.Props; import akka.event.Logging; import akka.event.LoggingAdapter; import akka.japi.Creator; +import akka.persistence.RecoveryFailure; import akka.serialization.Serialization; import com.google.common.base.Optional; @@ -144,8 +145,19 @@ public class Shard extends RaftActor { return Props.create(new ShardCreator(name, peerAddresses, datastoreContext)); } + @Override public void onReceiveRecover(Object message) { + LOG.debug("onReceiveRecover: Received message {} from {}", message.getClass().toString(), + getSender()); + + if (message instanceof RecoveryFailure){ + LOG.error(((RecoveryFailure) message).cause(), "Recovery failed because of this cause"); + } else { + super.onReceiveRecover(message); + } + } + @Override public void onReceiveCommand(Object message) { - LOG.debug("Received message {} from {}", message.getClass().toString(), + LOG.debug("onReceiveCommand: Received message {} from {}", message.getClass().toString(), getSender()); if (message.getClass() @@ -228,7 +240,8 @@ public class Shard extends RaftActor { .tell(new CreateTransactionReply( Serialization.serializedActorPath(transactionActor), createTransaction.getTransactionId()).toSerializable(), - getSelf()); + getSelf() + ); } private void commit(final ActorRef sender, Object serialized) { @@ -266,9 +279,9 @@ public class Shard extends RaftActor { Futures.addCallback(future, new FutureCallback() { @Override public void onSuccess(Void v) { - sender.tell(new CommitTransactionReply().toSerializable(),self); - shardMBean.incrementCommittedTransactionCount(); - shardMBean.setLastCommittedTransactionTime(new Date()); + sender.tell(new CommitTransactionReply().toSerializable(), self); + shardMBean.incrementCommittedTransactionCount(); + shardMBean.setLastCommittedTransactionTime(new Date()); } @Override diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModule.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModule.java index c26be148ee..e2fbacb461 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModule.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModule.java @@ -2,9 +2,12 @@ package org.opendaylight.controller.config.yang.config.distributed_datastore_pro import org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory; import org.opendaylight.controller.cluster.datastore.DistributedDataStoreProperties; +import org.osgi.framework.BundleContext; public class DistributedConfigDataStoreProviderModule extends org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedConfigDataStoreProviderModule { + private BundleContext bundleContext; + public DistributedConfigDataStoreProviderModule( org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { @@ -38,6 +41,10 @@ public class DistributedConfigDataStoreProviderModule extends props.getMaxShardDataChangeExecutorQueueSize().getValue(), props.getMaxShardDataChangeListenerQueueSize().getValue(), props.getShardTransactionIdleTimeoutInMinutes().getValue(), - props.getOperationTimeoutInSeconds().getValue())); + props.getOperationTimeoutInSeconds().getValue()), bundleContext); + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModuleFactory.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModuleFactory.java index 67bf599454..0cdaca3a15 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModuleFactory.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModuleFactory.java @@ -8,6 +8,29 @@ * Do not modify this file unless it is present under src/main directory */ package org.opendaylight.controller.config.yang.config.distributed_datastore_provider; + +import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; +import org.opendaylight.controller.config.spi.Module; +import org.osgi.framework.BundleContext; + public class DistributedConfigDataStoreProviderModuleFactory extends org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedConfigDataStoreProviderModuleFactory { + @Override + public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) { + DistributedConfigDataStoreProviderModule module = (DistributedConfigDataStoreProviderModule)super.createModule(instanceName,dependencyResolver,bundleContext); + module.setBundleContext(bundleContext); + return module; + } + + @Override + public Module createModule(String instanceName, DependencyResolver dependencyResolver, + DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception { + DistributedConfigDataStoreProviderModule module = (DistributedConfigDataStoreProviderModule)super.createModule(instanceName, dependencyResolver, + old, bundleContext); + module.setBundleContext(bundleContext); + return module; + } + + } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModule.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModule.java index a88d09457a..c185e871ea 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModule.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModule.java @@ -2,9 +2,12 @@ package org.opendaylight.controller.config.yang.config.distributed_datastore_pro import org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory; import org.opendaylight.controller.cluster.datastore.DistributedDataStoreProperties; +import org.osgi.framework.BundleContext; public class DistributedOperationalDataStoreProviderModule extends org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedOperationalDataStoreProviderModule { + private BundleContext bundleContext; + public DistributedOperationalDataStoreProviderModule( org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { @@ -39,7 +42,11 @@ public class DistributedOperationalDataStoreProviderModule extends props.getMaxShardDataChangeExecutorQueueSize().getValue(), props.getMaxShardDataChangeListenerQueueSize().getValue(), props.getShardTransactionIdleTimeoutInMinutes().getValue(), - props.getOperationTimeoutInSeconds().getValue())); + props.getOperationTimeoutInSeconds().getValue()), bundleContext); + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModuleFactory.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModuleFactory.java index c9965fee09..364fe62923 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModuleFactory.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModuleFactory.java @@ -8,6 +8,27 @@ * Do not modify this file unless it is present under src/main directory */ package org.opendaylight.controller.config.yang.config.distributed_datastore_provider; + +import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; +import org.opendaylight.controller.config.spi.Module; +import org.osgi.framework.BundleContext; + public class DistributedOperationalDataStoreProviderModuleFactory extends org.opendaylight.controller.config.yang.config.distributed_datastore_provider.AbstractDistributedOperationalDataStoreProviderModuleFactory { + @Override + public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) { + DistributedOperationalDataStoreProviderModule module = (DistributedOperationalDataStoreProviderModule)super.createModule(instanceName,dependencyResolver,bundleContext); + module.setBundleContext(bundleContext); + return module; + } + + @Override + public Module createModule(String instanceName, DependencyResolver dependencyResolver, + DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception { + DistributedOperationalDataStoreProviderModule module = (DistributedOperationalDataStoreProviderModule)super.createModule(instanceName, dependencyResolver, + old, bundleContext); + module.setBundleContext(bundleContext); + return module; + } } diff --git a/opendaylight/md-sal/sal-remoterpc-connector/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/pom.xml index 41cdd59d6b..8d454c4bd6 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/pom.xml +++ b/opendaylight/md-sal/sal-remoterpc-connector/pom.xml @@ -189,6 +189,7 @@ !org.iq80.*;!*snappy;!org.jboss.*;!com.jcraft.*;!org.fusesource.*;!*jetty*;!sun.security.*;* + diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorSystemFactory.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorSystemFactory.java index f1ca3ccd50..6a442c57cc 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorSystemFactory.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorSystemFactory.java @@ -10,12 +10,16 @@ package org.opendaylight.controller.remote.rpc; import akka.actor.ActorSystem; import akka.osgi.BundleDelegatingClassLoader; -import com.typesafe.config.ConfigFactory; +import org.opendaylight.controller.remote.rpc.utils.AkkaConfigurationReader; import org.osgi.framework.BundleContext; public class ActorSystemFactory { - private static volatile ActorSystem actorSystem = null; + + public static final String ACTOR_SYSTEM_NAME = "opendaylight-cluster-rpc"; + public static final String CONFIGURATION_NAME = "odl-cluster-rpc"; + + private static volatile ActorSystem actorSystem = null; public static final ActorSystem getInstance(){ return actorSystem; @@ -26,7 +30,7 @@ public class ActorSystemFactory { * * @param bundleContext */ - public static final void createInstance(final BundleContext bundleContext) { + public static final void createInstance(final BundleContext bundleContext, AkkaConfigurationReader akkaConfigurationReader) { if(actorSystem == null) { // Create an OSGi bundle classloader for actor system BundleDelegatingClassLoader classLoader = new BundleDelegatingClassLoader(bundleContext.getBundle(), @@ -34,8 +38,8 @@ public class ActorSystemFactory { synchronized (ActorSystemFactory.class) { // Double check if (actorSystem == null) { - ActorSystem system = ActorSystem.create("opendaylight-cluster-rpc", - ConfigFactory.load().getConfig("odl-cluster-rpc"), classLoader); + ActorSystem system = ActorSystem.create(ACTOR_SYSTEM_NAME, + akkaConfigurationReader.read().getConfig(CONFIGURATION_NAME), classLoader); actorSystem = system; } } @@ -43,4 +47,5 @@ public class ActorSystemFactory { throw new IllegalStateException("Actor system should be created only once. Use getInstance method to access existing actor system"); } } + } diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java index fc75f7747a..0e6b795c05 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.remote.rpc; +import org.opendaylight.controller.remote.rpc.utils.DefaultAkkaConfigurationReader; import org.opendaylight.controller.sal.core.api.Broker; import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry; import org.osgi.framework.BundleContext; @@ -16,7 +17,7 @@ import org.osgi.framework.BundleContext; public class RemoteRpcProviderFactory { public static RemoteRpcProvider createInstance(final Broker broker, final BundleContext bundleContext){ - ActorSystemFactory.createInstance(bundleContext); + ActorSystemFactory.createInstance(bundleContext, new DefaultAkkaConfigurationReader()); RemoteRpcProvider rpcProvider = new RemoteRpcProvider(ActorSystemFactory.getInstance(), (RpcProvisionRegistry) broker); broker.registerProvider(rpcProvider); diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/AkkaConfigurationReader.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/AkkaConfigurationReader.java new file mode 100644 index 0000000000..035ce9a203 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/AkkaConfigurationReader.java @@ -0,0 +1,15 @@ +/* + * 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.remote.rpc.utils; + +import com.typesafe.config.Config; + +public interface AkkaConfigurationReader { + Config read(); +} diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/DefaultAkkaConfigurationReader.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/DefaultAkkaConfigurationReader.java new file mode 100644 index 0000000000..a44d20ca39 --- /dev/null +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/DefaultAkkaConfigurationReader.java @@ -0,0 +1,26 @@ +/* + * 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.remote.rpc.utils; + +import com.google.common.base.Preconditions; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; + +import java.io.File; + +public class DefaultAkkaConfigurationReader implements AkkaConfigurationReader { + public static final String AKKA_CONF_PATH = "./configuration/initial/akka.conf"; + + @Override public Config read() { + File defaultConfigFile = new File(AKKA_CONF_PATH); + Preconditions.checkState(defaultConfigFile.exists(), "akka.conf is missing"); + return ConfigFactory.parseFile(defaultConfigFile); + + } +} diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/ActorSystemFactoryTest.java b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/ActorSystemFactoryTest.java index ed5fa6d16e..cd1cd91869 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/ActorSystemFactoryTest.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/test/java/org/opendaylight/controller/remote/rpc/ActorSystemFactoryTest.java @@ -10,9 +10,11 @@ package org.opendaylight.controller.remote.rpc; import akka.actor.ActorSystem; +import com.typesafe.config.ConfigFactory; import junit.framework.Assert; import org.junit.After; import org.junit.Test; +import org.opendaylight.controller.remote.rpc.utils.AkkaConfigurationReader; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; @@ -27,13 +29,17 @@ public class ActorSystemFactoryTest { public void testActorSystemCreation(){ BundleContext context = mock(BundleContext.class); when(context.getBundle()).thenReturn(mock(Bundle.class)); - ActorSystemFactory.createInstance(context); + + AkkaConfigurationReader reader = mock(AkkaConfigurationReader.class); + when(reader.read()).thenReturn(ConfigFactory.load()); + + ActorSystemFactory.createInstance(context, reader); system = ActorSystemFactory.getInstance(); Assert.assertNotNull(system); // Check illegal state exception try { - ActorSystemFactory.createInstance(context); + ActorSystemFactory.createInstance(context, reader); fail("Illegal State exception should be thrown, while creating actor system second time"); } catch (IllegalStateException e) { } @@ -45,5 +51,4 @@ public class ActorSystemFactoryTest { system.shutdown(); } } - } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java index 821290eca2..fe20e3a441 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java @@ -5,6 +5,8 @@ import org.opendaylight.controller.sal.restconf.impl.RestconfProviderImpl; public class RestConnectorModule extends org.opendaylight.controller.config.yang.md.sal.rest.connector.AbstractRestConnectorModule { + private static RestConnectorRuntimeRegistration runtimeRegistration; + public RestConnectorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); } @@ -27,8 +29,12 @@ public class RestConnectorModule extends org.opendaylight.controller.config.yang // Register it with the Broker getDomBrokerDependency().registerProvider(instance); + if(runtimeRegistration != null){ + runtimeRegistration.close(); + } - getRootRuntimeBeanRegistratorWrapper().register(instance); + runtimeRegistration = + getRootRuntimeBeanRegistratorWrapper().register(instance); return instance; } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfProviderImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfProviderImpl.java index c7c9cc0dc5..abadbf6cb8 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfProviderImpl.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfProviderImpl.java @@ -7,9 +7,6 @@ */ package org.opendaylight.controller.sal.restconf.impl; -import java.math.BigInteger; -import java.util.Collection; -import java.util.Collections; import org.opendaylight.controller.config.yang.md.sal.rest.connector.Config; import org.opendaylight.controller.config.yang.md.sal.rest.connector.Get; import org.opendaylight.controller.config.yang.md.sal.rest.connector.Operational; @@ -28,19 +25,21 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types. import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; -public class RestconfProviderImpl implements Provider, AutoCloseable, RestConnector, RestConnectorRuntimeMXBean { +import java.math.BigInteger; +import java.util.Collection; +import java.util.Collections; - public final static String NOT_INITALIZED_MSG = "Restconf is not initialized yet. Please try again later"; +public class RestconfProviderImpl implements Provider, AutoCloseable, RestConnector, RestConnectorRuntimeMXBean { private final StatisticsRestconfServiceWrapper stats = StatisticsRestconfServiceWrapper.getInstance(); private ListenerRegistration listenerRegistration; private PortNumber port; + private Thread webSocketServerThread; + public void setWebsocketPort(PortNumber port) { this.port = port; } - private Thread webSocketServerThread; - @Override public void onSessionInitiated(ProviderSession session) { final DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class); @@ -65,9 +64,12 @@ public class RestconfProviderImpl implements Provider, AutoCloseable, RestConnec @Override public void close() { + if (listenerRegistration != null) { listenerRegistration.close(); } + + WebSocketServer.destroyInstance(); webSocketServerThread.interrupt(); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServer.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServer.java index 67ed44f84e..0a5f5f0ff0 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServer.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServer.java @@ -16,11 +16,10 @@ import org.slf4j.LoggerFactory; public class WebSocketServer implements Runnable { private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class); - public static final String WEBSOCKET_SERVER_CONFIG_PROPERTY = "restconf.websocket.port"; public static final int DEFAULT_PORT = 8181; private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; - private static WebSocketServer singleton = null; + private static WebSocketServer instance = null; private int port = DEFAULT_PORT; private WebSocketServer(int port) { @@ -35,14 +34,11 @@ public class WebSocketServer implements Runnable { * @return instance of {@link WebSocketServer} */ public static WebSocketServer createInstance(int port) { - if (singleton != null) { - throw new IllegalStateException("createInstance() has already been called"); - } - if (port < 1024) { - throw new IllegalArgumentException("Privileged port (below 1024) is not allowed"); - } - singleton = new WebSocketServer(port); - return singleton; + Preconditions.checkState(instance == null, "createInstance() has already been called"); + Preconditions.checkArgument(port > 1024, "Privileged port (below 1024) is not allowed"); + + instance = new WebSocketServer(port); + return instance; } /** @@ -58,18 +54,18 @@ public class WebSocketServer implements Runnable { * @return instance of {@link WebSocketServer} */ public static WebSocketServer getInstance() { - Preconditions.checkNotNull(singleton, "createInstance() must be called prior to getInstance()"); - return singleton; + Preconditions.checkNotNull(instance, "createInstance() must be called prior to getInstance()"); + return instance; } /** * Destroy this already created instance */ public static void destroyInstance() { - if (singleton == null) { - throw new IllegalStateException("createInstance() must be called prior to destroyInstance()"); - } - getInstance().stop(); + Preconditions.checkState(instance != null, "createInstance() must be called prior to destroyInstance()"); + + instance.stop(); + instance = null; } @Override @@ -99,9 +95,11 @@ public class WebSocketServer implements Runnable { Notificator.removeAllListeners(); if (bossGroup != null) { bossGroup.shutdownGracefully(); + bossGroup = null; } if (workerGroup != null) { workerGroup.shutdownGracefully(); + workerGroup = null; } }