diff options
Diffstat (limited to 'lib/sasl/test/installer.erl')
-rw-r--r-- | lib/sasl/test/installer.erl | 816 |
1 files changed, 816 insertions, 0 deletions
diff --git a/lib/sasl/test/installer.erl b/lib/sasl/test/installer.erl new file mode 100644 index 0000000000..f5ceab0dc4 --- /dev/null +++ b/lib/sasl/test/installer.erl @@ -0,0 +1,816 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(installer). + +%%-compile(export_all). +-export([install_1/2]). +-export([install_2/1]). +-export([install_3/2]). +-export([install_3a/1]). +-export([install_4/1]). +-export([install_5/1]). +-export([install_5a/1]). +-export([install_6/1]). +-export([install_7/1]). +-export([install_8/1]). +-export([install_9/1]). +-export([install_10/1]). +-export([install_11/1]). +-export([client1_1/4]). +-export([client2/3]). +-export([stop/1]). +-export([unpack_p1h/2]). +-export([permanent_p1h/1]). +-export([reg_proc/1]). +-export([registered_loop/1]). + +-define(print(List), {rh_print, TestNode} ! {print, {?MODULE, ?LINE}, List}). +-define(print_line(Line,List), {rh_print, TestNode} ! {print, {?MODULE, Line}, List}). +-define(fail(Term), exit({?MODULE, ?LINE, Term})). +-define(fail_line(Line,Term), exit({?MODULE, Line, Term})). + +-define(check_release(Vsn,Status,Apps), + check_release(TestNode,node(),Vsn,Status,Apps,?LINE)). +-define(check_release_client(Node,Vsn,Status,Apps), + check_release(TestNode,Node,Vsn,Status,Apps,?LINE)). + +-define(check_running_app(App,Vsn), + check_running_app(TestNode,node(),App,Vsn,?LINE)). +-define(check_running_app_client(Node,App,Vsn), + check_running_app(TestNode,Node,App,Vsn,?LINE)). + + +install_1(TestNode,PrivDir) -> + ?print([TestNode]), + ?print(["install_1 start"]), + + % Unpack and install P1H + {ok, "P1H"} = unpack_release(PrivDir,"rel1"), + ?print(["unpack_release P1H ok"]), + ?check_release("P1H",unpacked,["a-1.0"]), + {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"), + ?print(["install_release P1H ok"]), + ?check_release("P1H",current,["a-1.0"]), + ?check_running_app(a,"1.0"), + X = a:a(), + ?print(["X", X]), + {key2, val2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + ?print(["install_1 end OK"]), + ok. + % release_handler_SUITE will reboot this node now! + +install_2(TestNode) -> + ?print(["install_2 start"]), + + % Check that P1H is still unpacked, install it and make_permanent + ?check_release("P1H",unpacked,["a-1.0"]), + ?print(["install_2 P1H unpacked"]), + {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"), + ?print(["install_2 install_release ok"]), + ?check_release("P1H",current,["a-1.0"]), + ?check_running_app(a,"1.0"), + ok = release_handler:make_permanent("P1H"). + % release_handler_SUITE will reboot this node now! + +install_3(TestNode,PrivDir) -> + ?print(["install_3 start"]), + + % Check that P1H is permanent + ?check_release("P1H",permanent,["a-1.0"]), + X = a:a(), + {key2, val2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + + % Unpack and install P1I + {ok, "P1I"} = unpack_release(PrivDir,"rel2"), + ?print(["install_3 unpack_release P1I ok"]), + ?check_release("P1I",unpacked,["a-1.1"]), + {ok,"P1H",[{extra, gott}]} = release_handler:check_install_release("P1I"), + {error,_} = release_handler:check_install_release("P1J"), + {ok,"P1H",[{extra, gott}]} = release_handler:install_release("P1I"), + ?print(["install_3 install_release P1I ok"]), + ?check_release("P1I",current,["a-1.1"]), + ?check_running_app(a,"1.1"), + X2 = a:a(), + {key2, newval2} = lists:keyfind(key2, 1, X2), + {key1, val1} = lists:keyfind(key1, 1, X2), + {ok, bval} = a:b(), + + % Unpack and install P2A + {ok, "P2A"} = unpack_release(PrivDir,"rel3"), + ?print(["install_3 unpack_release P2A ok"]), + ?check_release("P2A",unpacked,["a-1.1"]), + {ok, "P1I", [new_emu]} = release_handler:check_install_release("P2A"), + ?print(["install_3 check_install_release P2A ok"]), + ok = release_handler:make_permanent("P1I"), + ?print(["install_3 make_permanent P1I ok"]), + ?check_release("P1I",permanent,["a-1.1"]), + ok. + +install_3a(TestNode) -> + {ok, "P1I", [new_emu]} = release_handler:install_release("P2A"), + %% Node is rebooted by the release_handler:install_release + %% (init:reboot) because P2A includes a new erts vsn and the relup + %% file contains a 'restart_new_emulator' instruction. + ?print(["install_3 P2A installed"]), + ok. + + + +install_4(TestNode) -> + ?print(["install_4 start"]), + + % Check that P2A is in use. + ?check_release("P2A",current,["a-1.1"]), + ?check_running_app(a,"1.1"), + X = a:a(), + {key2, newval2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + {ok, bval} = a:b(), + ok. + % release_handler_SUITE will reboot this node now! + +install_5(TestNode) -> + ?print(["install_5 start"]), + + % Check that P1I is used + {ok, "P1I", [new_emu]} = release_handler:check_install_release("P2A"), + ok. + +install_5a(TestNode) -> + % Install P2A again + {ok, "P1I", [new_emu]} = release_handler:install_release("P2A"), + %% Node is rebooted by the release_handler:install_release + %% (init:reboot) because P2A includes a new erts vsn and the relup + %% file contains a 'restart_new_emulator' instruction. + ?print(["install_5 P2A installed"]), + ok. + +install_6(TestNode) -> + ?print(["install_6 start"]), + + % Check that P2A is used + ?check_release("P2A",current,["a-1.1"]), + ?check_running_app(a,"1.1"), + X = a:a(), + {key2, newval2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + {ok, bval} = a:b(), + ok = release_handler:make_permanent("P2A"). + % release_handler_SUITE will reboot this node now! + + +install_7(TestNode) -> + ?print(["install_7 start"]), + + % Check that P2A is used + ?check_release("P2A",permanent,["a-1.1"]), + + % Install old P1H + ok = release_handler:reboot_old_release("P1H"), + ok. + +install_8(TestNode) -> + ?print(["install_8 start"]), + + % Check that P1H is permanent + ?check_release("P1H",permanent,["a-1.0"]), + X = a:a(), + {key2, val2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + + %% Remove P1I and P2A and check that a-1.1 and erts-<latest> are removed + ok = release_handler:remove_release("P2A"), + ok = release_handler:remove_release("P1I"), + {ok, Libs} = file:list_dir(code:lib_dir()), + {_,_,StdlibVsn} = lists:keyfind(stdlib,1,application:which_applications()), + true = lists:member("stdlib-"++StdlibVsn, Libs), + true = lists:member("a-1.0", Libs), + false = lists:member("a-1.1", Libs), + {ok, Dirs} = file:list_dir(code:root_dir()), + ["erts-4.4"] = lists:filter(fun(Dir) -> lists:prefix("erts-",Dir) end, Dirs), + ok. + % release_handler_SUITE will reboot this node now! + +install_9(TestNode) -> + ?print(["install_9 start"]), + + % Check that P1H is permanent + ?check_release("P1H",permanent,["a-1.0"]), + X = a:a(), + {key2, val2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + + % Install old P1G + ok = release_handler:reboot_old_release("P1G"), + ok. + +install_10(TestNode) -> + ?print(["install_10 start"]), + + % Check that P1G is permanent + ?check_release("P1G",permanent,[]), + ?check_release("P1H",old,["a-1.0"]), + + %% Remove P1H and check that both versions of application a is removed + ok = release_handler:remove_release("P1H"), + {ok, Libs} = file:list_dir(code:lib_dir()), + {_,_,StdlibVsn} = lists:keyfind(stdlib,1,application:which_applications()), + true = lists:member("stdlib-"++StdlibVsn, Libs), + false = lists:member("a-1.0", Libs), + false = lists:member("a-1.1", Libs), + ok. + % release_handler_SUITE will reboot this node now! + +install_11(TestNode) -> + ?print(["install_11 start"]), + + % Check that P1G is permanent + ?check_release("P1G",permanent,[]), + ok. + + + +%%----------------------------------------------------------------- +%% This test starts a client node which uses this node as master +%% for the release_handler. +%% The client node runs all tests as in installer/1 test case. +%% Thus, the client node will be rebooted several times. +%% The to_erl /tmp/NODENAME@HOSTNAME/ command can be used to connect +%% to the client node. +%% run_erl logs for the client can be found in the directory: +%% code:root_dir() ++ "/clients/type1/NODENAME@HOSTNAME/log +%%----------------------------------------------------------------- + + +client1_1(TestNode,PrivDir,MasterDir,ClientSname) -> + TestHost = test_host(), + ?print(["client1_1 start"]), + + {ok,IP} = inet:getaddr(TestHost,inet), + erl_boot_server:start([IP]), + + ok = net_kernel:monitor_nodes(true), + Node = start_client(TestNode,client1,ClientSname), + trace_disallowed_calls(Node), + + %% Check env var for SASL on client node + SaslEnv = rpc:call(Node, application, get_all_env, [sasl]), + ?print([{client1_1,sasl_env},SaslEnv]), + {_,CliDir} = lists:keyfind(client_directory,1,SaslEnv), + {_,[Master]} = lists:keyfind(masters,1,SaslEnv), + {_,StartCli} = lists:keyfind(start_prg,1,SaslEnv), + NodeStr = atom_to_list(Node), + [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)), + true = (Master =:= node()), + case os:type() of + {unix,_} -> + true = (StartCli =:= filename:join([CliDir,"bin","start"])); + _ -> + ok + end, + + %% Unpack P1H on master + {ok, "P1H"} = unpack_release(PrivDir,"rel1"), + + %% Unpack and install P1H on client + Root = code:root_dir(), + P1HDir = filename:join([Root, "releases", "P1H"]), + + %% The AppDirs argument (last arg to set_unpacked) below is really + %% not necessary, it could just be [] since the path is the same + %% as default. But it is given here in order to force hitting the + %% release_handler:check_path function so it can be checked that + %% it does not use file:read_file_info on the client node, see + %% trace_disallowed_calls/1 and check_disallowed_calls/0 below. + %% (OTP-9142) + {ok, "P1H"} = rpc:call(Node, release_handler, set_unpacked, + [filename:join(P1HDir, "rel1.rel"), + [{a,"1.0",filename:join(MasterDir,lib)}]]), + + ?check_release_client(Node,"P1H",unpacked,["a-1.0"]), + + ok = rpc:call(Node, release_handler, install_file, + ["P1H", filename:join(P1HDir, "start.boot")]), + ok = rpc:call(Node, release_handler, install_file, + ["P1H", filename:join(P1HDir, "sys.config")]), + ok = rpc:call(Node, release_handler, install_file, + ["P1H", filename:join(P1HDir, "relup")]), + ?print([{release_handler_state, Node}, + rpc:call(Node, sys, get_status, [release_handler])]), + + {ok,"P1G",[new_appl]} = + rpc:call(Node, release_handler, check_install_release, ["P1H"]), + + {ok,"P1G",[new_appl]} = + rpc:call(Node, release_handler, install_release, ["P1H"]), + + Apps = rpc:call(Node, application, which_applications, []), + {a,"A CXC 138 11","1.0"} = lists:keyfind(a, 1, Apps), + X = rpc:call(Node, a, a, []), + {key2, val2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + + check_disallowed_calls(), + reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_2(TestNode,PrivDir,Node). + +client1_2(TestNode,PrivDir,Node) -> + ?print(["client1_2 start"]), + + %% Check that P1H is still unpacked, install it and make_permanent + ?check_release_client(Node,"P1H",unpacked,["a-1.0"]), + + {ok,"P1G",[new_appl]} = + rpc:call(Node, release_handler, install_release, ["P1H"]), + ?check_release_client(Node,"P1H",current,["a-1.0"]), + ?check_running_app_client(Node,a,"1.0"), + + ok = rpc:call(Node, release_handler, make_permanent, ["P1H"]), + ?check_release_client(Node,"P1H",permanent,["a-1.0"]), + + check_disallowed_calls(), + reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_3(TestNode,PrivDir,Node). + +client1_3(TestNode,PrivDir,Node) -> + ?print(["client1_3 start"]), + + %% Check that P1H is permanent + ?check_release_client(Node,"P1H",permanent,["a-1.0"]), + X = rpc:call(Node, a, a, []), + {key2, val2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + + %% Unpack P1I on master + {ok, "P1I"} = unpack_release(PrivDir,"rel2"), + + MasterRoot = code:root_dir(), + + %% Unpack and install P1I on client + P1IDir = filename:join([MasterRoot, "releases", "P1I"]), + {ok, "P1I"} = rpc:call(Node, release_handler, set_unpacked, + [filename:join(P1IDir, "rel2.rel"),[]]), + + ?check_release_client(Node,"P1I",unpacked,["a-1.1"]), + + ok = rpc:call(Node, release_handler, install_file, + ["P1I", filename:join(P1IDir, "start.boot")]), + ok = rpc:call(Node, release_handler, install_file, + ["P1I", filename:join(P1IDir, "sys.config")]), + ok = rpc:call(Node, release_handler, install_file, + ["P1I", filename:join(P1IDir, "relup")]), + + {ok,"P1H",[{extra, gott}]} = + rpc:call(Node, release_handler, check_install_release, ["P1I"]), + {error,_} = rpc:call(Node, release_handler, check_install_release, ["P1J"]), + {ok,"P1H",[{extra, gott}]} = + rpc:call(Node, release_handler, install_release, ["P1I"]), + + ?check_running_app_client(Node,a,"1.1"), + X2 = rpc:call(Node, a, a, []), + {key2, newval2} = lists:keyfind(key2, 1, X2), + {key1, val1} = lists:keyfind(key1, 1, X2), + {ok, bval} = rpc:call(Node, a, b, []), + + %% Unpack P2A on master + {ok, "P2A"} = unpack_release(PrivDir,"rel3"), + + %% Unpack and install P2A on client + P2ADir = filename:join([MasterRoot, "releases", "P2A"]), + {ok, "P2A"} = + rpc:call(Node, release_handler, set_unpacked, + [filename:join(P2ADir, "rel3.rel"),[]]), + + ok = rpc:call(Node, release_handler, install_file, + ["P2A", filename:join(P2ADir, "start.boot")]), + ok = rpc:call(Node, release_handler, install_file, + ["P2A", filename:join(P2ADir, "sys.config")]), + ok = rpc:call(Node, release_handler, install_file, + ["P2A", filename:join(P2ADir, "relup")]), + + {ok, "P1I", [new_emu]} = + rpc:call(Node, release_handler, check_install_release, ["P2A"]), + ok = rpc:call(Node, release_handler, make_permanent, ["P1I"]), + ?check_release_client(Node,"P1I",permanent,["a-1.1"]), + + %% since the install_release below reboot the node... + check_disallowed_calls(), + cover_client(TestNode,Node,stop_cover), + + {ok, "P1I", [new_emu]} = + rpc:call(Node, release_handler, install_release, ["P2A"]), + %% Reboots the client ! + + check_reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_4(TestNode,Node). + +client1_4(TestNode,Node) -> + ?print(["client1_4 start"]), + + %% Check that P2A is in use. + ?check_release_client(Node,"P2A",current,["a-1.1"]), + ?check_running_app_client(Node,a,"1.1"), + X = rpc:call(Node, a, a, []), + {key2, newval2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + {ok, bval} = rpc:call(Node, a, b, []), + + %% Reboot from P1I + check_disallowed_calls(), + reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_5(TestNode,Node). + +client1_5(TestNode,Node) -> + ?print(["client1_5 start"]), + + %% Check that P1I is used + {ok, "P1I", [new_emu]} = + rpc:call(Node, release_handler, check_install_release, ["P2A"]), + + %% since the install_release below will reboot the node... + check_disallowed_calls(), + cover_client(TestNode,Node,stop_cover), + + %% Install P2A again + {ok, "P1I", [new_emu]} = + rpc:call(Node, release_handler, install_release, ["P2A"]), + + %% We are rebooted again. + check_reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_6(TestNode,Node). + +client1_6(TestNode,Node) -> + ?print(["client1_6 start"]), + + %% Check that P2A is used + ?check_release_client(Node,"P2A",current,["a-1.1"]), + ?check_running_app_client(Node,a,"1.1"), + X = rpc:call(Node, a, a, []), + {key2, newval2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + {ok, bval} = rpc:call(Node, a, b, []), + + %% Make P2A permanent + ok = rpc:call(Node, release_handler, make_permanent, ["P2A"]), + + %% Reboot from P2A + check_disallowed_calls(), + reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_7(TestNode,Node). + +client1_7(TestNode,Node) -> + ?print(["client1_7 start"]), + + %% Check that P2A is used + ?check_release_client(Node,"P2A",permanent,["a-1.1"]), + + %% since the reboot_old_release below will reboot the node + check_disallowed_calls(), + cover_client(TestNode,Node,stop_cover), + + %% Install old P1H + rpc:call(Node, release_handler, reboot_old_release, ["P1H"]), + %% We are rebooted. + check_reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_8(TestNode,Node). + +client1_8(TestNode,Node) -> + ?print(["client1_8 start"]), + + %% Check that P1H is permanent + ?check_release_client(Node,"P1H",permanent,["a-1.0"]), + X = rpc:call(Node, a, a, []), + {key2, val2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + + %% Remove P1I and P2I from client + ok = rpc:call(Node, release_handler, set_removed, ["P2A"]), + ok = rpc:call(Node, release_handler, set_removed, ["P1I"]), + + check_disallowed_calls(), + reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_9(TestNode,Node). + +client1_9(TestNode,Node) -> + ?print(["client1_9 start"]), + + %% Check that P2A and P1I does not exists and that PiH is permanent. + Rels = rpc:call(Node, release_handler, which_releases, []), + false = lists:keysearch("P2A", 2, Rels), + false = lists:keysearch("P1I", 2, Rels), + ?check_release_client(Node,"P1H",permanent,["a-1.0"]), + X = rpc:call(Node, a, a, []), + {key2, val2} = lists:keyfind(key2, 1, X), + {key1, val1} = lists:keyfind(key1, 1, X), + + %% since the reboot_old_release below will reboot the node + check_disallowed_calls(), + cover_client(TestNode,Node,stop_cover), + + %% Install old P1G + rpc:call(Node, release_handler, reboot_old_release, ["P1G"]), + %% We are rebooted. + check_reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_10(TestNode,Node). + +client1_10(TestNode,Node) -> + ?print(["client1_10 start"]), + + %% Check that P1G is permanent + ?check_release_client(Node,"P1G",permanent,[]), + ?check_release_client(Node,"P1H",old,["a-1.0"]), + {error,client_node} = rpc:call(Node,release_handler,remove_release,["P1H"]), + ok = rpc:call(Node, release_handler, set_removed, ["P1H"]), + + check_disallowed_calls(), + reboot(TestNode,Node), + trace_disallowed_calls(Node), + + client1_11(TestNode,Node). + +client1_11(TestNode,Node) -> + ?print(["client1_11 start"]), + + %% Check that P1G is permanent + ?check_release_client(Node,"P1G",permanent,[]), + + check_disallowed_calls(), + stop_client(TestNode,Node), %% TEST IS OK !! + net_kernel:monitor_nodes(false), + + ok = release_handler:remove_release("P2A"), + ok = release_handler:remove_release("P1I"), + ok = release_handler:remove_release("P1H"), + ok. + +%% Start tracing of the file module on the client node. This module +%% shall never be called, since +%% 1) the node is a client from the release_handler's point of view, +%% so all file access should be done via rpc calls to the master +%% 2) it is started with erl_prim_loader loader set to 'inet' so all +%% code loading should be done via the inet to the master +%% (OTP-9142) +%% This function is called each time the client node is started and to +%% check if a call has been made, call check_disallowed_node/0 +trace_disallowed_calls(Node) -> + MasterProc = self(), + rpc:call(Node,dbg,tracer,[process,{fun(T,_) -> MasterProc ! T end,[]}]), + rpc:call(Node,dbg,p,[all,call]), + rpc:call(Node,dbg,tp,[file,[{'_',[],[{message,{caller}}]}]]). + +check_disallowed_calls() -> + receive + Trace when element(1,Trace)==trace -> + exit({disallowed_function_call,Trace}) + after 0 -> + ok + end. + +start_client(TestNode,Client,Sname) -> + Node = list_to_atom(lists:concat([Sname,"@",test_host()])), + case os:type() of + {unix,_} -> start_client_unix(TestNode,Sname,Node); + {win32,_} -> start_client_win32(TestNode,Client,Sname) + end, + receive + {nodeup, Node} -> + wait_started(TestNode,Node) + after 30000 -> + ?print([{start_client,failed,Node},net_adm:ping(Node)]), + ?fail({"can not start", Node}) + end. + +start_client_unix(TestNode,Sname,Node) -> + Start = filename:join(["clients", "type1", Node, "bin", "start"]), + Cmd = lists:concat(["env NODENAME=",Sname," ", + filename:join(code:root_dir(), Start)]), + ?print([{start_client,Sname},Cmd]), + Res = os:cmd(Cmd), + ?print([{start_client,result},Res]). + +start_client_win32(TestNode,Client,ClientSname) -> + Name = atom_to_list(ClientSname) ++ "_P1G", + RootDir = code:root_dir(), + ErtsBinDir = filename:join(RootDir,"erts-4.4/bin"), + + {ClientArgs,RelClientDir} = rh_test_lib:get_client_args(Client,ClientSname, + RootDir), + StartErlArgs = rh_test_lib:get_start_erl_args(RootDir,RelClientDir, + ClientArgs), + ServiceArgs = rh_test_lib:get_service_args(RootDir, RelClientDir, + ClientSname, StartErlArgs), + + ?print([{start_client,ClientSname},ServiceArgs]), + Erlsrv = filename:nativename(filename:join(ErtsBinDir,"erlsrv")), + rh_test_lib:erlsrv(Erlsrv,stop,Name), + rh_test_lib:erlsrv(Erlsrv,remove,Name), + ok = rh_test_lib:erlsrv(Erlsrv,add,Name,ServiceArgs), + ok = rh_test_lib:erlsrv(Erlsrv,start,Name), + ?print([{start_client,result},ok]), + ok. + +reboot(TestNode,Node) -> + cover_client(TestNode,Node,stop_cover), + rpc:call(Node, init, reboot, []), + check_reboot(TestNode,Node). + +%% This way of checking that the node is rebooted will only work if +%% the nodes are automatically re-connected after the reboot. This +%% happens for master/client (when sasl is started on the client). +check_reboot(TestNode,Node) -> + receive + {nodedown, Node} -> + receive + {nodeup, Node} -> wait_started(TestNode,Node) + after 30000 -> + ?fail({Node, "not rebooted",net_adm:ping(Node)}) + end + after 30000 -> + ?fail({Node, "not closing down",net_adm:ping(Node)}) + end. + +stop_client(TestNode,Node) -> + cover_client(TestNode,Node,stop_cover), + rpc:call(Node, init, stop, []), + receive + {nodedown, Node} -> ok + after 30000 -> + ?fail({Node, "not stopping"}) + end. + +wait_started(TestNode,Node) -> + case rpc:call(Node, init, get_status, []) of + {started, _} -> + cover_client(TestNode,Node,start_cover), + Node; + _ -> + timer:sleep(1000), + wait_started(TestNode,Node) + end. + +cover_client(TestNode,Node,Func) -> + R = rpc:call(TestNode,release_handler_SUITE,Func,[Node]), + ?print([{Func,Node,R}]). + + +%%----------------------------------------------------------------- +%% This test starts a client node which uses this node as master +%% for the release_handler. +%% The client node has the name cli2@HOSTNAME. +%% The client node is not allowed to do ANY release updates +%% as it also have another (non-existing) master node. +%% +%% The to_erl /tmp/cli2@HOSTNAME/ command can be used to connect +%% to the client node. +%% run_erl logs for the client can be found in the directory: +%% code:root_dir() ++ "/clients/type1/cli2@HOSTNAME/log +%%----------------------------------------------------------------- +client2(TestNode,PrivDir,ClientSname) -> + TestHost = test_host(), + ?print(["client2 start"]), + + %% Clean up if previous test case failed + release_handler:remove_release("P1H"), + + ok = net_kernel:monitor_nodes(true), + Node = start_client(TestNode,client2,ClientSname), + + %% Check env var for SASL on client node + SaslEnv = rpc:call(Node, application, get_all_env, [sasl]), + ?print([{client1_1,sasl_env},SaslEnv]), + {_,CliDir} = lists:keyfind(client_directory,1,SaslEnv), + {_,[Master,Master2]} = lists:keyfind(masters,1,SaslEnv), + {_,StartCli} = lists:keyfind(start_prg,1,SaslEnv), + NodeStr = atom_to_list(Node), + [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)), + true = (Master =:= node()), + true = (Master2 =:= list_to_atom("master2@"++TestHost)), + case os:type() of + {unix,_} -> + true = (StartCli =:= filename:join([CliDir,"bin","start"])); + _ -> + ok + end, + + {ok, "P1H"} = unpack_release(PrivDir,"rel1"), + + Root = code:root_dir(), + {error,{bad_masters,[Master2]}} = + rpc:call(Node, release_handler, set_unpacked, + [filename:join([Root, "releases", "P1H", "rel1.rel"]),[]]), + + {error,{no_such_release,"P1H"}} = + rpc:call(Node, release_handler, check_install_release, ["P1H"]), + + stop_client(TestNode,Node), %% TEST IS OK !! + net_kernel:monitor_nodes(false), + + release_handler:remove_release("P1H"), + ok. + + +stop(Now) -> + %% The timestamp is only used for debugging. It is printed by + %% release_handler_SUITE also. + R = init:stop(), + erlang:display({init_stop,Now,R}), + R. + +unpack_p1h(TestNode,PrivDir) -> + {ok, "P1H"} = unpack_release(PrivDir,"rel1"), + ?check_release("P1H",unpacked,["a-1.0"]), + ok. + +permanent_p1h(TestNode) -> + ?check_release("P1H",unpacked,["a-1.0"]), + {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"), + ?check_release("P1H",current,["a-1.0"]), + ok = release_handler:make_permanent("P1H"), + ?check_release("P1H",permanent,["a-1.0"]), + ok. + + +reg_proc(Name) -> + catch unregister(Name), + Pid = spawn_link(?MODULE, registered_loop, [Name]), + global:register_name(Name, Pid), + ok. + +registered_loop(_Name) -> + receive + kill -> + exit(killed) + end. + +check_release(TestNode,Node,Vsn,Status,Apps,Line) -> + case rpc:call(Node,release_handler,which_releases,[]) of + {badrpc,_}=Error -> + ?fail_line(Line,{check_release,Node,Vsn,Status,Error}); + Rels -> + ?print_line(Line,["check_release:", Rels]), + {"SASL-test", Vsn, Libs, Status} = lists:keyfind(Vsn, 2, Rels), + true = lists:all(fun(App) -> lists:member(App,Libs) end,Apps), + ok + end. + +check_running_app(TestNode,Node,App,Vsn,Line) -> + case rpc:call(Node,application,which_applications,[]) of + {badrpc,_}=Error -> + ?fail_line(Line,{check_running_app,Node,App,Vsn,Error}); + Apps -> + ?print_line(Line,["check_running_app:", Apps]), + {App, _, Vsn} = lists:keyfind(a, 1, Apps), + ok + end. + +test_host() -> + {ok,Host} = inet:gethostname(), + Host. + +unpack_release(PrivDir,Rel) -> + copy(filename:join([PrivDir,Rel,Rel++".tar.gz"]), + filename:join(code:root_dir(),releases)), + release_handler:unpack_release(Rel). + +copy(Src, DestDir) -> + Dest = filename:join(DestDir, filename:basename(Src)), + {ok,_} = file:copy(Src, Dest), + ok. + |