1# Test whether hibernation from partition works.
2
3{ system ? builtins.currentSystem
4, config ? {}
5, pkgs ? import ../.. { inherit system config; }
6, systemdStage1 ? false
7}:
8
9with import ../lib/testing-python.nix { inherit system pkgs; };
10
11let
12 # System configuration of the installed system, which is used for the actual
13 # hibernate testing.
14 installedConfig = with pkgs.lib; {
15 imports = [
16 ../modules/testing/test-instrumentation.nix
17 ../modules/profiles/qemu-guest.nix
18 ../modules/profiles/minimal.nix
19 ];
20
21 hardware.enableAllFirmware = mkForce false;
22 documentation.nixos.enable = false;
23 boot.loader.grub.device = "/dev/vda";
24
25 systemd.services.backdoor.conflicts = [ "sleep.target" ];
26
27 powerManagement.resumeCommands = "systemctl --no-block restart backdoor.service";
28
29 fileSystems."/" = {
30 device = "/dev/vda2";
31 fsType = "ext3";
32 };
33 swapDevices = mkOverride 0 [ { device = "/dev/vda1"; } ];
34 boot.resumeDevice = mkIf systemdStage1 "/dev/vda1";
35 boot.initrd.systemd = mkIf systemdStage1 {
36 enable = true;
37 emergencyAccess = true;
38 };
39 };
40 installedSystem = (import ../lib/eval-config.nix {
41 inherit system;
42 modules = [ installedConfig ];
43 }).config.system.build.toplevel;
44in makeTest {
45 name = "hibernate";
46
47 nodes = {
48 # System configuration used for installing the installedConfig from above.
49 machine = { config, lib, pkgs, ... }: {
50 imports = [
51 ../modules/profiles/installation-device.nix
52 ../modules/profiles/base.nix
53 ];
54
55 nix.settings = {
56 substituters = lib.mkForce [];
57 hashed-mirrors = null;
58 connect-timeout = 1;
59 };
60
61 virtualisation.diskSize = 8 * 1024;
62 virtualisation.emptyDiskImages = [
63 # Small root disk for installer
64 512
65 ];
66 virtualisation.rootDevice = "/dev/vdb";
67 };
68 };
69
70 # 9P doesn't support reconnection to virtio transport after a hibernation.
71 # Therefore, machine just hangs on any Nix store access.
72 # To avoid this, we install NixOS onto a temporary disk with everything we need
73 # included into the store.
74
75 testScript =
76 ''
77 def create_named_machine(name):
78 machine = create_machine(
79 {
80 "qemuFlags": "-cpu max ${
81 if system == "x86_64-linux" then "-m 1024"
82 else "-m 768 -enable-kvm -machine virt,gic-version=host"}",
83 "hdaInterface": "virtio",
84 "hda": "vm-state-machine/machine.qcow2",
85 "name": name,
86 }
87 )
88 driver.machines.append(machine)
89 return machine
90
91
92 # Install NixOS
93 machine.start()
94 machine.succeed(
95 # Partition /dev/vda
96 "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
97 + " mkpart primary linux-swap 1M 1024M"
98 + " mkpart primary ext2 1024M -1s",
99 "udevadm settle",
100 "mkfs.ext3 -L nixos /dev/vda2",
101 "mount LABEL=nixos /mnt",
102 "mkswap /dev/vda1 -L swap",
103 # Install onto /mnt
104 "nix-store --load-db < ${pkgs.closureInfo {rootPaths = [installedSystem];}}/registration",
105 "nixos-install --root /mnt --system ${installedSystem} --no-root-passwd --no-channel-copy >&2",
106 )
107 machine.shutdown()
108
109 # Start up
110 hibernate = create_named_machine("hibernate")
111
112 # Drop in file that checks if we un-hibernated properly (and not booted fresh)
113 hibernate.succeed(
114 "mkdir /run/test",
115 "mount -t ramfs -o size=1m ramfs /run/test",
116 "echo not persisted to disk > /run/test/suspended",
117 )
118
119 # Hibernate machine
120 hibernate.execute("systemctl hibernate >&2 &", check_return=False)
121 hibernate.wait_for_shutdown()
122
123 # Restore machine from hibernation, validate our ramfs file is there.
124 resume = create_named_machine("resume")
125 resume.start()
126 resume.succeed("grep 'not persisted to disk' /run/test/suspended")
127
128 # Ensure we don't restore from hibernation when booting again
129 resume.crash()
130 resume.wait_for_unit("default.target")
131 resume.fail("grep 'not persisted to disk' /run/test/suspended")
132 '';
133
134}