From d5fcf5d66568519595b533cc20651634d66d34fb Mon Sep 17 00:00:00 2001 From: Jakub Morvay Date: Fri, 9 Jun 2017 09:12:20 +0200 Subject: [PATCH] Bug 8621 - Add shutdown-shard-replica rpc to MdsalLowLevelTestProvider csit testing scenarios require clean shutdown of shard's local replica funcionality. This introduces shutdown-shard-replica rpc to MdsalLowLevelTestProvider. Upon invoking this rpc, local replica of specified module-based shard is gracefully stopped. Change-Id: Ia8e0be65ecc99f9e208ff4ffd737b210437a9f51 Signed-off-by: Jakub Morvay --- .../main/yang/odl-mdsal-lowlevel-control.yang | 11 ++++ .../provider/MdsalLowLevelTestProvider.java | 54 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/opendaylight/md-sal/samples/clustering-test-app/model/src/main/yang/odl-mdsal-lowlevel-control.yang b/opendaylight/md-sal/samples/clustering-test-app/model/src/main/yang/odl-mdsal-lowlevel-control.yang index de8df737b8..bc3e03998c 100644 --- a/opendaylight/md-sal/samples/clustering-test-app/model/src/main/yang/odl-mdsal-lowlevel-control.yang +++ b/opendaylight/md-sal/samples/clustering-test-app/model/src/main/yang/odl-mdsal-lowlevel-control.yang @@ -513,4 +513,15 @@ module odl-mdsal-lowlevel-control { // No output. } + rpc shutdown-shard-replica { + description "Upon receiving this, the member will try to gracefully shutdown local configuration + data store module-based shard replica."; + input { + leaf shard-name { + type string; + description "The name of the configuration data store module-based shard to be shutdown + gracefully."; + } + } + } } diff --git a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/MdsalLowLevelTestProvider.java b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/MdsalLowLevelTestProvider.java index 240741cf20..f0569fa07d 100644 --- a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/MdsalLowLevelTestProvider.java +++ b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/MdsalLowLevelTestProvider.java @@ -14,7 +14,10 @@ import akka.actor.ActorRef; import akka.actor.ActorSystem; import akka.actor.PoisonPill; import akka.actor.Props; +import akka.dispatch.OnComplete; +import akka.pattern.Patterns; import com.google.common.base.Optional; +import com.google.common.base.Strings; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.SettableFuture; @@ -33,6 +36,7 @@ import org.opendaylight.controller.cluster.databroker.actors.dds.SimpleDataStore import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface; import org.opendaylight.controller.cluster.datastore.utils.ActorContext; import org.opendaylight.controller.cluster.datastore.utils.ClusterUtils; +import org.opendaylight.controller.cluster.raft.client.messages.Shutdown; import org.opendaylight.controller.cluster.sharding.DistributedShardFactory; import org.opendaylight.controller.clustering.it.provider.impl.FlappingSingletonService; import org.opendaylight.controller.clustering.it.provider.impl.GetConstantService; @@ -81,6 +85,7 @@ import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.l import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterSingletonConstantInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RemovePrefixShardInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RemoveShardReplicaInput; +import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.ShutdownShardReplicaInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.StartPublishNotificationsInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.SubscribeYnlInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterBoundConstantInput; @@ -104,6 +109,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import scala.concurrent.duration.FiniteDuration; public class MdsalLowLevelTestProvider implements OdlMdsalLowlevelControlService { @@ -564,6 +570,54 @@ public class MdsalLowLevelTestProvider implements OdlMdsalLowlevelControlService return settableFuture; } + @Override + public Future> shutdownShardReplica(final ShutdownShardReplicaInput input) { + LOG.debug("Received shutdown-shard-replica rpc, input: {}", input); + + final String shardName = input.getShardName(); + if (Strings.isNullOrEmpty(shardName)) { + final RpcError rpcError = RpcResultBuilder.newError(ErrorType.APPLICATION, "bad-element", + "A valid shard name must be specified"); + return Futures.immediateFuture(RpcResultBuilder.failed().withRpcError(rpcError).build()); + } + + final SettableFuture> rpcResult = SettableFuture.create(); + final ActorContext context = configDataStore.getActorContext(); + + long timeoutInMS = Math.max(context.getDatastoreContext().getShardRaftConfig() + .getElectionTimeOutInterval().$times(3).toMillis(), 10000); + final FiniteDuration duration = FiniteDuration.apply(timeoutInMS, TimeUnit.MILLISECONDS); + final scala.concurrent.Promise shutdownShardAsk = akka.dispatch.Futures.promise(); + + context.findLocalShardAsync(shardName).onComplete(new OnComplete() { + @Override + public void onComplete(final Throwable throwable, final ActorRef actorRef) throws Throwable { + if (throwable != null) { + shutdownShardAsk.failure(throwable); + } else { + shutdownShardAsk.completeWith(Patterns.gracefulStop(actorRef, duration, Shutdown.INSTANCE)); + } + } + }, context.getClientDispatcher()); + + shutdownShardAsk.future().onComplete(new OnComplete() { + @Override + public void onComplete(final Throwable throwable, final Boolean gracefulStopResult) throws Throwable { + if (throwable != null) { + final RpcResult failedResult = RpcResultBuilder.failed() + .withError(ErrorType.APPLICATION, "Failed to gracefully shutdown shard", throwable).build(); + rpcResult.set(failedResult); + } else { + // according to Patterns.gracefulStop API, we don't have to + // check value of gracefulStopResult + rpcResult.set(RpcResultBuilder.success().build()); + } + } + }, context.getClientDispatcher()); + + return rpcResult; + } + @Override public Future> registerConstant(final RegisterConstantInput input) { -- 2.36.6