1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2011-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21-module(installer).
22
23-include("test_lib.hrl").
24
25%%-compile(export_all).
26-export([install_1/2]).
27-export([install_2/1]).
28-export([install_3/2]).
29-export([install_6a/1]).
30-export([install_4/1]).
31-export([install_5/1]).
32-export([install_5a/1]).
33-export([install_6/1]).
34-export([install_7/1]).
35-export([install_7a/1]).
36-export([install_8/1]).
37-export([install_8a/1]).
38-export([install_9/1]).
39-export([install_10/1]).
40-export([install_11/1]).
41-export([install_12/1]).
42-export([install_13/1]).
43-export([install_14/1]).
44-export([upgrade_restart_1/2]).
45-export([upgrade_restart_1a/1]).
46-export([upgrade_restart_2/1]).
47-export([upgrade_restart_2a/1]).
48-export([upgrade_restart_2b/1]).
49-export([upgrade_restart_3/1]).
50-export([client1_1/4]).
51-export([client2/3]).
52-export([stop/1]).
53-export([unpack_p1h/2]).
54-export([permanent_p1h/1]).
55-export([reg_proc/1]).
56-export([registered_loop/1]).
57
58-define(print(List),
59	io:format(user,"(~w:~w) ~tp~n",[?MODULE,?LINE,List]),
60	{rh_print, TestNode} ! {print, {?MODULE, ?LINE}, List}).
61-define(print_line(Line,List),
62	io:format(user,"(~w:~w) ~tp~n",[?MODULE,Line,List]),
63	{rh_print, TestNode} ! {print, {?MODULE, Line}, List}).
64-define(fail(Term), exit({?MODULE, ?LINE, Term})).
65-define(fail_line(Line,Term), exit({?MODULE, Line, Term})).
66
67-define(check_release_states(States),
68	check_release_states(TestNode,node(),States,?LINE)).
69-define(check_release_states_client(Node,States),
70	check_release_states(TestNode,Node,States,?LINE)).
71
72-define(check_release_lib(Vsn,Apps),
73	check_release_lib(TestNode,node(),Vsn,Apps,?LINE)).
74-define(check_release_lib_client(Node,Vsn,Apps),
75	check_release_lib(TestNode,Node,Vsn,Apps,?LINE)).
76
77-define(check_running_app(App,Vsn),
78	check_running_app(TestNode,node(),App,Vsn,?LINE)).
79-define(check_running_app_client(Node,App,Vsn),
80	check_running_app(TestNode,Node,App,Vsn,?LINE)).
81
82-define(check_disallowed_calls,check_disallowed_calls(TestNode,?LINE)).
83
84
85install_1(TestNode,PrivDir) ->
86    ?print([TestNode]),
87    ?print(["install_1 start"]),
88    ?check_release_states([permanent]),
89
90    % Unpack and install P1H
91    {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
92    ?check_release_states([permanent,unpacked]),
93    ?check_release_lib("P1H",["a-1.0"]),
94    {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
95    ?check_release_states([permanent,current]),
96    ?check_running_app(a,"1.0"),
97    X = a:a(),
98    ?print(["X", X]),
99    {key2, val2} = lists:keyfind(key2, 1, X),
100    {key1, val1} = lists:keyfind(key1, 1, X),
101    ?print(["install_1 end OK"]),
102    ok.
103    % release_handler_SUITE will reboot this node now!
104
105install_2(TestNode) ->
106    ?print(["install_2 start"]),
107
108    % Check that P1H is still unpacked, install it and make_permanent
109    ?check_release_states([permanent,unpacked]),
110    {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
111    ?print(["install_2 install_release ok"]),
112    ?check_release_states([permanent,current]),
113    ?check_running_app(a,"1.0"),
114    ok = release_handler:make_permanent("P1H"),
115    ?print(["install_2 make permanent P1H ok"]),
116    ?check_release_states([old,permanent]),
117    ?check_running_app(a,"1.0"),
118    ok.
119    % release_handler_SUITE will reboot this node now!
120
121install_3(TestNode,PrivDir) ->
122    ?print(["install_3 start"]),
123
124    % Check that P1H is permanent
125    ?check_release_states([old,permanent]),
126    ?check_running_app(a,"1.0"),
127    X = a:a(),
128    {key2, val2} = lists:keyfind(key2, 1, X),
129    {key1, val1} = lists:keyfind(key1, 1, X),
130
131    % Unpack and install P1I
132    {ok, "P1I"} = unpack_release(PrivDir,"rel2"),
133    ?check_release_states([old,permanent,unpacked]),
134    ?check_release_lib("P1I",["a-1.1"]),
135    {ok,"P1H",[{extra, gott}]} = release_handler:check_install_release("P1I"),
136    ?print(["install_3 check_install_release P1I ok"]),
137    {error,_} = release_handler:check_install_release("P1J"),
138    ?print(["install_3 check_install_release P1J fails - ok"]),
139    {ok,"P1H",[{extra, gott}]} = release_handler:install_release("P1I"),
140    ?check_release_states([old,permanent,current]),
141    ?check_running_app(a,"1.1"),
142    X2 = a:a(),
143    {key2, newval2} = lists:keyfind(key2, 1, X2),
144    {key1, val1} = lists:keyfind(key1, 1, X2),
145    {ok, bval} = a:b(),
146    ?print(["install_3 env ok"]),
147
148    % Unpack P2A
149    {ok, "P2A"} = unpack_release(PrivDir,"rel3"),
150    ?check_release_states([old,permanent,current,unpacked]),
151    ?check_release_lib("P2A",["a-1.1"]),
152    {ok, "P1I", [new_emu]} = release_handler:check_install_release("P2A"),
153    ?print(["install_3 check_install_release P2A ok"]),
154    ok.
155    % release_handler_SUITE will reboot this node now!
156
157install_4(TestNode) ->
158    ?print(["install_4 start"]),
159
160    %% Check that P1H is the one that is used
161    ?check_release_states([old,permanent,unpacked,unpacked]),
162    ?check_running_app(a,"1.0"),
163
164    %% Install P2A
165    {continue_after_restart, "P1H", [new_emu,new_appl]} =
166	release_handler:install_release("P2A"),
167    %% Node is rebooted by the release_handler:install_release
168    %% (init:reboot) because P2A includes a new erts vsn and the relup
169    %% file contains a 'restart_new_emulator' instruction.
170    ?print(["install_4 P2A installed"]),
171    ok.
172
173
174install_5(TestNode) ->
175    ?print(["install_5 start"]),
176
177    %% Check that the upgrade was done via a temporary release due to
178    %% new emulator version.
179    {"SASL-test","__new_emulator__P1H"} = init:script_id(),
180
181    %% Check that P2A is in use.
182    ?check_release_states([old,permanent,unpacked,current]),
183    ?check_running_app(a,"1.1"),
184    X = a:a(),
185    {key2, newval2} = lists:keyfind(key2, 1, X),
186    {key1, val1} = lists:keyfind(key1, 1, X),
187    {ok, bval} = a:b(),
188    ?print(["install_5 check env ok"]),
189    ok.
190
191install_5a(TestNode) ->
192    ?print(["install_5a start"]),
193
194    %% Install P1I (this will be a downgrade)
195    {ok, "P1I", [old_emu]} = release_handler:install_release("P1I"),
196    %% Node is rebooted by the release_handler:install_release
197    %% (init:reboot) because P2A includes a new erts vsn and the relup
198    %% file contains a 'restart_new_emulator' instruction.
199    ?print(["install_5a P1I installed"]),
200    ok.
201
202install_6(TestNode) ->
203    ?print(["install_6 start"]),
204
205    %% Check that P1I is used
206    ?check_release_states([old,permanent,current,old]),
207    ?check_running_app(a,"1.1"),
208
209    %% Make P1I permanent
210    ok = release_handler:make_permanent("P1I"),
211    ?check_release_states([old,old,permanent,old]),
212    ?check_running_app(a,"1.1"),
213    ok.
214
215install_6a(TestNode) ->
216    %% Install P2A
217    {continue_after_restart, "P1I", [new_emu]} =
218	release_handler:install_release("P2A"),
219    %% Node is rebooted by the release_handler:install_release
220    %% (init:reboot) because P2A includes a new erts vsn and the relup
221    %% file contains a 'restart_new_emulator' instruction.
222    ?print(["install_6a P2A installed"]),
223    ok.
224
225install_7(TestNode) ->
226    ?print(["install_7 start"]),
227
228    %% Check that the upgrade was done via a temporary release due to
229    %% new emulator version.
230    {"SASL-test","__new_emulator__P1I"} = init:script_id(),
231
232    % Check that P2A is in use.
233    ?check_release_states([old,old,permanent,current]),
234    ?check_running_app(a,"1.1"),
235    X = a:a(),
236    {key2, newval2} = lists:keyfind(key2, 1, X),
237    {key1, val1} = lists:keyfind(key1, 1, X),
238    {ok, bval} = a:b(),
239    ?print(["install_7 check env ok"]),
240    ok.
241
242install_7a(TestNode) ->
243    %% Install P1H (this will be a downgrade)
244    {ok, "P1H", [old_emu,old_appl]} = release_handler:install_release("P1H"),
245    %% Node is rebooted by the release_handler:install_release
246    %% (init:reboot) because P2A includes a new erts vsn and the relup
247    %% file contains a 'restart_new_emulator' instruction.
248    ?print(["install_7a P1H installed"]),
249    ok.
250
251install_8(TestNode) ->
252    ?print(["install_8 start"]),
253
254    %% Check that P1H is used
255    ?check_release_states([old,current,permanent,old]),
256    ?check_running_app(a,"1.0"),
257    {ok,"P1H",[new_emu,new_appl]} = release_handler:check_install_release("P2A"),
258    ?print(["install_8 check_install_release P2A ok"]),
259
260    %% Install P1I and check that it is permanent
261    {ok,"P1H",[{extra, gott}]} = release_handler:install_release("P1I"),
262    ?check_release_states([old,old,permanent,old]),
263    ?check_running_app(a,"1.1"),
264    ok.
265
266install_8a(TestNode) ->
267    % Install P2A again
268    {continue_after_restart, "P1I", [new_emu]} =
269	release_handler:install_release("P2A"),
270    %% Node is rebooted by the release_handler:install_release
271    %% (init:reboot) because P2A includes a new erts vsn and the relup
272    %% file contains a 'restart_new_emulator' instruction.
273    ?print(["install_8a P2A installed"]),
274    ok.
275
276install_9(TestNode) ->
277    ?print(["install_9 start"]),
278
279    %% Check that the upgrade was done via a temporary release due to
280    %% new emulator version.
281    {"SASL-test","__new_emulator__P1I"} = init:script_id(),
282
283    % Check that P2A is used
284    ?check_release_states([old,old,permanent,current]),
285    ?check_running_app(a,"1.1"),
286    X = a:a(),
287    {key2, newval2} = lists:keyfind(key2, 1, X),
288    {key1, val1} = lists:keyfind(key1, 1, X),
289    {ok, bval} = a:b(),
290    ?print(["install_9 check env ok"]),
291    ok = release_handler:make_permanent("P2A"),
292    ?check_release_states([old,old,old,permanent]),
293    ?check_running_app(a,"1.1"),
294    ok.
295    % release_handler_SUITE will reboot this node now!
296
297
298install_10(TestNode) ->
299    ?print(["install_10 start"]),
300
301    % Check that P2A is used
302    ?check_release_states([old,old,old,permanent]),
303    ?check_running_app(a,"1.1"),
304
305    % Install old P1H
306    ok = release_handler:reboot_old_release("P1H"),
307    ?print(["install_10 reboot_old ok"]),
308    ok.
309
310
311install_11(TestNode) ->
312    ?print(["install_11 start"]),
313
314    % Check that P1H is permanent
315    ?check_release_states([old,permanent,old,old]),
316    ?check_running_app(a,"1.0"),
317    X = a:a(),
318    {key2, val2} = lists:keyfind(key2, 1, X),
319    {key1, val1} = lists:keyfind(key1, 1, X),
320    ?print(["install_11 check env ok"]),
321
322    %% Remove P1I and P2A and check that a-1.1 and erts-<latest> are removed
323    ok = release_handler:remove_release("P2A"),
324    ?check_release_states([old,permanent,old]),
325    ok = release_handler:remove_release("P1I"),
326    ?check_release_states([old,permanent]),
327    {ok, Libs} = file:list_dir(code:lib_dir()),
328    {_,_,StdlibVsn} = lists:keyfind(stdlib,1,application:which_applications()),
329    true = lists:member("stdlib-"++StdlibVsn, Libs),
330    true = lists:member("a-1.0", Libs),
331    false = lists:member("a-1.1", Libs),
332    {ok, Dirs} = file:list_dir(code:root_dir()),
333    ErtsDir = "erts-"++?ertsvsn,
334    [ErtsDir] = lists:filter(fun(Dir) -> lists:prefix("erts-",Dir) end, Dirs),
335    ?print(["install_11 file checks ok"]),
336    ok.
337    % release_handler_SUITE will reboot this node now!
338
339install_12(TestNode) ->
340    ?print(["install_12 start"]),
341
342    % Check that P1H is permanent
343    ?check_release_states([old,permanent]),
344    ?check_running_app(a,"1.0"),
345    X = a:a(),
346    {key2, val2} = lists:keyfind(key2, 1, X),
347    {key1, val1} = lists:keyfind(key1, 1, X),
348    ?print(["install_12 check env ok"]),
349
350    % Install old P1G
351    ok = release_handler:reboot_old_release("P1G"),
352    ?print(["install_12 reboot_old ok"]),
353    ok.
354
355install_13(TestNode) ->
356    ?print(["install_13 start"]),
357
358    % Check that P1G is permanent
359    ?check_release_states([permanent,old]),
360    false = lists:keysearch(a,1,application:loaded_applications()),
361    ?print(["install_13 no a application found - ok"]),
362
363    %% Remove P1H and check that both versions of application a is removed
364    ok = release_handler:remove_release("P1H"),
365    ?check_release_states([permanent]),
366    {ok, Libs} = file:list_dir(code:lib_dir()),
367    {_,_,StdlibVsn} = lists:keyfind(stdlib,1,application:which_applications()),
368    true = lists:member("stdlib-"++StdlibVsn, Libs),
369    false = lists:member("a-1.0", Libs),
370    false = lists:member("a-1.1", Libs),
371    ?print(["install_13 file checks ok"]),
372    ok.
373    % release_handler_SUITE will reboot this node now!
374
375install_14(TestNode) ->
376    ?print(["install_14 start"]),
377
378    % Check that P1G is permanent
379    ?check_release_states([permanent]),
380    false = lists:keysearch(a,1,application:loaded_applications()),
381    ?print(["install_13 no a application found - ok"]),
382    ok.
383
384
385%%%-----------------------------------------------------------------
386%%% Ths test checks that an upgrade which both upgrades to a new
387%%% emulator version, and had a restart_emulator option to
388%%% systools:make_relup will be restarted twice on upgrade.
389%%% (On downgrade it will happen only once.)
390upgrade_restart_1(TestNode,PrivDir) ->
391    ?print([TestNode]),
392    ?print(["upgrade_restart_1 start"]),
393    ?check_release_states([permanent]),
394
395    {ok, "P2B"} = unpack_release(PrivDir,"rel4"),
396    ?check_release_states([permanent,unpacked]),
397    ?check_release_lib("P2B",["a-1.1"]),
398    ok.
399
400upgrade_restart_1a(TestNode) ->
401    ?print(["upgrade_restart_1a start"]),
402
403    {continue_after_restart,"P1G",[new_emu,add_appl]} =
404	release_handler:install_release("P2B"),
405    ?print(["upgrade_restart_1a P2B installed"]),
406    ok.
407
408upgrade_restart_2(TestNode) ->
409    ?print(["upgrade_restart_2 start"]),
410
411    %% Check that the node has been restarted once more after the tmp release
412    case init:script_id() of
413	{"SASL-test","P2B"} ->
414	    upgrade_restart_2a(TestNode);
415	{"SASL-test","__new_emulator__P1G"} ->
416	    %% catched the node too early - give it another try
417	    {wait,whereis(init)}
418    end.
419
420upgrade_restart_2a(TestNode) ->
421    ?print(["upgrade_restart_2a start"]),
422
423    %% This time we must be there, else something is definitely wrong
424    {"SASL-test","P2B"} = init:script_id(),
425
426    ?check_release_states([permanent,current]),
427    ?check_running_app(a,"1.1"),
428
429    ok = release_handler:make_permanent("P2B"),
430    ?check_release_states([old,permanent]),
431
432    ok.
433
434upgrade_restart_2b(TestNode) ->
435    ?print(["upgrade_restart_2b start"]),
436
437    {ok,"P1G",[old_emu,rm_appl]} = release_handler:install_release("P1G"),
438    ?print(["upgrade_restart_2b P1G installed"]),
439    ok.
440
441upgrade_restart_3(TestNode) ->
442    ?print(["upgrade_restart_3 start"]),
443
444    %% Ideally we should test that the node has only been restarted
445    %% once... but that's not so easy. Let's just check that P1G is running.
446    ?check_release_states([current,permanent]),
447    false = lists:keysearch(a,1,application:loaded_applications()),
448    ?print(["upgrade_restart_3 no a application found - ok"]),
449
450    ok.
451
452
453
454
455%%-----------------------------------------------------------------
456%% This test starts a client node which uses this node as master
457%% for the release_handler.
458%% The client node runs all tests as in installer/1 test case.
459%% Thus, the client node will be rebooted several times.
460%% The to_erl /tmp/NODENAME@HOSTNAME/ command can be used to connect
461%% to the client node.
462%% run_erl logs for the client can be found in the directory:
463%%   code:root_dir() ++ "/clients/type1/NODENAME@HOSTNAME/log
464%%-----------------------------------------------------------------
465
466
467client1_1(TestNode,PrivDir,MasterDir,ClientSname) ->
468    TestHost = test_host(),
469    ?print(["client1_1 start"]),
470
471    {ok,IP} = inet:getaddr(TestHost,inet),
472    erl_boot_server:start([IP]),
473
474    ok = net_kernel:monitor_nodes(true),
475    Node = start_client(TestNode,client1,ClientSname),
476    trace_disallowed_calls(Node),
477
478    ?check_release_states_client(Node,[permanent]),
479
480    %% Check env var for SASL on client node
481    SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
482    ?print([{client1_1,sasl_env},SaslEnv]),
483    {_,CliDir} = lists:keyfind(client_directory,1,SaslEnv),
484    {_,[Master]} = lists:keyfind(masters,1,SaslEnv),
485    {_,StartCli} = lists:keyfind(start_prg,1,SaslEnv),
486    NodeStr = atom_to_list(Node),
487    [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)),
488    true = (Master =:= node()),
489    case os:type() of
490	{unix,_} ->
491	    true = (StartCli =:= filename:join([CliDir,"bin","start"]));
492	_ ->
493	    ok
494    end,
495
496    %% Unpack P1H on master
497    {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
498
499    %% Unpack and install P1H on client
500    Root = code:root_dir(),
501    P1HDir = filename:join([Root, "releases", "P1H"]),
502
503    %% The AppDirs argument (last arg to set_unpacked) below is really
504    %% not necessary, it could just be [] since the path is the same
505    %% as default. But it is given here in order to force hitting the
506    %% release_handler:check_path function so it can be checked that
507    %% it does not use file:read_file_info on the client node, see
508    %% trace_disallowed_calls/1 and check_disallowed_calls/2 below.
509    %% (OTP-9142)
510    {ok, "P1H"} = rpc:call(Node, release_handler, set_unpacked,
511			   [filename:join(P1HDir, "rel1.rel"),
512			    [{a,"1.0",filename:join(MasterDir,lib)}]]),
513
514    ?check_release_states_client(Node,[permanent,unpacked]),
515    ?check_release_lib_client(Node,"P1H",["a-1.0"]),
516
517    ok = rpc:call(Node, release_handler, install_file,
518		  ["P1H", filename:join(P1HDir, "start.boot")]),
519    ok = rpc:call(Node, release_handler, install_file,
520		  ["P1H", filename:join(P1HDir, "sys.config")]),
521    ok = rpc:call(Node, release_handler, install_file,
522		  ["P1H", filename:join(P1HDir, "relup")]),
523    ?print([{release_handler_state, Node},
524	    rpc:call(Node, sys, get_status, [release_handler])]),
525
526    {ok,"P1G",[new_appl]} =
527	rpc:call(Node, release_handler, check_install_release, ["P1H"]),
528
529    {ok,"P1G",[new_appl]} =
530	rpc:call(Node, release_handler, install_release, ["P1H"]),
531
532    ?check_release_states_client(Node,[permanent,current]),
533    ?check_running_app_client(Node,a,"1.0"),
534
535    Apps = rpc:call(Node, application, which_applications, []),
536    {a,"A  CXC 138 11","1.0"} = lists:keyfind(a, 1, Apps),
537    X = rpc:call(Node, a, a, []),
538    {key2, val2} = lists:keyfind(key2, 1, X),
539    {key1, val1} = lists:keyfind(key1, 1, X),
540
541    ?check_disallowed_calls,
542    reboot(TestNode,Node),
543    trace_disallowed_calls(Node),
544
545    client1_2(TestNode,PrivDir,Node).
546
547client1_2(TestNode,PrivDir,Node) ->
548    ?print(["client1_2 start"]),
549
550    %% Check that P1H is still unpacked, install it and make_permanent
551    ?check_release_states_client(Node,[permanent,unpacked]),
552
553    {ok,"P1G",[new_appl]} =
554	rpc:call(Node, release_handler, install_release, ["P1H"]),
555    ?check_release_states_client(Node,[permanent,current]),
556    ?check_running_app_client(Node,a,"1.0"),
557
558    ok = rpc:call(Node, release_handler, make_permanent, ["P1H"]),
559    ?check_release_states_client(Node,[old,permanent]),
560
561    ?check_disallowed_calls,
562    reboot(TestNode,Node),
563    trace_disallowed_calls(Node),
564
565    client1_3(TestNode,PrivDir,Node).
566
567client1_3(TestNode,PrivDir,Node) ->
568    ?print(["client1_3 start"]),
569
570    %% Check that P1H is permanent
571    ?check_release_states_client(Node,[old,permanent]),
572    ?check_running_app_client(Node,a,"1.0"),
573
574    %% Unpack P1I on master
575    {ok, "P1I"} = unpack_release(PrivDir,"rel2"),
576
577    MasterRoot = code:root_dir(),
578
579    %% Unpack and install P1I on client
580    P1IDir = filename:join([MasterRoot, "releases", "P1I"]),
581    {ok, "P1I"} = rpc:call(Node, release_handler, set_unpacked,
582			   [filename:join(P1IDir, "rel2.rel"),[]]),
583
584    ?check_release_states_client(Node,[old,permanent,unpacked]),
585    ?check_release_lib_client(Node,"P1I",["a-1.1"]),
586
587    ok = rpc:call(Node, release_handler, install_file,
588                  ["P1I", filename:join(P1IDir, "start.boot")]),
589    ok = rpc:call(Node, release_handler, install_file,
590                  ["P1I", filename:join(P1IDir, "sys.config")]),
591    ok = rpc:call(Node, release_handler, install_file,
592                  ["P1I", filename:join(P1IDir, "relup")]),
593
594    {ok,"P1H",[{extra, gott}]} =
595        rpc:call(Node, release_handler, check_install_release, ["P1I"]),
596    {error,_} = rpc:call(Node, release_handler, check_install_release, ["P1J"]),
597    {ok,"P1H",[{extra, gott}]} =
598        rpc:call(Node, release_handler, install_release, ["P1I"]),
599
600    ?check_release_states_client(Node,[old,permanent,current]),
601    ?check_running_app_client(Node,a,"1.1"),
602    X2 = rpc:call(Node, a, a, []),
603    {key2, newval2} = lists:keyfind(key2, 1, X2),
604    {key1, val1} = lists:keyfind(key1, 1, X2),
605    {ok, bval} = rpc:call(Node, a, b, []),
606
607    %% Unpack P2A on master
608    {ok, "P2A"} = unpack_release(PrivDir,"rel3"),
609
610    %% Unpack and install P2A on client
611    P2ADir = filename:join([MasterRoot, "releases", "P2A"]),
612    {ok, "P2A"} =
613        rpc:call(Node, release_handler, set_unpacked,
614                 [filename:join(P2ADir, "rel3.rel"),[]]),
615
616    ?check_release_states_client(Node,[old,permanent,current,unpacked]),
617    ?check_release_lib_client(Node,"P2A",["a-1.1"]),
618
619    ok = rpc:call(Node, release_handler, install_file,
620                  ["P2A", filename:join(P2ADir, "start.boot")]),
621    ok = rpc:call(Node, release_handler, install_file,
622                  ["P2A", filename:join(P2ADir, "sys.config")]),
623    ok = rpc:call(Node, release_handler, install_file,
624                  ["P2A", filename:join(P2ADir, "relup")]),
625
626    {ok, "P1I", [new_emu]} =
627	rpc:call(Node, release_handler, check_install_release, ["P2A"]),
628
629    %% Reboot from P1H
630    ?check_disallowed_calls,
631    reboot(TestNode,Node),
632    trace_disallowed_calls(Node),
633
634    client1_4(TestNode,Node).
635
636client1_4(TestNode,Node) ->
637    ?print(["client1_4 start"]),
638
639    %% check that P1H is used
640    ?check_release_states_client(Node,[old,permanent,unpacked,unpacked]),
641
642    %% since the install_release below reboot the node...
643    ?check_disallowed_calls,
644    cover_client(TestNode,Node,stop_cover),
645
646    {continue_after_restart, "P1H", [new_emu,new_appl]} =
647	rpc:call(Node, release_handler, install_release, ["P2A"]),
648    %% Reboots the client !
649
650    check_reboot(TestNode,Node),
651    trace_disallowed_calls(Node),
652
653    client1_5(TestNode,Node).
654
655client1_5(TestNode,Node) ->
656    ?print(["client1_5 start"]),
657
658    %% Check that P2A is in use.
659    ?check_release_states_client(Node,[old,permanent,unpacked,current]),
660    ?check_running_app_client(Node,a,"1.1"),
661    X = rpc:call(Node, a, a, []),
662    {key2, newval2} = lists:keyfind(key2, 1, X),
663    {key1, val1} = lists:keyfind(key1, 1, X),
664    {ok, bval} = rpc:call(Node, a, b, []),
665
666    %% since the install_release below reboot the node...
667    ?check_disallowed_calls,
668    cover_client(TestNode,Node,stop_cover),
669
670    {ok,"P1I",[old_emu]} =
671        rpc:call(Node, release_handler, install_release, ["P1I"]),
672
673    check_reboot(TestNode,Node),
674    trace_disallowed_calls(Node),
675
676    client1_6(TestNode,Node).
677
678client1_6(TestNode,Node) ->
679    ?print(["client1_6 start"]),
680
681    ?check_release_states_client(Node,[old,permanent,current,old]),
682    ?check_running_app_client(Node,a,"1.1"),
683
684    ok = rpc:call(Node, release_handler, make_permanent, ["P1I"]),
685    ?check_release_states_client(Node,[old,old,permanent,old]),
686
687    %% since the install_release below reboot the node...
688    ?check_disallowed_calls,
689    cover_client(TestNode,Node,stop_cover),
690
691    {continue_after_restart, "P1I", [new_emu]} =
692	rpc:call(Node, release_handler, install_release, ["P2A"]),
693    %% Reboots the client !
694
695    check_reboot(TestNode,Node),
696    trace_disallowed_calls(Node),
697
698    client1_7(TestNode,Node).
699
700client1_7(TestNode,Node) ->
701    ?print(["client1_7 start"]),
702
703    %% Check that P2A is in use.
704    ?check_release_states_client(Node,[old,old,permanent,current]),
705    ?check_running_app_client(Node,a,"1.1"),
706    X = rpc:call(Node, a, a, []),
707    {key2, newval2} = lists:keyfind(key2, 1, X),
708    {key1, val1} = lists:keyfind(key1, 1, X),
709    {ok, bval} = rpc:call(Node, a, b, []),
710
711    %% since the install_release below reboot the node...
712    ?check_disallowed_calls,
713    cover_client(TestNode,Node,stop_cover),
714
715    {ok,"P1H",[old_emu,old_appl]} =
716        rpc:call(Node, release_handler, install_release, ["P1H"]),
717
718    check_reboot(TestNode,Node),
719    trace_disallowed_calls(Node),
720
721    client1_8(TestNode,Node).
722
723client1_8(TestNode,Node) ->
724    ?print(["client1_8 start"]),
725
726    %% Check that P1H is used
727    ?check_release_states_client(Node,[old,current,permanent,old]),
728    ?check_running_app_client(Node,a,"1.0"),
729    {ok, "P1H", [new_emu,new_appl]} =
730	rpc:call(Node, release_handler, check_install_release, ["P2A"]),
731
732
733    {ok,"P1H",[{extra, gott}]} =
734        rpc:call(Node, release_handler, install_release, ["P1I"]),
735    ?check_release_states_client(Node,[old,old,permanent,old]),
736    ?check_running_app_client(Node,a,"1.1"),
737
738
739    %% since the install_release below will reboot the node...
740    ?check_disallowed_calls,
741    cover_client(TestNode,Node,stop_cover),
742
743    %% Install P2A again
744    {continue_after_restart, "P1I", [new_emu]} =
745	rpc:call(Node, release_handler, install_release, ["P2A"]),
746
747    %% We are rebooted again.
748    check_reboot(TestNode,Node),
749    trace_disallowed_calls(Node),
750
751    client1_9(TestNode,Node).
752
753client1_9(TestNode,Node) ->
754    ?print(["client1_9 start"]),
755
756    %% Check that P2A is used
757    ?check_release_states_client(Node,[old,old,permanent,current]),
758    ?check_running_app_client(Node,a,"1.1"),
759    X = rpc:call(Node, a, a, []),
760    {key2, newval2} = lists:keyfind(key2, 1, X),
761    {key1, val1} = lists:keyfind(key1, 1, X),
762    {ok, bval} = rpc:call(Node, a, b, []),
763
764    %% Make P2A permanent
765    ok = rpc:call(Node, release_handler, make_permanent, ["P2A"]),
766    ?check_release_states_client(Node,[old,old,old,permanent]),
767
768    %% Reboot from P2A
769    ?check_disallowed_calls,
770    reboot(TestNode,Node),
771    trace_disallowed_calls(Node),
772
773    client1_10(TestNode,Node).
774
775client1_10(TestNode,Node) ->
776    ?print(["client1_10 start"]),
777
778    %% Check that P2A is used
779    ?check_release_states_client(Node,[old,old,old,permanent]),
780
781    %% since the reboot_old_release below will reboot the node
782    ?check_disallowed_calls,
783    cover_client(TestNode,Node,stop_cover),
784
785    %% Install old P1H
786    rpc:call(Node, release_handler, reboot_old_release, ["P1H"]),
787    %% We are rebooted.
788    check_reboot(TestNode,Node),
789    trace_disallowed_calls(Node),
790
791    client1_11(TestNode,Node).
792
793client1_11(TestNode,Node) ->
794    ?print(["client1_11 start"]),
795
796    %% Check that P1H is permanent
797    ?check_release_states_client(Node,[old,permanent,old,old]),
798    ?check_running_app_client(Node,a,"1.0"),
799    X = rpc:call(Node, a, a, []),
800    {key2, val2} = lists:keyfind(key2, 1, X),
801    {key1, val1} = lists:keyfind(key1, 1, X),
802
803    %% Remove P1I and P2A from client
804    ok = rpc:call(Node, release_handler, set_removed, ["P2A"]),
805    ?check_release_states_client(Node,[old,permanent,old]),
806    ok = rpc:call(Node, release_handler, set_removed, ["P1I"]),
807    ?check_release_states_client(Node,[old,permanent]),
808
809    %% Check that P2A and P1I does not exists
810    Rels = rpc:call(Node, release_handler, which_releases, []),
811    false = lists:keysearch("P2A", 2, Rels),
812    false = lists:keysearch("P1I", 2, Rels),
813    X = rpc:call(Node, a, a, []),
814    {key2, val2} = lists:keyfind(key2, 1, X),
815    {key1, val1} = lists:keyfind(key1, 1, X),
816
817    ?check_disallowed_calls,
818    reboot(TestNode,Node),
819    trace_disallowed_calls(Node),
820
821    client1_12(TestNode,Node).
822
823client1_12(TestNode,Node) ->
824    ?print(["client1_12 start"]),
825
826    ?check_release_states_client(Node,[old,permanent]),
827
828    %% since the reboot_old_release below will reboot the node
829    ?check_disallowed_calls,
830    cover_client(TestNode,Node,stop_cover),
831
832    %% Install old P1G
833    rpc:call(Node, release_handler, reboot_old_release, ["P1G"]),
834    %% We are rebooted.
835    check_reboot(TestNode,Node),
836    trace_disallowed_calls(Node),
837
838    client1_13(TestNode,Node).
839
840client1_13(TestNode,Node) ->
841    ?print(["client1_13 start"]),
842
843    %% Check that P1G is permanent
844    ?check_release_states_client(Node,[permanent,old]),
845    {error,client_node} = rpc:call(Node,release_handler,remove_release,["P1H"]),
846    ok = rpc:call(Node, release_handler, set_removed, ["P1H"]),
847    ?check_release_states_client(Node,[permanent]),
848
849    ?check_disallowed_calls,
850    reboot(TestNode,Node),
851    trace_disallowed_calls(Node),
852
853    client1_14(TestNode,Node).
854
855client1_14(TestNode,Node) ->
856    ?print(["client1_14 start"]),
857
858    %% Check that P1G is permanent
859    ?check_release_states_client(Node,[permanent]),
860
861    ?check_disallowed_calls,
862    stop_client(TestNode,Node),  %% TEST IS OK !!
863    net_kernel:monitor_nodes(false),
864
865    %% Remove releases from master
866    ok = release_handler:remove_release("P2A"),
867    ok = release_handler:remove_release("P1I"),
868    ok = release_handler:remove_release("P1H"),
869    ok.
870
871%% Start tracing of the file module on the client node. This module
872%% shall never be called, since
873%% 1) the node is a client from the release_handler's point of view,
874%%    so all file access should be done via rpc calls to the master
875%% 2) it is started with erl_prim_loader loader set to 'inet' so all
876%%    code loading should be done via the inet to the master
877%% (OTP-9142)
878%% This function is called each time the client node is started and to
879%% check if a call has been made, call check_disallowed_node/0
880trace_disallowed_calls(Node) ->
881    MasterProc = self(),
882    rpc:call(Node,dbg,tracer,[process,{fun(T,_) -> MasterProc ! T end,[]}]),
883    rpc:call(Node,dbg,p,[all,call]),
884    rpc:call(Node,dbg,tp,[file,[{'_',[],[{message,{caller}}]}]]),
885    %% File:native_name_encoding/0 is a BIF and OK to use
886    rpc:call(Node,dbg,ctp,[file,native_name_encoding,0]).
887
888check_disallowed_calls(TestNode,Line) ->
889    receive
890	Trace when element(1,Trace)==trace ->
891	    ?print_line(Line,["Disallowed function called",Trace]),
892	    exit({disallowed_function_call,Trace})
893    after 0 ->
894	    ok
895    end.
896
897start_client(TestNode,Client,Sname) ->
898    Node = list_to_atom(lists:concat([Sname,"@",test_host()])),
899    case os:type() of
900	{unix,_} -> start_client_unix(TestNode,Sname,Node);
901	{win32,_} -> start_client_win32(TestNode,Client,Sname)
902    end,
903    receive
904        {nodeup, Node} ->
905            wait_started(TestNode,Node)
906    after 60000 ->
907	    ?print([{start_client,failed,Node},net_adm:ping(Node)]),
908            ?fail({"cannot start", Node})
909    end.
910
911start_client_unix(TestNode,Sname,Node) ->
912    Start = filename:join(["clients", "type1", Node, "bin", "start"]),
913    Cmd = filename:join(code:root_dir(), Start),
914    ?print([{start_client,Sname},Cmd]),
915    Res = rh_test_lib:cmd(Cmd,[],[{"NODENAME",atom_to_list(Sname)}]),
916    ?print([{start_client,result},Res]).
917
918start_client_win32(TestNode,Client,ClientSname) ->
919    Name = atom_to_list(ClientSname) ++ "_P1G",
920    RootDir = code:root_dir(),
921    ErtsBinDir = filename:join([RootDir,"erts-"++?ertsvsn,"bin"]),
922
923    {ClientArgs,RelClientDir} = rh_test_lib:get_client_args(Client,ClientSname,
924							    RootDir),
925    StartErlArgs = rh_test_lib:get_start_erl_args(RootDir,RelClientDir,
926						  ClientArgs),
927    ServiceArgs = rh_test_lib:get_service_args(RootDir, RelClientDir,
928					       ClientSname, StartErlArgs),
929
930    ?print([{start_client,ClientSname},ServiceArgs]),
931    Erlsrv = filename:nativename(filename:join(ErtsBinDir,"erlsrv")),
932    rh_test_lib:erlsrv(Erlsrv,stop,Name),
933    rh_test_lib:erlsrv(Erlsrv,remove,Name),
934    ok = rh_test_lib:erlsrv(Erlsrv,add,Name,ServiceArgs),
935    ok = rh_test_lib:erlsrv(Erlsrv,start,Name),
936    ?print([{start_client,result},ok]),
937    ok.
938
939reboot(TestNode,Node) ->
940    cover_client(TestNode,Node,stop_cover),
941    rpc:call(Node, init, reboot, []),
942    check_reboot(TestNode,Node).
943
944%% This way of checking that the node is rebooted will only work if
945%% the nodes are automatically re-connected after the reboot. This
946%% happens for master/client (when sasl is started on the client).
947check_reboot(TestNode,Node) ->
948    receive
949        {nodedown, Node} ->
950            receive
951                {nodeup, Node} -> wait_started(TestNode,Node)
952            after 30000 ->
953		    ?fail({Node, "not rebooted",net_adm:ping(Node)})
954            end
955    after 30000 ->
956            ?fail({Node, "not closing down",net_adm:ping(Node)})
957    end.
958
959stop_client(TestNode,Node) ->
960    cover_client(TestNode,Node,stop_cover),
961    rpc:call(Node, init, stop, []),
962    receive
963        {nodedown, Node} -> ok
964    after 30000 ->
965            ?fail({Node, "not stopping"})
966    end.
967
968wait_started(TestNode,Node) ->
969    case rpc:call(Node, init, get_status, []) of
970        {started, _} ->
971	    cover_client(TestNode,Node,start_cover),
972            Node;
973        _ ->
974            timer:sleep(1000),
975            wait_started(TestNode,Node)
976    end.
977
978cover_client(TestNode,Node,Func) ->
979    R = rpc:call(TestNode,release_handler_SUITE,Func,[Node]),
980    ?print([{Func,Node,R}]).
981
982
983%%-----------------------------------------------------------------
984%% This test starts a client node which uses this node as master
985%% for the release_handler.
986%% The client node has the name cli2@HOSTNAME.
987%% The client node is not allowed to do ANY release updates
988%% as it also have another (non-existing) master node.
989%%
990%% The to_erl /tmp/cli2@HOSTNAME/ command can be used to connect
991%% to the client node.
992%% run_erl logs for the client can be found in the directory:
993%%   code:root_dir() ++ "/clients/type1/cli2@HOSTNAME/log
994%%-----------------------------------------------------------------
995client2(TestNode,PrivDir,ClientSname) ->
996    TestHost = test_host(),
997    ?print(["client2 start"]),
998
999    %% Clean up if previous test case failed
1000    release_handler:remove_release("P1H"),
1001
1002    ok = net_kernel:monitor_nodes(true),
1003    Node = start_client(TestNode,client2,ClientSname),
1004
1005    %% Check env var for SASL on client node
1006    SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
1007    ?print([{client1_1,sasl_env},SaslEnv]),
1008    {_,CliDir} = lists:keyfind(client_directory,1,SaslEnv),
1009    {_,[Master,Master2]} = lists:keyfind(masters,1,SaslEnv),
1010    {_,StartCli} = lists:keyfind(start_prg,1,SaslEnv),
1011    NodeStr = atom_to_list(Node),
1012    [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)),
1013    true = (Master =:= node()),
1014    true = (Master2 =:= list_to_atom("master2@"++TestHost)),
1015    case os:type() of
1016	{unix,_} ->
1017	    true = (StartCli =:= filename:join([CliDir,"bin","start"]));
1018	_ ->
1019	    ok
1020    end,
1021
1022    %% Unpack P1H on master
1023    {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
1024
1025    %% Try to set P1H unpacked on client
1026    Root = code:root_dir(),
1027    {error,{bad_masters,[Master2]}} =
1028	rpc:call(Node, release_handler, set_unpacked,
1029		 [filename:join([Root, "releases", "P1H", "rel1.rel"]),[]]),
1030
1031    {error,{no_such_release,"P1H"}} =
1032	rpc:call(Node, release_handler, check_install_release, ["P1H"]),
1033
1034    stop_client(TestNode,Node),  %% TEST IS OK !!
1035    net_kernel:monitor_nodes(false),
1036
1037    release_handler:remove_release("P1H"),
1038    ok.
1039
1040
1041stop(Now) ->
1042    %% The timestamp is only used for debugging. It is printed by
1043    %% release_handler_SUITE also.
1044    R = init:stop(),
1045    erlang:display({init_stop,Now,R}),
1046    R.
1047
1048unpack_p1h(TestNode,PrivDir) ->
1049    {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
1050    ?check_release_states([permanent,unpacked]),
1051    ?check_release_lib("P1H",["a-1.0"]),
1052    ok.
1053
1054permanent_p1h(TestNode) ->
1055    ?check_release_states([permanent,unpacked]),
1056    ?check_release_lib("P1H",["a-1.0"]),
1057    {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
1058    ?check_release_states([permanent,current]),
1059    ok = release_handler:make_permanent("P1H"),
1060    ?check_release_states([old,permanent]),
1061    ok.
1062
1063
1064reg_proc(Name) ->
1065    catch unregister(Name),
1066    Pid = spawn_link(?MODULE, registered_loop, [Name]),
1067    global:register_name(Name, Pid),
1068    ok.
1069
1070registered_loop(_Name) ->
1071    receive
1072        kill ->
1073            exit(killed)
1074    end.
1075
1076%% Checks that the list of states for all releases (sorted on vsn)
1077%% equals the input States
1078check_release_states(TestNode,Node,States,Line) ->
1079    case rpc:call(Node,release_handler,which_releases,[]) of
1080	{badrpc,_}=Error ->
1081	    ?fail_line(Line,{check_release_states,Node,States,Error});
1082	Rels ->
1083	    ?print_line(Line,["check_release_states:", Rels]),
1084	    States = [Status || {_,_,_,Status} <- lists:keysort(2,Rels)],
1085	    ok
1086    end.
1087
1088%% Check that the given release (Vsn) sees the correct vsn of App.
1089check_release_lib(TestNode,Node,Vsn,Apps,Line) ->
1090    case rpc:call(Node,release_handler,which_releases,[]) of
1091	{badrpc,_}=Error ->
1092	    ?fail_line(Line,{check_release_lib,Node,Vsn,Apps,Error});
1093	Rels ->
1094	    ?print_line(Line,["check_release_lib:", Rels]),
1095	    {"SASL-test", Vsn, Libs, _Status} = lists:keyfind(Vsn, 2, Rels),
1096	    true = lists:all(fun(App) -> lists:member(App,Libs) end,Apps),
1097	    ok
1098    end.
1099
1100%% Check that the given Vsn of App is executed
1101check_running_app(TestNode,Node,App,Vsn,Line) ->
1102    case rpc:call(Node,application,which_applications,[]) of
1103	{badrpc,_}=Error ->
1104	    ?fail_line(Line,{check_running_app,Node,App,Vsn,Error});
1105	Apps ->
1106	    ?print_line(Line,["check_running_app:", Apps]),
1107	    {App, _, Vsn} = lists:keyfind(App, 1, Apps),
1108	    ok
1109    end.
1110
1111test_host() ->
1112    {ok,Host} = inet:gethostname(),
1113    Host.
1114
1115unpack_release(PrivDir,Rel) ->
1116    copy(filename:join([PrivDir,Rel,Rel++".tar.gz"]),
1117	 filename:join(code:root_dir(),releases)),
1118    release_handler:unpack_release(Rel).
1119
1120copy(Src, DestDir) ->
1121    Dest = filename:join(DestDir, filename:basename(Src)),
1122    {ok,_} = file:copy(Src, Dest),
1123    ok.
1124
1125