Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mongoose service #1792

Merged
merged 15 commits into from
Apr 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions big_tests/tests/ejabberdctl_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ init_per_suite(Config) ->
CwdTokens = string:tokens(Cwd0, "/"),
Cwd = [$/ | string:join(lists:sublist(CwdTokens, 1, length(CwdTokens)-2), "/")],
TemplatePath = Cwd ++ "/roster.template",
start_mod_admin_extra(),
AuthMods = auth_modules(),
Node = mim(),
Config1 = ejabberd_node_utils:init(Node, Config),
Expand Down Expand Up @@ -1065,10 +1064,6 @@ fallback_timestamp(Days, {MegaSecs, Secs, _MicroSecs}) ->
{MegaSecs1, Secs1, 0}.


start_mod_admin_extra() ->
Domain = ct:get_config({hosts, mim, domain}),
{ok, _} = dynamic_modules:restart(Domain, mod_admin_extra, []).

get_user_data(User, Config) when is_atom(User) ->
get_user_data(escalus_users:get_options(Config, User, <<"newres">>), Config);
get_user_data(User, _Config) ->
Expand Down
7 changes: 7 additions & 0 deletions doc/Advanced-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,13 @@ For a specific configuration, please refer to [Modules](advanced-configuration/M
* **modules** (local)
* **Description:** List of enabled modules with their options.

### Services

For a specific configuration, please refer to [Services](advanced-configuration/Services.md) page.

* **services** (local)
* **Description:** List of enabled services with their options.

### Per-domain configuration

The `host_config` allows configuring most options separately for specific domains served by the cluster. It is best to put `host_config` tuple right after the global section it overrides/complements or even at the end of `ejabberd.cfg`.
Expand Down
3 changes: 0 additions & 3 deletions doc/advanced-configuration/Modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ Valid values: `no_queue`, `one_queue`, `{queues, N}`, `parallel`. Default: `one_
Implements [XEP-0050: Ad-Hoc Commands](http://xmpp.org/extensions/xep-0050.html) for advertising and executing application-specific commands, such as those related to a configuration workflow, using [XEP-0004: Data Forms](http://xmpp.org/extensions/xep-0004.html) in order to structure the information exchange.
This is extremely useful for use cases such as remote administration, user engagement via polls, and ChatBots.

### [mod_admin_extra](../modules/mod_admin_extra.md)
Significantly extends the `mongooseimctl` script capabilities.

### [mod_amp](../modules/mod_amp.md)
Implements a subset of [XEP-0079: Advanced Message Processing](http://xmpp.org/extensions/xep-0079.html) functionality, that enables entities to request, and servers to perform advanced processing of XMPP message stanzas, including reliable data transport, time-sensitive delivery, and expiration of transient messages.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
### Module Description
This module significantly extends `mongooseimctl` script capabilities. New functionalities appear as additional commands. For detailed description, just run `mongooseimctl` script with no parameters.
Some functionalities in MongooseIM are provided by "services".
A service is similar to a module, but while a module is started for every virtual host and may have global or host-specific configuration, a service is started only once with global configuration.
Service configuration is similar to a module configuration, e.g.:
```
{services, [
{service_admin_extra, [{submods, [node, accounts, sessions]}]}
]
}.
```

### Options
* `submods` (default: all submodules): List of function groups added by `mod_admin_extra`. Allowed elements:

## Service list

As of version 2.2, only one module is a "service provider".
Eventually the modules which are not host-specific will be refactored to be services.

### service_admin_extra

Provides additional commands to mongooseimctl script.

#### Options
* `submods` (default: all submodules): List of function groups added by `service_admin_extra`. Allowed elements:
* `accounts`: Adds `change_password`, `check_password_hash`, `delete_old_users`, `delete_old_users_vhost`, `ban_account`, `num_active_users`, `check_account`, `check_password`
* `last`: Adds `set_last`
* `node`: Adds `load_config`, `get_cookie`, `remove_node`
Expand All @@ -14,4 +31,4 @@ This module significantly extends `mongooseimctl` script capabilities. New funct
* `vcard`: Adds `get_vcard`, `get_vcard2`, `get_vcard2_multi`, `set_vcard`, `set_vcard2`, `set_vcard2_multi`

### Example configuration
` {mod_admin_extra, [{submods, [node, accounts, sessions]}]} `
` {service_admin_extra, [{submods, [node, accounts, sessions]}]} `
2 changes: 0 additions & 2 deletions doc/user-guide/ICE_tutorial/ejabberd.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -722,8 +722,6 @@
%% {":domain.com", "/", "_", "http://localhost:8080/:domain"}]
%% }]},

%{mod_admin_extra, [{submods, [node, accounts, sessions, vcard,
% roster, last, private, stanza, stats]}]},

% {mod_http_upload, [
%% Set max file size in bytes. Defaults to 10 MB.
Expand Down
18 changes: 17 additions & 1 deletion doc/user-guide/MongooseIM-High-level-Architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,23 @@

### Modules

At its core MongooseIM is a huge message router you can customise to fit your system's needs. You can choose and enable behaviours and functionalities by configuring any of the available modules. A wide range of options includes authentication, privacy, storage, backend integration and mobile optimisations. See '[Extension Modules](../advanced-configuration/Modules.md)' for a full list.
At its core MongooseIM is a huge message router you can customise to fit your system's needs.
You can choose and enable behaviours and functionalities by configuring any of the available modules.
A wide range of options includes authentication, privacy, storage, backend integration and mobile optimisations.
See '[Extension Modules](../advanced-configuration/Modules.md)' for a full list.

Modules can be configured and started either for all virutal hosts served by the instance or with individual configuration for only some of them.
Modules may include dependencies on services and on other modules.
If a module depends on other modules, required modules are started automatically with configuration provided by the dependent module.
If a module requires certain services which are not started, the module refuses to start.

### Services

Services provide certain functionalities not specific to virtual hosts but rather applied to the whole instance or to modules started for various hosts.
They are configured globally and launched on startup, before modules, so that dependencies are satisfied.
A service can require other services to be operational; required services are started automatically.
The required service must also be present in the server's configuration file.
They were introduced in MongooseIM 2.2; modules which are not host-specific are gradually being refactored as services.

### Databases

Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pages:
- 'Extension Modules': 'advanced-configuration/Modules.md'
- 'Listener Modules': 'advanced-configuration/Listener-modules.md'
- 'ACL': 'advanced-configuration/acl.md'
- 'Services': 'advanced-configuration/Services.md'
- 'Authentication backends':
- 'External Authentication Module': 'authentication-backends/External-authentication-module.md'
- 'HTTP Authentication Module': 'authentication-backends/HTTP-authentication-module.md'
Expand Down
19 changes: 15 additions & 4 deletions rel/files/ejabberd.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -686,11 +686,25 @@

{all_metrics_are_global, {{{all_metrics_are_global}}} }.

%%%. ========
%%%' SERVICES

%% Unlike modules, services are started per node and provide either features which are not
%% related to any particular host, or backend stuff which is used by modules.
%% This is handled by `mongoose_service` module.

{services,
[
{service_admin_extra, [{submods, [node, accounts, sessions, vcard,
roster, last, private, stanza, stats]}]}
]
}.

%%%. =======
%%%' MODULES

%%
%% Modules enabled in all ejabberd virtual hosts.
%% Modules enabled in all mongooseim virtual hosts.
%% For list of possible modules options, check documentation.
%%
{modules,
Expand All @@ -715,9 +729,6 @@
%% {":domain.com", "/", "_", "http://localhost:8080/:domain"}]
%% }]},

%{mod_admin_extra, [{submods, [node, accounts, sessions, vcard,
% roster, last, private, stanza, stats]}]},

% {mod_http_upload, [
%% Set max file size in bytes. Defaults to 10 MB.
%% Disabled if value is `undefined`.
Expand Down
17 changes: 17 additions & 0 deletions src/ejabberd_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ start(normal, _Args) ->
ejabberd_commands:init(),
mongoose_commands:init(),
mongoose_subhosts:init(),
mongoose_service:start(),
gen_mod:start(),
ejabberd_config:start(),
ejabberd_check:config(),
Expand All @@ -67,6 +68,7 @@ start(normal, _Args) ->
%% Profiling
%%ejabberd_debug:eprof_start(),
%%ejabberd_debug:fprof_start(),
start_services(),
start_modules(),
mongoose_metrics:init(),
ejabberd_listener:start_listeners(),
Expand All @@ -83,6 +85,7 @@ prep_stop(State) ->
mongoose_deprecations:stop(),
ejabberd_listener:stop_listeners(),
stop_modules(),
stop_services(),
mongoose_subhosts:stop(),
broadcast_c2s_shutdown(),
timer:sleep(5000),
Expand Down Expand Up @@ -141,6 +144,20 @@ stop_modules() ->
end
end, ?MYHOSTS).

-spec start_services() -> ok.
start_services() ->
lists:foreach(
fun({Service, _}) -> mongoose_service:ensure_loaded(Service) end,
ejabberd_config:get_local_option_or_default(services, [])
).

-spec stop_services() -> ok.
stop_services() ->
lists:foreach(
fun({Service, _Options}) -> mongoose_service:stop_service(Service) end,
mongoose_service:loaded_services_with_opts()
).

-spec connect_nodes() -> 'ok'.
connect_nodes() ->
case ejabberd_config:get_local_option(cluster_nodes) of
Expand Down
2 changes: 2 additions & 0 deletions src/ejabberd_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ process_term(Term, State) ->
add_option(http_connections, HttpConnections, State);
{all_metrics_are_global, Value} ->
add_option(all_metrics_are_global, Value, State);
{services, Value} ->
add_option(services, Value, State);
{_Opt, _Val} ->
process_term_for_hosts_and_pools(Term, State)
end.
Expand Down
22 changes: 19 additions & 3 deletions src/gen_mod.erl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
-type dep_hardness() :: soft | hard.
-type deps_list() :: [
{module(), dep_arguments(), dep_hardness()} |
{module(), dep_hardness()}
{module(), dep_hardness()} |
{service, mongoose_service:service()}
].

-export_type([deps_list/0]).
Expand Down Expand Up @@ -67,6 +68,8 @@
is_loaded/2,
get_deps/3]).

-export([is_app_running/1]). % we have to mock it in some tests

-include("mongoose.hrl").

-record(ejabberd_module, {
Expand Down Expand Up @@ -116,6 +119,7 @@ start_module_for_host(Host, Module, Opts0) ->
set_module_opts_mnesia(Host, Module, Opts),
ets:insert(ejabberd_modules, #ejabberd_module{module_host = {Module, Host}, opts = Opts}),
try
lists:map(fun mongoose_service:assert_loaded/1, get_required_services(Host, Module, Opts)),
Res = Module:start(Host, Opts),
{links, LinksAfter} = erlang:process_info(self(), links),
case lists:sort(LinksBefore) =:= lists:sort(LinksAfter) of
Expand Down Expand Up @@ -144,11 +148,11 @@ start_module_for_host(Host, Module, Opts0) ->
[Module, Host, Opts, Class, Reason,
erlang:get_stacktrace()]),
?CRITICAL_MSG(ErrorText, []),
case is_app_running(mongooseim) of
case ?MODULE:is_app_running(mongooseim) of
true ->
erlang:raise(Class, Reason, erlang:get_stacktrace());
false ->
?CRITICAL_MSG("ejabberd initialization was aborted "
?CRITICAL_MSG("mongooseim initialization was aborted "
"because a module start failed.~n"
"The trace is ~p.", [erlang:get_stacktrace()]),
timer:sleep(3000),
Expand Down Expand Up @@ -439,3 +443,15 @@ get_deps(Host, Module, Opts) ->
_ ->
[]
end.

-spec get_required_services(jid:server(), module(), proplists:proplist()) -> [atom()].
get_required_services(Host, Module, Options) ->
%% the module has to be loaded,
%% otherwise the erlang:function_exported/3 returns false
code:ensure_loaded(Module),
case erlang:function_exported(Module, deps, 2) of
true ->
[Service || {service, Service} <- Module:deps(Host, Options)];
_ ->
[]
end.
4 changes: 3 additions & 1 deletion src/global_distrib/mod_global_distrib_hosts_refresher.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
-export([start_link/1]).

%% gen_server API
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

%% gen_mod API
-export([deps/2, start/2, stop/1]).
Expand Down Expand Up @@ -107,6 +107,8 @@ handle_info(Msg, _State) ->
terminate(Reason, _State) ->
?INFO_MSG("mod_global_distrib_refresher has terminated with reason: ~p", [Reason]).

code_change(_, State, _) -> {ok, State}.

%%--------------------------------------------------------------------
%% Helper functions
%%--------------------------------------------------------------------
Expand Down
Loading