aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2004-05-22 19:48:35 +0000
committerAlexey Shchepin <alexey@process-one.net>2004-05-22 19:48:35 +0000
commit0b4539caa1271e65e2dbe24d8ae8baba236af3d3 (patch)
treed2ecad40af001136eb143236dcd2bd46b0f54cec
parent* src/mod_muc/mod_muc.erl: Added access rules for using serveice (diff)
* src/web/ejabberd_http.erl: Added options for enabling HTTP
polling and admin interface * src/web/ejabberd_web.erl: Likewise * src/ejabberd.cfg.example: Updated * src/web/ejabberd_web_admin.erl: Updated * doc/guide.tex: Updated SVN Revision: 236
-rw-r--r--ChangeLog11
-rw-r--r--doc/guide.html86
-rw-r--r--doc/guide.tex89
-rw-r--r--src/ejabberd.cfg.example3
-rw-r--r--src/web/ejabberd_http.erl34
-rw-r--r--src/web/ejabberd_web.erl10
-rw-r--r--src/web/ejabberd_web_admin.erl153
7 files changed, 332 insertions, 54 deletions
diff --git a/ChangeLog b/ChangeLog
index 259d74839..ba3d43ae6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2004-05-22 Alexey Shchepin <alexey@sevcom.net>
+
+ * src/web/ejabberd_http.erl: Added options for enabling HTTP
+ polling and admin interface
+ * src/web/ejabberd_web.erl: Likewise
+ * src/ejabberd.cfg.example: Updated
+
+ * src/web/ejabberd_web_admin.erl: Updated
+
+ * doc/guide.tex: Updated
+
2004-05-17 Alexey Shchepin <alexey@sevcom.net>
* src/mod_muc/mod_muc.erl: Added access rules for using serveice
diff --git a/doc/guide.html b/doc/guide.html
index fe22bbd91..f139dac6a 100644
--- a/doc/guide.html
+++ b/doc/guide.html
@@ -455,11 +455,23 @@ The following options are defined:
<DT><CODE><B>ejabberd_service</B></CODE><DD> This module serves connections from Jabber
services (i.&nbsp;e. that use the <TT>jabber:component:accept</TT> namespace).
</DL>
-For example, the following configuration defines that C2S connections are
-listened on port 5222 and 5223 (SSL) and denied for user ``<TT>bad</TT>'', S2S
-on port 5269, and that service <TT>conference.example.org</TT> must be
-connected to port 8888 with a password ``<TT>secret</TT>''. Also all users
-except admins have traffic limit 1000&nbsp;b/s.
+For example, the following configuration defines that:
+<UL><LI>
+C2S connections are listened on port 5222 and 5223 (SSL) and denied for
+ user ``<TT>bad</TT>''
+<LI>S2S connections are listened on port 5269
+<LI>All users except admins have traffic limit 1000&nbsp;B/s
+<LI>AIM service <TT>aim.example.org</TT> is connected to port 5233 with
+ password ``<TT>aimsecret</TT>''
+<LI>JIT services <TT>icq.example.org</TT> and <TT>sms.example.org</TT> are
+ connected to port 5234 with password ``<TT>jitsecret</TT>''
+<LI>MSN service <TT>msn.example.org</TT> is connected to port 5235 with
+ password ``<TT>msnsecret</TT>''
+<LI>YAHOO service <TT>yahoo.example.org</TT> is connected to port 5236 with
+ password ``<TT>yahoosecret</TT>''
+<LI>ILE service <TT>ile.example.org</TT> is connected to port 5237 with
+ password ``<TT>ilesecret</TT>''
+</UL>
<PRE>
{acl, blocked, {user, "bad"}}.
{access, c2s, [{deny, blocked},
@@ -467,14 +479,62 @@ except admins have traffic limit 1000&nbsp;b/s.
{shaper, normal, {maxrate, 1000}}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
-{listen, [{5222, ejabberd_c2s, [{access, c2s},
- {shaper, c2s_shaper}]},
- {5223, ejabberd_c2s, [{access, c2s},
- {ssl, [{certfile, "/path/to/ssl.pem"}]}]},
- {5269, ejabberd_s2s_in, []},
- {8888, ejabberd_service,
- [{hosts, ["conference.example.org"], [{password, "secret"}]}]}
- ]}.
+{listen,
+ [{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]},
+ {5223, ejabberd_c2s, [{access, c2s},
+ ssl, {certfile, "/path/to/ssl.pem"}]},
+ {5269, ejabberd_s2s_in, []},
+ {5233, ejabberd_service, [{host, "aim.example.org",
+ [{password, "aimsecret"}]}]},
+ {5234, ejabberd_service, [{hosts, ["icq.example.org", "sms.example.org"],
+ [{password, "jitsecret"}]}]},
+ {5235, ejabberd_service, [{host, "msn.example.org",
+ [{password, "msnsecret"}]}]},
+ {5236, ejabberd_service, [{host, "yahoo.example.org",
+ [{password, "yahoosecret"}]}]},
+ {5237, ejabberd_service, [{host, "gg.example.org",
+ [{password, "ggsecret"}]}]},
+ {5238, ejabberd_service, [{host, "ile.example.org",
+ [{password, "ilesecret"}]}]}
+ ]
+}.
+</PRE>Note, that for jabberd14- or wpjabberd-based services you need to make the
+transports log and do xdb by themselves:
+<PRE>
+ &lt;!--
+ You need to add elogger and rlogger entries here when using ejabberd.
+ In this case the transport will do the logging.
+ --&gt;
+
+ &lt;log id='elogger'&gt;
+ &lt;host/&gt;
+ &lt;logtype/&gt;
+ &lt;format&gt;%d: [%t] (%h): %s&lt;/format&gt;
+ &lt;file&gt;/var/log/jabber/error/aim-t.log&lt;/file&gt;
+ &lt;/log&gt;
+
+ &lt;log id='rlogger'&gt;
+ &lt;host/&gt;
+ &lt;logtype&gt;record&lt;/logtype&gt;
+ &lt;format&gt;%d %h %s&lt;/format&gt;
+ &lt;file&gt;/var/log/jabber/record/aim-t.log&lt;/file&gt;
+ &lt;/log&gt;
+
+ &lt;!--
+ Some Jabber server implementations do not provide
+ XDB services (for example jabberd 2.0 and ejabberd).
+ AIM-t is loaded into handle all XDB requests.
+ --&gt;
+
+ &lt;xdb id="xdb"&gt;
+ &lt;host/&gt;
+ &lt;load&gt;
+ &lt;xdb_file&gt;/usr/lib/jabber/xdb_file.so&lt;/xdb_file&gt; &lt;!-- this is a lib of wpjabber or jabberd --&gt;
+ &lt;/load&gt;
+ &lt;xdb_file xmlns="jabber:config:xdb_file"&gt;
+ &lt;spool&gt;&lt;jabberd:cmdline flag='s'&gt;/var/spool/jabber&lt;/jabberd:cmdline&gt;&lt;/spool&gt;
+ &lt;/xdb_file&gt;
+ &lt;/xdb&gt;
</PRE>
<!--TOC subsubsection Modules-->
diff --git a/doc/guide.tex b/doc/guide.tex
index 7e980b3d9..1d9bbe9e0 100644
--- a/doc/guide.tex
+++ b/doc/guide.tex
@@ -437,11 +437,23 @@ Currently three modules are implemented:
services (i.\,e.\ that use the \texttt{jabber:component:accept} namespace).
\end{description}
-For example, the following configuration defines that C2S connections are
-listened on port 5222 and 5223 (SSL) and denied for user ``\texttt{bad}'', S2S
-on port 5269, and that service \texttt{conference.example.org} must be
-connected to port 8888 with a password ``\texttt{secret}''. Also all users
-except admins have traffic limit 1000\,b/s.
+For example, the following configuration defines that:
+\begin{itemize}
+\item C2S connections are listened on port 5222 and 5223 (SSL) and denied for
+ user ``\texttt{bad}''
+\item S2S connections are listened on port 5269
+\item All users except admins have traffic limit 1000\,B/s
+\item AIM service \texttt{aim.example.org} is connected to port 5233 with
+ password ``\texttt{aimsecret}''
+\item JIT services \texttt{icq.example.org} and \texttt{sms.example.org} are
+ connected to port 5234 with password ``\texttt{jitsecret}''
+\item MSN service \texttt{msn.example.org} is connected to port 5235 with
+ password ``\texttt{msnsecret}''
+\item YAHOO service \texttt{yahoo.example.org} is connected to port 5236 with
+ password ``\texttt{yahoosecret}''
+\item ILE service \texttt{ile.example.org} is connected to port 5237 with
+ password ``\texttt{ilesecret}''
+\end{itemize}
\begin{verbatim}
{acl, blocked, {user, "bad"}}.
{access, c2s, [{deny, blocked},
@@ -449,17 +461,64 @@ except admins have traffic limit 1000\,b/s.
{shaper, normal, {maxrate, 1000}}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
-{listen, [{5222, ejabberd_c2s, [{access, c2s},
- {shaper, c2s_shaper}]},
- {5223, ejabberd_c2s, [{access, c2s},
- ssl, {certfile, "/path/to/ssl.pem"}]},
- {5269, ejabberd_s2s_in, []},
- {8888, ejabberd_service,
- [{hosts, ["conference.example.org"], [{password, "secret"}]}]}
- ]}.
+{listen,
+ [{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]},
+ {5223, ejabberd_c2s, [{access, c2s},
+ ssl, {certfile, "/path/to/ssl.pem"}]},
+ {5269, ejabberd_s2s_in, []},
+ {5233, ejabberd_service, [{host, "aim.example.org",
+ [{password, "aimsecret"}]}]},
+ {5234, ejabberd_service, [{hosts, ["icq.example.org", "sms.example.org"],
+ [{password, "jitsecret"}]}]},
+ {5235, ejabberd_service, [{host, "msn.example.org",
+ [{password, "msnsecret"}]}]},
+ {5236, ejabberd_service, [{host, "yahoo.example.org",
+ [{password, "yahoosecret"}]}]},
+ {5237, ejabberd_service, [{host, "gg.example.org",
+ [{password, "ggsecret"}]}]},
+ {5238, ejabberd_service, [{host, "ile.example.org",
+ [{password, "ilesecret"}]}]}
+ ]
+}.
+\end{verbatim}
+Note, that for jabberd14- or wpjabberd-based services you need to make the
+transports log and do xdb by themselves:
+\begin{verbatim}
+ <!--
+ You need to add elogger and rlogger entries here when using ejabberd.
+ In this case the transport will do the logging.
+ -->
+
+ <log id='elogger'>
+ <host/>
+ <logtype/>
+ <format>%d: [%t] (%h): %s</format>
+ <file>/var/log/jabber/error/aim-t.log</file>
+ </log>
+
+ <log id='rlogger'>
+ <host/>
+ <logtype>record</logtype>
+ <format>%d %h %s</format>
+ <file>/var/log/jabber/record/aim-t.log</file>
+ </log>
+
+ <!--
+ Some Jabber server implementations do not provide
+ XDB services (for example jabberd 2.0 and ejabberd).
+ AIM-t is loaded into handle all XDB requests.
+ -->
+
+ <xdb id="xdb">
+ <host/>
+ <load>
+ <xdb_file>/usr/lib/jabber/xdb_file.so</xdb_file> <!-- this is a lib of wpjabber or jabberd -->
+ </load>
+ <xdb_file xmlns="jabber:config:xdb_file">
+ <spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
+ </xdb_file>
+ </xdb>
\end{verbatim}
-
-
\subsubsection{Modules}
diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example
index cae56ec53..2285ef84a 100644
--- a/src/ejabberd.cfg.example
+++ b/src/ejabberd.cfg.example
@@ -91,8 +91,9 @@
[{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper}]},
{5223, ejabberd_c2s, [{access, c2s}, ssl, {certfile, "./ssl.pem"}]},
{5269, ejabberd_s2s_in, [{shaper, s2s_shaper}]},
+ {5280, ejabberd_http, [http_poll, web_admin]},
{8888, ejabberd_service, [{access, all},
- {hosts, ["conference.e.localhost", "muc.e.localhost"],
+ {hosts, ["icq.localhost", "sms.localhost"],
[{password, "secret"}]}]}
]}.
diff --git a/src/web/ejabberd_http.erl b/src/web/ejabberd_http.erl
index 6ef8a4032..0723fd572 100644
--- a/src/web/ejabberd_http.erl
+++ b/src/web/ejabberd_http.erl
@@ -25,7 +25,9 @@
request_path,
request_auth,
request_content_length,
- request_lang = "en"
+ request_lang = "en",
+ use_http_poll = false,
+ use_web_admin = false
}).
@@ -49,9 +51,15 @@ start_link({SockMod, Socket}, Opts) ->
ssl ->
ssl:setopts(Socket, [{packet, http}, {recbuf, 8192}])
end,
+ UseHTTPPoll = lists:member(http_poll, Opts),
+ UseWebAdmin = lists:member(web_admin, Opts),
+ io:format("S: ~p~n", [{UseHTTPPoll, UseWebAdmin}]),
{ok, proc_lib:spawn_link(ejabberd_http,
receive_headers,
- [#state{sockmod = SockMod, socket = Socket}])}.
+ [#state{sockmod = SockMod,
+ socket = Socket,
+ use_http_poll = UseHTTPPoll,
+ use_web_admin = UseWebAdmin}])}.
send_text(State, Text) ->
@@ -93,7 +101,10 @@ receive_headers(State) ->
ssl ->
ssl:setopts(Socket, [{packet, http}])
end,
- receive_headers(#state{sockmod = SockMod, socket = Socket});
+ receive_headers(#state{sockmod = SockMod,
+ socket = Socket,
+ use_http_poll = State#state.use_http_poll,
+ use_web_admin = State#state.use_web_admin});
{error, _Reason} ->
ok;
_ ->
@@ -105,7 +116,9 @@ receive_headers(State) ->
process_request(#state{request_method = 'GET',
request_path = {abs_path, Path},
request_auth = Auth,
- request_lang = Lang}) ->
+ request_lang = Lang,
+ use_http_poll = UseHTTPPoll,
+ use_web_admin = UseWebAdmin}) ->
User = case Auth of
{U, P} ->
case ejabberd_auth:check_password(U, P) of
@@ -136,7 +149,10 @@ process_request(#state{request_method = 'GET',
q = LQuery,
user = User,
lang = Lang},
- case ejabberd_web:process_get(Request) of
+ io:format("~p~n", [{{UseHTTPPoll, UseWebAdmin},
+ Request}]),
+ case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin},
+ Request) of
El when element(1, El) == xmlelement ->
make_xhtml_output(200, [], El);
{Status, Headers, El} when
@@ -157,7 +173,10 @@ process_request(#state{request_method = 'POST',
request_content_length = Len,
request_lang = Lang,
sockmod = SockMod,
- socket = Socket} = State) when is_integer(Len) ->
+ socket = Socket,
+ use_http_poll = UseHTTPPoll,
+ use_web_admin = UseWebAdmin} = State)
+ when is_integer(Len) ->
User = case Auth of
{U, P} ->
case ejabberd_auth:check_password(U, P) of
@@ -197,7 +216,8 @@ process_request(#state{request_method = 'POST',
user = User,
data = Data,
lang = Lang},
- case ejabberd_web:process_get(Request) of
+ case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin},
+ Request) of
El when element(1, El) == xmlelement ->
make_xhtml_output(200, [], El);
{Status, Headers, El} when
diff --git a/src/web/ejabberd_web.erl b/src/web/ejabberd_web.erl
index b59641c44..4ef511e52 100644
--- a/src/web/ejabberd_web.erl
+++ b/src/web/ejabberd_web.erl
@@ -12,7 +12,7 @@
%% External exports
-export([make_xhtml/1,
- process_get/1]).
+ process_get/2]).
-include("ejabberd.hrl").
-include("jlib.hrl").
@@ -49,7 +49,8 @@ make_xhtml(Els) ->
{"value", Value}])).
-process_get(#request{user = User,
+process_get({_, true},
+ #request{user = User,
path = ["admin" | RPath],
q = Query,
lang = Lang} = Request) ->
@@ -69,13 +70,14 @@ process_get(#request{user = User,
[{xmlcdata, "401 Unauthorized"}]}])}
end;
-process_get(#request{user = User,
+process_get({true, _},
+ #request{user = User,
path = ["http-poll" | RPath],
q = Query,
lang = Lang} = Request) ->
ejabberd_http_poll:process_request(Request#request{path = RPath});
-process_get(_Request) ->
+process_get(_, _Request) ->
{404, [], make_xhtml([?XC("h1", "Not found")])}.
diff --git a/src/web/ejabberd_web_admin.erl b/src/web/ejabberd_web_admin.erl
index 46801bc1f..c021fde2b 100644
--- a/src/web/ejabberd_web_admin.erl
+++ b/src/web/ejabberd_web_admin.erl
@@ -1,7 +1,7 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_web_admin.erl
%%% Author : Alexey Shchepin <alexey@sevcom.net>
-%%% Purpose :
+%%% Purpose : Administration web interface
%%% Created : 9 Apr 2004 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
@@ -543,7 +543,7 @@ process_admin(#request{user = User,
ACLs = lists:flatten(io_lib:format("~p.", [ets:tab2list(acl)])),
make_xhtml([?XCT("h1", "ejabberd ACLs configuration")] ++
case Res of
- ok -> [?CT("submited"), ?P];
+ ok -> [?CT("submitted"), ?P];
error -> [?CT("bad format"), ?P];
nothing -> []
end ++
@@ -584,7 +584,7 @@ process_admin(#request{method = Method,
ACLs = lists:keysort(2, ets:tab2list(acl)),
make_xhtml([?XCT("h1", "ejabberd ACLs configuration")] ++
case Res of
- ok -> [?CT("submited"), ?P];
+ ok -> [?CT("submitted"), ?P];
error -> [?CT("bad format"), ?P];
nothing -> []
end ++
@@ -651,7 +651,7 @@ process_admin(#request{user = User,
[{{access, '$1', '$2'}}]}])])),
make_xhtml([?XC("h1", "ejabberd access rules configuration")] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -689,7 +689,7 @@ process_admin(#request{method = Method,
[{{access, '$1', '$2'}}]}]),
make_xhtml([?XC("h1", "ejabberd access rules configuration")] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -730,7 +730,7 @@ process_admin(#request{method = Method,
make_xhtml([?XC("h1",
"'" ++ SName ++ "' access rule configuration")] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -1103,7 +1103,7 @@ user_info(User, Query, Lang) ->
?INPUTT("submit", "chpassword", "Change Password")],
[?XC("h1", "User: " ++ User)] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -1174,12 +1174,23 @@ search_running_node(SNode, [Node | Nodes]) ->
end.
get_node(Node, [], Query, Lang) ->
- [?XC("h1", "Node: " ++ atom_to_list(Node)),
- ?XE("ul",
- [?LI([?ACT("db/", "DB Management")]),
- ?LI([?ACT("backup/", "Backup Management")]),
- ?LI([?ACT("statistics/", "Statistics")])
- ])];
+ Res = node_parse_query(Node, Query),
+ [?XC("h1", "Node: " ++ atom_to_list(Node))] ++
+ case Res of
+ ok -> [?C("submitted"), ?P];
+ error -> [?C("bad format"), ?P];
+ nothing -> []
+ end ++
+ [?XE("ul",
+ [?LI([?ACT("db/", "DB Management")]),
+ ?LI([?ACT("backup/", "Backup Management")]),
+ ?LI([?ACT("stats/", "Statistics")])
+ ]),
+ ?XAE("form", [{"method", "post"}],
+ [?INPUTT("submit", "restart", "Restart"),
+ ?C(" "),
+ ?INPUTT("submit", "stop", "Stop")])
+ ];
get_node(Node, ["db"], Query, Lang) ->
case rpc:call(Node, mnesia, system_info, [tables]) of
@@ -1224,7 +1235,7 @@ get_node(Node, ["db"], Query, Lang) ->
end, STables),
[?XC("h1", "DB Tables at " ++ atom_to_list(Node))] ++
case Res of
- ok -> [?C("submited"), ?P];
+ ok -> [?C("submitted"), ?P];
error -> [?C("bad format"), ?P];
nothing -> []
end ++
@@ -1249,6 +1260,7 @@ get_node(Node, ["db"], Query, Lang) ->
end;
get_node(Node, ["backup"], Query, Lang) ->
+ Res = node_backup_parse_query(Node, Query),
[?XC("h1", "Backup Management at " ++ atom_to_list(Node)),
?XAE("form", [{"method", "post"}],
[?XAE("table", [],
@@ -1292,10 +1304,77 @@ get_node(Node, ["backup"], Query, Lang) ->
])
])])];
+get_node(Node, ["stats"], Query, Lang) ->
+ UpTime = rpc:call(Node, erlang, statistics, [wall_clock]),
+ UpTimeS = io_lib:format("~.3f", [element(1, UpTime)/1000]),
+ CPUTime = rpc:call(Node, erlang, statistics, [runtime]),
+ CPUTimeS = io_lib:format("~.3f", [element(1, CPUTime)/1000]),
+ Users = length(
+ rpc:call(Node, ejabberd_sm, dirty_get_my_sessions_list, [])),
+ TransactionsCommited =
+ rpc:call(Node, mnesia, system_info, [transaction_commits]),
+ TransactionsAborted =
+ rpc:call(Node, mnesia, system_info, [transaction_failures]),
+ TransactionsRestarted =
+ rpc:call(Node, mnesia, system_info, [transaction_restarts]),
+ TransactionsLogged =
+ rpc:call(Node, mnesia, system_info, [transaction_log_writes]),
+
+ [?XC("h1", atom_to_list(Node) ++ " statistics"),
+ ?XAE("table", [],
+ [?XE("tbody",
+ [?XE("tr", [?XCT("td", "Uptime"),
+ ?XAC("td", [{"class", "alignright"}],
+ UpTimeS)]),
+ ?XE("tr", [?XCT("td", "CPU Time"),
+ ?XAC("td", [{"class", "alignright"}],
+ CPUTimeS)]),
+ ?XE("tr", [?XCT("td", "Authentificated users"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(Users))]),
+ ?XE("tr", [?XCT("td", "Transactions commited"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(TransactionsCommited))]),
+ ?XE("tr", [?XCT("td", "Transactions aborted"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(TransactionsAborted))]),
+ ?XE("tr", [?XCT("td", "Transactions restarted"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(TransactionsRestarted))]),
+ ?XE("tr", [?XCT("td", "Transactions logged"),
+ ?XAC("td", [{"class", "alignright"}],
+ integer_to_list(TransactionsLogged))])
+ ])
+ ])];
+
get_node(Node, NPath, Query, Lang) ->
[?XC("h1", "Not found")].
+node_parse_query(Node, Query) ->
+ case lists:keysearch("restart", 1, Query) of
+ {value, _} ->
+ case rpc:call(Node, init, restart, []) of
+ {badrpc, _Reason} ->
+ error;
+ _ ->
+ ok
+ end;
+ _ ->
+ case lists:keysearch("delete", 1, Query) of
+ {value, _} ->
+ case rpc:call(Node, init, restart, []) of
+ {badrpc, _Reason} ->
+ error;
+ _ ->
+ ok
+ end;
+ _ ->
+ nothing
+ end
+ end.
+
+
db_storage_select(ID, Opt, Lang) ->
?XAE("select", [{"name", "table" ++ ID}],
lists:map(
@@ -1345,3 +1424,49 @@ node_db_parse_query(Node, Tables, Query) ->
end, Tables),
ok.
+node_backup_parse_query(Node, Query) ->
+ lists:foldl(
+ fun(Action, nothing) ->
+ case lists:keysearch(Action, 1, Query) of
+ {value, _} ->
+ case lists:keysearch(Action ++ "path", 1, Query) of
+ {value, {_, Path}} ->
+ Res =
+ case Action of
+ "store" ->
+ rpc:call(Node, mnesia,
+ backup, [Path]);
+ "restore" ->
+ rpc:call(Node, mnesia,
+ restore,
+ [Path, [{default_op,
+ keep_tables}]]);
+ "fallback" ->
+ rpc:call(Node, mnesia,
+ install_fallback, [Path]);
+ "dump" ->
+ rpc:call(Node, mnesia,
+ dump_to_textfile, [Path]);
+ "load" ->
+ rpc:call(Node, mnesia,
+ load_textfile, [Path])
+ end,
+ case Res of
+ {error, _Reason} ->
+ error;
+ {badrpc, _Reason} ->
+ error;
+ _ ->
+ ok
+ end;
+ _ ->
+ error
+ end;
+ _ ->
+ nothing
+ end;
+ (_Action, Res) ->
+ Res
+ end, nothing, ["store", "restore", "fallback", "dump", "load"]).
+
+