-
Notifications
You must be signed in to change notification settings - Fork 377
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
box: prevent demoted leader from being a candidate in the next elections
Currently, the demoted leader sees that nobody has requested a vote in the newly persisted term (because it has just written it without voting, and nobody had time to see the new term yet), and hence votes for itself, becoming the most probable winner of the next elections. To prevent this from happening, let's forbid the demoted leader to be a candidate in the next elections using `box_raft_leader_step_off`. Closes #9855 NO_DOC=<bugfix> Co-authored-by: Serge Petrenko <sergepetrenko@tarantool.org> (cherry picked from commit 05d03a1)
- Loading branch information
1 parent
4783926
commit ac21b08
Showing
7 changed files
with
112 additions
and
10 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
changelogs/unreleased/gh-9855-box-ctl-demote-guarantee-demoting.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## bugfix/replication | ||
|
||
* Fixed a bug that allowed the old leader in | ||
`box.cfg{election_mode = 'candidate'` mode to get re-elected after resigning | ||
himself through `box.ctl.demote` (gh-9855). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
test/replication-luatest/gh_9855_box_ctl_demote_guarantee_demoting_test.lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
local t = require('luatest') | ||
local replica_set = require('luatest.replica_set') | ||
local server = require('luatest.server') | ||
|
||
local g = t.group() | ||
|
||
g.before_each(function(cg) | ||
cg.replica_set = replica_set:new{} | ||
local box_cfg = { | ||
replication = { | ||
server.build_listen_uri('server1', cg.replica_set.id), | ||
server.build_listen_uri('server2', cg.replica_set.id), | ||
}, | ||
election_mode = 'candidate', | ||
replication_timeout = 0.1, | ||
election_timeout = 0.5, | ||
} | ||
cg.server1 = cg.replica_set:build_and_add_server{ | ||
alias = 'server1', | ||
box_cfg = box_cfg, | ||
} | ||
box_cfg.election_mode = 'voter' | ||
cg.server2 = cg.replica_set:build_and_add_server{ | ||
alias = 'server2', | ||
box_cfg = box_cfg, | ||
} | ||
cg.replica_set:start() | ||
cg.replica_set:wait_for_fullmesh() | ||
end) | ||
|
||
g.after_each(function(cg) | ||
cg.replica_set:drop() | ||
end) | ||
|
||
-- Test that the demoted leader can still win in subsequent elections. | ||
local function test_subsequent_elections(demoted_leader, current_leader) | ||
current_leader:exec(function() | ||
box.ctl.demote() | ||
end) | ||
demoted_leader:wait_for_election_leader(); | ||
demoted_leader:exec(function() | ||
t.assert_equals(box.info.election.vote, box.info.election.leader) | ||
end) | ||
current_leader:exec(function() | ||
t.assert_equals(box.info.election.vote, box.info.election.leader) | ||
end) | ||
end | ||
|
||
-- Test that the demoted leader cannot get elected after resigning himself | ||
-- through `box.ctl.demote`. | ||
g.test_demote_guarantee = function(cg) | ||
cg.server1:wait_for_election_leader() | ||
cg.server2:update_box_cfg({election_mode = 'candidate'}) | ||
cg.server1:exec(function() | ||
box.ctl.demote() | ||
end) | ||
cg.server2:wait_for_election_leader(); | ||
cg.server1:exec(function() | ||
t.assert_equals(box.info.election.vote, box.info.election.leader) | ||
end) | ||
test_subsequent_elections(cg.server1, cg.server2) | ||
end | ||
|
||
-- Test that the demoted leader waits for leader death timeout after resigning | ||
-- himself through `box.ctl.demote` and starts subsequent elections. | ||
g.test_demoted_leader_election_in_subsequent_elections = function(cg) | ||
cg.server1:wait_for_election_leader() | ||
local demoted_term = cg.server1:get_election_term() | ||
cg.server1:exec(function() | ||
box.ctl.demote() | ||
end) | ||
cg.server1:wait_for_election_leader() | ||
cg.server1:exec(function(demoted_term) | ||
t.assert_equals(box.info.election.term, demoted_term + 1) | ||
t.assert_equals(box.info.election.vote, box.info.election.leader) | ||
end, {demoted_term}) | ||
end |