summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_admin.erl31
-rw-r--r--src/ejabberd_cluster.erl51
2 files changed, 82 insertions, 0 deletions
diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl
index 2068f10c..c51a2754 100644
--- a/src/ejabberd_admin.erl
+++ b/src/ejabberd_admin.erl
@@ -33,6 +33,8 @@
stop_kindly/2, send_service_message_all_mucs/2,
registered_vhosts/0,
reload_config/0,
+ %% Cluster
+ join_cluster/1, leave_cluster/1, list_cluster/0,
%% Erlang
update_list/0, update/1,
%% Accounts
@@ -146,6 +148,22 @@ commands() ->
args = [],
result = {res, rescode}},
+ #ejabberd_commands{name = join_cluster, tags = [cluster],
+ desc = "Join this node into the cluster handled by Node",
+ module = ?MODULE, function = join_cluster,
+ args = [{node, binary}],
+ result = {res, rescode}},
+ #ejabberd_commands{name = leave_cluster, tags = [cluster],
+ desc = "Remove node handled by Node from the cluster",
+ module = ?MODULE, function = leave_cluster,
+ args = [{node, binary}],
+ result = {res, rescode}},
+ #ejabberd_commands{name = list_cluster, tags = [cluster],
+ desc = "List nodes that are part of the cluster handled by Node",
+ module = ?MODULE, function = list_cluster,
+ args = [],
+ result = {nodes, {list, {node, atom}}}},
+
#ejabberd_commands{name = import_file, tags = [mnesia],
desc = "Import user data from jabberd14 spool file",
module = ?MODULE, function = import_file,
@@ -374,6 +392,19 @@ reload_config() ->
shaper:start().
%%%
+%%% Cluster management
+%%%
+
+join_cluster(NodeBin) ->
+ ejabberd_cluster:join(list_to_atom(binary_to_list(NodeBin))).
+
+leave_cluster(NodeBin) ->
+ ejabberd_cluster:leave(list_to_atom(binary_to_list(NodeBin))).
+
+list_cluster() ->
+ ejabberd_cluster:get_nodes().
+
+%%%
%%% Migration management
%%%
diff --git a/src/ejabberd_cluster.erl b/src/ejabberd_cluster.erl
index 5c3a0fc5..eb523fee 100644
--- a/src/ejabberd_cluster.erl
+++ b/src/ejabberd_cluster.erl
@@ -27,6 +27,7 @@
%% API
-export([get_nodes/0, call/4, multicall/3, multicall/4]).
+-export([join/1, leave/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -51,3 +52,53 @@ multicall(Module, Function, Args) ->
multicall(Nodes, Module, Function, Args) ->
rpc:multicall(Nodes, Module, Function, Args, 5000).
+-spec join(node()) -> ok | {error, any()}.
+
+join(Node) ->
+ case {node(), net_adm:ping(Node)} of
+ {Node, _} ->
+ {error, {not_master, Node}};
+ {_, pong} ->
+ application:stop(ejabberd),
+ application:stop(mnesia),
+ mnesia:delete_schema([node()]),
+ application:start(mnesia),
+ mnesia:change_config(extra_db_nodes, [Node]),
+ mnesia:change_table_copy_type(schema, node(), disc_copies),
+ spawn(fun() ->
+ lists:foreach(fun(Table) ->
+ Type = call(Node, mnesia, table_info, [Table, storage_type]),
+ mnesia:add_table_copy(Table, node(), Type)
+ end, mnesia:system_info(tables)--[schema])
+ end),
+ application:start(ejabberd);
+ _ ->
+ {error, {no_ping, Node}}
+ end.
+
+-spec leave(node()) -> ok | {error, any()}.
+
+leave(Node) ->
+ case {node(), net_adm:ping(Node)} of
+ {Node, _} ->
+ Cluster = get_nodes()--[Node],
+ leave(Cluster, Node);
+ {_, pong} ->
+ rpc:call(Node, ?MODULE, leave, [Node], 10000);
+ {_, pang} ->
+ case mnesia:del_table_copy(schema, Node) of
+ {atomic, ok} -> ok;
+ {aborted, Reason} -> {error, Reason}
+ end
+ end.
+leave([], Node) ->
+ {error, {no_cluster, Node}};
+leave([Master|_], Node) ->
+ application:stop(ejabberd),
+ application:stop(mnesia),
+ call(Master, mnesia, del_table_copy, [schema, Node]),
+ spawn(fun() ->
+ mnesia:delete_schema([node()]),
+ erlang:halt(0)
+ end),
+ ok.