]> granicus.if.org Git - ejabberd/commitdiff
* src/web/ejabberd_web_admin.erl: Updated CSS, added modules
authorAlexey Shchepin <alexey@process-one.net>
Mon, 23 May 2005 00:30:29 +0000 (00:30 +0000)
committerAlexey Shchepin <alexey@process-one.net>
Mon, 23 May 2005 00:30:29 +0000 (00:30 +0000)
management (thanks to Sergei Golovan)

* src/gen_mod.erl: Added function loaded_modules_with_opts/0, new
API for module stopping (thanks to Sergei Golovan)
* src/mod_muc/mod_muc.erl: Moved a process name to a macros,
updated module stopping (thanks to Sergei Golovan)
* src/mod_irc/mod_irc.erl: Likewise
* src/mod_pubsub/mod_pubsub.erl: Likewise
* src/mod_announce.erl: Updated module stopping (thanks to Sergei
Golovan)
* src/mod_echo.erl: Likewise
* src/mod_offline.erl: Likewise

SVN Revision: 354

ChangeLog
src/gen_mod.erl
src/mod_announce.erl
src/mod_echo.erl
src/mod_irc/mod_irc.erl
src/mod_muc/mod_muc.erl
src/mod_offline.erl
src/mod_pubsub/mod_pubsub.erl
src/web/ejabberd_web_admin.erl

index 630ed1540ba8d170dfe57394bb77ab0d83f81ee2..9633b9f1739f9a77d6799d79ae7705486954f408 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2005-05-23  Alexey Shchepin  <alexey@sevcom.net>
 
+       * src/web/ejabberd_web_admin.erl: Updated CSS, added modules
+       management (thanks to Sergei Golovan)
+
+       * src/gen_mod.erl: Added function loaded_modules_with_opts/0, new
+       API for module stopping (thanks to Sergei Golovan)
+       * src/mod_muc/mod_muc.erl: Moved a process name to a macros,
+       updated module stopping (thanks to Sergei Golovan)
+       * src/mod_irc/mod_irc.erl: Likewise
+       * src/mod_pubsub/mod_pubsub.erl: Likewise
+       * src/mod_announce.erl: Updated module stopping (thanks to Sergei
+       Golovan)
+       * src/mod_echo.erl: Likewise
+       * src/mod_offline.erl: Likewise
+
        * src/web/ejabberd_http.erl: "Connection:" header value now
        matched case-insensitive, and returned to client, replaced
        duplicate is_space($\r) with is_space($\t) (thanks to Maxim
index 205c843c80609d46eccc0ca7764758266c16522e..768869d52cc84534c15c1599fe7605312c35cb68 100644 (file)
@@ -17,6 +17,7 @@
         get_opt/3,
         get_module_opt/3,
         loaded_modules/0,
+        loaded_modules_with_opts/0,
         get_hosts/2]).
 
 -export([behaviour_info/1]).
@@ -52,11 +53,39 @@ stop_module(Module) ->
     case catch Module:stop() of
        {'EXIT', Reason} ->
            ?ERROR_MSG("~p", [Reason]);
+       {wait, ProcList} when is_list(ProcList) ->
+           lists:foreach(fun wait_for_process/1, ProcList),
+           ets:delete(ejabberd_modules, Module),
+           ok;
+       {wait, Process} ->
+           wait_for_process(Process),
+           ets:delete(ejabberd_modules, Module),
+           ok;
        _ ->
            ets:delete(ejabberd_modules, Module),
            ok
     end.
 
+wait_for_process(Process) ->
+    MonitorReference = erlang:monitor(process, Process),
+    wait_for_stop(Process, MonitorReference).
+
+wait_for_stop(Process, MonitorReference) ->
+    receive
+       {'DOWN', MonitorReference, _Type, _Object, _Info} ->
+           ok
+    after 5000 ->
+           catch exit(whereis(Process), kill),
+           wait_for_stop1(MonitorReference)
+    end.
+
+wait_for_stop1(MonitorReference) ->
+    receive
+       {'DOWN', MonitorReference, _Type, _Object, _Info} ->
+           ok
+    after 5000 ->
+           ok
+    end.
 
 get_opt(Opt, Opts) ->
     case lists:keysearch(Opt, 1, Opts) of
@@ -86,7 +115,15 @@ get_module_opt(Module, Opt, Default) ->
 
 loaded_modules() ->
     ets:select(ejabberd_modules,
-              [{#ejabberd_module{_ = '_', module = '$1'}, [],['$1']}]).
+              [{#ejabberd_module{_ = '_', module = '$1'},
+                [],
+                ['$1']}]).
+
+loaded_modules_with_opts() ->
+    ets:select(ejabberd_modules,
+              [{#ejabberd_module{_ = '_', module = '$1', opts = '$2'},
+                [],
+                [{{'$1', '$2'}}]}]).
 
 get_hosts(Opts, Prefix) ->
     case catch gen_mod:get_opt(hosts, Opts) of
index 495eac260831e53ae48a48dda2e0b729c9673bc9..b8581a376efaa61b45c9ea197581bd31cd7f2596 100644 (file)
@@ -70,7 +70,7 @@ stop() ->
     ejabberd_hooks:delete(sm_register_connection_hook,
                          ?MODULE, send_motd, 50),
     exit(whereis(?PROCNAME), stop),
-    ok.
+    {wait, ?PROCNAME}.
 
 announce(From, To, Packet) ->
     case To of
index f7a268f6add40da9193252bfd0582f8889d6ffa9..b93bba912e895d8418f3e393679dc765bba5d486 100644 (file)
 -include("ejabberd.hrl").
 -include("jlib.hrl").
 
-
+-define(PROCNAME, ejabberd_mod_echo).
 
 start(Opts) ->
     %Host = gen_mod:get_opt(host, Opts),
     Host = gen_mod:get_opt(host, Opts, "echo." ++ ?MYNAME),
-    register(ejabberd_mod_echo, spawn(?MODULE, init, [Host])).
+    register(?PROCNAME, spawn(?MODULE, init, [Host])).
 
 init(Host) ->
     ejabberd_router:register_route(Host),
@@ -41,5 +41,6 @@ loop(Host) ->
     end.
 
 stop() ->
-    ejabberd_mod_echo ! stop,
-    ok.
+    ?PROCNAME ! stop,
+    {wait, ?PROCNAME}.
+
index 337d9761bb2129b9890756be892ed9860a28450d..9b05876fd50a69c1ea2b938e4ed39eaf18455cbc 100644 (file)
@@ -24,6 +24,8 @@
 -record(irc_connection, {jid_server_host, pid}).
 -record(irc_custom, {us_host, data}).
 
+-define(PROCNAME, ejabberd_mod_irc).
+
 start(Opts) ->
     iconv:start(),
     mnesia:create_table(irc_custom,
@@ -33,7 +35,7 @@ start(Opts) ->
     Host = hd(Hosts),
     update_table(Host),
     Access = gen_mod:get_opt(access, Opts, all),
-    register(ejabberd_mod_irc, spawn(?MODULE, init, [Hosts, Access])).
+    register(?PROCNAME, spawn(?MODULE, init, [Hosts, Access])).
 
 init(Hosts, Access) ->
     catch ets:new(irc_connection, [named_table,
@@ -172,11 +174,10 @@ do_route1(Host, From, To, Packet) ->
     end.
 
 
-
-
 stop() ->
-    ejabberd_mod_irc ! stop,
-    ok.
+    ?PROCNAME ! stop,
+    {wait, ?PROCNAME}.
+
 
 closed_connection(Host, From, Server) ->
     ets:delete(irc_connection, {From, Server, Host}).
index e7ffe42db5da60ae2ca54cdc02b8624aa4ca0940..f3c61e5954d83f0d8aaccac95e17ea3e8e019edc 100644 (file)
@@ -30,6 +30,7 @@
 -record(muc_online_room, {name_host, pid}).
 -record(muc_registered, {us_host, nick}).
 
+-define(PROCNAME, ejabberd_mod_muc).
 
 start(Opts) ->
     mnesia:create_table(muc_room,
@@ -45,7 +46,7 @@ start(Opts) ->
     Access = gen_mod:get_opt(access, Opts, all),
     AccessCreate = gen_mod:get_opt(access_create, Opts, all),
     AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
-    register(ejabberd_mod_muc,
+    register(?PROCNAME,
             spawn(?MODULE, init,
                   [Hosts, {Access, AccessCreate, AccessAdmin}])).
 
@@ -252,12 +253,12 @@ do_route1(Host, Access, From, To, Packet) ->
 
 
 room_destroyed(Host, Room) ->
-    ejabberd_mod_muc ! {room_destroyed, {Room, Host}},
+    ?PROCNAME ! {room_destroyed, {Room, Host}},
     ok.
 
 stop() ->
-    ejabberd_mod_muc ! stop,
-    ok.
+    ?PROCNAME ! stop,
+    {wait, ?PROCNAME}.
 
 
 store_room(Host, Name, Opts) ->
index 3d7bd0e060c277b9d864a193bf79ea61e10b5465..1c79d6a5d0b4add0debf614406c7e4645df52cfa 100644 (file)
@@ -89,7 +89,7 @@ stop() ->
     ejabberd_hooks:delete(remove_user,
                          ?MODULE, remove_user, 50),
     exit(whereis(?PROCNAME), stop),
-    ok.
+    {wait, ?PROCNAME}.
 
 store_packet(From, To, Packet) ->
     Type = xml:get_tag_attr_s("type", Packet),
index 1823be44d21b4508e7e896df6b9e1c7f2a9d6605..40cdabc44510dc0d11b115197168321169cd8054 100644 (file)
@@ -35,6 +35,7 @@
                 subscription = none}).
 -record(item, {id, publisher, payload}).
 
+-define(PROCNAME, ejabberd_mod_pubsub).
 
 start(Opts) ->
     mnesia:create_table(pubsub_node,
@@ -45,7 +46,7 @@ start(Opts) ->
     update_table(Host),
     mnesia:add_table_index(pubsub_node, host_parent),
     ServedHosts = gen_mod:get_opt(served_hosts, Opts, []),
-    register(ejabberd_mod_pubsub,
+    register(?PROCNAME,
             proc_lib:spawn_link(?MODULE, init, [Hosts, ServedHosts, self()])).
 
 
@@ -202,8 +203,8 @@ do_route(Host, From, To, Packet) ->
 
 
 stop() ->
-    ejabberd_mod_pubsub ! stop,
-    ok.
+    ?PROCNAME ! stop,
+    {wait, ?PROCNAME}.
 
 
 
index 754e89c372f232c7d1475caf3b9a5d91ccac0ea2..dacbf7817378a90f8637fd20bce4717ee8d7569b 100644 (file)
@@ -185,12 +185,12 @@ html>body #container {
 
 #navigation ul {
   position: absolute;
-  top: 55px;
+  top: 54px;
   left: 0;
-  padding: 0 1px 1px;
+  padding: 0 1px 1px 1px;
   margin: 0;
   font-family: Verdana, Arial, Helvetica, sans-serif; 
-  font-size: 7.5pt;
+  font-size: 8pt;
   font-weight: bold;
   background: #d47911;
   width: 13em;
@@ -206,9 +206,9 @@ html>body #container {
 #navigation ul li a {
   margin: 0;
   display: block;
-  padding: 0.25em 0.5em 0.25em 0.75em;
+  padding: 3px 6px 3px 9px;
   border-left: 1em solid #ffc78c;
-  border-top: 1px solid gray;
+  border-top: 1px solid #d47911;
   background: #ffe3c9;
   text-decoration: none;
 }
@@ -257,7 +257,7 @@ input {
 
 input[type=submit] {
   font-family: Verdana, Arial, Helvetica, sans-serif; 
-  font-size: 7pt;
+  font-size: 8pt;
   font-weight: bold;
   color: #ffffff;
   background-color: #fe8a00;
@@ -1683,6 +1683,7 @@ get_node(Node, [], Query, Lang) ->
             [?LI([?ACT("db/", "DB Management")]),
              ?LI([?ACT("backup/", "Backup Management")]),
              ?LI([?ACT("ports/", "Listened Ports Management")]),
+             ?LI([?ACT("modules/", "Modules Management")]),
              ?LI([?ACT("stats/", "Statistics")])
             ]),
         ?XAE("form", [{"method", "post"}],
@@ -1825,6 +1826,28 @@ get_node(Node, ["ports"], Query, Lang) ->
              [node_ports_to_xhtml(NewPorts, Lang)])
        ];
 
+get_node(Node, ["modules"], Query, Lang) ->
+    Modules = rpc:call(Node, gen_mod, loaded_modules_with_opts, []),
+    Res = case catch node_modules_parse_query(Node, Modules, Query) of
+             submitted ->
+                 ok;
+             {'EXIT', Reason} ->
+                 ?INFO_MSG("~p~n", [Reason]),
+                 error;
+             _ ->
+                 nothing
+         end,
+    NewModules = lists:sort(rpc:call(Node, gen_mod, loaded_modules_with_opts, [])),
+    [?XC("h1", ?T("Modules at ") ++ atom_to_list(Node))] ++
+       case Res of
+           ok -> [?CT("submitted"), ?P];
+           error -> [?CT("bad format"), ?P];
+           nothing -> []
+       end ++
+       [?XAE("form", [{"method", "post"}],
+             [node_modules_to_xhtml(NewModules, Lang)])
+       ];
+
 get_node(Node, ["stats"], Query, Lang) ->
     UpTime = rpc:call(Node, erlang, statistics, [wall_clock]),
     UpTimeS = io_lib:format("~.3f", [element(1, UpTime)/1000]),
@@ -2041,13 +2064,13 @@ node_ports_parse_query(Node, Ports, Query) ->
                      Module = list_to_atom(SModule),
                      {ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
                      {ok, Opts} = erl_parse:parse_term(Tokens),
-                     ejabberd_listener:delete_listener(Port),
-                     ejabberd_listener:add_listener(Port, Module, Opts),
+                     rpc:call(Node, ejabberd_listener, delete_listener, [Port]),
+                     rpc:call(Node, ejabberd_listener, add_listener, [Port, Module, Opts]),
                      throw(submitted);
                  _ ->
                      case lists:keysearch("delete" ++ SPort, 1, Query) of
                          {value, _} ->
-                             ejabberd_listener:delete_listener(Port),
+                             rpc:call(Node, ejabberd_listener, delete_listener, [Port]),
                              throw(submitted);
                          _ ->
                              ok
@@ -2066,12 +2089,81 @@ node_ports_parse_query(Node, Ports, Query) ->
            Module = list_to_atom(SModule),
            {ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
            {ok, Opts} = erl_parse:parse_term(Tokens),
-           ejabberd_listener:add_listener(Port, Module, Opts),
+           rpc:call(Node, ejabberd_listener, add_listener, [Port, Module, Opts]),
            throw(submitted);
        _ ->
            ok
     end.
 
+node_modules_to_xhtml(Modules, Lang) ->
+    ?XAE("table", [],
+        [?XE("thead",
+             [?XE("tr",
+                  [?XCT("td", "Module"),
+                   ?XCT("td", "Options")
+                  ])]),
+         ?XE("tbody",
+             lists:map(
+               fun({Module, Opts} = E) ->
+                       SModule = atom_to_list(Module),
+                       ID = term_to_id(E),
+                       ?XE("tr",
+                           [?XC("td", SModule),
+                            ?XE("td", [?INPUTS("text", "opts" ++ SModule,
+                                               term_to_string(Opts), "40")]),
+                            ?XE("td", [?INPUTT("submit", "restart" ++ SModule,
+                                               "Restart")]),
+                            ?XE("td", [?INPUTT("submit", "stop" ++ SModule,
+                                               "Stop")])
+                           ]
+                          )
+               end, Modules) ++
+             [?XE("tr",
+                  [?XE("td", [?INPUT("text", "modulenew", "")]),
+                   ?XE("td", [?INPUTS("text", "optsnew", "", "40")]),
+                   ?XAE("td", [{"colspan", "2"}],
+                        [?INPUTT("submit", "start", "Start")])
+                  ]
+                 )]
+            )]).
+
+node_modules_parse_query(Node, Modules, Query) ->
+    lists:foreach(
+      fun({Module, _Opts1}) ->
+             SModule = atom_to_list(Module),
+             case lists:keysearch("restart" ++ SModule, 1, Query) of
+                 {value, _} ->
+                     {value, {_, SOpts}} =
+                          lists:keysearch("opts" ++ SModule, 1, Query),
+                     {ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
+                     {ok, Opts} = erl_parse:parse_term(Tokens),
+                     rpc:call(Node, gen_mod, stop_module, [Module]),
+                     rpc:call(Node, gen_mod, start_module, [Module, Opts]),
+                     throw(submitted);
+                 _ ->
+                     case lists:keysearch("stop" ++ SModule, 1, Query) of
+                         {value, _} ->
+                             rpc:call(Node, gen_mod, stop_module, [Module]),
+                             throw(submitted);
+                         _ ->
+                             ok
+                     end
+             end
+      end, Modules),
+    case lists:keysearch("start", 1, Query) of
+       {value, _} ->
+           {{value, {_, SModule}},
+            {value, {_, SOpts}}} =
+               {lists:keysearch("modulenew", 1, Query),
+                lists:keysearch("optsnew", 1, Query)},
+           Module = list_to_atom(SModule),
+           {ok, Tokens, _} = erl_scan:string(SOpts ++ "."),
+           {ok, Opts} = erl_parse:parse_term(Tokens),
+           rpc:call(Node, gen_mod, start_module, [Module, Opts]),
+           throw(submitted);
+       _ ->
+           ok
+    end.
 
 
 pretty_print(El) ->