summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rabbit_mnesia.erl80
-rw-r--r--src/rabbit_node_monitor.erl36
2 files changed, 86 insertions, 30 deletions
diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl
index a67c0fe9ad..5cfdd5e05c 100644
--- a/src/rabbit_mnesia.erl
+++ b/src/rabbit_mnesia.erl
@@ -125,14 +125,37 @@ prepare() ->
init() ->
ensure_mnesia_running(),
ensure_mnesia_dir(),
- DiscNode = is_disc_node(),
- init_db_and_upgrade(all_clustered_nodes(), DiscNode, DiscNode),
+ case is_virgin_node() of
+ true -> init_from_config();
+ false -> normal_init(is_disc_node(), all_clustered_nodes())
+ end,
%% We intuitively expect the global name server to be synced when
%% Mnesia is up. In fact that's not guaranteed to be the case - let's
%% make it so.
ok = global:sync(),
ok.
+normal_init(DiscNode, AllNodes) ->
+ DiscNode = is_disc_node(),
+ init_db_and_upgrade(AllNodes, DiscNode, DiscNode).
+
+init_from_config() ->
+ {ok, {TryNodes, DiscNode}} =
+ application:get_env(rabbit, cluster_nodes),
+ case find_good_node(TryNodes -- [node()]) of
+ {ok, Node} ->
+ rabbit_log:info("Node '~p' selected for clustering from "
+ "configuration~n", [Node]),
+ {ok, {_, DiscNodes, _}} = discover_cluster(Node),
+ init_db_and_upgrade(DiscNodes, DiscNode, false),
+ rabbit_node_monitor:notify_joined_cluster();
+ none ->
+ rabbit_log:warning("Could not find any suitable node amongst the "
+ "ones provided in the configuration: ~p~n",
+ [TryNodes]),
+ normal_init(DiscNode, [node()])
+ end.
+
%% Make the node join a cluster. The node will be reset automatically before we
%% actually cluster it. The nodes provided will be used to find out about the
%% nodes in the cluster.
@@ -428,10 +451,10 @@ running_clustered_disc_nodes() ->
mnesia_nodes() ->
case mnesia:system_info(is_running) of
no -> {error, mnesia_not_running};
- yes -> %% If the tables are not present, it means that `init_db/3' hasn't
- %% been run yet. In other words, either we are a virgin node or a
- %% restarted RAM node. In both cases we're not interested in what
- %% mnesia has to say.
+ yes -> %% If the tables are not present, it means that `init_db/3'
+ %% hasn't been run yet. In other words, either we are a virgin
+ %% node or a restarted RAM node. In both cases we're not
+ %% interested in what mnesia has to say.
IsDiscNode = mnesia:system_info(use_dir),
Tables = mnesia:system_info(tables),
{Table, _} = case table_definitions(case IsDiscNode of
@@ -690,10 +713,8 @@ check_cluster_consistency() ->
{error, Error};
{OTP, Rabbit, Res} ->
rabbit_misc:sequence_error(
- [check_version_consistency(
- erlang:system_info(otp_release), OTP, "OTP"),
- check_version_consistency(
- rabbit_misc:version(), Rabbit, "Rabbit"),
+ [check_otp_consistency(OTP),
+ check_rabbit_consistency(Rabbit),
case Res of
{ok, Status} ->
check_nodes_consistency(Node, Status);
@@ -701,8 +722,7 @@ check_cluster_consistency() ->
{error, Error}
end])
end;
- (_Node, {ok, Status}) ->
- {ok, Status}
+ (_Node, {ok, Status}) -> {ok, Status}
end, {error, no_nodes}, AllNodes)
of
{ok, Status = {RemoteAllNodes, _, _}} ->
@@ -1130,3 +1150,39 @@ check_version_consistency(This, Remote, Name) ->
{error, {inconsistent_cluster,
rabbit_misc:format("~s version mismatch: local node is ~s, "
"remote node ~s", [Name, This, Remote])}}.
+
+check_otp_consistency(Remote) ->
+ check_version_consistency(erlang:system_info(otp_release), Remote, "OTP").
+
+check_rabbit_consistency(Remote) ->
+ check_version_consistency(rabbit_misc:version(), Remote, "Rabbit").
+
+%% This is fairly tricky. We want to know if the node is in the state that a
+%% `reset' would leave it in. We cannot simply check if the mnesia tables
+%% aren't there because restarted RAM nodes won't have tables while still being
+%% non-virgin. What we do instead is to check if the mnesia directory is non
+%% existant or empty, with the exception of the cluster status file, which will
+%% be there thanks to `rabbit_node_monitor:prepare_cluster_status_file/0'.
+is_virgin_node() ->
+ case rabbit_file:list_dir(dir()) of
+ {error, enoent} -> true;
+ {ok, []} -> true;
+ {ok, [File]} -> (dir() ++ "/" ++ File) =:=
+ rabbit_node_monitor:cluster_status_file_name();
+ {ok, Files} -> false
+ end.
+
+find_good_node([]) ->
+ none;
+find_good_node([Node | Nodes]) ->
+ case rpc:call(Node, rabbit_mnesia, node_info, []) of
+ {badrpc, _Reason} ->
+ find_good_node(Nodes);
+ {OTP, Rabbit, _} ->
+ case rabbit_misc:sequence_error([check_otp_consistency(OTP),
+ check_rabbit_consistency(Rabbit)])
+ of
+ {error, _} -> find_good_node(Nodes);
+ ok -> {ok, Node}
+ end
+ end.
diff --git a/src/rabbit_node_monitor.erl b/src/rabbit_node_monitor.erl
index 849f5d3139..b2d1c11c82 100644
--- a/src/rabbit_node_monitor.erl
+++ b/src/rabbit_node_monitor.erl
@@ -18,7 +18,8 @@
-behaviour(gen_server).
--export([prepare_cluster_status_file/0,
+-export([cluster_status_file_name/0,
+ prepare_cluster_status_file/0,
write_cluster_status_file/1,
read_cluster_status_file/0,
update_cluster_status_file/0,
@@ -80,26 +81,27 @@
%% various situations. Obviously when mnesia is offline the information we have
%% will be outdated, but it can't be otherwise.
-cluster_status_file_filename() ->
+cluster_status_file_name() ->
rabbit_mnesia:dir() ++ "/cluster_nodes.config".
prepare_cluster_status_file() ->
NotPresent =
fun (AllNodes0, WantDiscNode) ->
- ThisNode = [node()],
+ ThisNode = [node()],
- RunningNodes0 = legacy_read_previously_running_nodes(),
- legacy_delete_previously_running_nodes(),
+ RunningNodes0 = legacy_read_previously_running_nodes(),
+ legacy_delete_previously_running_nodes(),
- RunningNodes = lists:usort(RunningNodes0 ++ ThisNode),
- AllNodes =
- lists:usort(AllNodes0 ++ RunningNodes),
- DiscNodes = case WantDiscNode of
- true -> ThisNode;
- false -> []
- end,
+ RunningNodes = lists:usort(RunningNodes0 ++ ThisNode),
+ AllNodes =
+ lists:usort(AllNodes0 ++ RunningNodes),
+ DiscNodes = case WantDiscNode of
+ true -> ThisNode;
+ false -> []
+ end,
- ok = write_cluster_status_file({AllNodes, DiscNodes, RunningNodes})
+ ok = write_cluster_status_file({AllNodes, DiscNodes,
+ RunningNodes})
end,
case try_read_cluster_status_file() of
{ok, _} ->
@@ -108,14 +110,12 @@ prepare_cluster_status_file() ->
%% Legacy file
NotPresent(AllNodes, legacy_should_be_disc_node(AllNodes));
{error, {cannot_read_file, _, enoent}} ->
- {ok, {AllNodes, WantDiscNode}} =
- application:get_env(rabbit, cluster_nodes),
- NotPresent(AllNodes, WantDiscNode)
+ NotPresent([], true)
end.
write_cluster_status_file(Status) ->
- FileName = cluster_status_file_filename(),
+ FileName = cluster_status_file_name(),
case rabbit_file:write_term_file(FileName, [Status]) of
ok -> ok;
{error, Reason} ->
@@ -124,7 +124,7 @@ write_cluster_status_file(Status) ->
end.
try_read_cluster_status_file() ->
- FileName = cluster_status_file_filename(),
+ FileName = cluster_status_file_name(),
case rabbit_file:read_term_file(FileName) of
{ok, [{_, _, _} = Status]} ->
{ok, Status};