Disallow remove leader in single node 91/32391/3
authorTom Pantelis <tpanteli@brocade.com>
Tue, 12 Jan 2016 06:30:29 +0000 (01:30 -0500)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 15 Jan 2016 13:15:29 +0000 (13:15 +0000)
We don't want to allow removal of the leader in a single node cluster,
ie when there's no followers.

Change-Id: I3bedd1727736c7dfec55ba696f5ef1197a68c89d
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorServerConfigurationSupport.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/ServerChangeStatus.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorServerConfigurationSupportTest.java

index 3db0316..95269f6 100644 (file)
@@ -78,7 +78,10 @@ class RaftActorServerConfigurationSupport {
     private void onRemoveServer(RemoveServer removeServer, ActorRef sender) {
         LOG.debug("{}: onRemoveServer: {}, state: {}", raftContext.getId(), removeServer, currentOperationState);
         boolean isSelf = removeServer.getServerId().equals(raftActor.getId());
-        if(!isSelf && !raftContext.getPeerIds().contains(removeServer.getServerId())) {
+        if(isSelf && !raftContext.hasFollowers()) {
+            sender.tell(new RemoveServerReply(ServerChangeStatus.NOT_SUPPORTED, raftActor.getLeaderId()),
+                    raftActor.getSelf());
+        } else if(!isSelf && !raftContext.getPeerIds().contains(removeServer.getServerId())) {
             sender.tell(new RemoveServerReply(ServerChangeStatus.DOES_NOT_EXIST, raftActor.getLeaderId()),
                     raftActor.getSelf());
         } else {
index 7616fe6..8f6a370 100644 (file)
@@ -45,7 +45,7 @@ public enum ServerChangeStatus {
     PRIOR_REQUEST_CONSENSUS_TIMEOUT,
 
     /**
-     * An unsupported request, for example removing the current leader may not be supported (at least initially)
+     * An unsupported request, for example removing the leader in a single node cluster.
      */
     NOT_SUPPORTED,
 }
index 3420c4f..0025a6d 100644 (file)
@@ -821,6 +821,18 @@ public class RaftActorServerConfigurationSupportTest extends AbstractActorTest {
         MessageCollectorActor.expectFirstMatching(leaderCollector, ServerRemoved.class);
     }
 
+    @Test
+    public void testRemoveServerLeaderWithNoFollowers() {
+        TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(
+                MockLeaderRaftActor.props(Collections.<String, String>emptyMap(),
+                        new MockRaftActorContext()).withDispatcher(Dispatchers.DefaultDispatcherId()),
+                actorFactory.generateActorId(LEADER_ID));
+
+        leaderActor.tell(new RemoveServer(LEADER_ID), testKit.getRef());
+        RemoveServerReply removeServerReply = testKit.expectMsgClass(JavaTestKit.duration("5 seconds"), RemoveServerReply.class);
+        assertEquals("getStatus", ServerChangeStatus.NOT_SUPPORTED, removeServerReply.getStatus());
+    }
+
     private ServerInfo votingServer(String id) {
         return new ServerInfo(id, true);
     }