use of org.opendaylight.controller.cluster.raft.messages.AddServer in project controller by opendaylight.
the class ShardManager method execAddShard.
private void execAddShard(final String shardName, final ShardInformation shardInfo, final RemotePrimaryShardFound response, final boolean removeShardOnFailure, final ActorRef sender) {
final String localShardAddress = peerAddressResolver.getShardActorAddress(shardName, cluster.getCurrentMemberName());
// inform ShardLeader to add this shard as a replica by sending an AddServer message
LOG.debug("{}: Sending AddServer message to peer {} for shard {}", persistenceId(), response.getPrimaryPath(), shardInfo.getShardId());
final Timeout addServerTimeout = new Timeout(shardInfo.getDatastoreContext().getShardLeaderElectionTimeout().duration());
final Future<Object> futureObj = ask(getContext().actorSelection(response.getPrimaryPath()), new AddServer(shardInfo.getShardId().toString(), localShardAddress, true), addServerTimeout);
futureObj.onComplete(new OnComplete<Object>() {
@Override
public void onComplete(final Throwable failure, final Object addServerResponse) {
if (failure != null) {
LOG.debug("{}: AddServer request to {} for {} failed", persistenceId(), response.getPrimaryPath(), shardName, failure);
final String msg = String.format("AddServer request to leader %s for shard %s failed", response.getPrimaryPath(), shardName);
self().tell(new ForwardedAddServerFailure(shardName, msg, failure, removeShardOnFailure), sender);
} else {
self().tell(new ForwardedAddServerReply(shardInfo, (AddServerReply) addServerResponse, response.getPrimaryPath(), removeShardOnFailure), sender);
}
}
}, new Dispatchers(context().system().dispatchers()).getDispatcher(Dispatchers.DispatcherType.Client));
}
use of org.opendaylight.controller.cluster.raft.messages.AddServer in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testAddServersAsNonVoting.
@Test
public void testAddServersAsNonVoting() throws Exception {
LOG.info("testAddServersAsNonVoting starting");
setupNewFollower();
RaftActorContext initialActorContext = new MockRaftActorContext();
TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
final RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
final ActorRef leaderCollectorActor = newLeaderCollectorActor(leaderRaftActor);
leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), false), testKit.getRef());
AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, addServerReply.getStatus());
assertEquals("getLeaderHint", LEADER_ID, addServerReply.getLeaderHint().get());
// Verify ServerConfigurationPayload entry in leader's log
expectFirstMatching(leaderCollectorActor, ApplyState.class);
assertEquals("Leader journal last index", 0, leaderActorContext.getReplicatedLog().lastIndex());
assertEquals("Leader commit index", 0, leaderActorContext.getCommitIndex());
assertEquals("Leader last applied index", 0, leaderActorContext.getLastApplied());
verifyServerConfigurationPayloadEntry(leaderActorContext.getReplicatedLog(), votingServer(LEADER_ID), nonVotingServer(NEW_SERVER_ID));
// Verify ServerConfigurationPayload entry in the new follower
expectFirstMatching(newFollowerCollectorActor, ApplyState.class);
assertEquals("New follower journal last index", 0, newFollowerActorContext.getReplicatedLog().lastIndex());
verifyServerConfigurationPayloadEntry(newFollowerActorContext.getReplicatedLog(), votingServer(LEADER_ID), nonVotingServer(NEW_SERVER_ID));
// Verify new server config was applied in the new follower
assertEquals("New follower peers", Sets.newHashSet(LEADER_ID), newFollowerActorContext.getPeerIds());
assertNoneMatching(newFollowerCollectorActor, InstallSnapshot.class, 500);
// Add another non-voting server.
clearMessages(leaderCollectorActor);
RaftActorContext follower2ActorContext = newFollowerContext(NEW_SERVER_ID2, followerActor);
Follower newFollower2 = new Follower(follower2ActorContext);
followerActor.underlyingActor().setBehavior(newFollower2);
leaderActor.tell(new AddServer(NEW_SERVER_ID2, followerActor.path().toString(), false), testKit.getRef());
addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, addServerReply.getStatus());
assertEquals("getLeaderHint", java.util.Optional.of(LEADER_ID), addServerReply.getLeaderHint());
expectFirstMatching(leaderCollectorActor, ApplyState.class);
assertEquals("Leader journal last index", 1, leaderActorContext.getReplicatedLog().lastIndex());
assertEquals("Leader commit index", 1, leaderActorContext.getCommitIndex());
assertEquals("Leader last applied index", 1, leaderActorContext.getLastApplied());
verifyServerConfigurationPayloadEntry(leaderActorContext.getReplicatedLog(), votingServer(LEADER_ID), nonVotingServer(NEW_SERVER_ID), nonVotingServer(NEW_SERVER_ID2));
LOG.info("testAddServersAsNonVoting ending");
}
use of org.opendaylight.controller.cluster.raft.messages.AddServer in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testAddServerWithLeaderChangeBeforePriorSnapshotComplete.
@Test
public void testAddServerWithLeaderChangeBeforePriorSnapshotComplete() throws Exception {
LOG.info("testAddServerWithLeaderChangeBeforePriorSnapshotComplete starting");
setupNewFollower();
RaftActorContext initialActorContext = new MockRaftActorContext();
TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setElectionTimeoutFactor(100);
final ActorRef leaderCollectorActor = newLeaderCollectorActor(leaderRaftActor);
// Drop the commit message so the snapshot doesn't complete yet.
leaderRaftActor.setDropMessageOfType(COMMIT_MESSAGE_CLASS);
leaderActor.tell(new InitiateCaptureSnapshot(), leaderActor);
leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
Object commitMsg = expectFirstMatching(leaderCollectorActor, COMMIT_MESSAGE_CLASS);
// Change the leader behavior to follower
leaderActor.tell(new Follower(leaderActorContext), leaderActor);
// Drop CaptureSnapshotReply in case install snapshot is incorrectly initiated after the prior
// snapshot completes. This will prevent the invalid snapshot from completing and fail the
// isCapturing assertion below.
leaderRaftActor.setDropMessageOfType(CaptureSnapshotReply.class);
// Complete the prior snapshot - this should be a no-op b/c it's no longer the leader
leaderActor.tell(commitMsg, leaderActor);
leaderActor.tell(new RaftActorServerConfigurationSupport.ServerOperationTimeout(NEW_SERVER_ID), leaderActor);
AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.NO_LEADER, addServerReply.getStatus());
assertEquals("Leader peers size", 0, leaderActorContext.getPeerIds().size());
assertEquals("isCapturing", false, leaderActorContext.getSnapshotManager().isCapturing());
LOG.info("testAddServerWithLeaderChangeBeforePriorSnapshotComplete ending");
}
use of org.opendaylight.controller.cluster.raft.messages.AddServer in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testAddServerWithNoConsensusReached.
@Test
public void testAddServerWithNoConsensusReached() {
LOG.info("testAddServerWithNoConsensusReached starting");
setupNewFollower();
RaftActorContext initialActorContext = new MockRaftActorContext();
TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
final RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
final ActorRef leaderCollectorActor = newLeaderCollectorActor(leaderRaftActor);
// Drop UnInitializedFollowerSnapshotReply initially
leaderRaftActor.setDropMessageOfType(UnInitializedFollowerSnapshotReply.class);
MockNewFollowerRaftActor newFollowerRaftActorInstance = newFollowerRaftActor.underlyingActor();
newFollowerCollectorActor = newCollectorActor(newFollowerRaftActorInstance, NEW_SERVER_ID);
// Drop AppendEntries to the new follower so consensus isn't reached
newFollowerRaftActorInstance.setDropMessageOfType(AppendEntries.class);
leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
// Capture the UnInitializedFollowerSnapshotReply
Object snapshotReply = expectFirstMatching(leaderCollectorActor, UnInitializedFollowerSnapshotReply.class);
// Send the UnInitializedFollowerSnapshotReply to resume the first request
leaderRaftActor.setDropMessageOfType(null);
leaderActor.tell(snapshotReply, leaderActor);
expectFirstMatching(newFollowerCollectorActor, AppendEntries.class);
// Send a second AddServer
leaderActor.tell(new AddServer(NEW_SERVER_ID2, "", false), testKit.getRef());
// The first AddServer should succeed with OK even though consensus wasn't reached
AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, addServerReply.getStatus());
assertEquals("getLeaderHint", LEADER_ID, addServerReply.getLeaderHint().get());
// Verify ServerConfigurationPayload entry in leader's log
verifyServerConfigurationPayloadEntry(leaderActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(NEW_SERVER_ID));
// The second AddServer should fail since consensus wasn't reached for the first
addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.PRIOR_REQUEST_CONSENSUS_TIMEOUT, addServerReply.getStatus());
// Re-send the second AddServer - should also fail
leaderActor.tell(new AddServer(NEW_SERVER_ID2, "", false), testKit.getRef());
addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.PRIOR_REQUEST_CONSENSUS_TIMEOUT, addServerReply.getStatus());
LOG.info("testAddServerWithNoConsensusReached ending");
}
use of org.opendaylight.controller.cluster.raft.messages.AddServer in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testAddServerWithNoLeader.
@Test
public void testAddServerWithNoLeader() {
LOG.info("testAddServerWithNoLeader starting");
setupNewFollower();
DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
configParams.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS));
TestActorRef<MockRaftActor> noLeaderActor = actorFactory.createTestActor(MockRaftActor.builder().id(LEADER_ID).peerAddresses(ImmutableMap.of(FOLLOWER_ID, followerActor.path().toString())).config(configParams).persistent(Optional.of(false)).props().withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
noLeaderActor.underlyingActor().waitForInitializeBehaviorComplete();
noLeaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.NO_LEADER, addServerReply.getStatus());
LOG.info("testAddServerWithNoLeader ending");
}
Aggregations