mirror of
https://github.com/processone/ejabberd.git
synced 2024-09-21 14:06:57 +02:00
Support to select what modules to update. Split large function in smaller ones.
SVN Revision: 2107
This commit is contained in:
parent
7f5cce8196
commit
4094482a9f
@ -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().
|
||||||
|
@ -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 ++
|
||||||
|
[{"type", Type},
|
||||||
|
{"name", Name},
|
||||||
|
{"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
|
||||||
@ -145,6 +151,8 @@ make_xhtml(Els, Host, Node, Lang) ->
|
|||||||
[?XCT("title", "ejabberd Web Admin"),
|
[?XCT("title", "ejabberd Web Admin"),
|
||||||
{xmlelement, "meta", [{"http-equiv", "Content-Type"},
|
{xmlelement, "meta", [{"http-equiv", "Content-Type"},
|
||||||
{"content", "text/html; charset=utf-8"}], []},
|
{"content", "text/html; charset=utf-8"}], []},
|
||||||
|
{xmlelement, "script", [{"src", Base ++ "/additions.js"},
|
||||||
|
{"type", "text/javascript"}], [?C(" ")]},
|
||||||
{xmlelement, "link", [{"href", Base ++ "favicon.ico"},
|
{xmlelement, "link", [{"href", Base ++ "favicon.ico"},
|
||||||
{"type", "image/x-icon"},
|
{"type", "image/x-icon"},
|
||||||
{"rel", "shortcut icon"}], []},
|
{"rel", "shortcut icon"}], []},
|
||||||
@ -184,6 +192,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),
|
||||||
"
|
"
|
||||||
@ -519,6 +545,10 @@ h3 {
|
|||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#content ul.nolistyle>li {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
#content li.big {
|
#content li.big {
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
}
|
}
|
||||||
@ -640,6 +670,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,
|
||||||
@ -1927,9 +1960,28 @@ 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),
|
||||||
|
%%?XA("input", [{"checked", ""}, %% Selected by default
|
||||||
|
%% {"type", "checkbox"},
|
||||||
|
%% {"name", "selected"},
|
||||||
|
%% {"value", BeamString}]),
|
||||||
|
?C(BeamString)])
|
||||||
|
end,
|
||||||
|
UpdatedBeams),
|
||||||
|
SelectButtons =
|
||||||
|
[?BR,
|
||||||
|
?INPUTATTRS("button", "selectall", "Select All",
|
||||||
|
[{"onClick", "selectAll()"}]),
|
||||||
|
?C(" "),
|
||||||
|
?INPUTATTRS("button", "unselectall", "Unselect All",
|
||||||
|
[{"onClick", "unSelectAll()"}])],
|
||||||
|
%%?XE("ul", BeamsLis)
|
||||||
|
?XAE("ul", [{"class", "nolistyle"}], 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])),
|
||||||
@ -1946,6 +1998,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")
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
@ -2268,7 +2321,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} ->
|
||||||
|
Loading…
Reference in New Issue
Block a user