about summary refs log tree commit diff
path: root/nixpkgs/nixos/tests/hibernate.nix
blob: 7a4b331169a39b760113b5c49ac069725950c4c0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Test whether hibernation from partition works.

{ system ? builtins.currentSystem
, config ? {}
, pkgs ? import ../.. { inherit system config; }
, systemdStage1 ? false
}:

with import ../lib/testing-python.nix { inherit system pkgs; };

let
  # System configuration of the installed system, which is used for the actual
  # hibernate testing.
  installedConfig = with pkgs.lib; {
    imports = [
      ../modules/testing/test-instrumentation.nix
      ../modules/profiles/qemu-guest.nix
      ../modules/profiles/minimal.nix
    ];

    hardware.enableAllFirmware = mkForce false;
    documentation.nixos.enable = false;
    boot.loader.grub.device = "/dev/vda";

    systemd.services.backdoor.conflicts = [ "sleep.target" ];

    powerManagement.resumeCommands = "systemctl --no-block restart backdoor.service";

    fileSystems = {
      "/".device = "/dev/vda2";
    };
    swapDevices = mkOverride 0 [ { device = "/dev/vda1"; } ];
    boot.resumeDevice = mkIf systemdStage1 "/dev/vda1";
    boot.initrd.systemd = mkIf systemdStage1 {
      enable = true;
      emergencyAccess = true;
    };
  };
  installedSystem = (import ../lib/eval-config.nix {
    inherit system;
    modules = [ installedConfig ];
  }).config.system.build.toplevel;
in makeTest {
  name = "hibernate";

  nodes = {
    # System configuration used for installing the installedConfig from above.
    machine = { config, lib, pkgs, ... }: with lib; {
      imports = [
        ../modules/profiles/installation-device.nix
        ../modules/profiles/base.nix
      ];

      nix.settings = {
        substituters = mkForce [];
        hashed-mirrors = null;
        connect-timeout = 1;
      };

      virtualisation.diskSize = 8 * 1024;
      virtualisation.emptyDiskImages = [
        # Small root disk for installer
        512
      ];
      virtualisation.bootDevice = "/dev/vdb";
    };
  };

  # 9P doesn't support reconnection to virtio transport after a hibernation.
  # Therefore, machine just hangs on any Nix store access.
  # To avoid this, we install NixOS onto a temporary disk with everything we need
  # included into the store.

  testScript =
    ''
      def create_named_machine(name):
          machine = create_machine(
              {
                  "qemuFlags": "-cpu max ${
                    if system == "x86_64-linux" then "-m 1024"
                    else "-m 768 -enable-kvm -machine virt,gic-version=host"}",
                  "hdaInterface": "virtio",
                  "hda": "vm-state-machine/machine.qcow2",
                  "name": name,
              }
          )
          driver.machines.append(machine)
          return machine


      # Install NixOS
      machine.start()
      machine.succeed(
          # Partition /dev/vda
          "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
          + " mkpart primary linux-swap 1M 1024M"
          + " mkpart primary ext2 1024M -1s",
          "udevadm settle",
          "mkfs.ext3 -L nixos /dev/vda2",
          "mount LABEL=nixos /mnt",
          "mkswap /dev/vda1 -L swap",
          # Install onto /mnt
          "nix-store --load-db < ${pkgs.closureInfo {rootPaths = [installedSystem];}}/registration",
          "nixos-install --root /mnt --system ${installedSystem} --no-root-passwd --no-channel-copy >&2",
      )
      machine.shutdown()

      # Start up
      hibernate = create_named_machine("hibernate")

      # Drop in file that checks if we un-hibernated properly (and not booted fresh)
      hibernate.succeed(
          "mkdir /run/test",
          "mount -t ramfs -o size=1m ramfs /run/test",
          "echo not persisted to disk > /run/test/suspended",
      )

      # Hibernate machine
      hibernate.execute("systemctl hibernate >&2 &", check_return=False)
      hibernate.wait_for_shutdown()

      # Restore machine from hibernation, validate our ramfs file is there.
      resume = create_named_machine("resume")
      resume.start()
      resume.succeed("grep 'not persisted to disk' /run/test/suspended")

      # Ensure we don't restore from hibernation when booting again
      resume.crash()
      resume.wait_for_unit("default.target")
      resume.fail("grep 'not persisted to disk' /run/test/suspended")
    '';

}