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));
}
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");
}
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;
}
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);
}
};
}
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);
}
};
}
Aggregations