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