# Run a V2 membership change that removes the leader and adds another voter as a
# single operation, using joint consensus and explicitly determining when to
# transition out of the joint config. Leadership is transferred by campaigning a
# designated voter in the new config once the old leader steps down. After the
# reconfiguration completes, we verify that the removed leader cannot campaign
# to become leader.

# We'll turn this back on after the boilerplate.
log-level none
----
ok

# Bootstrap n1, n2, n3.
add-nodes 3 voters=(1,2,3) index=2 step-down-on-removal=true
----
ok

# n1 campaigns to become leader.
campaign 1
----
ok

stabilize
----
ok

log-level info
----
ok

raft-state
----
1: StateLeader (Voter) Term:1 Lead:1
2: StateFollower (Voter) Term:1 Lead:1
3: StateFollower (Voter) Term:1 Lead:1

# create n4
add-nodes 1
----
INFO 4 switched to configuration voters=()
INFO 4 became follower at term 0
INFO newRaft 4 [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0]

# Start reconfiguration to remove n1 and add n4.
propose-conf-change 1 v1=false transition=explicit
r1 v4
----
ok

# Enter joint config.
stabilize log-level=none
----
ok

raft-state
----
1: StateLeader (Voter) Term:1 Lead:1
2: StateFollower (Voter) Term:1 Lead:1
3: StateFollower (Voter) Term:1 Lead:1
4: StateFollower (Voter) Term:1 Lead:1

# n4 will propose a transition out of the joint config.
propose-conf-change 4
----
ok

# The group commits the command and everyone switches to the final config.
# n1 steps down as leader.
stabilize
----
> 4 handling Ready
  Ready MustSync=false:
  Messages:
  4->1 MsgProp Term:0 Log:0/0 Entries:[0/0 EntryConfChangeV2]
> 1 receiving messages
  4->1 MsgProp Term:0 Log:0/0 Entries:[0/0 EntryConfChangeV2]
> 1 handling Ready
  Ready MustSync=true:
  Entries:
  1/5 EntryConfChangeV2
  Messages:
  1->2 MsgApp Term:1 Log:1/4 Commit:4 Entries:[1/5 EntryConfChangeV2]
  1->3 MsgApp Term:1 Log:1/4 Commit:4 Entries:[1/5 EntryConfChangeV2]
  1->4 MsgApp Term:1 Log:1/4 Commit:4 Entries:[1/5 EntryConfChangeV2]
> 2 receiving messages
  1->2 MsgApp Term:1 Log:1/4 Commit:4 Entries:[1/5 EntryConfChangeV2]
> 3 receiving messages
  1->3 MsgApp Term:1 Log:1/4 Commit:4 Entries:[1/5 EntryConfChangeV2]
> 4 receiving messages
  1->4 MsgApp Term:1 Log:1/4 Commit:4 Entries:[1/5 EntryConfChangeV2]
> 2 handling Ready
  Ready MustSync=true:
  Entries:
  1/5 EntryConfChangeV2
  Messages:
  2->1 MsgAppResp Term:1 Log:0/5
> 3 handling Ready
  Ready MustSync=true:
  Entries:
  1/5 EntryConfChangeV2
  Messages:
  3->1 MsgAppResp Term:1 Log:0/5
> 4 handling Ready
  Ready MustSync=true:
  Entries:
  1/5 EntryConfChangeV2
  Messages:
  4->1 MsgAppResp Term:1 Log:0/5
> 1 receiving messages
  2->1 MsgAppResp Term:1 Log:0/5
  3->1 MsgAppResp Term:1 Log:0/5
  4->1 MsgAppResp Term:1 Log:0/5
> 1 handling Ready
  Ready MustSync=false:
  HardState Term:1 Vote:1 Commit:5
  CommittedEntries:
  1/5 EntryConfChangeV2
  Messages:
  1->2 MsgApp Term:1 Log:1/5 Commit:5
  1->3 MsgApp Term:1 Log:1/5 Commit:5
  1->4 MsgApp Term:1 Log:1/5 Commit:5
  INFO 1 switched to configuration voters=(2 3 4)
  INFO 1 became follower at term 1
> 2 receiving messages
  1->2 MsgApp Term:1 Log:1/5 Commit:5
> 3 receiving messages
  1->3 MsgApp Term:1 Log:1/5 Commit:5
> 4 receiving messages
  1->4 MsgApp Term:1 Log:1/5 Commit:5
> 1 handling Ready
  Ready MustSync=false:
  Lead:0 State:StateFollower
> 2 handling Ready
  Ready MustSync=false:
  HardState Term:1 Vote:1 Commit:5
  CommittedEntries:
  1/5 EntryConfChangeV2
  Messages:
  2->1 MsgAppResp Term:1 Log:0/5
  INFO 2 switched to configuration voters=(2 3 4)
> 3 handling Ready
  Ready MustSync=false:
  HardState Term:1 Vote:1 Commit:5
  CommittedEntries:
  1/5 EntryConfChangeV2
  Messages:
  3->1 MsgAppResp Term:1 Log:0/5
  INFO 3 switched to configuration voters=(2 3 4)
> 4 handling Ready
  Ready MustSync=false:
  HardState Term:1 Commit:5
  CommittedEntries:
  1/5 EntryConfChangeV2
  Messages:
  4->1 MsgAppResp Term:1 Log:0/5
  INFO 4 switched to configuration voters=(2 3 4)
> 1 receiving messages
  2->1 MsgAppResp Term:1 Log:0/5
  3->1 MsgAppResp Term:1 Log:0/5
  4->1 MsgAppResp Term:1 Log:0/5

# n1 is out of the configuration.
raft-state
----
1: StateFollower (Non-Voter) Term:1 Lead:0
2: StateFollower (Voter) Term:1 Lead:1
3: StateFollower (Voter) Term:1 Lead:1
4: StateFollower (Voter) Term:1 Lead:1

# Make sure n1 cannot campaign to become leader.
campaign 1
----
WARN 1 is unpromotable and can not campaign

# Campaign the dedicated voter n2 to become the new leader.
campaign 2
----
INFO 2 is starting a new election at term 1
INFO 2 became candidate at term 2
INFO 2 [logterm: 1, index: 5] sent MsgVote request to 3 at term 2
INFO 2 [logterm: 1, index: 5] sent MsgVote request to 4 at term 2

stabilize log-level=none
----
ok

raft-state
----
1: StateFollower (Non-Voter) Term:1 Lead:0
2: StateLeader (Voter) Term:2 Lead:2
3: StateFollower (Voter) Term:2 Lead:2
4: StateFollower (Voter) Term:2 Lead:2
