use of org.opendaylight.controller.cluster.raft.persisted.ServerInfo in project controller by opendaylight.
the class NonVotingFollowerIntegrationTest method setupLeaderAndNonVotingFollower.
private void setupLeaderAndNonVotingFollower() {
snapshotBatchCount = 100;
int persistedTerm = 1;
// Set up a persisted ServerConfigurationPayload with the leader voting and the follower non-voting.
ServerConfigurationPayload persistedServerConfig = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(leaderId, true), new ServerInfo(follower1Id, false)));
SimpleReplicatedLogEntry persistedServerConfigEntry = new SimpleReplicatedLogEntry(0, persistedTerm, persistedServerConfig);
InMemoryJournal.addEntry(leaderId, 1, new UpdateElectionTerm(persistedTerm, leaderId));
InMemoryJournal.addEntry(leaderId, 2, persistedServerConfigEntry);
InMemoryJournal.addEntry(follower1Id, 1, new UpdateElectionTerm(persistedTerm, leaderId));
InMemoryJournal.addEntry(follower1Id, 2, persistedServerConfigEntry);
DefaultConfigParamsImpl followerConfigParams = newFollowerConfigParams();
follower1Actor = newTestRaftActor(follower1Id, follower1Builder.peerAddresses(ImmutableMap.of(leaderId, testActorPath(leaderId))).config(followerConfigParams).persistent(Optional.of(false)));
peerAddresses = ImmutableMap.<String, String>builder().put(follower1Id, follower1Actor.path().toString()).build();
leaderConfigParams = newLeaderConfigParams();
leaderActor = newTestRaftActor(leaderId, TestRaftActor.newBuilder().peerAddresses(peerAddresses).config(leaderConfigParams).persistent(Optional.of(false)));
followerInstance = follower1Actor.underlyingActor();
follower1CollectorActor = followerInstance.collectorActor();
leaderInstance = leaderActor.underlyingActor();
leaderCollectorActor = leaderInstance.collectorActor();
leaderContext = leaderInstance.getRaftActorContext();
follower1Context = followerInstance.getRaftActorContext();
waitUntilLeader(leaderActor);
// Verify leader's context after startup
currentTerm = persistedTerm + 1;
assertEquals("Leader term", currentTerm, leaderContext.getTermInformation().getCurrentTerm());
assertEquals("Leader server config", Sets.newHashSet(persistedServerConfig.getServerConfig()), Sets.newHashSet(leaderContext.getPeerServerInfo(true).getServerConfig()));
assertEquals("Leader isVotingMember", true, leaderContext.isVotingMember());
// Verify follower's context after startup
MessageCollectorActor.expectFirstMatching(follower1CollectorActor, AppendEntries.class);
assertEquals("Follower term", currentTerm, follower1Context.getTermInformation().getCurrentTerm());
assertEquals("Follower server config", Sets.newHashSet(persistedServerConfig.getServerConfig()), Sets.newHashSet(follower1Context.getPeerServerInfo(true).getServerConfig()));
assertEquals("FollowerisVotingMember", false, follower1Context.isVotingMember());
}
use of org.opendaylight.controller.cluster.raft.persisted.ServerInfo in project controller by opendaylight.
the class RaftActorContextImplTest method testUpdatePeerIds.
@Test
public void testUpdatePeerIds() {
RaftActorContextImpl context = new RaftActorContextImpl(actor, actor.underlyingActor().getContext(), "self", new ElectionTermImpl(createProvider(), "test", LOG), -1, -1, Maps.newHashMap(ImmutableMap.<String, String>of("peer1", "peerAddress1")), new DefaultConfigParamsImpl(), createProvider(), applyState -> {
}, LOG);
context.updatePeerIds(new ServerConfigurationPayload(Arrays.asList(new ServerInfo("self", false), new ServerInfo("peer2", true), new ServerInfo("peer3", false))));
verifyPeerInfo(context, "peer1", null);
verifyPeerInfo(context, "peer2", true);
verifyPeerInfo(context, "peer3", false);
assertEquals("isVotingMember", false, context.isVotingMember());
context.updatePeerIds(new ServerConfigurationPayload(Arrays.asList(new ServerInfo("self", true), new ServerInfo("peer2", true), new ServerInfo("peer3", true))));
verifyPeerInfo(context, "peer2", true);
verifyPeerInfo(context, "peer3", true);
assertEquals("isVotingMember", true, context.isVotingMember());
context.updatePeerIds(new ServerConfigurationPayload(Arrays.asList(new ServerInfo("peer2", true), new ServerInfo("peer3", true))));
verifyPeerInfo(context, "peer2", true);
verifyPeerInfo(context, "peer3", true);
assertEquals("isVotingMember", false, context.isVotingMember());
}
use of org.opendaylight.controller.cluster.raft.persisted.ServerInfo in project controller by opendaylight.
the class RaftActorRecoverySupportTest method testServerConfigurationPayloadApplied.
@Test
public void testServerConfigurationPayloadApplied() {
String follower1 = "follower1";
String follower2 = "follower2";
String follower3 = "follower3";
context.addToPeers(follower1, null, VotingState.VOTING);
context.addToPeers(follower2, null, VotingState.VOTING);
// add new Server
ServerConfigurationPayload obj = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(localId, true), new ServerInfo(follower1, true), new ServerInfo(follower2, false), new ServerInfo(follower3, true)));
sendMessageToSupport(new SimpleReplicatedLogEntry(0, 1, obj));
// verify new peers
assertTrue("Dynamic server configuration", context.isDynamicServerConfigurationInUse());
assertEquals("New peer Ids", Sets.newHashSet(follower1, follower2, follower3), Sets.newHashSet(context.getPeerIds()));
assertEquals("follower1 isVoting", true, context.getPeerInfo(follower1).isVoting());
assertEquals("follower2 isVoting", false, context.getPeerInfo(follower2).isVoting());
assertEquals("follower3 isVoting", true, context.getPeerInfo(follower3).isVoting());
sendMessageToSupport(new ApplyJournalEntries(0));
verify(mockCohort, never()).startLogRecoveryBatch(anyInt());
verify(mockCohort, never()).appendRecoveredLogEntry(any(Payload.class));
// remove existing follower1
obj = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(localId, true), new ServerInfo("follower2", true), new ServerInfo("follower3", true)));
sendMessageToSupport(new SimpleReplicatedLogEntry(1, 1, obj));
// verify new peers
assertTrue("Dynamic server configuration", context.isDynamicServerConfigurationInUse());
assertEquals("New peer Ids", Sets.newHashSet(follower2, follower3), Sets.newHashSet(context.getPeerIds()));
}
use of org.opendaylight.controller.cluster.raft.persisted.ServerInfo in project controller by opendaylight.
the class RaftActorRecoverySupportTest method testServerConfigurationPayloadAppliedWithPersistenceDisabled.
@Test
public void testServerConfigurationPayloadAppliedWithPersistenceDisabled() {
doReturn(false).when(mockPersistence).isRecoveryApplicable();
String follower = "follower";
ServerConfigurationPayload obj = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(localId, true), new ServerInfo(follower, true)));
sendMessageToSupport(new SimpleReplicatedLogEntry(0, 1, obj));
// verify new peers
assertEquals("New peer Ids", Sets.newHashSet(follower), Sets.newHashSet(context.getPeerIds()));
}
use of org.opendaylight.controller.cluster.raft.persisted.ServerInfo in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testChangeToVotingWithNoLeaderAndForwardedToOtherNodeAfterElectionTimeout.
@Test
public void testChangeToVotingWithNoLeaderAndForwardedToOtherNodeAfterElectionTimeout() {
LOG.info("testChangeToVotingWithNoLeaderAndForwardedToOtherNodeAfterElectionTimeout starting");
final String node1ID = "node1";
final String node2ID = "node2";
final PeerAddressResolver peerAddressResolver = peerId -> peerId.equals(node1ID) ? actorFactory.createTestActorPath(node1ID) : peerId.equals(node2ID) ? actorFactory.createTestActorPath(node2ID) : null;
DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
configParams.setHeartBeatInterval(new FiniteDuration(100, TimeUnit.MILLISECONDS));
configParams.setElectionTimeoutFactor(3);
configParams.setPeerAddressResolver(peerAddressResolver);
ServerConfigurationPayload persistedServerConfig = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(node1ID, false), new ServerInfo(node2ID, false)));
SimpleReplicatedLogEntry persistedServerConfigEntry = new SimpleReplicatedLogEntry(0, 1, persistedServerConfig);
InMemoryJournal.addEntry(node1ID, 1, new UpdateElectionTerm(1, "node1"));
InMemoryJournal.addEntry(node1ID, 2, persistedServerConfigEntry);
InMemoryJournal.addEntry(node2ID, 1, new UpdateElectionTerm(1, "node1"));
InMemoryJournal.addEntry(node2ID, 2, persistedServerConfigEntry);
InMemoryJournal.addEntry(node2ID, 3, new SimpleReplicatedLogEntry(1, 1, new MockRaftActorContext.MockPayload("2")));
InMemoryJournal.addEntry(node2ID, 4, new ApplyJournalEntries(1));
ActorRef node1Collector = actorFactory.createActor(MessageCollectorActor.props(), actorFactory.generateActorId("collector"));
TestActorRef<CollectingMockRaftActor> node1RaftActorRef = actorFactory.createTestActor(CollectingMockRaftActor.props(node1ID, ImmutableMap.<String, String>of(), configParams, PERSISTENT, node1Collector).withDispatcher(Dispatchers.DefaultDispatcherId()), node1ID);
final CollectingMockRaftActor node1RaftActor = node1RaftActorRef.underlyingActor();
ActorRef node2Collector = actorFactory.createActor(MessageCollectorActor.props(), actorFactory.generateActorId("collector"));
TestActorRef<CollectingMockRaftActor> node2RaftActorRef = actorFactory.createTestActor(CollectingMockRaftActor.props(node2ID, ImmutableMap.<String, String>of(), configParams, PERSISTENT, node2Collector).withDispatcher(Dispatchers.DefaultDispatcherId()), node2ID);
final CollectingMockRaftActor node2RaftActor = node2RaftActorRef.underlyingActor();
// Send a ChangeServersVotingStatus message to node1 to change mode1 to voting. This should cause
// node1 to try to elect itself as leader in order to apply the new server config. However node1's log
// is behind node2's so node2 should not grant node1's vote. This should cause node1 to time out and
// forward the request to node2.
ChangeServersVotingStatus changeServers = new ChangeServersVotingStatus(ImmutableMap.of(node1ID, true, node2ID, true));
node1RaftActorRef.tell(changeServers, testKit.getRef());
ServerChangeReply reply = testKit.expectMsgClass(testKit.duration("5 seconds"), ServerChangeReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, reply.getStatus());
MessageCollectorActor.expectFirstMatching(node2Collector, ApplyJournalEntries.class);
verifyServerConfigurationPayloadEntry(node2RaftActor.getRaftActorContext().getReplicatedLog(), votingServer(node1ID), votingServer(node2ID));
assertEquals("getRaftState", RaftState.Leader, node2RaftActor.getRaftState());
MessageCollectorActor.expectFirstMatching(node1Collector, ApplyJournalEntries.class);
verifyServerConfigurationPayloadEntry(node1RaftActor.getRaftActorContext().getReplicatedLog(), votingServer(node1ID), votingServer(node2ID));
assertEquals("isVotingMember", true, node1RaftActor.getRaftActorContext().isVotingMember());
assertEquals("getRaftState", RaftState.Follower, node1RaftActor.getRaftState());
LOG.info("testChangeToVotingWithNoLeaderAndForwardedToOtherNodeAfterElectionTimeout ending");
}
Aggregations