diff options
| author | Andrew Bruce <me@andrewbruce.net> | 2016-10-05 15:21:47 +0100 |
|---|---|---|
| committer | Andrew Bruce <me@andrewbruce.net> | 2016-10-05 15:21:47 +0100 |
| commit | c1c56a29b098b7c5ad0915a340a2a039e61a22a3 (patch) | |
| tree | 4f5fb822ed7e359a264920650e0522ebc2be6013 /src | |
| parent | 75795f977c8b96fa580d58cd9bda049e312b2044 (diff) | |
| download | rabbitmq-server-git-c1c56a29b098b7c5ad0915a340a2a039e61a22a3.tar.gz | |
Choose master from intersection of sync slaves and policy nodes
Previously, when applying an HA policy with the 'nodes' type, if the
current master was not part of the new policy, then the first
synchronised slave was chosen as the new master. This would happen even
if the node was not part of the new policy.
For example, if we began with:
Master A
Slaves [B, C]
Then requested a new policy of just [C], we'd end up with:
Master B
Slaves [C]
Instead, choose the master from the intersection of (nodes in
the policy) and (synchronised slaves).
Issue #990
[#126767013]
Diffstat (limited to 'src')
| -rw-r--r-- | src/rabbit_mirror_queue_mode_nodes.erl | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/src/rabbit_mirror_queue_mode_nodes.erl b/src/rabbit_mirror_queue_mode_nodes.erl index e63f340373..31c55722a5 100644 --- a/src/rabbit_mirror_queue_mode_nodes.erl +++ b/src/rabbit_mirror_queue_mode_nodes.erl @@ -32,29 +32,37 @@ description() -> [{description, <<"Mirror queue to specified nodes">>}]. -suggested_queue_nodes(Nodes0, MNode, _SNodes, SSNodes, Poss) -> - Nodes1 = [list_to_atom(binary_to_list(Node)) || Node <- Nodes0], +suggested_queue_nodes(PolicyNodes0, CurrentMaster, _SNodes, SSNodes, NodesRunningRabbitMQ) -> + PolicyNodes1 = [list_to_atom(binary_to_list(Node)) || Node <- PolicyNodes0], %% If the current master is not in the nodes specified, then what we want %% to do depends on whether there are any synchronised slaves. If there %% are then we can just kill the current master - the admin has asked for %% a migration and we should give it to them. If there are not however %% then we must keep the master around so as not to lose messages. - Nodes = case SSNodes of - [] -> lists:usort([MNode | Nodes1]); - _ -> Nodes1 - end, - Unavailable = Nodes -- Poss, - Available = Nodes -- Unavailable, - case Available of + + PolicyNodes = case SSNodes of + [] -> lists:usort([CurrentMaster | PolicyNodes1]); + _ -> PolicyNodes1 + end, + Unavailable = PolicyNodes -- NodesRunningRabbitMQ, + AvailablePolicyNodes = PolicyNodes -- Unavailable, + case AvailablePolicyNodes of [] -> %% We have never heard of anything? Not much we can do but %% keep the master alive. - {MNode, []}; - _ -> case lists:member(MNode, Available) of - true -> {MNode, Available -- [MNode]}; + {CurrentMaster, []}; + _ -> case lists:member(CurrentMaster, AvailablePolicyNodes) of + true -> {CurrentMaster, + AvailablePolicyNodes -- [CurrentMaster]}; false -> %% Make sure the new master is synced! In order to %% get here SSNodes must not be empty. - [NewMNode | _] = SSNodes, - {NewMNode, Available -- [NewMNode]} + SyncPolicyNodes = [Node || + Node <- AvailablePolicyNodes, + lists:member(Node, SSNodes)], + NewMaster = case SyncPolicyNodes of + [Node | _] -> Node; + [] -> erlang:hd(SSNodes) + end, + {NewMaster, AvailablePolicyNodes -- [NewMaster]} end end. |
