aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_admin.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejabberd_admin.erl')
-rw-r--r--src/ejabberd_admin.erl340
1 files changed, 261 insertions, 79 deletions
diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl
index ae2fac3e1..3e02e6bd0 100644
--- a/src/ejabberd_admin.erl
+++ b/src/ejabberd_admin.erl
@@ -5,7 +5,7 @@
%%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net>
%%%
%%%
-%%% ejabberd, Copyright (C) 2002-2016 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2019 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -26,13 +26,17 @@
-module(ejabberd_admin).
-author('mickael.remond@process-one.net').
--export([start/0, stop/0,
+-behaviour(gen_server).
+
+-export([start_link/0,
%% Server
status/0, reopen_log/0, rotate_log/0,
set_loglevel/1,
stop_kindly/2, send_service_message_all_mucs/2,
registered_vhosts/0,
reload_config/0,
+ dump_config/1,
+ convert_to_yaml/2,
%% Cluster
join_cluster/1, leave_cluster/1, list_cluster/0,
%% Erlang
@@ -48,23 +52,50 @@
set_master/1,
backup_mnesia/1, restore_mnesia/1,
dump_mnesia/1, dump_table/2, load_mnesia/1,
+ mnesia_info/0, mnesia_table_info/1,
install_fallback_mnesia/1,
dump_to_textfile/1, dump_to_textfile/2,
mnesia_change_nodename/4,
restore/1, % Still used by some modules
+ clear_cache/0,
+ gc/0,
get_commands_spec/0
]).
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
--include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_commands.hrl").
-start() ->
- ejabberd_commands:register_commands(get_commands_spec()).
+-record(state, {}).
+
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+init([]) ->
+ process_flag(trap_exit, true),
+ ejabberd_commands:register_commands(get_commands_spec()),
+ {ok, #state{}}.
+
+handle_call(Request, From, State) ->
+ ?WARNING_MSG("Unexpected call from ~p: ~p", [From, Request]),
+ {noreply, State}.
+
+handle_cast(Msg, State) ->
+ ?WARNING_MSG("Unexpected cast: ~p", [Msg]),
+ {noreply, State}.
-stop() ->
+handle_info(Info, State) ->
+ ?WARNING_MSG("Unexpected info: ~p", [Info]),
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
ejabberd_commands:unregister_commands(get_commands_spec()).
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
%%%
%%% ejabberd commands
%%%
@@ -76,6 +107,9 @@ get_commands_spec() ->
#ejabberd_commands{name = status, tags = [server],
desc = "Get status of the ejabberd server",
module = ?MODULE, function = status,
+ result_desc = "Result tuple",
+ result_example = {ok, <<"The node ejabberd@localhost is started with status: started"
+ "ejabberd X.X is running in that node">>},
args = [], result = {res, restuple}},
#ejabberd_commands{name = stop, tags = [server],
desc = "Stop ejabberd gracefully",
@@ -97,34 +131,40 @@ get_commands_spec() ->
#ejabberd_commands{name = stop_kindly, tags = [server],
desc = "Inform users and rooms, wait, and stop the server",
longdesc = "Provide the delay in seconds, and the "
- "announcement quoted, for example: \n"
- "ejabberdctl stop_kindly 60 "
- "\\\"The server will stop in one minute.\\\"",
+ "announcement quoted, for example: \n"
+ "ejabberdctl stop_kindly 60 "
+ "\\\"The server will stop in one minute.\\\"",
module = ?MODULE, function = stop_kindly,
+ args_desc = ["Seconds to wait", "Announcement to send, with quotes"],
+ args_example = [60, <<"Server will stop now.">>],
args = [{delay, integer}, {announcement, string}],
result = {res, rescode}},
#ejabberd_commands{name = get_loglevel, tags = [logs, server],
desc = "Get the current loglevel",
module = ejabberd_logger, function = get,
+ result_desc = "Tuple with the log level number, its keyword and description",
+ result_example = warning,
args = [],
- result = {leveltuple, {tuple, [{levelnumber, integer},
- {levelatom, atom},
- {leveldesc, string}
- ]}}},
+ result = {levelatom, atom}},
#ejabberd_commands{name = set_loglevel, tags = [logs, server],
- desc = "Set the loglevel (0 to 5)",
+ desc = "Set the loglevel",
module = ?MODULE, function = set_loglevel,
- args = [{loglevel, integer}],
- result = {logger, atom}},
+ args_desc = ["Desired logging level: none | emergency | alert | critical "
+ "| error | warning | notice | info | debug"],
+ args_example = [debug],
+ args = [{loglevel, string}],
+ result = {res, rescode}},
#ejabberd_commands{name = update_list, tags = [server],
desc = "List modified modules that can be updated",
module = ?MODULE, function = update_list,
args = [],
+ result_example = ["mod_configure", "mod_vcard"],
result = {modules, {list, {module, string}}}},
#ejabberd_commands{name = update, tags = [server],
desc = "Update the given module, or use the keyword: all",
module = ?MODULE, function = update,
+ args_example = ["mod_vcard"],
args = [{module, string}],
result = {res, restuple}},
@@ -132,25 +172,36 @@ get_commands_spec() ->
desc = "Register a user",
policy = admin,
module = ?MODULE, function = register,
+ args_desc = ["Username", "Local vhost served by ejabberd", "Password"],
+ args_example = [<<"bob">>, <<"example.com">>, <<"SomEPass44">>],
args = [{user, binary}, {host, binary}, {password, binary}],
result = {res, restuple}},
#ejabberd_commands{name = unregister, tags = [accounts],
desc = "Unregister a user",
+ policy = admin,
module = ?MODULE, function = unregister,
+ args_desc = ["Username", "Local vhost served by ejabberd"],
+ args_example = [<<"bob">>, <<"example.com">>],
args = [{user, binary}, {host, binary}],
result = {res, restuple}},
#ejabberd_commands{name = registered_users, tags = [accounts],
desc = "List all registered users in HOST",
module = ?MODULE, function = registered_users,
+ args_desc = ["Local vhost"],
+ args_example = [<<"example.com">>],
+ result_desc = "List of registered accounts usernames",
+ result_example = [<<"user1">>, <<"user2">>],
args = [{host, binary}],
result = {users, {list, {username, string}}}},
- #ejabberd_commands{name = registered_vhosts, tags = [server],
+ #ejabberd_commands{name = registered_vhosts, tags = [server],
desc = "List all registered vhosts in SERVER",
module = ?MODULE, function = registered_vhosts,
+ result_desc = "List of available vhosts",
+ result_example = [<<"example.com">>, <<"anon.example.com">>],
args = [],
result = {vhosts, {list, {vhost, string}}}},
- #ejabberd_commands{name = reload_config, tags = [server],
- desc = "Reload config file in memory (only affects ACL and Access)",
+ #ejabberd_commands{name = reload_config, tags = [server, config],
+ desc = "Reload config file in memory",
module = ?MODULE, function = reload_config,
args = [],
result = {res, rescode}},
@@ -158,61 +209,95 @@ get_commands_spec() ->
#ejabberd_commands{name = join_cluster, tags = [cluster],
desc = "Join this node into the cluster handled by Node",
module = ?MODULE, function = join_cluster,
+ args_desc = ["Nodename of the node to join"],
+ args_example = [<<"ejabberd1@machine7">>],
args = [{node, binary}],
result = {res, rescode}},
#ejabberd_commands{name = leave_cluster, tags = [cluster],
- desc = "Remove node handled by Node from the cluster",
+ desc = "Remove and shutdown Node from the running cluster",
+ longdesc = "This command can be run from any running node of the cluster, "
+ "even the node to be removed.",
module = ?MODULE, function = leave_cluster,
+ args_desc = ["Nodename of the node to kick from the cluster"],
+ args_example = [<<"ejabberd1@machine8">>],
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,
+ result_example = [ejabberd1@machine7, ejabberd1@machine8],
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,
+ args_desc = ["Full path to the jabberd14 spool file"],
+ args_example = ["/var/lib/ejabberd/jabberd14.spool"],
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = import_dir, tags = [mnesia],
desc = "Import users data from jabberd14 spool dir",
module = ?MODULE, function = import_dir,
+ args_desc = ["Full path to the jabberd14 spool directory"],
+ args_example = ["/var/lib/ejabberd/jabberd14/"],
args = [{file, string}],
result = {res, restuple}},
-
#ejabberd_commands{name = import_piefxis, tags = [mnesia],
desc = "Import users data from a PIEFXIS file (XEP-0227)",
module = ejabberd_piefxis, function = import_file,
+ args_desc = ["Full path to the PIEFXIS file"],
+ args_example = ["/var/lib/ejabberd/example.com.xml"],
args = [{file, string}], result = {res, rescode}},
#ejabberd_commands{name = export_piefxis, tags = [mnesia],
desc = "Export data of all users in the server to PIEFXIS files (XEP-0227)",
module = ejabberd_piefxis, function = export_server,
+ args_desc = ["Full path to a directory"],
+ args_example = ["/var/lib/ejabberd/"],
args = [{dir, string}], result = {res, rescode}},
#ejabberd_commands{name = export_piefxis_host, tags = [mnesia],
desc = "Export data of users in a host to PIEFXIS files (XEP-0227)",
module = ejabberd_piefxis, function = export_host,
+ args_desc = ["Full path to a directory", "Vhost to export"],
+ args_example = ["/var/lib/ejabberd/", "example.com"],
args = [{dir, string}, {host, string}], result = {res, rescode}},
#ejabberd_commands{name = delete_mnesia, tags = [mnesia, sql],
- desc = "Export all tables as SQL queries to a file",
+ desc = "Delete elements in Mnesia database for a given vhost",
module = ejd2sql, function = delete,
+ args_desc = ["Vhost which content will be deleted in Mnesia database"],
+ args_example = ["example.com"],
args = [{host, string}], result = {res, rescode}},
#ejabberd_commands{name = convert_to_scram, tags = [sql],
desc = "Convert the passwords in 'users' ODBC table to SCRAM",
module = ejabberd_auth_sql, function = convert_to_scram,
+ args_desc = ["Vhost which users' passwords will be scrammed"],
+ args_example = ["example.com"],
args = [{host, binary}], result = {res, rescode}},
- #ejabberd_commands{name = import_prosody, tags = [mnesia, sql, riak],
+ #ejabberd_commands{name = import_prosody, tags = [mnesia, sql],
desc = "Import data from Prosody",
+ longdesc = "Note: this method requires ejabberd compiled with optional tools support "
+ "and package must provide optional luerl dependency.",
module = prosody2ejabberd, function = from_dir,
+ args_desc = ["Full path to the Prosody data directory"],
+ args_example = ["/var/lib/prosody/datadump/"],
args = [{dir, string}], result = {res, rescode}},
#ejabberd_commands{name = convert_to_yaml, tags = [config],
desc = "Convert the input file from Erlang to YAML format",
- module = ejabberd_config, function = convert_to_yaml,
+ module = ?MODULE, function = convert_to_yaml,
+ args_desc = ["Full path to the original configuration file", "And full path to final file"],
+ args_example = ["/etc/ejabberd/ejabberd.cfg", "/etc/ejabberd/ejabberd.yml"],
args = [{in, string}, {out, string}],
result = {res, rescode}},
+ #ejabberd_commands{name = dump_config, tags = [config],
+ desc = "Dump configuration in YAML format as seen by ejabberd",
+ module = ?MODULE, function = dump_config,
+ args_desc = ["Full path to output file"],
+ args_example = ["/tmp/ejabberd.yml"],
+ args = [{out, string}],
+ result = {res, rescode}},
#ejabberd_commands{name = delete_expired_messages, tags = [purge],
desc = "Delete expired offline messages from database",
@@ -221,11 +306,16 @@ get_commands_spec() ->
#ejabberd_commands{name = delete_old_messages, tags = [purge],
desc = "Delete offline messages older than DAYS",
module = ?MODULE, function = delete_old_messages,
+ args_desc = ["Number of days"],
+ args_example = [31],
args = [{days, integer}], result = {res, rescode}},
#ejabberd_commands{name = export2sql, tags = [mnesia],
- desc = "Export virtual host information from Mnesia tables to SQL files",
+ desc = "Export virtual host information from Mnesia tables to SQL file",
+ longdesc = "Configure the modules to use SQL, then call this command.",
module = ejd2sql, function = export,
+ args_desc = ["Vhost", "Full path to the destination SQL file"],
+ args_example = ["example.com", "/var/lib/ejabberd/example.com.sql"],
args = [{host, string}, {file, string}],
result = {res, rescode}},
#ejabberd_commands{name = set_master, tags = [mnesia],
@@ -233,37 +323,73 @@ get_commands_spec() ->
longdesc = "If you provide as nodename \"self\", this "
"node will be set as its own master.",
module = ?MODULE, function = set_master,
+ args_desc = ["Name of the erlang node that will be considered master of this node"],
+ args_example = ["ejabberd@machine7"],
args = [{nodename, string}], result = {res, restuple}},
#ejabberd_commands{name = mnesia_change_nodename, tags = [mnesia],
desc = "Change the erlang node name in a backup file",
module = ?MODULE, function = mnesia_change_nodename,
+ args_desc = ["Name of the old erlang node", "Name of the new node",
+ "Path to old backup file", "Path to the new backup file"],
+ args_example = ["ejabberd@machine1", "ejabberd@machine2",
+ "/var/lib/ejabberd/old.backup", "/var/lib/ejabberd/new.backup"],
args = [{oldnodename, string}, {newnodename, string},
{oldbackup, string}, {newbackup, string}],
result = {res, restuple}},
#ejabberd_commands{name = backup, tags = [mnesia],
desc = "Store the database to backup file",
module = ?MODULE, function = backup_mnesia,
+ args_desc = ["Full path for the destination backup file"],
+ args_example = ["/var/lib/ejabberd/database.backup"],
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = restore, tags = [mnesia],
desc = "Restore the database from backup file",
module = ?MODULE, function = restore_mnesia,
+ args_desc = ["Full path to the backup file"],
+ args_example = ["/var/lib/ejabberd/database.backup"],
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = dump, tags = [mnesia],
- desc = "Dump the database to text file",
+ desc = "Dump the database to a text file",
module = ?MODULE, function = dump_mnesia,
+ args_desc = ["Full path for the text file"],
+ args_example = ["/var/lib/ejabberd/database.txt"],
args = [{file, string}], result = {res, restuple}},
#ejabberd_commands{name = dump_table, tags = [mnesia],
- desc = "Dump a table to text file",
+ desc = "Dump a table to a text file",
module = ?MODULE, function = dump_table,
+ args_desc = ["Full path for the text file", "Table name"],
+ args_example = ["/var/lib/ejabberd/table-muc-registered.txt", "muc_registered"],
args = [{file, string}, {table, string}], result = {res, restuple}},
#ejabberd_commands{name = load, tags = [mnesia],
- desc = "Restore the database from text file",
+ desc = "Restore the database from a text file",
module = ?MODULE, function = load_mnesia,
+ args_desc = ["Full path to the text file"],
+ args_example = ["/var/lib/ejabberd/database.txt"],
args = [{file, string}], result = {res, restuple}},
+ #ejabberd_commands{name = mnesia_info, tags = [mnesia],
+ desc = "Dump info on global Mnesia state",
+ module = ?MODULE, function = mnesia_info,
+ args = [], result = {res, string}},
+ #ejabberd_commands{name = mnesia_table_info, tags = [mnesia],
+ desc = "Dump info on Mnesia table state",
+ module = ?MODULE, function = mnesia_table_info,
+ args_desc = ["Mnesia table name"],
+ args_example = ["roster"],
+ args = [{table, string}], result = {res, string}},
#ejabberd_commands{name = install_fallback, tags = [mnesia],
desc = "Install the database from a fallback file",
module = ?MODULE, function = install_fallback_mnesia,
- args = [{file, string}], result = {res, restuple}}
+ args_desc = ["Full path to the fallback file"],
+ args_example = ["/var/lib/ejabberd/database.fallback"],
+ args = [{file, string}], result = {res, restuple}},
+ #ejabberd_commands{name = clear_cache, tags = [server],
+ desc = "Clear database cache on all nodes",
+ module = ?MODULE, function = clear_cache,
+ args = [], result = {res, rescode}},
+ #ejabberd_commands{name = gc, tags = [server],
+ desc = "Force full garbage collection",
+ module = ?MODULE, function = gc,
+ args = [], result = {res, rescode}}
].
@@ -280,37 +406,43 @@ status() ->
false ->
{ejabberd_not_running, "ejabberd is not running in that node."};
{value, {_, _, Version}} ->
- {ok, io_lib:format("ejabberd ~s is running in that node", [Version])}
+ {ok, io_lib:format("ejabberd ~ts is running in that node", [Version])}
end,
{Is_running, String1 ++ String2}.
reopen_log() ->
- ejabberd_hooks:run(reopen_log_hook, []),
- ejabberd_logger:reopen_log().
+ ejabberd_hooks:run(reopen_log_hook, []).
rotate_log() ->
- ejabberd_hooks:run(rotate_log_hook, []),
- ejabberd_logger:rotate_log().
+ ejabberd_hooks:run(rotate_log_hook, []).
set_loglevel(LogLevel) ->
- {module, Module} = ejabberd_logger:set(LogLevel),
- Module.
-
+ try binary_to_existing_atom(iolist_to_binary(LogLevel), latin1) of
+ Level ->
+ case lists:member(Level, ejabberd_logger:loglevels()) of
+ true ->
+ ejabberd_logger:set(Level);
+ false ->
+ {error, "Invalid log level"}
+ end
+ catch _:_ ->
+ {error, "Invalid log level"}
+ end.
%%%
%%% Stop Kindly
%%%
stop_kindly(DelaySeconds, AnnouncementTextString) ->
- Subject = list_to_binary(io_lib:format("Server stop in ~p seconds!", [DelaySeconds])),
- WaitingDesc = list_to_binary(io_lib:format("Waiting ~p seconds", [DelaySeconds])),
+ Subject = (str:format("Server stop in ~p seconds!", [DelaySeconds])),
+ WaitingDesc = (str:format("Waiting ~p seconds", [DelaySeconds])),
AnnouncementText = list_to_binary(AnnouncementTextString),
Steps = [
{"Stopping ejabberd port listeners",
ejabberd_listener, stop_listeners, []},
{"Sending announcement to connected users",
mod_announce, send_announcement_to_all,
- [?MYNAME, Subject, AnnouncementText]},
+ [ejabberd_config:get_myname(), Subject, AnnouncementText]},
{"Sending service message to MUC rooms",
ejabberd_admin, send_service_message_all_mucs,
[Subject, AnnouncementText]},
@@ -318,7 +450,7 @@ stop_kindly(DelaySeconds, AnnouncementTextString) ->
{"Stopping ejabberd", application, stop, [ejabberd]},
{"Stopping Mnesia", mnesia, stop, []},
{"Stopping Erlang node", init, stop, []}
- ],
+ ],
NumberLast = length(Steps),
TimestampStart = calendar:datetime_to_gregorian_seconds({date(), time()}),
lists:foldl(
@@ -326,7 +458,7 @@ stop_kindly(DelaySeconds, AnnouncementTextString) ->
SecondsDiff =
calendar:datetime_to_gregorian_seconds({date(), time()})
- TimestampStart,
- io:format("[~p/~p ~ps] ~s... ",
+ io:format("[~p/~p ~ps] ~ts... ",
[NumberThis, NumberLast, SecondsDiff, Desc]),
Result = (catch apply(Mod, Func, Args)),
io:format("~p~n", [Result]),
@@ -337,15 +469,16 @@ stop_kindly(DelaySeconds, AnnouncementTextString) ->
ok.
send_service_message_all_mucs(Subject, AnnouncementText) ->
- Message = list_to_binary(
- io_lib:format("~s~n~s", [Subject, AnnouncementText])),
+ Message = str:format("~ts~n~ts", [Subject, AnnouncementText]),
lists:foreach(
fun(ServerHost) ->
- MUCHost = gen_mod:get_module_opt_host(
- ServerHost, mod_muc, <<"conference.@HOST@">>),
- mod_muc:broadcast_service_message(MUCHost, Message)
+ MUCHosts = gen_mod:get_module_opt_hosts(ServerHost, mod_muc),
+ lists:foreach(
+ fun(MUCHost) ->
+ mod_muc:broadcast_service_message(ServerHost, MUCHost, Message)
+ end, MUCHosts)
end,
- ?MYHOSTS).
+ ejabberd_option:hosts()).
%%%
%%% ejabberd_update
@@ -367,8 +500,8 @@ update_module(ModuleNameBin) when is_binary(ModuleNameBin) ->
update_module(ModuleNameString) ->
ModuleName = list_to_atom(ModuleNameString),
case ejabberd_update:update([ModuleName]) of
- {ok, _Res} -> {ok, []};
- {error, Reason} -> {error, Reason}
+ {ok, _Res} -> {ok, []};
+ {error, Reason} -> {error, Reason}
end.
%%%
@@ -376,34 +509,69 @@ update_module(ModuleNameString) ->
%%%
register(User, Host, Password) ->
- case ejabberd_auth:try_register(User, Host, Password) of
- {atomic, ok} ->
- {ok, io_lib:format("User ~s@~s successfully registered", [User, Host])};
- {atomic, exists} ->
- Msg = io_lib:format("User ~s@~s already registered", [User, Host]),
- {error, conflict, 10090, Msg};
- {error, Reason} ->
- String = io_lib:format("Can't register user ~s@~s at node ~p: ~p",
- [User, Host, node(), Reason]),
- {error, cannot_register, 10001, String}
+ case is_my_host(Host) of
+ true ->
+ case ejabberd_auth:try_register(User, Host, Password) of
+ ok ->
+ {ok, io_lib:format("User ~ts@~ts successfully registered", [User, Host])};
+ {error, exists} ->
+ Msg = io_lib:format("User ~ts@~ts already registered", [User, Host]),
+ {error, conflict, 10090, Msg};
+ {error, Reason} ->
+ String = io_lib:format("Can't register user ~ts@~ts at node ~p: ~ts",
+ [User, Host, node(),
+ mod_register:format_error(Reason)]),
+ {error, cannot_register, 10001, String}
+ end;
+ false ->
+ {error, cannot_register, 10001, "Unknown virtual host"}
end.
unregister(User, Host) ->
- ejabberd_auth:remove_user(User, Host),
- {ok, ""}.
+ case is_my_host(Host) of
+ true ->
+ ejabberd_auth:remove_user(User, Host),
+ {ok, ""};
+ false ->
+ {error, "Unknown virtual host"}
+ end.
registered_users(Host) ->
- Users = ejabberd_auth:get_vh_registered_users(Host),
- SUsers = lists:sort(Users),
- lists:map(fun({U, _S}) -> U end, SUsers).
+ case is_my_host(Host) of
+ true ->
+ Users = ejabberd_auth:get_users(Host),
+ SUsers = lists:sort(Users),
+ lists:map(fun({U, _S}) -> U end, SUsers);
+ false ->
+ {error, "Unknown virtual host"}
+ end.
registered_vhosts() ->
- ?MYHOSTS.
+ ejabberd_option:hosts().
reload_config() ->
- ejabberd_config:reload_file(),
- acl:start(),
- shaper:start().
+ case ejabberd_config:reload() of
+ ok -> {ok, ""};
+ Err ->
+ Reason = ejabberd_config:format_error(Err),
+ {error, Reason}
+ end.
+
+dump_config(Path) ->
+ case ejabberd_config:dump(Path) of
+ ok -> {ok, ""};
+ Err ->
+ Reason = ejabberd_config:format_error(Err),
+ {error, Reason}
+ end.
+
+convert_to_yaml(In, Out) ->
+ case ejabberd_config:convert_to_yaml(In, Out) of
+ ok -> {ok, ""};
+ Err ->
+ Reason = ejabberd_config:format_error(Err),
+ {error, Reason}
+ end.
%%%
%%% Cluster management
@@ -442,7 +610,6 @@ import_dir(Path) ->
{cannot_import_dir, String}
end.
-
%%%
%%% Purge DB
%%%
@@ -451,13 +618,13 @@ delete_expired_messages() ->
lists:foreach(
fun(Host) ->
{atomic, ok} = mod_offline:remove_expired_messages(Host)
- end, ?MYHOSTS).
+ end, ejabberd_option:hosts()).
delete_old_messages(Days) ->
lists:foreach(
fun(Host) ->
{atomic, _} = mod_offline:remove_old_messages(Days, Host)
- end, ?MYHOSTS).
+ end, ejabberd_option:hosts()).
%%%
%%% Mnesia management
@@ -491,10 +658,6 @@ restore_mnesia(Path) ->
case ejabberd_admin:restore(Path) of
{atomic, _} ->
{ok, ""};
- {error, Reason} ->
- String = io_lib:format("Can't restore backup from ~p at node ~p: ~p",
- [filename:absname(Path), node(), Reason]),
- {cannot_restore, String};
{aborted,{no_exists,Table}} ->
String = io_lib:format("Can't restore backup from ~p at node ~p: Table ~p does not exist.",
[filename:absname(Path), node(), Table]),
@@ -517,20 +680,19 @@ restore(Path) ->
%% Obsolete tables or tables created by module who are no longer used are not
%% restored and are ignored.
keep_tables() ->
- lists:flatten([acl, passwd, config, local_config,
+ lists:flatten([acl, passwd, config,
keep_modules_tables()]).
%% Returns the list of modules tables in use, according to the list of actually
%% loaded modules
keep_modules_tables() ->
lists:map(fun(Module) -> module_tables(Module) end,
- gen_mod:loaded_modules(?MYNAME)).
+ gen_mod:loaded_modules(ejabberd_config:get_myname())).
%% TODO: This mapping should probably be moved to a callback function in each
%% module.
%% Mapping between modules and their tables
module_tables(mod_announce) -> [motd, motd_users];
-module_tables(mod_irc) -> [irc_custom];
module_tables(mod_last) -> [last_activity];
module_tables(mod_muc) -> [muc_room, muc_registered];
module_tables(mod_offline) -> [offline_msg];
@@ -610,6 +772,13 @@ load_mnesia(Path) ->
{cannot_load, String}
end.
+mnesia_info() ->
+ lists:flatten(io_lib:format("~p", [mnesia:system_info(all)])).
+
+mnesia_table_info(Table) ->
+ ATable = list_to_atom(Table),
+ lists:flatten(io_lib:format("~p", [mnesia:table_info(ATable, all)])).
+
install_fallback_mnesia(Path) ->
case mnesia:install_fallback(Path) of
ok ->
@@ -665,3 +834,16 @@ mnesia_change_nodename(FromString, ToString, Source, Target) ->
{[Other], Acc}
end,
mnesia:traverse_backup(Source, Target, Convert, switched).
+
+clear_cache() ->
+ Nodes = ejabberd_cluster:get_nodes(),
+ lists:foreach(fun(T) -> ets_cache:clear(T, Nodes) end, ets_cache:all()).
+
+gc() ->
+ lists:foreach(fun erlang:garbage_collect/1, processes()).
+
+-spec is_my_host(binary()) -> boolean().
+is_my_host(Host) ->
+ try ejabberd_router:is_my_host(Host)
+ catch _:{invalid_domain, _} -> false
+ end.