Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 1 addition & 50 deletions deps/rabbit/docs/rabbitmqctl.8
Original file line number Diff line number Diff line change
Expand Up @@ -286,28 +286,6 @@ For example, to wait for two RabbitMQ nodes to start:
.sp
.Dl rabbitmqctl await_online_nodes 2
.\" ------------------------------------------------------------------
.It Cm change_cluster_node_type Ar type
.Pp
Changes the type of the cluster node.
.Pp
The
.Ar type
must be one of the following:
.Bl -bullet -compact
.It
.Cm disc
.It
.Cm ram
.El
.Pp
The node must be stopped for this operation to succeed, and when turning
a node into a RAM node the node must not be the only disc node in the
cluster.
.Pp
For example, this command will turn a RAM node into a disc node:
.sp
.Dl rabbitmqctl change_cluster_node_type disc
.\" ------------------------------------------------------------------
.It Cm cluster_status
.Pp
Displays all the nodes in the cluster grouped by node type, together
Expand Down Expand Up @@ -413,14 +391,10 @@ from the node
.sp
.Dl rabbitmqctl -n hare@mcnulty forget_cluster_node rabbit@stringer
.\" ------------------------------------------------------------------
.It Cm join_cluster Ar seed-node Op Fl -ram
.It Cm join_cluster Ar seed-node
.Bl -tag -width Ds
.It Ar seed-node
Existing cluster member (seed node) to cluster with.
.It Fl -ram
If provided, the node will join the cluster as a RAM node.
RAM node use is discouraged. Use only if you understand why
exactly you need to use them.
.El
.Pp
Instructs the node to become a member of the cluster that the specified
Expand All @@ -431,23 +405,6 @@ For this command to succeed the RabbitMQ application must have been
stopped, e.g. with
.Cm stop_app .
.Pp
Cluster nodes can be of two types: disc or RAM.
Disc nodes replicate data in RAM and on disk, thus providing redundancy
in the event of node failure and recovery from global events such as
power failure across all nodes.
RAM nodes replicate data in RAM only (except for queue contents, which
can reside on disk if the queue is persistent or too big to fit in
memory) and are mainly used for scalability.
RAM nodes are more performant only when managing resources (e.g.\&
adding/removing queues, exchanges, or bindings).
A cluster must always have at least one disc node and usually should
have more than one.
.Pp
The node will be a disc node by default.
If you wish to create a RAM node, provide the
.Fl -ram
flag.
.Pp
After executing the
.Cm join_cluster
command, whenever the RabbitMQ application is started on the current
Expand All @@ -461,12 +418,6 @@ You can also remove nodes remotely with the
.Cm forget_cluster_node
command.
.Pp
For example, this command instructs the RabbitMQ node to join the cluster that
.Qq hare@elena
is part of, as a ram node:
.sp
.Dl rabbitmqctl join_cluster hare@elena --ram
.Pp
To learn more, see the
.Lk https://www.rabbitmq.com/docs/clustering "RabbitMQ Clustering guide".
.\" ------------------------------------------------------------------
Expand Down
6 changes: 4 additions & 2 deletions deps/rabbit/src/rabbit_db_cluster.erl
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,10 @@ join(RemoteNode, NodeType)
Error
end.

join_using_mnesia(ClusterNodes, NodeType) when is_list(ClusterNodes) ->
rabbit_mnesia:join_cluster(ClusterNodes, NodeType).
join_using_mnesia(ClusterNodes, disc) when is_list(ClusterNodes) ->
rabbit_mnesia:join_cluster(ClusterNodes, disc);
join_using_mnesia(_ClusterNodes, ram = NodeType) ->
{error, {node_type_unsupported, mnesia, NodeType}}.

join_using_khepri(ClusterNodes, disc) ->
rabbit_khepri:add_member(node(), ClusterNodes);
Expand Down
2 changes: 1 addition & 1 deletion deps/rabbit/src/rabbit_mnesia.erl
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@

-rabbit_deprecated_feature(
{ram_node_type,
#{deprecation_phase => permitted_by_default,
#{deprecation_phase => removed,
doc_url => "https://blog.rabbitmq.com/posts/2021/08/4.0-deprecation-announcements/#removal-of-ram-nodes"
}}).

Expand Down
159 changes: 22 additions & 137 deletions deps/rabbit/test/clustering_management_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ groups() ->
join_cluster_bad_operations,
join_to_start_interval,
forget_cluster_node,
change_cluster_node_type,
change_cluster_when_node_offline
]}
]},
Expand All @@ -57,16 +56,14 @@ groups() ->
pid_file_and_await_node_startup,
await_running_count,
start_with_invalid_schema_in_path,
persistent_cluster_id,
reset_last_disc_node
persistent_cluster_id
]}
]}
]},
{khepri_store, [], [
{clustered_2_nodes, [],
[
{cluster_size_2, [], [
change_cluster_node_type_in_khepri,
forget_node_in_khepri,
forget_removes_things_in_khepri,
reset_in_khepri,
Expand Down Expand Up @@ -277,20 +274,19 @@ join_and_part_cluster(Config) ->
stop_join_start(Config, Rabbit, Bunny),
assert_clustered([Rabbit, Bunny]),

stop_join_start(Config, Hare, Bunny, true),
assert_cluster_status(
{[Bunny, Hare, Rabbit], [Bunny, Rabbit], [Bunny, Hare, Rabbit]},
[Rabbit, Hare, Bunny]),
stop_join_start(Config, Hare, Bunny),
assert_clustered([Rabbit, Bunny, Hare]),

%% Allow clustering with already clustered node
ok = stop_app(Config, Rabbit),
ok = join_cluster(Config, Rabbit, Hare),
ok = start_app(Config, Rabbit),

assert_clustered([Rabbit, Bunny, Hare]),

stop_reset_start(Config, Rabbit),
assert_not_clustered(Rabbit),
assert_cluster_status({[Bunny, Hare], [Bunny], [Bunny, Hare]},
[Hare, Bunny]),
assert_clustered([Bunny, Hare]),

stop_reset_start(Config, Hare),
assert_not_clustered(Hare),
Expand Down Expand Up @@ -385,12 +381,7 @@ join_and_part_cluster_in_khepri(Config) ->
assert_clustered([Rabbit, Bunny, Hare]).

join_cluster_bad_operations(Config) ->
[Rabbit, Hare, Bunny] = cluster_members(Config),

UsePrelaunch = rabbit_ct_broker_helpers:rpc(
Config, Hare,
erlang, function_exported,
[rabbit_prelaunch, get_context, 0]),
[Rabbit, _Hare, _Bunny] = cluster_members(Config),

%% Nonexistent node
ok = stop_app(Config, Rabbit),
Expand All @@ -404,30 +395,6 @@ join_cluster_bad_operations(Config) ->
ok = start_app(Config, Rabbit),
assert_not_clustered(Rabbit),

%% Do not let the node leave the cluster or reset if it's the only
%% ram node
stop_join_start(Config, Hare, Rabbit, true),
assert_cluster_status({[Rabbit, Hare], [Rabbit], [Rabbit, Hare]},
[Rabbit, Hare]),
ok = stop_app(Config, Hare),
assert_failure(fun () -> join_cluster(Config, Rabbit, Bunny) end),
assert_failure(fun () -> reset(Config, Rabbit) end),
ok = start_app(Config, Hare),
assert_cluster_status({[Rabbit, Hare], [Rabbit], [Rabbit, Hare]},
[Rabbit, Hare]),

%% Cannot start RAM-only node first
ok = stop_app(Config, Rabbit),
ok = stop_app(Config, Hare),
assert_failure(fun () -> start_app(Config, Hare) end),
ok = start_app(Config, Rabbit),
case UsePrelaunch of
true ->
ok = start_app(Config, Hare);
false ->
%% The Erlang VM has stopped after previous rabbit app failure
ok = rabbit_ct_broker_helpers:start_node(Config, Hare)
end,
ok.

join_cluster_bad_operations_in_khepri(Config) ->
Expand Down Expand Up @@ -470,10 +437,10 @@ join_cluster_in_minority(Config) ->
ok = rabbit_ct_broker_helpers:stop_node(Config, Rabbit),

ok = stop_app(Config, Hare),
?assertEqual(ok, join_cluster(Config, Hare, Bunny, false)),
?assertEqual(ok, join_cluster(Config, Hare, Bunny)),

ok = rabbit_ct_broker_helpers:start_node(Config, Rabbit),
?assertEqual(ok, join_cluster(Config, Hare, Rabbit, false)),
?assertEqual(ok, join_cluster(Config, Hare, Rabbit)),
?assertEqual(ok, start_app(Config, Hare)),

assert_clustered([Rabbit, Bunny, Hare]).
Expand All @@ -489,10 +456,10 @@ join_cluster_with_rabbit_stopped(Config) ->
ok = stop_app(Config, Rabbit),

ok = stop_app(Config, Hare),
?assertEqual(ok, join_cluster(Config, Hare, Bunny, false)),
?assertEqual(ok, join_cluster(Config, Hare, Bunny)),

ok = start_app(Config, Rabbit),
?assertEqual(ok, join_cluster(Config, Hare, Rabbit, false)),
?assertEqual(ok, join_cluster(Config, Hare, Rabbit)),
?assertEqual(ok, start_app(Config, Hare)),

assert_clustered([Rabbit, Bunny, Hare]).
Expand Down Expand Up @@ -758,27 +725,6 @@ is_in_minority(Ret) ->
{error, _, Msg} = Ret,
?assertMatch(match, re:run(Msg, ".*timed out.*minority.*", [{capture, none}])).

reset_last_disc_node(Config) ->
[Rabbit, Hare | _] = cluster_members(Config),

stop_app(Config, Hare),
?assertEqual(ok, change_cluster_node_type(Config, Hare, ram)),
start_app(Config, Hare),

case rabbit_ct_broker_helpers:enable_feature_flag(Config, [Rabbit], khepri_db) of
ok ->
%% The reset works after the switch to Khepri because the RAM node was
%% implicitly converted to a disc one as Khepri always writes data on disc.
stop_app(Config, Rabbit),
?assertEqual(ok, reset(Config, Rabbit)),
start_app(Config, Rabbit),
assert_not_clustered(Rabbit),
assert_not_clustered(Hare),
ok;
{skip, _} = Skip ->
Skip
end.

forget_offline_removes_things(Config) ->
[Rabbit, Hare] = rabbit_ct_broker_helpers:get_node_configs(Config,
nodename),
Expand Down Expand Up @@ -833,54 +779,6 @@ force_boot_in_khepri(Config) ->
?assertMatch({ok, []}, rabbit_ct_broker_helpers:rabbitmqctl(Config, Rabbit, ["force_boot"])),
ok.

change_cluster_node_type(Config) ->
[Rabbit, Hare, _Bunny] = cluster_members(Config),

%% Trying to change the node to the ram type when not clustered should always fail
ok = stop_app(Config, Rabbit),
assert_failure(fun () -> change_cluster_node_type(Config, Rabbit, ram) end),
ok = start_app(Config, Rabbit),

ok = stop_app(Config, Rabbit),
join_cluster(Config, Rabbit, Hare),
assert_cluster_status({[Rabbit, Hare], [Rabbit, Hare], [Hare]},
[Rabbit, Hare]),
change_cluster_node_type(Config, Rabbit, ram),
assert_cluster_status({[Rabbit, Hare], [Hare], [Rabbit, Hare], [Hare], [Hare]},
[Rabbit, Hare]),
change_cluster_node_type(Config, Rabbit, disc),

assert_cluster_status({[Rabbit, Hare], [Rabbit, Hare], [Hare]},
[Rabbit, Hare]),
change_cluster_node_type(Config, Rabbit, ram),
ok = start_app(Config, Rabbit),
assert_cluster_status({[Rabbit, Hare], [Hare], [Hare, Rabbit]},
[Rabbit, Hare]),

%% Changing to ram when you're the only ram node should fail
ok = stop_app(Config, Hare),
assert_failure(fun () -> change_cluster_node_type(Config, Hare, ram) end),
ok = start_app(Config, Hare).

change_cluster_node_type_in_khepri(Config) ->
[Rabbit, Hare] = cluster_members(Config),

assert_cluster_status({[Rabbit, Hare], [Rabbit, Hare], [Rabbit, Hare]},
[Rabbit, Hare]),

ok = stop_app(Config, Rabbit),
{error, 69, Msg} = change_cluster_node_type(Config, Rabbit, ram),
?assertEqual(
match,
re:run(
Msg, "Feature `ram_node_type` is deprecated",
[{capture, none}])),

ok = change_cluster_node_type(Config, Rabbit, disc),
ok = start_app(Config, Rabbit),
assert_cluster_status({[Rabbit, Hare], [Rabbit, Hare], [Rabbit, Hare]},
[Rabbit, Hare]).

change_cluster_when_node_offline(Config) ->
[Rabbit, Hare, Bunny] = cluster_members(Config),

Expand Down Expand Up @@ -942,8 +840,14 @@ classic_config_discovery_node_list(Config) ->
ok = rpc:call(Hare, application, set_env,
[rabbit, cluster_nodes, {[Rabbit], ram}]),
ok = start_app(Config, Hare),
assert_cluster_status({[Rabbit, Hare], [Rabbit], [Rabbit, Hare]},
[Rabbit, Hare]),
%% 4.2 nodes can still be RAM. 4.3+ nodes can't.
case rabbit_ct_helpers:is_mixed_versions() of
true ->
assert_cluster_status({[Rabbit, Hare], [Rabbit], [Rabbit, Hare]},
[Rabbit, Hare]);
false ->
assert_clustered([Rabbit, Hare])
end,

%% List of nodes [node()] is equivalent to {[node()], disk}
ok = stop_app(Config, Hare),
Expand Down Expand Up @@ -1281,15 +1185,7 @@ start_app(Config, Node) ->
end.

join_cluster(Config, Node, To) ->
join_cluster(Config, Node, To, false).

join_cluster(Config, Node, To, Ram) ->
Cmd = case Ram of
true ->
["join_cluster", "--ram", atom_to_list(To)];
false ->
["join_cluster", atom_to_list(To)]
end,
Cmd = ["join_cluster", atom_to_list(To)],
case rabbit_ct_broker_helpers:rabbitmqctl(Config, Node, Cmd) of
{ok, _} -> ok;
Error -> Error
Expand Down Expand Up @@ -1326,22 +1222,11 @@ forget_cluster_node(Config, Node, Removee, RemoveWhenOffline) ->
forget_cluster_node(Config, Node, Removee) ->
forget_cluster_node(Config, Node, Removee, false).

change_cluster_node_type(Config, Node, Type) ->
Ret = rabbit_ct_broker_helpers:rabbitmqctl(
Config, Node, ["change_cluster_node_type", atom_to_list(Type)]),
case Ret of
{ok, _} -> ok;
Error -> Error
end.

stop_join_start(Config, Node, ClusterTo, Ram) ->
stop_join_start(Config, Node, ClusterTo) ->
ok = stop_app(Config, Node),
ok = join_cluster(Config, Node, ClusterTo, Ram),
ok = join_cluster(Config, Node, ClusterTo),
ok = start_app(Config, Node).

stop_join_start(Config, Node, ClusterTo) ->
stop_join_start(Config, Node, ClusterTo, false).

stop_reset_start(Config, Node) ->
ok = stop_app(Config, Node),
ok = reset(Config, Node),
Expand Down
Loading
Loading