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