diff --git a/changelogs/unreleased/anon-on-failure-ballot.md b/changelogs/unreleased/anon-on-failure-ballot.md new file mode 100644 index 0000000000000000000000000000000000000000..f01ee0eeada02bad21b256116c1db4640ccb6e28 --- /dev/null +++ b/changelogs/unreleased/anon-on-failure-ballot.md @@ -0,0 +1,4 @@ +## bugfix/replication + +* Fixed a bug when new instances could try to register via an anon instance + which previously failed to apply `box.cfg{replication_anon = false}`. diff --git a/src/box/box.cc b/src/box/box.cc index 28ab9802325c915b06de4fe8a63ef304d018e3e9..a489dd5614e81a24944a4455760adb2403b070a1 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -1970,6 +1970,7 @@ box_set_replication_anon(void) if (!anon) { auto guard = make_scoped_guard([&]{ replication_anon = !anon; + box_broadcast_ballot(); }); /* Turn anonymous instance into a normal one. */ replication_anon = anon; diff --git a/test/replication-luatest/anon_test.lua b/test/replication-luatest/anon_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..750bf4003fc2d9e0cd2b529a57e868103402fc33 --- /dev/null +++ b/test/replication-luatest/anon_test.lua @@ -0,0 +1,61 @@ +local server = require('luatest.server') +local t = require('luatest') +local g = t.group() + +g.before_all = function(lg) + lg.master = server:new({alias = 'master'}) + lg.master:start() +end + +g.after_all = function(lg) + lg.master:drop() +end + +-- +-- When an instance failed to apply cfg{replication_anon = false}, it used to +-- report itself as non-anon in the ballot anyway. Shouldn't be so. +-- +g.test_ballot_on_deanon_fail = function(lg) + local box_cfg = { + replication_anon = true, + read_only = true, + replication = { + lg.master.net_box_uri, + }, + } + local replica = server:new({ + alias = 'replica', + box_cfg = box_cfg, + }) + replica:start() + replica:exec(function() + t.assert_equals(box.info.id, 0) + end) + lg.master:exec(function() + rawset(_G, 'test_trigger', function() + error('Reject _cluster update') + end) + box.space._cluster:on_replace(_G.test_trigger) + end) + replica:exec(function() + local fiber = require('fiber') + local iproto = box.iproto + local is_anon = nil + local w = box.watch('internal.ballot', function(_, value) + is_anon = value[iproto.key.BALLOT][iproto.ballot_key.IS_ANON] + end) + fiber.yield() + t.assert(is_anon) + is_anon = nil + t.assert_error_msg_contains('Reject _cluster update', box.cfg, + {replication_anon = false}) + fiber.yield() + t.assert(is_anon) + w:unregister() + end) + replica:drop() + lg.master:exec(function() + box.space._cluster:on_replace(nil, _G.test_trigger) + _G.test_trigger = nil + end) +end