mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-28 17:38:54 +01:00
Support to select what modules to update. Split large function in smaller ones.
SVN Revision: 2109
This commit is contained in:
parent
dc613df3b1
commit
a1fe76fb5b
@ -28,13 +28,15 @@
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
%% API
|
||||
-export([update/0, update_info/0]).
|
||||
-export([update/0, update/1, update_info/0]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
%%====================================================================
|
||||
%% API
|
||||
%%====================================================================
|
||||
|
||||
%% Update all the modified modules
|
||||
update() ->
|
||||
case update_info() of
|
||||
{ok, Dir, _UpdatedBeams, _Script, LowLevelScript, _Check} ->
|
||||
@ -48,48 +50,91 @@ update() ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
update_info() ->
|
||||
Dir = filename:dirname(code:which(ejabberd)),
|
||||
case file:list_dir(Dir) of
|
||||
{ok, Files} ->
|
||||
Beams = [list_to_atom(filename:rootname(FN)) ||
|
||||
FN <- Files, lists:suffix(".beam", FN)],
|
||||
UpdatedBeams =
|
||||
lists:filter(
|
||||
fun(Module) ->
|
||||
{ok, {Module, NewVsn}} =
|
||||
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,
|
||||
%% Update only the specified modules
|
||||
update(ModulesToUpdate) ->
|
||||
case update_info() of
|
||||
{ok, Dir, UpdatedBeamsAll, _Script, _LowLevelScript, _Check} ->
|
||||
UpdatedBeamsNow =
|
||||
[A || A <- UpdatedBeamsAll, B <- ModulesToUpdate, A == B],
|
||||
{_, LowLevelScript, _} = build_script(Dir, UpdatedBeamsNow),
|
||||
Eval =
|
||||
release_handler_1:eval_script(
|
||||
LowLevelScript, [],
|
||||
[{ejabberd, "", filename:join(Dir, "..")}]),
|
||||
?INFO_MSG("check: ~p~n", [Check]),
|
||||
{ok, Dir, UpdatedBeams, Script, LowLevelScript, Check};
|
||||
?INFO_MSG("eval: ~p~n", [Eval]),
|
||||
Eval;
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
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
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% 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,
|
||||
{name, %% Name of the application, atom().
|
||||
type = permanent, %% Application start type, atom().
|
||||
|
@ -39,6 +39,12 @@
|
||||
-include("ejabberd_http.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) ->
|
||||
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 = [
|
||||
?XMLATTR('http-equiv', <<"Content-Type">>),
|
||||
?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 = [
|
||||
?XMLATTR('href', Base ++ "favicon.ico"),
|
||||
?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(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) ->
|
||||
Base = get_base_path(Host, cluster),
|
||||
"
|
||||
@ -525,6 +555,10 @@ h3 {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#content ul.noliststyle > li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#content li.big {
|
||||
font-size: 10pt;
|
||||
}
|
||||
@ -646,6 +680,9 @@ process_admin(_Host, #request{path = ["logo.png"]}) ->
|
||||
process_admin(_Host, #request{path = ["logo-fill.png"]}) ->
|
||||
{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,
|
||||
#request{path = ["acls-raw"],
|
||||
q = Query,
|
||||
@ -1953,9 +1990,32 @@ get_node(global, Node, ["update"], Query, Lang) ->
|
||||
[] ->
|
||||
?CT("None");
|
||||
_ ->
|
||||
?XE('ul',
|
||||
[?LI([?C(atom_to_list(Beam))]) ||
|
||||
Beam <- UpdatedBeams])
|
||||
BeamsLis =
|
||||
lists:map(
|
||||
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,
|
||||
FmtScript = ?XC('pre', io_lib:format("~p", [Script])),
|
||||
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', "Low level update script"), FmtLowLevelScript,
|
||||
?XCT('h3', "Script check"), ?XC("pre", atom_to_list(Check)),
|
||||
?BR,
|
||||
?INPUTT("submit", "update", "Update")
|
||||
])
|
||||
];
|
||||
@ -2294,7 +2355,9 @@ node_modules_parse_query(Host, Node, Modules, Query) ->
|
||||
node_update_parse_query(Node, Query) ->
|
||||
case lists:keysearch("update", 1, Query) of
|
||||
{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;
|
||||
{error, Error} ->
|
||||
|
Loading…
Reference in New Issue
Block a user