diff options
| author | Gerhard Lazu <gerhard@users.noreply.github.com> | 2017-03-29 17:58:26 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-03-29 17:58:26 +0100 |
| commit | d2b155e0d3f8313905797a4e56a576e79d30c2fc (patch) | |
| tree | 97bf37c9012a1b894a1a15c5b1bbbfcb3d3d2eaa | |
| parent | 3c19685dcdeecbf64a67612627ac2208afaa3d38 (diff) | |
| parent | 6c00bf57485c42ec641f83d095d3daacc605b585 (diff) | |
| download | rabbitmq-server-git-d2b155e0d3f8313905797a4e56a576e79d30c2fc.tar.gz | |
Merge pull request #1166 from rabbitmq/rabbitmq-server-1162
Introduce rabbitmqctl shutdown command.
| -rw-r--r-- | src/rabbit_control_main.erl | 36 | ||||
| -rw-r--r-- | test/rabbitmqctl_shutdown_SUITE.erl | 104 |
2 files changed, 130 insertions, 10 deletions
diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl index d6bc81945e..a600ad5234 100644 --- a/src/rabbit_control_main.erl +++ b/src/rabbit_control_main.erl @@ -269,6 +269,22 @@ do_action(Command, Node, Args, Opts, Inform, Timeout) -> action(Command, Node, Args, Opts, Inform) end. +shutdown_node_and_wait_pid_to_stop(Node, Pid, Inform) -> + Inform("Shutting down RabbitMQ node ~p running at PID ~p", [Node, Pid]), + Res = call(Node, {rabbit, stop_and_halt, []}), + case Res of + ok -> wait_for_process_death(Pid); + _ -> ok + end, + Res. + +action(shutdown, Node, [], _Opts, Inform) -> + case rpc:call(Node, os, getpid, []) of + Pid when is_list(Pid) -> + shutdown_node_and_wait_pid_to_stop(Node, Pid, Inform); + Error -> Error + end; + action(stop, Node, Args, _Opts, Inform) -> Inform("Stopping and halting node ~p", [Node]), Res = call(Node, {rabbit, stop_and_halt, []}), @@ -290,14 +306,14 @@ action(start_app, Node, [], _Opts, Inform) -> action(reset, Node, [], _Opts, Inform) -> Inform("Resetting node ~p", [Node]), - require_mnesia_stopped(Node, + require_mnesia_stopped(Node, fun() -> call(Node, {rabbit_mnesia, reset, []}) end); action(force_reset, Node, [], _Opts, Inform) -> Inform("Forcefully resetting node ~p", [Node]), - require_mnesia_stopped(Node, + require_mnesia_stopped(Node, fun() -> call(Node, {rabbit_mnesia, force_reset, []}) end); @@ -309,21 +325,21 @@ action(join_cluster, Node, [ClusterNodeS], Opts, Inform) -> false -> disc end, Inform("Clustering node ~p with ~p", [Node, ClusterNode]), - require_mnesia_stopped(Node, + require_mnesia_stopped(Node, fun() -> rpc_call(Node, rabbit_mnesia, join_cluster, [ClusterNode, NodeType]) end); action(change_cluster_node_type, Node, ["ram"], _Opts, Inform) -> Inform("Turning ~p into a ram node", [Node]), - require_mnesia_stopped(Node, + require_mnesia_stopped(Node, fun() -> rpc_call(Node, rabbit_mnesia, change_cluster_node_type, [ram]) end); action(change_cluster_node_type, Node, [Type], _Opts, Inform) when Type =:= "disc" orelse Type =:= "disk" -> Inform("Turning ~p into a disc node", [Node]), - require_mnesia_stopped(Node, + require_mnesia_stopped(Node, fun() -> rpc_call(Node, rabbit_mnesia, change_cluster_node_type, [disc]) end); @@ -331,7 +347,7 @@ action(change_cluster_node_type, Node, [Type], _Opts, Inform) action(update_cluster_nodes, Node, [ClusterNodeS], _Opts, Inform) -> ClusterNode = list_to_atom(ClusterNodeS), Inform("Updating cluster nodes for ~p from ~p", [Node, ClusterNode]), - require_mnesia_stopped(Node, + require_mnesia_stopped(Node, fun() -> rpc_call(Node, rabbit_mnesia, update_cluster_nodes, [ClusterNode]) end); @@ -496,9 +512,9 @@ action(set_disk_free_limit, Node, ["mem_relative", Arg], _Opts, Inform) -> _ -> Arg end), Inform("Setting disk free limit on ~p to ~p of total RAM", [Node, Frac]), - rpc_call(Node, - rabbit_disk_monitor, - set_disk_free_limit, + rpc_call(Node, + rabbit_disk_monitor, + set_disk_free_limit, [{mem_relative, Frac}]); @@ -962,7 +978,7 @@ escape(Bin, IsEscaped) when is_binary(Bin) -> escape(L, false) when is_list(L) -> escape_char(lists:reverse(L), []); escape(L, true) when is_list(L) -> - L. + L. escape_char([$\\ | T], Acc) -> escape_char(T, [$\\, $\\ | Acc]); diff --git a/test/rabbitmqctl_shutdown_SUITE.erl b/test/rabbitmqctl_shutdown_SUITE.erl new file mode 100644 index 0000000000..6f681a697b --- /dev/null +++ b/test/rabbitmqctl_shutdown_SUITE.erl @@ -0,0 +1,104 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is GoPivotal, Inc. +%% Copyright (c) 2016 Pivotal Software, Inc. All rights reserved. +%% +-module(rabbitmqctl_shutdown_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("amqp_client/include/amqp_client.hrl"). + +-compile(export_all). + +all() -> + [ + {group, shutdown_running_node}%, + % {group, shutdown_not_running_node} + ]. + +groups() -> + StopTests = [ + shutdown_fails_if_unable_to_contact_node, + shutdown_fails_if_unable_to_stop + ], + [ + {shutdown_running_node, [], + % StopTests ++ + [shutdown_running_node_ok]}, + {shutdown_not_running_node, [], StopTests} + ]. + +init_per_suite(Config) -> + rabbit_ct_helpers:log_environment(), + rabbit_ct_helpers:run_setup_steps(Config). + +end_per_suite(Config) -> + rabbit_ct_helpers:run_teardown_steps(Config). + +init_per_group(shutdown_running_node, Config) -> + rabbit_ct_helpers:set_config(Config, [ + {rmq_nodename_suffix, ?MODULE}, + {need_start, true} + ]); +init_per_group(shutdown_not_running_node, Config) -> + rabbit_ct_helpers:set_config(Config, [ + {rmq_nodename_suffix, ?MODULE} + ]). + +end_per_group(shutdown_running_node, Config) -> + rabbit_ct_helpers:run_teardown_steps(Config, []); +end_per_group(shutdown_not_running_node, Config) -> + rabbit_ct_helpers:run_teardown_steps(Config, []). + +init_per_testcase(Testcase, Config0) -> + Config1 = case ?config(need_start, Config0) of + true -> + rabbit_ct_helpers:run_setup_steps(Config0, + rabbit_ct_broker_helpers:setup_steps() ++ + [fun save_node/1]); + _ -> + rabbit_ct_helpers:set_config(Config0, + [{node, non_existent_node@localhost}]) + end, + rabbit_ct_helpers:testcase_started(Config1, Testcase). + +end_per_testcase(Testcase, Config0) -> + Config1 = case ?config(need_start, Config0) of + true -> + rabbit_ct_helpers:run_teardown_steps(Config0, + rabbit_ct_broker_helpers:teardown_steps()); + _ -> Config0 + end, + rabbit_ct_helpers:testcase_finished(Config1, Testcase). + +save_node(Config) -> + Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename), + rabbit_ct_helpers:set_config(Config, [{node, Node}]). + +shutdown_running_node_ok(Config) -> + Node = ?config(node, Config), + Pid = node_pid(Node), + ok = rabbit_control_main:action(shutdown, Node, [], [], fun ct:pal/2), + false = erlang_pid_is_running(Pid), + false = node_is_running(Node). + +node_pid(Node) -> + Val = rpc:call(Node, os, getpid, []), + true = is_list(Val), + list_to_integer(Val). + +erlang_pid_is_running(Pid) -> + rabbit_misc:is_os_process_alive(integer_to_list(Pid)). + +node_is_running(Node) -> + net_adm:ping(Node) == pong. |
