summaryrefslogtreecommitdiff
path: root/src/rabbit_nodes.erl
blob: 329c07dc9f7c4cefd005deec730891c2487c8fe8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
%% 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 VMware, Inc.
%% Copyright (c) 2007-2012 VMware, Inc.  All rights reserved.
%%

-module(rabbit_nodes).

-export([names/1, diagnostics/1, make/1, parts/1, cookie_hash/0]).

-define(EPMD_TIMEOUT, 30000).

%%----------------------------------------------------------------------------
%% Specs
%%----------------------------------------------------------------------------

-ifdef(use_specs).

-spec(names/1 :: (string()) -> rabbit_types:ok_or_error2(
                                 [{string(), integer()}], term())).
-spec(diagnostics/1 :: ([node()]) -> string()).
-spec(make/1 :: ({string(), string()} | string()) -> node()).
-spec(parts/1 :: (node() | string()) -> {string(), string()}).
-spec(cookie_hash/0 :: () -> string()).

-endif.

%%----------------------------------------------------------------------------

names(Hostname) ->
    Self = self(),
    process_flag(trap_exit, true),
    Pid = spawn_link(fun () -> Self ! {names, net_adm:names(Hostname)} end),
    timer:exit_after(?EPMD_TIMEOUT, Pid, timeout),
    Res = receive
              {names, Names}        -> Names;
              {'EXIT', Pid, Reason} -> {error, Reason}
          end,
    process_flag(trap_exit, false),
    Res.

diagnostics(Nodes) ->
    Hosts = lists:usort([element(2, parts(Node)) || Node <- Nodes]),
    NodeDiags = [{"~nDIAGNOSTICS~n===========~n~n"
                  "nodes in question: ~p~n~n"
                  "hosts, their running nodes and ports:", [Nodes]}] ++
        [diagnostics_host(Host) || Host <- Hosts] ++
        diagnostics0(),
    lists:flatten([io_lib:format(F ++ "~n", A) || NodeDiag <- NodeDiags,
                                                  {F, A}   <- [NodeDiag]]).

diagnostics0() ->
    [{"~ncurrent node details:~n- node name: ~w", [node()]},
     case init:get_argument(home) of
         {ok, [[Home]]} -> {"- home dir: ~s", [Home]};
         Other          -> {"- no home dir: ~p", [Other]}
     end,
     {"- cookie hash: ~s", [cookie_hash()]}].

diagnostics_host(Host) ->
    case names(Host) of
        {error, EpmdReason} ->
            {"- unable to connect to epmd on ~s: ~w",
             [Host, EpmdReason]};
        {ok, NamePorts} ->
            {"- ~s: ~p",
             [Host, [{list_to_atom(Name), Port} ||
                        {Name, Port} <- NamePorts]]}
    end.

make({Prefix, Suffix}) -> list_to_atom(lists:append([Prefix, "@", Suffix]));
make(NodeStr)          -> make(parts(NodeStr)).

parts(Node) when is_atom(Node) ->
    parts(atom_to_list(Node));
parts(NodeStr) ->
    case lists:splitwith(fun (E) -> E =/= $@ end, NodeStr) of
        {Prefix, []}     -> {_, Suffix} = parts(node()),
                            {Prefix, Suffix};
        {Prefix, Suffix} -> {Prefix, tl(Suffix)}
    end.

cookie_hash() ->
    base64:encode_to_string(erlang:md5(atom_to_list(erlang:get_cookie()))).