summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2014-10-24 16:12:39 +0100
committerSimon MacMullen <simon@rabbitmq.com>2014-10-24 16:12:39 +0100
commit5f718633f55a851b797283cc7ecdb523649b3570 (patch)
tree23dc70e48ab83c6db4dfd4746d39192e46dd90bd
parent3b5475471a491360d36bcac3da42c22aa5770ff9 (diff)
downloadrabbitmq-server-git-5f718633f55a851b797283cc7ecdb523649b3570.tar.gz
*Do* start epmd ourselves if we want to impersonate a node. And just allow net_kernel:start() to fail and catch the error later.
-rw-r--r--src/rabbit_cli.erl23
-rw-r--r--src/rabbit_control_main.erl10
-rw-r--r--src/rabbit_nodes.erl24
3 files changed, 41 insertions, 16 deletions
diff --git a/src/rabbit_cli.erl b/src/rabbit_cli.erl
index a946c12a16..58f40a3ce9 100644
--- a/src/rabbit_cli.erl
+++ b/src/rabbit_cli.erl
@@ -17,7 +17,8 @@
-module(rabbit_cli).
-include("rabbit_cli.hrl").
--export([main/3, name_type/0, parse_arguments/4]).
+-export([main/3, start_distribution/0, start_distribution/1,
+ parse_arguments/4]).
%%----------------------------------------------------------------------------
@@ -31,7 +32,8 @@
-spec(main/3 :: (fun (([string()], string()) -> parse_result()),
fun ((atom(), atom(), [any()], [any()]) -> any()),
atom()) -> no_return()).
--spec(name_type/0 :: () -> 'shortnames' | 'longnames').
+-spec(start_distribution/0 :: () -> {'ok', pid()} | {'error', any()}).
+-spec(start_distribution/1 :: (string()) -> {'ok', pid()} | {'error', any()}).
-spec(usage/1 :: (atom()) -> no_return()).
-spec(parse_arguments/4 ::
([{atom(), [{string(), optdef()}]} | atom()],
@@ -42,6 +44,7 @@
%%----------------------------------------------------------------------------
main(ParseFun, DoFun, UsageMod) ->
+ error_logger:tty(false),
{ok, [[NodeStr|_]|_]} = init:get_argument(nodename),
{Command, Opts, Args} =
case ParseFun(init:get_plain_arguments(), NodeStr) of
@@ -77,12 +80,6 @@ main(ParseFun, DoFun, UsageMod) ->
{'EXIT', {badarg, _}} ->
print_error("invalid parameter: ~p", [Args]),
usage(UsageMod);
- {error, {distribution_failed, _}} ->
- print_error(
- "Could not start distribution.~n"
- "The most likely reason is that epmd has not been started by~n"
- "the server. Make sure the server is running.~n", []),
- rabbit_misc:quit(2);
{error, {Problem, Reason}} when is_atom(Problem), is_binary(Reason) ->
%% We handle this common case specially to avoid ~p since
%% that has i18n issues
@@ -111,11 +108,11 @@ main(ParseFun, DoFun, UsageMod) ->
end.
start_distribution() ->
- CtlNodeName = rabbit_misc:format("rabbitmq-cli-~s", [os:getpid()]),
- case net_kernel:start([list_to_atom(CtlNodeName), name_type()]) of
- {ok, _} -> ok;
- {error, Reason} -> throw({error, {distribution_failed, Reason}})
- end.
+ start_distribution(list_to_atom(
+ rabbit_misc:format("rabbitmq-cli-~s", [os:getpid()]))).
+
+start_distribution(Name) ->
+ net_kernel:start([Name, name_type()]).
name_type() ->
case os:getenv("RABBITMQ_USE_LONGNAME") of
diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl
index e5a28b559d..5410185608 100644
--- a/src/rabbit_control_main.erl
+++ b/src/rabbit_control_main.erl
@@ -584,12 +584,18 @@ exit_loop(Port) ->
end.
become(BecomeNode) ->
+ %% We might not have started distribution if epmd was not running,
+ %% but we need it now even if we have to start epmd ourselves.
+ case erlang:is_alive() of
+ true -> ok;
+ false -> rabbit_nodes:ensure_epmd(),
+ rabbit_cli:start_distribution()
+ end,
case net_adm:ping(BecomeNode) of
pong -> exit({node_running, BecomeNode});
pang -> io:format(" * Impersonating node: ~s...", [BecomeNode]),
- error_logger:tty(false),
ok = net_kernel:stop(),
- {ok, _} = net_kernel:start([BecomeNode,rabbit_cli:name_type()]),
+ {ok, _} = rabbit_cli:start_distribution(BecomeNode),
io:format(" done~n", []),
Dir = mnesia:system_info(directory),
io:format(" * Mnesia directory : ~s~n", [Dir])
diff --git a/src/rabbit_nodes.erl b/src/rabbit_nodes.erl
index 7f7fcc3126..66d05428c6 100644
--- a/src/rabbit_nodes.erl
+++ b/src/rabbit_nodes.erl
@@ -18,7 +18,7 @@
-export([names/1, diagnostics/1, make/1, parts/1, cookie_hash/0,
is_running/2, is_process_running/2,
- cluster_name/0, set_cluster_name/1]).
+ cluster_name/0, set_cluster_name/1, ensure_epmd/0]).
-include_lib("kernel/include/inet.hrl").
@@ -41,6 +41,7 @@
-spec(is_process_running/2 :: (node(), atom()) -> boolean()).
-spec(cluster_name/0 :: () -> binary()).
-spec(set_cluster_name/1 :: (binary()) -> 'ok').
+-spec(ensure_epmd/0 :: () -> 'ok').
-endif.
@@ -77,6 +78,10 @@ diagnostics_node(Node) ->
{Name, Host} = parts(Node),
[{"~s:", [Node]} |
case names(Host) of
+ {error, address} ->
+ [{" * connection refused from epmd (port ~s) on ~s~n"
+ " - has the server started it?~n",
+ [epmd_port(), Host]}];
{error, Reason} ->
[{" * unable to connect to epmd (port ~s) on ~s: ~s~n",
[epmd_port(), Host, rabbit_misc:format_inet_error(Reason)]}];
@@ -197,3 +202,20 @@ cluster_name_default() ->
set_cluster_name(Name) ->
rabbit_runtime_parameters:set_global(cluster_name, Name).
+
+ensure_epmd() ->
+ {ok, Root} = init:get_argument(root),
+ {ok, Prog} = init:get_argument(progname),
+ ID = random:uniform(1000000000),
+ Port = open_port(
+ {spawn_executable, filename:join([Root, "bin", Prog])},
+ [{args, ["-sname", rabbit_misc:format("epmd-starter-~b", [ID]),
+ "-noshell", "-eval", "halt()."]},
+ exit_status, stderr_to_stdout, use_stdio]),
+ port_shutdown_loop(Port).
+
+port_shutdown_loop(Port) ->
+ receive
+ {Port, {exit_status, _Rc}} -> ok;
+ {Port, _} -> port_shutdown_loop(Port)
+ end.