26
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-30 17:43:57 +01:00

Support to select what modules to update. Split large function in smaller ones.

SVN Revision: 2109
This commit is contained in:
Badlop 2009-05-27 17:29:43 +00:00
parent dc613df3b1
commit a1fe76fb5b
2 changed files with 145 additions and 37 deletions

View File

@ -28,13 +28,15 @@
-author('alexey@process-one.net'). -author('alexey@process-one.net').
%% API %% API
-export([update/0, update_info/0]). -export([update/0, update/1, update_info/0]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
%%==================================================================== %%====================================================================
%% API %% API
%%==================================================================== %%====================================================================
%% Update all the modified modules
update() -> update() ->
case update_info() of case update_info() of
{ok, Dir, _UpdatedBeams, _Script, LowLevelScript, _Check} -> {ok, Dir, _UpdatedBeams, _Script, LowLevelScript, _Check} ->
@ -48,48 +50,91 @@ update() ->
{error, Reason} {error, Reason}
end. end.
update_info() -> %% Update only the specified modules
Dir = filename:dirname(code:which(ejabberd)), update(ModulesToUpdate) ->
case file:list_dir(Dir) of case update_info() of
{ok, Files} -> {ok, Dir, UpdatedBeamsAll, _Script, _LowLevelScript, _Check} ->
Beams = [list_to_atom(filename:rootname(FN)) || UpdatedBeamsNow =
FN <- Files, lists:suffix(".beam", FN)], [A || A <- UpdatedBeamsAll, B <- ModulesToUpdate, A == B],
UpdatedBeams = {_, LowLevelScript, _} = build_script(Dir, UpdatedBeamsNow),
lists:filter( Eval =
fun(Module) -> release_handler_1:eval_script(
{ok, {Module, NewVsn}} = LowLevelScript, [],
beam_lib:version(code:which(Module)),
case code:is_loaded(Module) of
{file, _} ->
Attrs = Module:module_info(attributes),
{value, {vsn, CurVsn}} =
lists:keysearch(vsn, 1, Attrs),
NewVsn /= CurVsn;
false ->
false
end
end, Beams),
?INFO_MSG("beam files: ~p~n", [UpdatedBeams]),
Script = make_script(UpdatedBeams),
?INFO_MSG("script: ~p~n", [Script]),
LowLevelScript = make_low_level_script(UpdatedBeams, Script),
?INFO_MSG("low level script: ~p~n", [LowLevelScript]),
Check =
release_handler_1:check_script(
LowLevelScript,
[{ejabberd, "", filename:join(Dir, "..")}]), [{ejabberd, "", filename:join(Dir, "..")}]),
?INFO_MSG("check: ~p~n", [Check]), ?INFO_MSG("eval: ~p~n", [Eval]),
{ok, Dir, UpdatedBeams, Script, LowLevelScript, Check}; Eval;
{error, Reason} -> {error, Reason} ->
{error, Reason} {error, Reason}
end. end.
%% Get information about the modified modules
update_info() ->
Dir = filename:dirname(code:which(ejabberd)),
case file:list_dir(Dir) of
{ok, Files} ->
update_info(Dir, Files);
{error, Reason} ->
{error, Reason}
end.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%%% Internal functions %%% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% From systools.hrl update_info(Dir, Files) ->
Beams = lists:sort(get_beams(Files)),
UpdatedBeams = get_updated_beams(Beams),
?INFO_MSG("beam files: ~p~n", [UpdatedBeams]),
{Script, LowLevelScript, Check} = build_script(Dir, UpdatedBeams),
{ok, Dir, UpdatedBeams, Script, LowLevelScript, Check}.
get_beams(Files) ->
[list_to_atom(filename:rootname(FN))
|| FN <- Files, lists:suffix(".beam", FN)].
%% Return only the beams that have different version
get_updated_beams(Beams) ->
lists:filter(
fun(Module) ->
NewVsn = get_new_version(Module),
case code:is_loaded(Module) of
{file, _} ->
CurVsn = get_current_version(Module),
(NewVsn /= CurVsn
andalso NewVsn /= unknown_version);
false ->
false
end
end, Beams).
get_new_version(Module) ->
Path = code:which(Module),
VersionRes = beam_lib:version(Path),
case VersionRes of
{ok, {Module, NewVsn}} -> NewVsn;
%% If a m1.erl has -module("m2"):
_ -> unknown_version
end.
get_current_version(Module) ->
Attrs = Module:module_info(attributes),
{value, {vsn, CurVsn}} = lists:keysearch(vsn, 1, Attrs),
CurVsn.
%% @spec(Dir::string(), UpdatedBeams::[atom()]) -> {Script,LowLevelScript,Check}
build_script(Dir, UpdatedBeams) ->
Script = make_script(UpdatedBeams),
?INFO_MSG("script: ~p~n", [Script]),
LowLevelScript = make_low_level_script(UpdatedBeams, Script),
?INFO_MSG("low level script: ~p~n", [LowLevelScript]),
Check =
release_handler_1:check_script(
LowLevelScript,
[{ejabberd, "", filename:join(Dir, "..")}]),
?INFO_MSG("check: ~p~n", [Check]),
{Script, LowLevelScript, Check}.
%% Copied from Erlang/OTP file: lib/sasl/src/systools.hrl
-record(application, -record(application,
{name, %% Name of the application, atom(). {name, %% Name of the application, atom().
type = permanent, %% Application start type, atom(). type = permanent, %% Application start type, atom().

View File

@ -39,6 +39,12 @@
-include("ejabberd_http.hrl"). -include("ejabberd_http.hrl").
-include("ejabberd_web_admin.hrl"). -include("ejabberd_web_admin.hrl").
-define(INPUTATTRS(Type, Name, Value, Attrs),
?XA("input", Attrs ++
[?XMLATTR('type', Type),
?XMLATTR('name', Name),
?XMLATTR('value', Value)])).
process(["doc", LocalFile], _Request) -> process(["doc", LocalFile], _Request) ->
DocPath = case os:getenv("EJABBERD_DOC_PATH") of DocPath = case os:getenv("EJABBERD_DOC_PATH") of
@ -149,6 +155,12 @@ make_xhtml(Els, Host, Node, Lang) ->
#xmlel{ns = ?NS_XHTML, name = 'meta', attrs = [ #xmlel{ns = ?NS_XHTML, name = 'meta', attrs = [
?XMLATTR('http-equiv', <<"Content-Type">>), ?XMLATTR('http-equiv', <<"Content-Type">>),
?XMLATTR('content', <<"text/html; charset=utf-8">>)]}, ?XMLATTR('content', <<"text/html; charset=utf-8">>)]},
#xmlel{ns = ?NS_XHTML, name = 'script',
%% This children is to ensure exmpp puts: <script ...></script>
children = [?C(".")],
attrs = [
?XMLATTR('src', Base ++ "additions.js"),
?XMLATTR('type', <<"text/javascript">>)]},
#xmlel{ns = ?NS_XHTML, name = 'link', attrs = [ #xmlel{ns = ?NS_XHTML, name = 'link', attrs = [
?XMLATTR('href', Base ++ "favicon.ico"), ?XMLATTR('href', Base ++ "favicon.ico"),
?XMLATTR('type', <<"image/x-icon">>), ?XMLATTR('type', <<"image/x-icon">>),
@ -190,6 +202,24 @@ get_base_path(Host, cluster) -> "/admin/server/" ++ Host ++ "/";
get_base_path(global, Node) -> "/admin/node/" ++ atom_to_list(Node) ++ "/"; get_base_path(global, Node) -> "/admin/node/" ++ atom_to_list(Node) ++ "/";
get_base_path(Host, Node) -> "/admin/server/" ++ Host ++ "/node/" ++ atom_to_list(Node) ++ "/". get_base_path(Host, Node) -> "/admin/server/" ++ Host ++ "/node/" ++ atom_to_list(Node) ++ "/".
additions_js() ->
"
function selectAll() {
for(i=0;i<document.forms[0].elements.length;i++)
{ var e = document.forms[0].elements[i];
if(e.type == 'checkbox')
{ e.checked = true; }
}
}
function unSelectAll() {
for(i=0;i<document.forms[0].elements.length;i++)
{ var e = document.forms[0].elements[i];
if(e.type == 'checkbox')
{ e.checked = false; }
}
}
".
css(Host) -> css(Host) ->
Base = get_base_path(Host, cluster), Base = get_base_path(Host, cluster),
" "
@ -525,6 +555,10 @@ h3 {
padding-left: 10px; padding-left: 10px;
} }
#content ul.noliststyle > li {
list-style-type: none;
}
#content li.big { #content li.big {
font-size: 10pt; font-size: 10pt;
} }
@ -646,6 +680,9 @@ process_admin(_Host, #request{path = ["logo.png"]}) ->
process_admin(_Host, #request{path = ["logo-fill.png"]}) -> process_admin(_Host, #request{path = ["logo-fill.png"]}) ->
{200, [{"Content-Type", "image/png"}, last_modified(), cache_control_public()], logo_fill()}; {200, [{"Content-Type", "image/png"}, last_modified(), cache_control_public()], logo_fill()};
process_admin(_Host, #request{path = ["additions.js"]}) ->
{200, [{"Content-Type", "text/javascript"}, last_modified(), cache_control_public()], additions_js()};
process_admin(Host, process_admin(Host,
#request{path = ["acls-raw"], #request{path = ["acls-raw"],
q = Query, q = Query,
@ -1953,9 +1990,32 @@ get_node(global, Node, ["update"], Query, Lang) ->
[] -> [] ->
?CT("None"); ?CT("None");
_ -> _ ->
?XE('ul', BeamsLis =
[?LI([?C(atom_to_list(Beam))]) || lists:map(
Beam <- UpdatedBeams]) fun(Beam) ->
BeamString = atom_to_list(Beam),
?LI([
?INPUT("checkbox", "selected", BeamString),
%% If we want checkboxes selected by default:
%%?XA("input", [{"checked", ""},
%% {"type", "checkbox"},
%% {"name", "selected"},
%% {"value", BeamString}]),
?C(BeamString)])
end,
UpdatedBeams),
SelectButtons =
[?BR,
?INPUTATTRS(<<"button">>, <<"selectall">>,
<<"Select All">>,
[?XMLATTR('onClick', <<"selectAll()">>)]),
?C(" "),
?INPUTATTRS(<<"button">>, <<"unselectall">>,
<<"Unselect All">>,
[?XMLATTR('onClick', <<"unSelectAll()">>)])],
%%?XE("ul", BeamsLis)
?XAE('ul', [?XMLATTR('class', <<"noliststyle">>)],
BeamsLis ++ SelectButtons)
end, end,
FmtScript = ?XC('pre', io_lib:format("~p", [Script])), FmtScript = ?XC('pre', io_lib:format("~p", [Script])),
FmtLowLevelScript = ?XC('pre', io_lib:format("~p", [LowLevelScript])), FmtLowLevelScript = ?XC('pre', io_lib:format("~p", [LowLevelScript])),
@ -1972,6 +2032,7 @@ get_node(global, Node, ["update"], Query, Lang) ->
?XCT('h3', "Update script"), FmtScript, ?XCT('h3', "Update script"), FmtScript,
?XCT('h3', "Low level update script"), FmtLowLevelScript, ?XCT('h3', "Low level update script"), FmtLowLevelScript,
?XCT('h3', "Script check"), ?XC("pre", atom_to_list(Check)), ?XCT('h3', "Script check"), ?XC("pre", atom_to_list(Check)),
?BR,
?INPUTT("submit", "update", "Update") ?INPUTT("submit", "update", "Update")
]) ])
]; ];
@ -2294,7 +2355,9 @@ node_modules_parse_query(Host, Node, Modules, Query) ->
node_update_parse_query(Node, Query) -> node_update_parse_query(Node, Query) ->
case lists:keysearch("update", 1, Query) of case lists:keysearch("update", 1, Query) of
{value, _} -> {value, _} ->
case rpc:call(Node, ejabberd_update, update, []) of ModulesToUpdateStrings = proplists:get_all_values("selected",Query),
ModulesToUpdate = [list_to_atom(M) || M <- ModulesToUpdateStrings],
case rpc:call(Node, ejabberd_update, update, [ModulesToUpdate]) of
{ok, _} -> {ok, _} ->
ok; ok;
{error, Error} -> {error, Error} ->