at 24.11-pre 69 kB view raw
1# Test configuration switching. 2 3import ./make-test-python.nix ({ lib, pkgs, ng, ...} : let 4 5 # Simple service that can either be socket-activated or that will 6 # listen on port 1234 if not socket-activated. 7 # A connection to the socket causes 'hello' to be written to the client. 8 socketTest = pkgs.writeScript "socket-test.py" /* python */ '' 9 #!${pkgs.python3}/bin/python3 10 11 from socketserver import TCPServer, StreamRequestHandler 12 import socket 13 import os 14 15 16 class Handler(StreamRequestHandler): 17 def handle(self): 18 self.wfile.write("hello".encode("utf-8")) 19 20 21 class Server(TCPServer): 22 def __init__(self, server_address, handler_cls): 23 listenFds = os.getenv('LISTEN_FDS') 24 if listenFds is None or int(listenFds) < 1: 25 print(f'Binding to {server_address}') 26 TCPServer.__init__( 27 self, server_address, handler_cls, bind_and_activate=True) 28 else: 29 TCPServer.__init__( 30 self, server_address, handler_cls, bind_and_activate=False) 31 # Override socket 32 print(f'Got activated by {os.getenv("LISTEN_FDNAMES")} ' 33 f'with {listenFds} FDs') 34 self.socket = socket.fromfd(3, self.address_family, 35 self.socket_type) 36 37 38 if __name__ == "__main__": 39 server = Server(("localhost", 1234), Handler) 40 server.serve_forever() 41 ''; 42 43in { 44 name = "switch-test"; 45 meta = with pkgs.lib.maintainers; { 46 maintainers = [ gleber das_j ]; 47 }; 48 49 nodes = { 50 machine = { pkgs, lib, ... }: { 51 system.switch = { 52 enable = !ng; 53 enableNg = ng; 54 }; 55 56 environment.systemPackages = [ pkgs.socat ]; # for the socket activation stuff 57 users.mutableUsers = false; 58 59 # For boot/switch testing 60 system.build.installBootLoader = lib.mkForce (pkgs.writeShellScript "install-dummy-loader" '' 61 echo "installing dummy bootloader" 62 touch /tmp/bootloader-installed 63 ''); 64 65 specialisation = rec { 66 brokenInitInterface.configuration.config.system.extraSystemBuilderCmds = '' 67 echo "systemd 0" > $out/init-interface-version 68 ''; 69 70 modifiedSystemConf.configuration.systemd.extraConfig = '' 71 # Hello world! 72 ''; 73 74 addedMount.configuration.virtualisation.fileSystems."/test" = { 75 device = "tmpfs"; 76 fsType = "tmpfs"; 77 }; 78 79 addedMountOptsModified.configuration = { 80 imports = [ addedMount.configuration ]; 81 virtualisation.fileSystems."/test".options = [ "x-test" ]; 82 }; 83 84 addedMountDevModified.configuration = { 85 imports = [ addedMountOptsModified.configuration ]; 86 virtualisation.fileSystems."/test".device = lib.mkForce "ramfs"; 87 }; 88 89 storeMountModified.configuration = { 90 virtualisation.fileSystems."/".device = lib.mkForce "auto"; 91 }; 92 93 swap.configuration.swapDevices = lib.mkVMOverride [ 94 { device = "/swapfile"; size = 1; } 95 ]; 96 97 simpleService.configuration = { 98 systemd.services.test = { 99 wantedBy = [ "multi-user.target" ]; 100 serviceConfig = { 101 Type = "oneshot"; 102 RemainAfterExit = true; 103 ExecStart = "${pkgs.coreutils}/bin/true"; 104 ExecReload = "${pkgs.coreutils}/bin/true"; 105 }; 106 }; 107 }; 108 109 simpleServiceSeparateActivationScript.configuration = { 110 system.activatable = false; 111 systemd.services.test = { 112 wantedBy = [ "multi-user.target" ]; 113 serviceConfig = { 114 Type = "oneshot"; 115 RemainAfterExit = true; 116 ExecStart = "${pkgs.coreutils}/bin/true"; 117 ExecReload = "${pkgs.coreutils}/bin/true"; 118 }; 119 }; 120 }; 121 122 simpleServiceDifferentDescription.configuration = { 123 imports = [ simpleService.configuration ]; 124 systemd.services.test.description = "Test unit"; 125 }; 126 127 simpleServiceModified.configuration = { 128 imports = [ simpleService.configuration ]; 129 systemd.services.test.serviceConfig.X-Test = true; 130 }; 131 132 simpleServiceNostop.configuration = { 133 imports = [ simpleService.configuration ]; 134 systemd.services.test.stopIfChanged = false; 135 }; 136 137 simpleServiceReload.configuration = { 138 imports = [ simpleService.configuration ]; 139 systemd.services.test = { 140 reloadIfChanged = true; 141 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true"; 142 }; 143 }; 144 145 simpleServiceNorestart.configuration = { 146 imports = [ simpleService.configuration ]; 147 systemd.services.test.restartIfChanged = false; 148 }; 149 150 simpleServiceFailing.configuration = { 151 imports = [ simpleServiceModified.configuration ]; 152 systemd.services.test.serviceConfig.ExecStart = lib.mkForce "${pkgs.coreutils}/bin/false"; 153 }; 154 155 autorestartService.configuration = { 156 # A service that immediately goes into restarting (but without failing) 157 systemd.services.autorestart = { 158 wantedBy = [ "multi-user.target" ]; 159 serviceConfig = { 160 Type = "simple"; 161 Restart = "always"; 162 RestartSec = "20y"; # Should be long enough 163 ExecStart = "${pkgs.coreutils}/bin/true"; 164 }; 165 }; 166 }; 167 168 autorestartServiceFailing.configuration = { 169 imports = [ autorestartService.configuration ]; 170 systemd.services.autorestart.serviceConfig = { 171 ExecStart = lib.mkForce "${pkgs.coreutils}/bin/false"; 172 }; 173 }; 174 175 simpleServiceWithExtraSection.configuration = { 176 imports = [ simpleServiceNostop.configuration ]; 177 systemd.packages = [ (pkgs.writeTextFile { 178 name = "systemd-extra-section"; 179 destination = "/etc/systemd/system/test.service"; 180 text = '' 181 [X-Test] 182 X-Test-Value=a 183 ''; 184 }) ]; 185 }; 186 187 simpleServiceWithExtraSectionOtherName.configuration = { 188 imports = [ simpleServiceNostop.configuration ]; 189 systemd.packages = [ (pkgs.writeTextFile { 190 name = "systemd-extra-section"; 191 destination = "/etc/systemd/system/test.service"; 192 text = '' 193 [X-Test2] 194 X-Test-Value=a 195 ''; 196 }) ]; 197 }; 198 199 simpleServiceWithInstallSection.configuration = { 200 imports = [ simpleServiceNostop.configuration ]; 201 systemd.packages = [ (pkgs.writeTextFile { 202 name = "systemd-extra-section"; 203 destination = "/etc/systemd/system/test.service"; 204 text = '' 205 [Install] 206 WantedBy=multi-user.target 207 ''; 208 }) ]; 209 }; 210 211 simpleServiceWithExtraKey.configuration = { 212 imports = [ simpleServiceNostop.configuration ]; 213 systemd.services.test.serviceConfig."X-Test" = "test"; 214 }; 215 216 simpleServiceWithExtraKeyOtherValue.configuration = { 217 imports = [ simpleServiceNostop.configuration ]; 218 systemd.services.test.serviceConfig."X-Test" = "test2"; 219 }; 220 221 simpleServiceWithExtraKeyOtherName.configuration = { 222 imports = [ simpleServiceNostop.configuration ]; 223 systemd.services.test.serviceConfig."X-Test2" = "test"; 224 }; 225 226 simpleServiceReloadTrigger.configuration = { 227 imports = [ simpleServiceNostop.configuration ]; 228 systemd.services.test.reloadTriggers = [ "/dev/null" ]; 229 }; 230 231 simpleServiceReloadTriggerModified.configuration = { 232 imports = [ simpleServiceNostop.configuration ]; 233 systemd.services.test.reloadTriggers = [ "/dev/zero" ]; 234 }; 235 236 simpleServiceReloadTriggerModifiedAndSomethingElse.configuration = { 237 imports = [ simpleServiceNostop.configuration ]; 238 systemd.services.test = { 239 reloadTriggers = [ "/dev/zero" ]; 240 serviceConfig."X-Test" = "test"; 241 }; 242 }; 243 244 simpleServiceReloadTriggerModifiedSomethingElse.configuration = { 245 imports = [ simpleServiceNostop.configuration ]; 246 systemd.services.test.serviceConfig."X-Test" = "test"; 247 }; 248 249 unitWithBackslash.configuration = { 250 systemd.services."escaped\\x2ddash" = { 251 wantedBy = [ "multi-user.target" ]; 252 serviceConfig = { 253 Type = "oneshot"; 254 RemainAfterExit = true; 255 ExecStart = "${pkgs.coreutils}/bin/true"; 256 ExecReload = "${pkgs.coreutils}/bin/true"; 257 }; 258 }; 259 }; 260 261 unitWithBackslashModified.configuration = { 262 imports = [ unitWithBackslash.configuration ]; 263 systemd.services."escaped\\x2ddash".serviceConfig.X-Test = "test"; 264 }; 265 266 unitStartingWithDash.configuration = { 267 systemd.services."-" = { 268 wantedBy = [ "multi-user.target" ]; 269 serviceConfig = { 270 Type = "oneshot"; 271 RemainAfterExit = true; 272 ExecStart = "${pkgs.coreutils}/bin/true"; 273 }; 274 }; 275 }; 276 277 unitStartingWithDashModified.configuration = { 278 imports = [ unitStartingWithDash.configuration ]; 279 systemd.services."-" = { 280 reloadIfChanged = true; 281 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true"; 282 }; 283 }; 284 285 unitWithRequirement.configuration = { 286 systemd.services.required-service = { 287 wantedBy = [ "multi-user.target" ]; 288 serviceConfig = { 289 Type = "oneshot"; 290 RemainAfterExit = true; 291 ExecStart = "${pkgs.coreutils}/bin/true"; 292 ExecReload = "${pkgs.coreutils}/bin/true"; 293 }; 294 }; 295 systemd.services.test-service = { 296 wantedBy = [ "multi-user.target" ]; 297 requires = [ "required-service.service" ]; 298 serviceConfig = { 299 Type = "oneshot"; 300 RemainAfterExit = true; 301 ExecStart = "${pkgs.coreutils}/bin/true"; 302 ExecReload = "${pkgs.coreutils}/bin/true"; 303 }; 304 }; 305 }; 306 307 unitWithRequirementModified.configuration = { 308 imports = [ unitWithRequirement.configuration ]; 309 systemd.services.required-service.serviceConfig.X-Test = "test"; 310 systemd.services.test-service.reloadTriggers = [ "test" ]; 311 }; 312 313 unitWithRequirementModifiedNostart.configuration = { 314 imports = [ unitWithRequirement.configuration ]; 315 systemd.services.test-service.unitConfig.RefuseManualStart = true; 316 }; 317 318 unitWithTemplate.configuration = { 319 systemd.services."instantiated@".serviceConfig = { 320 Type = "oneshot"; 321 RemainAfterExit = true; 322 ExecStart = "${pkgs.coreutils}/bin/true"; 323 ExecReload = "${pkgs.coreutils}/bin/true"; 324 }; 325 systemd.services."instantiated@one" = { 326 wantedBy = [ "multi-user.target" ]; 327 overrideStrategy = "asDropin"; 328 }; 329 systemd.services."instantiated@two" = { 330 wantedBy = [ "multi-user.target" ]; 331 overrideStrategy = "asDropin"; 332 }; 333 }; 334 335 unitWithTemplateModified.configuration = { 336 imports = [ unitWithTemplate.configuration ]; 337 systemd.services."instantiated@".serviceConfig.X-Test = "test"; 338 }; 339 340 restart-and-reload-by-activation-script.configuration = { 341 systemd.services = rec { 342 simple-service = { 343 # No wantedBy so we can check if the activation script restart triggers them 344 serviceConfig = { 345 Type = "oneshot"; 346 RemainAfterExit = true; 347 ExecStart = "${pkgs.coreutils}/bin/true"; 348 ExecReload = "${pkgs.coreutils}/bin/true"; 349 }; 350 }; 351 "templated-simple-service@" = simple-service; 352 "templated-simple-service@instance".overrideStrategy = "asDropin"; 353 354 simple-restart-service = simple-service // { 355 stopIfChanged = false; 356 }; 357 "templated-simple-restart-service@" = simple-restart-service; 358 "templated-simple-restart-service@instance".overrideStrategy = "asDropin"; 359 360 simple-reload-service = simple-service // { 361 reloadIfChanged = true; 362 }; 363 "templated-simple-reload-service@" = simple-reload-service; 364 "templated-simple-reload-service@instance".overrideStrategy = "asDropin"; 365 366 no-restart-service = simple-service // { 367 restartIfChanged = false; 368 }; 369 "templated-no-restart-service@" = no-restart-service; 370 "templated-no-restart-service@instance".overrideStrategy = "asDropin"; 371 372 reload-triggers = simple-service // { 373 wantedBy = [ "multi-user.target" ]; 374 }; 375 "templated-reload-triggers@" = simple-service; 376 "templated-reload-triggers@instance" = { 377 overrideStrategy = "asDropin"; 378 wantedBy = [ "multi-user.target" ]; 379 }; 380 381 reload-triggers-and-restart-by-as = simple-service; 382 "templated-reload-triggers-and-restart-by-as@" = reload-triggers-and-restart-by-as; 383 "templated-reload-triggers-and-restart-by-as@instance".overrideStrategy = "asDropin"; 384 385 reload-triggers-and-restart = simple-service // { 386 stopIfChanged = false; # easier to check for this 387 wantedBy = [ "multi-user.target" ]; 388 }; 389 "templated-reload-triggers-and-restart@" = simple-service; 390 "templated-reload-triggers-and-restart@instance" = { 391 overrideStrategy = "asDropin"; 392 stopIfChanged = false; # easier to check for this 393 wantedBy = [ "multi-user.target" ]; 394 }; 395 }; 396 397 system.activationScripts.restart-and-reload-test = { 398 supportsDryActivation = true; 399 deps = []; 400 text = '' 401 if [ "$NIXOS_ACTION" = dry-activate ]; then 402 f=/run/nixos/dry-activation-restart-list 403 g=/run/nixos/dry-activation-reload-list 404 else 405 f=/run/nixos/activation-restart-list 406 g=/run/nixos/activation-reload-list 407 fi 408 cat <<EOF >> "$f" 409 simple-service.service 410 simple-restart-service.service 411 simple-reload-service.service 412 no-restart-service.service 413 reload-triggers-and-restart-by-as.service 414 templated-simple-service@instance.service 415 templated-simple-restart-service@instance.service 416 templated-simple-reload-service@instance.service 417 templated-no-restart-service@instance.service 418 templated-reload-triggers-and-restart-by-as@instance.service 419 EOF 420 421 cat <<EOF >> "$g" 422 reload-triggers.service 423 reload-triggers-and-restart-by-as.service 424 reload-triggers-and-restart.service 425 templated-reload-triggers@instance.service 426 templated-reload-triggers-and-restart-by-as@instance.service 427 templated-reload-triggers-and-restart@instance.service 428 EOF 429 ''; 430 }; 431 }; 432 433 restart-and-reload-by-activation-script-modified.configuration = { 434 imports = [ restart-and-reload-by-activation-script.configuration ]; 435 systemd.services.reload-triggers-and-restart.serviceConfig.X-Modified = "test"; 436 systemd.services."templated-reload-triggers-and-restart@instance" = { 437 overrideStrategy = "asDropin"; 438 serviceConfig.X-Modified = "test"; 439 }; 440 }; 441 442 simple-socket.configuration = { 443 systemd.services.socket-activated = { 444 description = "A socket-activated service"; 445 stopIfChanged = lib.mkDefault false; 446 serviceConfig = { 447 ExecStart = socketTest; 448 ExecReload = "${pkgs.coreutils}/bin/true"; 449 }; 450 }; 451 systemd.sockets.socket-activated = { 452 wantedBy = [ "sockets.target" ]; 453 listenStreams = [ "/run/test.sock" ]; 454 socketConfig.SocketMode = lib.mkDefault "0777"; 455 }; 456 }; 457 458 simple-socket-service-modified.configuration = { 459 imports = [ simple-socket.configuration ]; 460 systemd.services.socket-activated.serviceConfig.X-Test = "test"; 461 }; 462 463 simple-socket-stop-if-changed.configuration = { 464 imports = [ simple-socket.configuration ]; 465 systemd.services.socket-activated.stopIfChanged = true; 466 }; 467 468 simple-socket-stop-if-changed-and-reloadtrigger.configuration = { 469 imports = [ simple-socket.configuration ]; 470 systemd.services.socket-activated = { 471 stopIfChanged = true; 472 reloadTriggers = [ "test" ]; 473 }; 474 }; 475 476 mount.configuration = { 477 systemd.mounts = [ 478 { 479 description = "Testmount"; 480 what = "tmpfs"; 481 type = "tmpfs"; 482 where = "/testmount"; 483 options = "size=1M"; 484 wantedBy = [ "local-fs.target" ]; 485 } 486 ]; 487 }; 488 489 mountOptionsModified.configuration = { 490 systemd.mounts = [ 491 { 492 description = "Testmount"; 493 what = "tmpfs"; 494 type = "tmpfs"; 495 where = "/testmount"; 496 options = "size=10M"; 497 wantedBy = [ "local-fs.target" ]; 498 } 499 ]; 500 }; 501 502 mountModified.configuration = { 503 systemd.mounts = [ 504 { 505 description = "Testmount"; 506 what = "ramfs"; 507 type = "ramfs"; 508 where = "/testmount"; 509 options = "size=10M"; 510 wantedBy = [ "local-fs.target" ]; 511 } 512 ]; 513 }; 514 515 timer.configuration = { 516 systemd.timers.test-timer = { 517 wantedBy = [ "timers.target" ]; 518 timerConfig.OnCalendar = "@1395716396"; # chosen by fair dice roll 519 }; 520 systemd.services.test-timer = { 521 serviceConfig = { 522 Type = "oneshot"; 523 ExecStart = "${pkgs.coreutils}/bin/true"; 524 }; 525 }; 526 }; 527 528 timerModified.configuration = { 529 imports = [ timer.configuration ]; 530 systemd.timers.test-timer.timerConfig.OnCalendar = lib.mkForce "Fri 2012-11-23 16:00:00"; 531 }; 532 533 hybridSleepModified.configuration = { 534 systemd.targets.hybrid-sleep.unitConfig.X-Test = true; 535 }; 536 537 target.configuration = { 538 systemd.targets.test-target.wantedBy = [ "multi-user.target" ]; 539 # We use this service to figure out whether the target was modified. 540 # This is the only way because targets are filtered and therefore not 541 # printed when they are started/stopped. 542 systemd.services.test-service = { 543 bindsTo = [ "test-target.target" ]; 544 serviceConfig.ExecStart = "${pkgs.coreutils}/bin/sleep infinity"; 545 }; 546 }; 547 548 targetModified.configuration = { 549 imports = [ target.configuration ]; 550 systemd.targets.test-target.unitConfig.X-Test = true; 551 }; 552 553 targetModifiedStopOnReconfig.configuration = { 554 imports = [ target.configuration ]; 555 systemd.targets.test-target.unitConfig.X-StopOnReconfiguration = true; 556 }; 557 558 path.configuration = { 559 systemd.paths.test-watch = { 560 wantedBy = [ "paths.target" ]; 561 pathConfig.PathExists = "/testpath"; 562 }; 563 systemd.services.test-watch = { 564 serviceConfig = { 565 Type = "oneshot"; 566 RemainAfterExit = true; 567 ExecStart = "${pkgs.coreutils}/bin/touch /testpath-modified"; 568 }; 569 }; 570 }; 571 572 pathModified.configuration = { 573 imports = [ path.configuration ]; 574 systemd.paths.test-watch.pathConfig.PathExists = lib.mkForce "/testpath2"; 575 }; 576 577 slice.configuration = { 578 systemd.slices.testslice.sliceConfig.MemoryMax = "1"; # don't allow memory allocation 579 systemd.services.testservice = { 580 serviceConfig = { 581 Type = "oneshot"; 582 RemainAfterExit = true; 583 ExecStart = "${pkgs.coreutils}/bin/true"; 584 Slice = "testslice.slice"; 585 }; 586 }; 587 }; 588 589 sliceModified.configuration = { 590 imports = [ slice.configuration ]; 591 systemd.slices.testslice.sliceConfig.MemoryMax = lib.mkForce null; 592 }; 593 }; 594 }; 595 596 other = { 597 users.mutableUsers = true; 598 }; 599 }; 600 601 testScript = { nodes, ... }: let 602 originalSystem = nodes.machine.system.build.toplevel; 603 otherSystem = nodes.other.system.build.toplevel; 604 machine = nodes.machine.system.build.toplevel; 605 606 # Ensures failures pass through using pipefail, otherwise failing to 607 # switch-to-configuration is hidden by the success of `tee`. 608 stderrRunner = pkgs.writeScript "stderr-runner" '' 609 #! ${pkgs.runtimeShell} 610 set -e 611 set -o pipefail 612 exec env -i "$@" | tee /dev/stderr 613 ''; 614 615 # Returns a comma separated representation of the given list in sorted 616 # order, that matches the output format of switch-to-configuration.pl 617 sortedUnits = xs: lib.concatStringsSep ", " (builtins.sort builtins.lessThan xs); 618 619 dbusService = { 620 "dbus" = "dbus.service"; 621 "broker" = "dbus-broker.service"; 622 }.${nodes.machine.services.dbus.implementation}; 623 in /* python */ '' 624 def switch_to_specialisation(system, name, action="test", fail=False): 625 if name == "": 626 switcher = f"{system}/bin/switch-to-configuration" 627 else: 628 switcher = f"{system}/specialisation/{name}/bin/switch-to-configuration" 629 return run_switch(switcher, action, fail) 630 631 # like above but stc = switcher 632 def run_switch(switcher, action="test", fail=False): 633 out = machine.fail(f"{switcher} {action} 2>&1") if fail \ 634 else machine.succeed(f"{switcher} {action} 2>&1") 635 assert_lacks(out, "switch-to-configuration line") # Perl warnings 636 return out 637 638 def assert_contains(haystack, needle): 639 if needle not in haystack: 640 print("The haystack that will cause the following exception is:") 641 print("---") 642 print(haystack) 643 print("---") 644 raise Exception(f"Expected string '{needle}' was not found") 645 646 def assert_lacks(haystack, needle): 647 if needle in haystack: 648 print("The haystack that will cause the following exception is:") 649 print("---") 650 print(haystack, end="") 651 print("---") 652 raise Exception(f"Unexpected string '{needle}' was found") 653 654 655 machine.wait_for_unit("multi-user.target") 656 657 machine.succeed( 658 "${stderrRunner} ${originalSystem}/bin/switch-to-configuration test" 659 ) 660 # This tests whether the /etc/os-release parser works which is a fallback 661 # when /etc/NIXOS is missing. If the parser does not work, switch-to-configuration 662 # would fail. 663 machine.succeed("rm /etc/NIXOS") 664 machine.succeed( 665 "${stderrRunner} ${otherSystem}/bin/switch-to-configuration test" 666 ) 667 668 669 with subtest("actions"): 670 # boot action 671 machine.fail("test -f /tmp/bootloader-installed") 672 out = switch_to_specialisation("${machine}", "simpleService", action="boot") 673 assert_contains(out, "installing dummy bootloader") 674 assert_lacks(out, "activating the configuration...") # good indicator of a system activation 675 machine.succeed("test -f /tmp/bootloader-installed") 676 machine.succeed("rm /tmp/bootloader-installed") 677 678 # switch action 679 machine.fail("test -f /tmp/bootloader-installed") 680 out = switch_to_specialisation("${machine}", "", action="switch") 681 assert_contains(out, "installing dummy bootloader") 682 assert_contains(out, "activating the configuration...") # good indicator of a system activation 683 machine.succeed("test -f /tmp/bootloader-installed") 684 685 # test and dry-activate actions are tested further down below 686 687 # invalid action fails the script 688 switch_to_specialisation("${machine}", "", action="broken-action", fail=True) 689 # no action fails the script 690 assert "Usage:" in machine.fail("${machine}/bin/switch-to-configuration 2>&1") 691 692 with subtest("init interface version"): 693 # Do not try to switch to an invalid init interface version 694 assert "incompatible" in switch_to_specialisation("${machine}", "brokenInitInterface", fail=True) 695 696 with subtest("systemd restarts"): 697 # systemd is restarted when its system.conf changes 698 out = switch_to_specialisation("${machine}", "modifiedSystemConf") 699 assert_contains(out, "restarting systemd...") 700 701 with subtest("continuing from an aborted switch"): 702 # An aborted switch will write into a file what it tried to start 703 # and a second switch should continue from this 704 machine.succeed("echo ${dbusService} > /run/nixos/start-list") 705 out = switch_to_specialisation("${machine}", "modifiedSystemConf") 706 assert_contains(out, "starting the following units: ${dbusService}\n") 707 708 with subtest("fstab mounts"): 709 switch_to_specialisation("${machine}", "") 710 # add a mountpoint 711 out = switch_to_specialisation("${machine}", "addedMount") 712 assert_lacks(out, "stopping the following units:") 713 assert_lacks(out, "NOT restarting the following changed units:") 714 assert_lacks(out, "\nrestarting the following units:") 715 assert_lacks(out, "\nstarting the following units:") 716 assert_contains(out, "the following new units were started: test.mount\n") 717 # modify the mountpoint's options 718 out = switch_to_specialisation("${machine}", "addedMountOptsModified") 719 assert_lacks(out, "stopping the following units:") 720 assert_lacks(out, "NOT restarting the following changed units:") 721 assert_contains(out, "reloading the following units: test.mount\n") 722 assert_lacks(out, "\nrestarting the following units:") 723 assert_lacks(out, "\nstarting the following units:") 724 assert_lacks(out, "the following new units were started:") 725 # modify the device 726 out = switch_to_specialisation("${machine}", "addedMountDevModified") 727 assert_lacks(out, "stopping the following units:") 728 assert_lacks(out, "NOT restarting the following changed units:") 729 assert_lacks(out, "reloading the following units:") 730 assert_contains(out, "\nrestarting the following units: test.mount\n") 731 assert_lacks(out, "\nstarting the following units:") 732 assert_lacks(out, "the following new units were started:") 733 # modify both 734 out = switch_to_specialisation("${machine}", "addedMount") 735 assert_lacks(out, "stopping the following units:") 736 assert_lacks(out, "NOT restarting the following changed units:") 737 assert_lacks(out, "reloading the following units:") 738 assert_contains(out, "\nrestarting the following units: test.mount\n") 739 assert_lacks(out, "\nstarting the following units:") 740 assert_lacks(out, "the following new units were started:") 741 # remove the mount 742 out = switch_to_specialisation("${machine}", "") 743 assert_contains(out, "stopping the following units: test.mount\n") 744 assert_lacks(out, "NOT restarting the following changed units:") 745 assert_contains(out, "reloading the following units: ${dbusService}\n") 746 assert_lacks(out, "\nrestarting the following units:") 747 assert_lacks(out, "\nstarting the following units:") 748 assert_lacks(out, "the following new units were started:") 749 # change something about the / mount 750 out = switch_to_specialisation("${machine}", "storeMountModified") 751 assert_lacks(out, "stopping the following units:") 752 assert_contains(out, "NOT restarting the following changed units: -.mount") 753 assert_contains(out, "reloading the following units: ${dbusService}\n") 754 assert_lacks(out, "\nrestarting the following units:") 755 assert_lacks(out, "\nstarting the following units:") 756 assert_lacks(out, "the following new units were started:") 757 758 with subtest("swaps"): 759 switch_to_specialisation("${machine}", "") 760 # add a swap 761 out = switch_to_specialisation("${machine}", "swap") 762 assert_lacks(out, "stopping the following units:") 763 assert_lacks(out, "NOT restarting the following changed units:") 764 assert_contains(out, "reloading the following units: ${dbusService}\n") 765 assert_lacks(out, "\nrestarting the following units:") 766 assert_lacks(out, "\nstarting the following units:") 767 assert_contains(out, "the following new units were started: swapfile.swap") 768 # remove it 769 out = switch_to_specialisation("${machine}", "") 770 assert_contains(out, "stopping swap device: /swapfile") 771 assert_lacks(out, "stopping the following units:") 772 assert_lacks(out, "NOT restarting the following changed units:") 773 assert_contains(out, "reloading the following units: ${dbusService}\n") 774 assert_lacks(out, "\nrestarting the following units:") 775 assert_lacks(out, "\nstarting the following units:") 776 assert_lacks(out, "the following new units were started:") 777 778 with subtest("services"): 779 switch_to_specialisation("${machine}", "") 780 # Nothing happens when nothing is changed 781 out = switch_to_specialisation("${machine}", "") 782 assert_lacks(out, "stopping the following units:") 783 assert_lacks(out, "NOT restarting the following changed units:") 784 assert_lacks(out, "reloading the following units:") 785 assert_lacks(out, "\nrestarting the following units:") 786 assert_lacks(out, "\nstarting the following units:") 787 assert_lacks(out, "the following new units were started:") 788 789 # Start a simple service 790 out = switch_to_specialisation("${machine}", "simpleService") 791 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader 792 assert_lacks(out, "stopping the following units:") 793 assert_lacks(out, "NOT restarting the following changed units:") 794 assert_contains(out, "reloading the following units: ${dbusService}\n") # huh 795 assert_lacks(out, "\nrestarting the following units:") 796 assert_lacks(out, "\nstarting the following units:") 797 assert_contains(out, "the following new units were started: test.service\n") 798 799 # Not changing anything doesn't do anything 800 out = switch_to_specialisation("${machine}", "simpleService") 801 assert_lacks(out, "stopping the following units:") 802 assert_lacks(out, "NOT restarting the following changed units:") 803 assert_lacks(out, "reloading the following units:") 804 assert_lacks(out, "\nrestarting the following units:") 805 assert_lacks(out, "\nstarting the following units:") 806 assert_lacks(out, "the following new units were started:") 807 808 # Only changing the description does nothing 809 out = switch_to_specialisation("${machine}", "simpleServiceDifferentDescription") 810 assert_lacks(out, "stopping the following units:") 811 assert_lacks(out, "NOT restarting the following changed units:") 812 assert_lacks(out, "reloading the following units:") 813 assert_lacks(out, "\nrestarting the following units:") 814 assert_lacks(out, "\nstarting the following units:") 815 assert_lacks(out, "the following new units were started:") 816 817 # Restart the simple service 818 out = switch_to_specialisation("${machine}", "simpleServiceModified") 819 assert_contains(out, "stopping the following units: test.service\n") 820 assert_lacks(out, "NOT restarting the following changed units:") 821 assert_lacks(out, "reloading the following units:") 822 assert_lacks(out, "\nrestarting the following units:") 823 assert_contains(out, "\nstarting the following units: test.service\n") 824 assert_lacks(out, "the following new units were started:") 825 826 # Restart the service with stopIfChanged=false 827 out = switch_to_specialisation("${machine}", "simpleServiceNostop") 828 assert_lacks(out, "stopping the following units:") 829 assert_lacks(out, "NOT restarting the following changed units:") 830 assert_lacks(out, "reloading the following units:") 831 assert_contains(out, "\nrestarting the following units: test.service\n") 832 assert_lacks(out, "\nstarting the following units:") 833 assert_lacks(out, "the following new units were started:") 834 835 # Reload the service with reloadIfChanged=true 836 out = switch_to_specialisation("${machine}", "simpleServiceReload") 837 assert_lacks(out, "stopping the following units:") 838 assert_lacks(out, "NOT restarting the following changed units:") 839 assert_contains(out, "reloading the following units: test.service\n") 840 assert_lacks(out, "\nrestarting the following units:") 841 assert_lacks(out, "\nstarting the following units:") 842 assert_lacks(out, "the following new units were started:") 843 844 # Nothing happens when restartIfChanged=false 845 out = switch_to_specialisation("${machine}", "simpleServiceNorestart") 846 assert_lacks(out, "stopping the following units:") 847 assert_contains(out, "NOT restarting the following changed units: test.service\n") 848 assert_lacks(out, "reloading the following units:") 849 assert_lacks(out, "\nrestarting the following units:") 850 assert_lacks(out, "\nstarting the following units:") 851 assert_lacks(out, "the following new units were started:") 852 853 # Dry mode shows different messages 854 out = switch_to_specialisation("${machine}", "simpleService", action="dry-activate") 855 assert_lacks(out, "stopping the following units:") 856 assert_lacks(out, "NOT restarting the following changed units:") 857 assert_lacks(out, "reloading the following units:") 858 assert_lacks(out, "\nrestarting the following units:") 859 assert_lacks(out, "\nstarting the following units:") 860 assert_lacks(out, "the following new units were started:") 861 assert_contains(out, "would start the following units: test.service\n") 862 863 out = switch_to_specialisation("${machine}", "", action="test") 864 865 # Ensure the service can be started when the activation script isn't in toplevel 866 # This is a lot like "Start a simple service", except activation-only deps could be gc-ed 867 out = run_switch("${nodes.machine.specialisation.simpleServiceSeparateActivationScript.configuration.system.build.separateActivationScript}/bin/switch-to-configuration"); 868 assert_lacks(out, "installing dummy bootloader") # test does not install a bootloader 869 assert_lacks(out, "stopping the following units:") 870 assert_lacks(out, "NOT restarting the following changed units:") 871 assert_contains(out, "reloading the following units: ${dbusService}\n") # huh 872 assert_lacks(out, "\nrestarting the following units:") 873 assert_lacks(out, "\nstarting the following units:") 874 assert_contains(out, "the following new units were started: test.service\n") 875 machine.succeed("! test -e /run/current-system/activate") 876 machine.succeed("! test -e /run/current-system/dry-activate") 877 machine.succeed("! test -e /run/current-system/bin/switch-to-configuration") 878 879 # Ensure \ works in unit names 880 out = switch_to_specialisation("${machine}", "unitWithBackslash") 881 assert_contains(out, "stopping the following units: test.service\n") 882 assert_lacks(out, "NOT restarting the following changed units:") 883 assert_lacks(out, "reloading the following units:") 884 assert_lacks(out, "\nrestarting the following units:") 885 assert_lacks(out, "\nstarting the following units:") 886 assert_contains(out, "the following new units were started: escaped\\x2ddash.service\n") 887 888 out = switch_to_specialisation("${machine}", "unitWithBackslashModified") 889 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n") 890 assert_lacks(out, "NOT restarting the following changed units:") 891 assert_lacks(out, "reloading the following units:") 892 assert_lacks(out, "\nrestarting the following units:") 893 assert_contains(out, "\nstarting the following units: escaped\\x2ddash.service\n") 894 assert_lacks(out, "the following new units were started:") 895 896 # Ensure units can start with a dash 897 out = switch_to_specialisation("${machine}", "unitStartingWithDash") 898 assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n") 899 assert_lacks(out, "NOT restarting the following changed units:") 900 assert_lacks(out, "reloading the following units:") 901 assert_lacks(out, "\nrestarting the following units:") 902 assert_lacks(out, "\nstarting the following units:") 903 assert_contains(out, "the following new units were started: -.service\n") 904 905 # The regression only occurs when reloading units 906 out = switch_to_specialisation("${machine}", "unitStartingWithDashModified") 907 assert_lacks(out, "stopping the following units:") 908 assert_lacks(out, "NOT restarting the following changed units:") 909 assert_contains(out, "reloading the following units: -.service") 910 assert_lacks(out, "\nrestarting the following units:") 911 assert_lacks(out, "\nstarting the following units:") 912 assert_lacks(out, "the following new units were started:") 913 914 # Ensure units that require changed units are properly reloaded 915 out = switch_to_specialisation("${machine}", "unitWithRequirement") 916 assert_contains(out, "stopping the following units: -.service\n") 917 assert_lacks(out, "NOT restarting the following changed units:") 918 assert_lacks(out, "reloading the following units:") 919 assert_lacks(out, "\nrestarting the following units:") 920 assert_lacks(out, "\nstarting the following units:") 921 assert_contains(out, "the following new units were started: required-service.service, test-service.service\n") 922 923 out = switch_to_specialisation("${machine}", "unitWithRequirementModified") 924 assert_contains(out, "stopping the following units: required-service.service\n") 925 assert_lacks(out, "NOT restarting the following changed units:") 926 assert_lacks(out, "reloading the following units:") 927 assert_lacks(out, "\nrestarting the following units:") 928 assert_contains(out, "\nstarting the following units: required-service.service, test-service.service\n") 929 assert_lacks(out, "the following new units were started:") 930 931 # Unless the unit asks to be not restarted 932 out = switch_to_specialisation("${machine}", "unitWithRequirementModifiedNostart") 933 assert_contains(out, "stopping the following units: required-service.service\n") 934 assert_lacks(out, "NOT restarting the following changed units:") 935 assert_lacks(out, "reloading the following units:") 936 assert_lacks(out, "\nrestarting the following units:") 937 assert_contains(out, "\nstarting the following units: required-service.service\n") 938 assert_lacks(out, "the following new units were started:") 939 940 # Ensure templated units are restarted when the base unit changes 941 switch_to_specialisation("${machine}", "unitWithTemplate") 942 out = switch_to_specialisation("${machine}", "unitWithTemplateModified") 943 assert_contains(out, "stopping the following units: instantiated@one.service, instantiated@two.service\n") 944 assert_lacks(out, "NOT restarting the following changed units:") 945 assert_lacks(out, "reloading the following units:") 946 assert_lacks(out, "\nrestarting the following units:") 947 assert_contains(out, "\nstarting the following units: instantiated@one.service, instantiated@two.service\n") 948 assert_lacks(out, "the following new units were started:") 949 950 with subtest("failing units"): 951 # Let the simple service fail 952 switch_to_specialisation("${machine}", "simpleServiceModified") 953 out = switch_to_specialisation("${machine}", "simpleServiceFailing", fail=True) 954 assert_contains(out, "stopping the following units: test.service\n") 955 assert_lacks(out, "NOT restarting the following changed units:") 956 assert_lacks(out, "reloading the following units:") 957 assert_lacks(out, "\nrestarting the following units:") 958 assert_contains(out, "\nstarting the following units: test.service\n") 959 assert_lacks(out, "the following new units were started:") 960 assert_contains(out, "warning: the following units failed: test.service\n") 961 assert_contains(out, "Main PID:") # output of systemctl 962 963 # A unit that gets into autorestart without failing is not treated as failed 964 out = switch_to_specialisation("${machine}", "autorestartService") 965 assert_lacks(out, "stopping the following units:") 966 assert_lacks(out, "NOT restarting the following changed units:") 967 assert_lacks(out, "reloading the following units:") 968 assert_lacks(out, "\nrestarting the following units:") 969 assert_lacks(out, "\nstarting the following units:") 970 assert_contains(out, "the following new units were started: autorestart.service\n") 971 machine.systemctl('stop autorestart.service') # cancel the 20y timer 972 973 # Switching to the same system should do nothing (especially not treat the unit as failed) 974 out = switch_to_specialisation("${machine}", "autorestartService") 975 assert_lacks(out, "stopping the following units:") 976 assert_lacks(out, "NOT restarting the following changed units:") 977 assert_lacks(out, "reloading the following units:") 978 assert_lacks(out, "\nrestarting the following units:") 979 assert_lacks(out, "\nstarting the following units:") 980 assert_contains(out, "the following new units were started: autorestart.service\n") 981 machine.systemctl('stop autorestart.service') # cancel the 20y timer 982 983 # If systemd thinks the unit has failed and is in autorestart, we should show it as failed 984 out = switch_to_specialisation("${machine}", "autorestartServiceFailing", fail=True) 985 assert_lacks(out, "stopping the following units:") 986 assert_lacks(out, "NOT restarting the following changed units:") 987 assert_lacks(out, "reloading the following units:") 988 assert_lacks(out, "\nrestarting the following units:") 989 assert_lacks(out, "\nstarting the following units:") 990 assert_lacks(out, "the following new units were started:") 991 assert_contains(out, "warning: the following units failed: autorestart.service\n") 992 assert_contains(out, "Main PID:") # output of systemctl 993 994 with subtest("unit file parser"): 995 # Switch to a well-known state 996 switch_to_specialisation("${machine}", "simpleServiceNostop") 997 998 # Add a section 999 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSection") 1000 assert_lacks(out, "stopping the following units:") 1001 assert_lacks(out, "NOT restarting the following changed units:") 1002 assert_lacks(out, "reloading the following units:") 1003 assert_contains(out, "\nrestarting the following units: test.service\n") 1004 assert_lacks(out, "\nstarting the following units:") 1005 assert_lacks(out, "the following new units were started:") 1006 1007 # Rename it 1008 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSectionOtherName") 1009 assert_lacks(out, "stopping the following units:") 1010 assert_lacks(out, "NOT restarting the following changed units:") 1011 assert_lacks(out, "reloading the following units:") 1012 assert_contains(out, "\nrestarting the following units: test.service\n") 1013 assert_lacks(out, "\nstarting the following units:") 1014 assert_lacks(out, "the following new units were started:") 1015 1016 # Remove it 1017 out = switch_to_specialisation("${machine}", "simpleServiceNostop") 1018 assert_lacks(out, "stopping the following units:") 1019 assert_lacks(out, "NOT restarting the following changed units:") 1020 assert_lacks(out, "reloading the following units:") 1021 assert_contains(out, "\nrestarting the following units: test.service\n") 1022 assert_lacks(out, "\nstarting the following units:") 1023 assert_lacks(out, "the following new units were started:") 1024 1025 # [Install] section is ignored 1026 out = switch_to_specialisation("${machine}", "simpleServiceWithInstallSection") 1027 assert_lacks(out, "stopping the following units:") 1028 assert_lacks(out, "NOT restarting the following changed units:") 1029 assert_lacks(out, "reloading the following units:") 1030 assert_lacks(out, "\nrestarting the following units:") 1031 assert_lacks(out, "\nstarting the following units:") 1032 assert_lacks(out, "the following new units were started:") 1033 1034 # Add a key 1035 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKey") 1036 assert_lacks(out, "stopping the following units:") 1037 assert_lacks(out, "NOT restarting the following changed units:") 1038 assert_lacks(out, "reloading the following units:") 1039 assert_contains(out, "\nrestarting the following units: test.service\n") 1040 assert_lacks(out, "\nstarting the following units:") 1041 assert_lacks(out, "the following new units were started:") 1042 1043 # Change its value 1044 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherValue") 1045 assert_lacks(out, "stopping the following units:") 1046 assert_lacks(out, "NOT restarting the following changed units:") 1047 assert_lacks(out, "reloading the following units:") 1048 assert_contains(out, "\nrestarting the following units: test.service\n") 1049 assert_lacks(out, "\nstarting the following units:") 1050 assert_lacks(out, "the following new units were started:") 1051 1052 # Rename it 1053 out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherName") 1054 assert_lacks(out, "stopping the following units:") 1055 assert_lacks(out, "NOT restarting the following changed units:") 1056 assert_lacks(out, "reloading the following units:") 1057 assert_contains(out, "\nrestarting the following units: test.service\n") 1058 assert_lacks(out, "\nstarting the following units:") 1059 assert_lacks(out, "the following new units were started:") 1060 1061 # Remove it 1062 out = switch_to_specialisation("${machine}", "simpleServiceNostop") 1063 assert_lacks(out, "stopping the following units:") 1064 assert_lacks(out, "NOT restarting the following changed units:") 1065 assert_lacks(out, "reloading the following units:") 1066 assert_contains(out, "\nrestarting the following units: test.service\n") 1067 assert_lacks(out, "\nstarting the following units:") 1068 assert_lacks(out, "the following new units were started:") 1069 1070 # Add a reload trigger 1071 out = switch_to_specialisation("${machine}", "simpleServiceReloadTrigger") 1072 assert_lacks(out, "stopping the following units:") 1073 assert_lacks(out, "NOT restarting the following changed units:") 1074 assert_contains(out, "reloading the following units: test.service\n") 1075 assert_lacks(out, "\nrestarting the following units:") 1076 assert_lacks(out, "\nstarting the following units:") 1077 assert_lacks(out, "the following new units were started:") 1078 1079 # Modify the reload trigger 1080 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModified") 1081 assert_lacks(out, "stopping the following units:") 1082 assert_lacks(out, "NOT restarting the following changed units:") 1083 assert_contains(out, "reloading the following units: test.service\n") 1084 assert_lacks(out, "\nrestarting the following units:") 1085 assert_lacks(out, "\nstarting the following units:") 1086 assert_lacks(out, "the following new units were started:") 1087 1088 # Modify the reload trigger and something else 1089 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedAndSomethingElse") 1090 assert_lacks(out, "stopping the following units:") 1091 assert_lacks(out, "NOT restarting the following changed units:") 1092 assert_lacks(out, "reloading the following units:") 1093 assert_contains(out, "\nrestarting the following units: test.service\n") 1094 assert_lacks(out, "\nstarting the following units:") 1095 assert_lacks(out, "the following new units were started:") 1096 1097 # Remove the reload trigger 1098 out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedSomethingElse") 1099 assert_lacks(out, "stopping the following units:") 1100 assert_lacks(out, "NOT restarting the following changed units:") 1101 assert_lacks(out, "reloading the following units:") 1102 assert_lacks(out, "\nrestarting the following units:") 1103 assert_lacks(out, "\nstarting the following units:") 1104 assert_lacks(out, "the following new units were started:") 1105 1106 with subtest("restart and reload by activation script"): 1107 switch_to_specialisation("${machine}", "simpleServiceNorestart") 1108 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script") 1109 assert_contains(out, "stopping the following units: test.service\n") 1110 assert_lacks(out, "NOT restarting the following changed units:") 1111 assert_lacks(out, "reloading the following units:") 1112 assert_lacks(out, "restarting the following units:") 1113 assert_contains(out, "\nstarting the following units: ${sortedUnits [ 1114 "no-restart-service.service" 1115 "reload-triggers-and-restart-by-as.service" 1116 "simple-reload-service.service" 1117 "simple-restart-service.service" 1118 "simple-service.service" 1119 "templated-no-restart-service@instance.service" 1120 "templated-reload-triggers-and-restart-by-as@instance.service" 1121 "templated-simple-reload-service@instance.service" 1122 "templated-simple-restart-service@instance.service" 1123 "templated-simple-service@instance.service" 1124 ]}\n") 1125 assert_contains(out, "the following new units were started: ${sortedUnits [ 1126 "no-restart-service.service" 1127 "reload-triggers-and-restart-by-as.service" 1128 "reload-triggers-and-restart.service" 1129 "reload-triggers.service" 1130 "simple-reload-service.service" 1131 "simple-restart-service.service" 1132 "simple-service.service" 1133 "system-templated\\\\x2dno\\\\x2drestart\\\\x2dservice.slice" 1134 "system-templated\\\\x2dreload\\\\x2dtriggers.slice" 1135 "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart.slice" 1136 "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart\\\\x2dby\\\\x2das.slice" 1137 "system-templated\\\\x2dsimple\\\\x2dreload\\\\x2dservice.slice" 1138 "system-templated\\\\x2dsimple\\\\x2drestart\\\\x2dservice.slice" 1139 "system-templated\\\\x2dsimple\\\\x2dservice.slice" 1140 "templated-no-restart-service@instance.service" 1141 "templated-reload-triggers-and-restart-by-as@instance.service" 1142 "templated-reload-triggers-and-restart@instance.service" 1143 "templated-reload-triggers@instance.service" 1144 "templated-simple-reload-service@instance.service" 1145 "templated-simple-restart-service@instance.service" 1146 "templated-simple-service@instance.service" 1147 ]}\n") 1148 # Switch to the same system where the example services get restarted 1149 # and reloaded by the activation script 1150 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script") 1151 assert_lacks(out, "stopping the following units:") 1152 assert_lacks(out, "NOT restarting the following changed units:") 1153 assert_contains(out, "reloading the following units: ${sortedUnits [ 1154 "reload-triggers-and-restart.service" 1155 "reload-triggers.service" 1156 "simple-reload-service.service" 1157 "templated-reload-triggers-and-restart@instance.service" 1158 "templated-reload-triggers@instance.service" 1159 "templated-simple-reload-service@instance.service" 1160 ]}\n") 1161 assert_contains(out, "restarting the following units: ${sortedUnits [ 1162 "reload-triggers-and-restart-by-as.service" 1163 "simple-restart-service.service" 1164 "simple-service.service" 1165 "templated-reload-triggers-and-restart-by-as@instance.service" 1166 "templated-simple-restart-service@instance.service" 1167 "templated-simple-service@instance.service" 1168 ]}\n") 1169 assert_lacks(out, "\nstarting the following units:") 1170 assert_lacks(out, "the following new units were started:") 1171 # Switch to the same system and see if the service gets restarted when it's modified 1172 # while the fact that it's supposed to be reloaded by the activation script is ignored. 1173 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script-modified") 1174 assert_lacks(out, "stopping the following units:") 1175 assert_lacks(out, "NOT restarting the following changed units:") 1176 assert_contains(out, "reloading the following units: ${sortedUnits [ 1177 "reload-triggers.service" 1178 "simple-reload-service.service" 1179 "templated-reload-triggers@instance.service" 1180 "templated-simple-reload-service@instance.service" 1181 ]}\n") 1182 assert_contains(out, "restarting the following units: ${sortedUnits [ 1183 "reload-triggers-and-restart-by-as.service" 1184 "reload-triggers-and-restart.service" 1185 "simple-restart-service.service" 1186 "simple-service.service" 1187 "templated-reload-triggers-and-restart-by-as@instance.service" 1188 "templated-reload-triggers-and-restart@instance.service" 1189 "templated-simple-restart-service@instance.service" 1190 "templated-simple-service@instance.service" 1191 ]}\n") 1192 assert_lacks(out, "\nstarting the following units:") 1193 assert_lacks(out, "the following new units were started:") 1194 # The same, but in dry mode 1195 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script", action="dry-activate") 1196 assert_lacks(out, "would stop the following units:") 1197 assert_lacks(out, "would NOT stop the following changed units:") 1198 assert_contains(out, "would reload the following units: ${sortedUnits [ 1199 "reload-triggers.service" 1200 "simple-reload-service.service" 1201 "templated-reload-triggers@instance.service" 1202 "templated-simple-reload-service@instance.service" 1203 ]}\n") 1204 assert_contains(out, "would restart the following units: ${sortedUnits [ 1205 "reload-triggers-and-restart-by-as.service" 1206 "reload-triggers-and-restart.service" 1207 "simple-restart-service.service" 1208 "simple-service.service" 1209 "templated-reload-triggers-and-restart-by-as@instance.service" 1210 "templated-reload-triggers-and-restart@instance.service" 1211 "templated-simple-restart-service@instance.service" 1212 "templated-simple-service@instance.service" 1213 ]}\n") 1214 assert_lacks(out, "\nwould start the following units:") 1215 1216 with subtest("socket-activated services"): 1217 # Socket-activated services don't get started, just the socket 1218 machine.fail("[ -S /run/test.sock ]") 1219 out = switch_to_specialisation("${machine}", "simple-socket") 1220 # assert_lacks(out, "stopping the following units:") not relevant 1221 assert_lacks(out, "NOT restarting the following changed units:") 1222 assert_lacks(out, "reloading the following units:") 1223 assert_lacks(out, "\nrestarting the following units:") 1224 assert_lacks(out, "\nstarting the following units:") 1225 assert_contains(out, "the following new units were started: socket-activated.socket\n") 1226 machine.succeed("[ -S /run/test.sock ]") 1227 1228 # Changing a non-activated service does nothing 1229 out = switch_to_specialisation("${machine}", "simple-socket-service-modified") 1230 assert_lacks(out, "stopping the following units:") 1231 assert_lacks(out, "NOT restarting the following changed units:") 1232 assert_lacks(out, "reloading the following units:") 1233 assert_lacks(out, "\nrestarting the following units:") 1234 assert_lacks(out, "\nstarting the following units:") 1235 assert_lacks(out, "the following new units were started:") 1236 machine.succeed("[ -S /run/test.sock ]") 1237 # The unit is properly activated when the socket is accessed 1238 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello": 1239 raise Exception("Socket was not properly activated") # idk how that would happen tbh 1240 1241 # Changing an activated service with stopIfChanged=false restarts the service 1242 out = switch_to_specialisation("${machine}", "simple-socket") 1243 assert_lacks(out, "stopping the following units:") 1244 assert_lacks(out, "NOT restarting the following changed units:") 1245 assert_lacks(out, "reloading the following units:") 1246 assert_contains(out, "\nrestarting the following units: socket-activated.service\n") 1247 assert_lacks(out, "\nstarting the following units:") 1248 assert_lacks(out, "the following new units were started:") 1249 machine.succeed("[ -S /run/test.sock ]") 1250 # Socket-activation of the unit still works 1251 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello": 1252 raise Exception("Socket was not properly activated after the service was restarted") 1253 1254 # Changing an activated service with stopIfChanged=true stops the service and 1255 # socket and starts the socket 1256 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed") 1257 assert_contains(out, "stopping the following units: socket-activated.service, socket-activated.socket\n") 1258 assert_lacks(out, "NOT restarting the following changed units:") 1259 assert_lacks(out, "reloading the following units:") 1260 assert_lacks(out, "\nrestarting the following units:") 1261 assert_contains(out, "\nstarting the following units: socket-activated.socket\n") 1262 assert_lacks(out, "the following new units were started:") 1263 machine.succeed("[ -S /run/test.sock ]") 1264 # Socket-activation of the unit still works 1265 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello": 1266 raise Exception("Socket was not properly activated after the service was restarted") 1267 1268 # Changing a reload trigger of a socket-activated unit only reloads it 1269 out = switch_to_specialisation("${machine}", "simple-socket-stop-if-changed-and-reloadtrigger") 1270 assert_lacks(out, "stopping the following units:") 1271 assert_lacks(out, "NOT restarting the following changed units:") 1272 assert_contains(out, "reloading the following units: socket-activated.service\n") 1273 assert_lacks(out, "\nrestarting the following units:") 1274 assert_lacks(out, "\nstarting the following units: socket-activated.socket") 1275 assert_lacks(out, "the following new units were started:") 1276 machine.succeed("[ -S /run/test.sock ]") 1277 # Socket-activation of the unit still works 1278 if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello": 1279 raise Exception("Socket was not properly activated after the service was restarted") 1280 1281 with subtest("mounts"): 1282 switch_to_specialisation("${machine}", "mount") 1283 out = machine.succeed("mount | grep 'on /testmount'") 1284 assert_contains(out, "size=1024k") 1285 # Changing options reloads the unit 1286 out = switch_to_specialisation("${machine}", "mountOptionsModified") 1287 assert_lacks(out, "stopping the following units:") 1288 assert_lacks(out, "NOT restarting the following changed units:") 1289 assert_contains(out, "reloading the following units: testmount.mount\n") 1290 assert_lacks(out, "\nrestarting the following units:") 1291 assert_lacks(out, "\nstarting the following units:") 1292 assert_lacks(out, "the following new units were started:") 1293 # It changed 1294 out = machine.succeed("mount | grep 'on /testmount'") 1295 assert_contains(out, "size=10240k") 1296 # Changing anything but `Options=` restarts the unit 1297 out = switch_to_specialisation("${machine}", "mountModified") 1298 assert_lacks(out, "stopping the following units:") 1299 assert_lacks(out, "NOT restarting the following changed units:") 1300 assert_lacks(out, "reloading the following units:") 1301 assert_contains(out, "\nrestarting the following units: testmount.mount\n") 1302 assert_lacks(out, "\nstarting the following units:") 1303 assert_lacks(out, "the following new units were started:") 1304 # It changed 1305 out = machine.succeed("mount | grep 'on /testmount'") 1306 assert_contains(out, "ramfs") 1307 1308 with subtest("timers"): 1309 switch_to_specialisation("${machine}", "timer") 1310 out = machine.succeed("systemctl show test-timer.timer") 1311 assert_contains(out, "OnCalendar=2014-03-25 02:59:56 UTC") 1312 out = switch_to_specialisation("${machine}", "timerModified") 1313 assert_lacks(out, "stopping the following units:") 1314 assert_lacks(out, "NOT restarting the following units:") 1315 assert_lacks(out, "reloading the following units:") 1316 assert_contains(out, "\nrestarting the following units: test-timer.timer\n") 1317 assert_lacks(out, "\nstarting the following units:") 1318 assert_lacks(out, "the following new units were started:") 1319 # It changed 1320 out = machine.succeed("systemctl show test-timer.timer") 1321 assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00") 1322 1323 with subtest("targets"): 1324 # Modifying some special targets like hybrid-sleep.target does nothing 1325 out = switch_to_specialisation("${machine}", "hybridSleepModified") 1326 assert_contains(out, "stopping the following units: test-timer.timer\n") 1327 assert_lacks(out, "NOT restarting the following changed units:") 1328 assert_lacks(out, "reloading the following units:") 1329 assert_lacks(out, "\nrestarting the following units:") 1330 assert_lacks(out, "\nstarting the following units:") 1331 assert_lacks(out, "the following new units were started:") 1332 1333 # Adding a new target starts it 1334 out = switch_to_specialisation("${machine}", "target") 1335 assert_lacks(out, "stopping the following units:") 1336 assert_lacks(out, "NOT restarting the following changed units:") 1337 assert_lacks(out, "reloading the following units:") 1338 assert_lacks(out, "\nrestarting the following units:") 1339 assert_lacks(out, "\nstarting the following units:") 1340 assert_contains(out, "the following new units were started: test-target.target\n") 1341 1342 # Changing a target doesn't print anything because the unit is filtered 1343 machine.systemctl("start test-service.service") 1344 out = switch_to_specialisation("${machine}", "targetModified") 1345 assert_lacks(out, "stopping the following units:") 1346 assert_lacks(out, "NOT restarting the following changed units:") 1347 assert_lacks(out, "reloading the following units:") 1348 assert_lacks(out, "\nrestarting the following units:") 1349 assert_lacks(out, "\nstarting the following units:") 1350 assert_lacks(out, "the following new units were started:") 1351 machine.succeed("systemctl is-active test-service.service") # target was not restarted 1352 1353 # With X-StopOnReconfiguration, the target gets stopped and started 1354 out = switch_to_specialisation("${machine}", "targetModifiedStopOnReconfig") 1355 assert_lacks(out, "stopping the following units:") 1356 assert_lacks(out, "NOT restarting the following changed units:") 1357 assert_lacks(out, "reloading the following units:") 1358 assert_lacks(out, "\nrestarting the following units:") 1359 assert_lacks(out, "\nstarting the following units:") 1360 assert_lacks(out, "the following new units were started:") 1361 machine.fail("systemctl is-active test-service.servce") # target was restarted 1362 1363 # Remove the target by switching to the old specialisation 1364 out = switch_to_specialisation("${machine}", "timerModified") 1365 assert_contains(out, "stopping the following units: test-target.target\n") 1366 assert_lacks(out, "NOT restarting the following changed units:") 1367 assert_lacks(out, "reloading the following units:") 1368 assert_lacks(out, "\nrestarting the following units:") 1369 assert_lacks(out, "\nstarting the following units:") 1370 assert_contains(out, "the following new units were started: test-timer.timer\n") 1371 1372 with subtest("paths"): 1373 out = switch_to_specialisation("${machine}", "path") 1374 assert_contains(out, "stopping the following units: test-timer.timer\n") 1375 assert_lacks(out, "NOT restarting the following changed units:") 1376 assert_lacks(out, "reloading the following units:") 1377 assert_lacks(out, "\nrestarting the following units:") 1378 assert_lacks(out, "\nstarting the following units:") 1379 assert_contains(out, "the following new units were started: test-watch.path\n") 1380 machine.fail("test -f /testpath-modified") 1381 1382 # touch the file, unit should be triggered 1383 machine.succeed("touch /testpath") 1384 machine.wait_until_succeeds("test -f /testpath-modified") 1385 machine.succeed("rm /testpath /testpath-modified") 1386 machine.systemctl("stop test-watch.service") 1387 switch_to_specialisation("${machine}", "pathModified") 1388 machine.succeed("touch /testpath") 1389 machine.fail("test -f /testpath-modified") 1390 machine.succeed("touch /testpath2") 1391 machine.wait_until_succeeds("test -f /testpath-modified") 1392 1393 # This test ensures that changes to slice configuration get applied. 1394 # We test this by having a slice that allows no memory allocation at 1395 # all and starting a service within it. If the service crashes, the slice 1396 # is applied and if we modify the slice to allow memory allocation, the 1397 # service should successfully start. 1398 with subtest("slices"): 1399 machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # allow OOMing 1400 out = switch_to_specialisation("${machine}", "slice") 1401 # assert_lacks(out, "stopping the following units:") not relevant 1402 assert_lacks(out, "NOT restarting the following changed units:") 1403 assert_lacks(out, "reloading the following units:") 1404 assert_lacks(out, "\nrestarting the following units:") 1405 assert_lacks(out, "\nstarting the following units:") 1406 assert_lacks(out, "the following new units were started:") 1407 machine.fail("systemctl start testservice.service") 1408 1409 out = switch_to_specialisation("${machine}", "sliceModified") 1410 assert_lacks(out, "stopping the following units:") 1411 assert_lacks(out, "NOT restarting the following changed units:") 1412 assert_lacks(out, "reloading the following units:") 1413 assert_lacks(out, "\nrestarting the following units:") 1414 assert_lacks(out, "\nstarting the following units:") 1415 assert_lacks(out, "the following new units were started:") 1416 machine.succeed("systemctl start testservice.service") 1417 machine.succeed("echo 1 > /proc/sys/vm/panic_on_oom") # disallow OOMing 1418 ''; 1419})