Search in sources :

Example 1 with ChangeShardMembersVotingStatus

use of org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus in project controller by opendaylight.

the class ShardManager method changeShardMembersVotingStatus.

private void changeShardMembersVotingStatus(final ChangeServersVotingStatus changeServersVotingStatus, final String shardName, final ActorRef shardActorRef, final ActorRef sender) {
    if (isShardReplicaOperationInProgress(shardName, sender)) {
        return;
    }
    shardReplicaOperationsInProgress.add(shardName);
    DatastoreContext datastoreContext = newShardDatastoreContextBuilder(shardName).build();
    final ShardIdentifier shardId = getShardIdentifier(cluster.getCurrentMemberName(), shardName);
    LOG.debug("{}: Sending ChangeServersVotingStatus message {} to local shard {}", persistenceId(), changeServersVotingStatus, shardActorRef.path());
    Timeout timeout = new Timeout(datastoreContext.getShardLeaderElectionTimeout().duration().$times(2));
    Future<Object> futureObj = ask(shardActorRef, changeServersVotingStatus, timeout);
    futureObj.onComplete(new OnComplete<Object>() {

        @Override
        public void onComplete(final Throwable failure, final Object response) {
            shardReplicaOperationsInProgress.remove(shardName);
            if (failure != null) {
                String msg = String.format("ChangeServersVotingStatus request to local shard %s failed", shardActorRef.path());
                LOG.debug("{}: {}", persistenceId(), msg, failure);
                sender.tell(new Status.Failure(new RuntimeException(msg, failure)), self());
            } else {
                LOG.debug("{}: Received {} from local shard {}", persistenceId(), response, shardActorRef.path());
                ServerChangeReply replyMsg = (ServerChangeReply) response;
                if (replyMsg.getStatus() == ServerChangeStatus.OK) {
                    LOG.debug("{}: ChangeServersVotingStatus succeeded for shard {}", persistenceId(), shardName);
                    sender.tell(new Status.Success(null), getSelf());
                } else if (replyMsg.getStatus() == ServerChangeStatus.INVALID_REQUEST) {
                    sender.tell(new Status.Failure(new IllegalArgumentException(String.format("The requested voting state change for shard %s is invalid. At least one member " + "must be voting", shardId.getShardName()))), getSelf());
                } else {
                    LOG.warn("{}: ChangeServersVotingStatus failed for shard {} with status {}", persistenceId(), shardName, replyMsg.getStatus());
                    Exception error = getServerChangeException(ChangeServersVotingStatus.class, replyMsg.getStatus(), shardActorRef.path().toString(), shardId);
                    sender.tell(new Status.Failure(error), getSelf());
                }
            }
        }
    }, new Dispatchers(context().system().dispatchers()).getDispatcher(Dispatchers.DispatcherType.Client));
}
Also used : FollowerInitialSyncUpStatus(org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus) ChangeShardMembersVotingStatus(org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus) FlipShardMembersVotingStatus(org.opendaylight.controller.cluster.datastore.messages.FlipShardMembersVotingStatus) Status(akka.actor.Status) ServerChangeStatus(org.opendaylight.controller.cluster.raft.messages.ServerChangeStatus) ChangeServersVotingStatus(org.opendaylight.controller.cluster.raft.messages.ChangeServersVotingStatus) Timeout(akka.util.Timeout) ShardIdentifier(org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier) SaveSnapshotSuccess(akka.persistence.SaveSnapshotSuccess) DeleteSnapshotsSuccess(akka.persistence.DeleteSnapshotsSuccess) AlreadyExistsException(org.opendaylight.controller.cluster.datastore.exceptions.AlreadyExistsException) PrimaryNotFoundException(org.opendaylight.controller.cluster.datastore.exceptions.PrimaryNotFoundException) NotInitializedException(org.opendaylight.controller.cluster.datastore.exceptions.NotInitializedException) TimeoutException(java.util.concurrent.TimeoutException) NoShardLeaderException(org.opendaylight.controller.cluster.datastore.exceptions.NoShardLeaderException) DatastoreContext(org.opendaylight.controller.cluster.datastore.DatastoreContext) ServerChangeReply(org.opendaylight.controller.cluster.raft.messages.ServerChangeReply) SaveSnapshotFailure(akka.persistence.SaveSnapshotFailure) DeleteSnapshotsFailure(akka.persistence.DeleteSnapshotsFailure) Dispatchers(org.opendaylight.controller.cluster.common.actor.Dispatchers)

Example 2 with ChangeShardMembersVotingStatus

use of org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus in project controller by opendaylight.

the class DistributedEntityOwnershipIntegrationTest method testEntityOwnershipWithNonVotingMembers.

@Test
public void testEntityOwnershipWithNonVotingMembers() throws Exception {
    followerDatastoreContextBuilder.shardElectionTimeoutFactor(5).customRaftPolicyImplementation(DisableElectionsRaftPolicy.class.getName());
    String name = "testEntityOwnershipWithNonVotingMembers";
    final MemberNode member1LeaderNode = MemberNode.builder(memberNodes).akkaConfig("Member1").useAkkaArtery(false).testName(name).moduleShardsConfig(MODULE_SHARDS_5_NODE_CONFIG).schemaContext(SCHEMA_CONTEXT).createOperDatastore(false).datastoreContextBuilder(leaderDatastoreContextBuilder).build();
    final MemberNode member2FollowerNode = MemberNode.builder(memberNodes).akkaConfig("Member2").useAkkaArtery(false).testName(name).moduleShardsConfig(MODULE_SHARDS_5_NODE_CONFIG).schemaContext(SCHEMA_CONTEXT).createOperDatastore(false).datastoreContextBuilder(followerDatastoreContextBuilder).build();
    final MemberNode member3FollowerNode = MemberNode.builder(memberNodes).akkaConfig("Member3").useAkkaArtery(false).testName(name).moduleShardsConfig(MODULE_SHARDS_5_NODE_CONFIG).schemaContext(SCHEMA_CONTEXT).createOperDatastore(false).datastoreContextBuilder(followerDatastoreContextBuilder).build();
    final MemberNode member4FollowerNode = MemberNode.builder(memberNodes).akkaConfig("Member4").useAkkaArtery(false).testName(name).moduleShardsConfig(MODULE_SHARDS_5_NODE_CONFIG).schemaContext(SCHEMA_CONTEXT).createOperDatastore(false).datastoreContextBuilder(followerDatastoreContextBuilder).build();
    final MemberNode member5FollowerNode = MemberNode.builder(memberNodes).akkaConfig("Member5").useAkkaArtery(false).testName(name).moduleShardsConfig(MODULE_SHARDS_5_NODE_CONFIG).schemaContext(SCHEMA_CONTEXT).createOperDatastore(false).datastoreContextBuilder(followerDatastoreContextBuilder).build();
    AbstractDataStore leaderDistributedDataStore = member1LeaderNode.configDataStore();
    leaderDistributedDataStore.waitTillReady();
    member2FollowerNode.configDataStore().waitTillReady();
    member3FollowerNode.configDataStore().waitTillReady();
    member4FollowerNode.configDataStore().waitTillReady();
    member5FollowerNode.configDataStore().waitTillReady();
    member1LeaderNode.waitForMembersUp("member-2", "member-3", "member-4", "member-5");
    final DOMEntityOwnershipService member3EntityOwnershipService = newOwnershipService(member3FollowerNode.configDataStore());
    final DOMEntityOwnershipService member4EntityOwnershipService = newOwnershipService(member4FollowerNode.configDataStore());
    final DOMEntityOwnershipService member5EntityOwnershipService = newOwnershipService(member5FollowerNode.configDataStore());
    newOwnershipService(member1LeaderNode.configDataStore());
    member1LeaderNode.kit().waitUntilLeader(member1LeaderNode.configDataStore().getActorContext(), ENTITY_OWNERSHIP_SHARD_NAME);
    // Make member4 and member5 non-voting
    Future<Object> future = Patterns.ask(leaderDistributedDataStore.getActorContext().getShardManager(), new ChangeShardMembersVotingStatus(ENTITY_OWNERSHIP_SHARD_NAME, ImmutableMap.of("member-4", false, "member-5", false)), new Timeout(10, TimeUnit.SECONDS));
    Object response = Await.result(future, FiniteDuration.apply(10, TimeUnit.SECONDS));
    if (response instanceof Throwable) {
        throw new AssertionError("ChangeShardMembersVotingStatus failed", (Throwable) response);
    }
    assertNull("Expected null Success response. Actual " + response, response);
    // Register member4 candidate for entity1 - it should not become owner since it's non-voting
    member4EntityOwnershipService.registerCandidate(ENTITY1);
    verifyCandidates(leaderDistributedDataStore, ENTITY1, "member-4");
    // Register member5 candidate for entity2 - it should not become owner since it's non-voting
    member5EntityOwnershipService.registerCandidate(ENTITY2);
    verifyCandidates(leaderDistributedDataStore, ENTITY2, "member-5");
    Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
    verifyOwner(leaderDistributedDataStore, ENTITY1, "");
    verifyOwner(leaderDistributedDataStore, ENTITY2, "");
    // Register member3 candidate for entity1 - it should become owner since it's voting
    member3EntityOwnershipService.registerCandidate(ENTITY1);
    verifyCandidates(leaderDistributedDataStore, ENTITY1, "member-4", "member-3");
    verifyOwner(leaderDistributedDataStore, ENTITY1, "member-3");
    // Switch member4 and member5 back to voting and member3 non-voting. This should result in member4 and member5
    // to become entity owners.
    future = Patterns.ask(leaderDistributedDataStore.getActorContext().getShardManager(), new ChangeShardMembersVotingStatus(ENTITY_OWNERSHIP_SHARD_NAME, ImmutableMap.of("member-3", false, "member-4", true, "member-5", true)), new Timeout(10, TimeUnit.SECONDS));
    response = Await.result(future, FiniteDuration.apply(10, TimeUnit.SECONDS));
    if (response instanceof Throwable) {
        throw new AssertionError("ChangeShardMembersVotingStatus failed", (Throwable) response);
    }
    assertNull("Expected null Success response. Actual " + response, response);
    verifyOwner(leaderDistributedDataStore, ENTITY1, "member-4");
    verifyOwner(leaderDistributedDataStore, ENTITY2, "member-5");
}
Also used : ChangeShardMembersVotingStatus(org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus) DOMEntityOwnershipService(org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipService) MemberNode(org.opendaylight.controller.cluster.datastore.MemberNode) Timeout(akka.util.Timeout) DisableElectionsRaftPolicy(org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy) AbstractDataStore(org.opendaylight.controller.cluster.datastore.AbstractDataStore) Test(org.junit.Test)

Example 3 with ChangeShardMembersVotingStatus

use of org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus in project controller by opendaylight.

the class ClusterAdminRpcService method changeMemberVotingStatesForShard.

@Override
public Future<RpcResult<Void>> changeMemberVotingStatesForShard(ChangeMemberVotingStatesForShardInput input) {
    final String shardName = input.getShardName();
    if (Strings.isNullOrEmpty(shardName)) {
        return newFailedRpcResultFuture("A valid shard name must be specified");
    }
    DataStoreType dataStoreType = input.getDataStoreType();
    if (dataStoreType == null) {
        return newFailedRpcResultFuture("A valid DataStoreType must be specified");
    }
    List<MemberVotingState> memberVotingStates = input.getMemberVotingState();
    if (memberVotingStates == null || memberVotingStates.isEmpty()) {
        return newFailedRpcResultFuture("No member voting state input was specified");
    }
    ChangeShardMembersVotingStatus changeVotingStatus = toChangeShardMembersVotingStatus(shardName, memberVotingStates);
    LOG.info("Change member voting states for shard {}: {}", shardName, changeVotingStatus.getMeberVotingStatusMap());
    final SettableFuture<RpcResult<Void>> returnFuture = SettableFuture.create();
    ListenableFuture<Success> future = sendMessageToShardManager(dataStoreType, changeVotingStatus);
    Futures.addCallback(future, new FutureCallback<Success>() {

        @Override
        public void onSuccess(Success success) {
            LOG.info("Successfully changed member voting states for shard {}", shardName);
            returnFuture.set(newSuccessfulResult());
        }

        @Override
        public void onFailure(Throwable failure) {
            onMessageFailure(String.format("Failed to change member voting states for shard %s", shardName), returnFuture, failure);
        }
    }, MoreExecutors.directExecutor());
    return returnFuture;
}
Also used : ChangeShardMembersVotingStatus(org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus) MemberVotingState(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.cluster.admin.rev151013.member.voting.states.input.MemberVotingState) RpcResult(org.opendaylight.yangtools.yang.common.RpcResult) Success(akka.actor.Status.Success) DataStoreType(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.cluster.admin.rev151013.DataStoreType)

Example 4 with ChangeShardMembersVotingStatus

use of org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus in project controller by opendaylight.

the class ShardManagerTest method testChangeServersVotingStatus.

@Test
public void testChangeServersVotingStatus() throws Exception {
    new TestKit(getSystem()) {

        {
            String memberId = "member-1-shard-default-" + shardMrgIDSuffix;
            ActorRef respondActor = actorFactory.createActor(Props.create(MockRespondActor.class, ChangeServersVotingStatus.class, new ServerChangeReply(ServerChangeStatus.OK, null)), memberId);
            ActorRef shardManager = getSystem().actorOf(newPropsShardMgrWithMockShardActor(respondActor));
            shardManager.tell(new UpdateSchemaContext(TestModel.createTestContext()), getRef());
            shardManager.tell(new ActorInitialized(), respondActor);
            shardManager.tell(new ShardLeaderStateChanged(memberId, memberId, mock(DataTree.class), DataStoreVersions.CURRENT_VERSION), getRef());
            shardManager.tell(new RoleChangeNotification(memberId, RaftState.Candidate.name(), RaftState.Leader.name()), respondActor);
            shardManager.tell(new ChangeShardMembersVotingStatus("default", ImmutableMap.of("member-2", Boolean.TRUE)), getRef());
            ChangeServersVotingStatus actualChangeStatusMsg = MessageCollectorActor.expectFirstMatching(respondActor, ChangeServersVotingStatus.class);
            assertEquals("ChangeServersVotingStatus map", actualChangeStatusMsg.getServerVotingStatusMap(), ImmutableMap.of(ShardIdentifier.create("default", MemberName.forName("member-2"), shardMrgIDSuffix).toString(), Boolean.TRUE));
            expectMsgClass(duration("5 seconds"), Success.class);
        }
    };
}
Also used : ChangeShardMembersVotingStatus(org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus) UpdateSchemaContext(org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext) ShardLeaderStateChanged(org.opendaylight.controller.cluster.datastore.messages.ShardLeaderStateChanged) ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) ChangeServersVotingStatus(org.opendaylight.controller.cluster.raft.messages.ChangeServersVotingStatus) RoleChangeNotification(org.opendaylight.controller.cluster.notifications.RoleChangeNotification) ActorInitialized(org.opendaylight.controller.cluster.datastore.messages.ActorInitialized) TestKit(akka.testkit.javadsl.TestKit) AddressFromURIString(akka.actor.AddressFromURIString) ServerChangeReply(org.opendaylight.controller.cluster.raft.messages.ServerChangeReply) Test(org.junit.Test) AbstractShardManagerTest(org.opendaylight.controller.cluster.datastore.AbstractShardManagerTest)

Example 5 with ChangeShardMembersVotingStatus

use of org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus in project controller by opendaylight.

the class ShardManagerTest method testChangeServersVotingStatusWithNoLeader.

@Test
public void testChangeServersVotingStatusWithNoLeader() throws Exception {
    new TestKit(getSystem()) {

        {
            String memberId = "member-1-shard-default-" + shardMrgIDSuffix;
            ActorRef respondActor = actorFactory.createActor(Props.create(MockRespondActor.class, ChangeServersVotingStatus.class, new ServerChangeReply(ServerChangeStatus.NO_LEADER, null)), memberId);
            ActorRef shardManager = getSystem().actorOf(newPropsShardMgrWithMockShardActor(respondActor));
            shardManager.tell(new UpdateSchemaContext(TestModel.createTestContext()), getRef());
            shardManager.tell(new ActorInitialized(), respondActor);
            shardManager.tell(new RoleChangeNotification(memberId, null, RaftState.Follower.name()), respondActor);
            shardManager.tell(new ChangeShardMembersVotingStatus("default", ImmutableMap.of("member-2", Boolean.TRUE)), getRef());
            MessageCollectorActor.expectFirstMatching(respondActor, ChangeServersVotingStatus.class);
            Status.Failure resp = expectMsgClass(duration("5 seconds"), Status.Failure.class);
            assertEquals("Failure resposnse", true, resp.cause() instanceof NoShardLeaderException);
        }
    };
}
Also used : ChangeShardMembersVotingStatus(org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus) FollowerInitialSyncUpStatus(org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus) ChangeShardMembersVotingStatus(org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus) Status(akka.actor.Status) ServerChangeStatus(org.opendaylight.controller.cluster.raft.messages.ServerChangeStatus) ChangeServersVotingStatus(org.opendaylight.controller.cluster.raft.messages.ChangeServersVotingStatus) UpdateSchemaContext(org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext) ActorRef(akka.actor.ActorRef) TestActorRef(akka.testkit.TestActorRef) RoleChangeNotification(org.opendaylight.controller.cluster.notifications.RoleChangeNotification) TestKit(akka.testkit.javadsl.TestKit) AddressFromURIString(akka.actor.AddressFromURIString) NoShardLeaderException(org.opendaylight.controller.cluster.datastore.exceptions.NoShardLeaderException) ChangeServersVotingStatus(org.opendaylight.controller.cluster.raft.messages.ChangeServersVotingStatus) ActorInitialized(org.opendaylight.controller.cluster.datastore.messages.ActorInitialized) ServerChangeReply(org.opendaylight.controller.cluster.raft.messages.ServerChangeReply) Failure(akka.actor.Status.Failure) Test(org.junit.Test) AbstractShardManagerTest(org.opendaylight.controller.cluster.datastore.AbstractShardManagerTest)

Aggregations

ChangeShardMembersVotingStatus (org.opendaylight.controller.cluster.datastore.messages.ChangeShardMembersVotingStatus)5 Test (org.junit.Test)3 ChangeServersVotingStatus (org.opendaylight.controller.cluster.raft.messages.ChangeServersVotingStatus)3 ServerChangeReply (org.opendaylight.controller.cluster.raft.messages.ServerChangeReply)3 ActorRef (akka.actor.ActorRef)2 AddressFromURIString (akka.actor.AddressFromURIString)2 Status (akka.actor.Status)2 TestActorRef (akka.testkit.TestActorRef)2 TestKit (akka.testkit.javadsl.TestKit)2 Timeout (akka.util.Timeout)2 AbstractShardManagerTest (org.opendaylight.controller.cluster.datastore.AbstractShardManagerTest)2 NoShardLeaderException (org.opendaylight.controller.cluster.datastore.exceptions.NoShardLeaderException)2 ActorInitialized (org.opendaylight.controller.cluster.datastore.messages.ActorInitialized)2 UpdateSchemaContext (org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext)2 RoleChangeNotification (org.opendaylight.controller.cluster.notifications.RoleChangeNotification)2 FollowerInitialSyncUpStatus (org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus)2 ServerChangeStatus (org.opendaylight.controller.cluster.raft.messages.ServerChangeStatus)2 Failure (akka.actor.Status.Failure)1 Success (akka.actor.Status.Success)1 DeleteSnapshotsFailure (akka.persistence.DeleteSnapshotsFailure)1