Rather than relying on carefully avoiding touching the 9P-mounted /nix/store, we instead install a small NixOS system, similar to the installer tests, and boot from that. This avoids the various pitfalls associated with trying to unsuspend properly and trades off a bunch of boilerplate for what will hopefully be a more reliable test. Additionally, this test now actually tests booting the system using a bootloader, rather than the previous method of just booting the kernel directly.wip/yesman
parent
bdf8e0fc31
commit
32d80aaaa5
@ -1,44 +1,120 @@ |
||||
# Test whether hibernation from partition works. |
||||
|
||||
import ./make-test-python.nix (pkgs: { |
||||
name = "hibernate"; |
||||
{ system ? builtins.currentSystem |
||||
, config ? {} |
||||
, pkgs ? import ../.. { inherit system config; } |
||||
}: |
||||
|
||||
nodes = { |
||||
machine = { config, lib, pkgs, ... }: with lib; { |
||||
virtualisation.emptyDiskImages = [ config.virtualisation.memorySize ]; |
||||
with import ../lib/testing-python.nix { inherit system pkgs; }; |
||||
|
||||
systemd.services.backdoor.conflicts = [ "sleep.target" ]; |
||||
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 |
||||
]; |
||||
|
||||
swapDevices = mkOverride 0 [ { device = "/dev/vdb"; } ]; |
||||
hardware.enableAllFirmware = mkForce false; |
||||
documentation.nixos.enable = false; |
||||
boot.loader.grub.device = "/dev/vda"; |
||||
|
||||
networking.firewall.allowedTCPPorts = [ 4444 ]; |
||||
systemd.services.backdoor.conflicts = [ "sleep.target" ]; |
||||
|
||||
systemd.services.listener.serviceConfig.ExecStart = "${pkgs.netcat}/bin/nc -l 4444 -k"; |
||||
powerManagement.resumeCommands = "systemctl --no-block restart backdoor.service"; |
||||
|
||||
fileSystems = { |
||||
"/".device = "/dev/vda2"; |
||||
}; |
||||
swapDevices = mkOverride 0 [ { device = "/dev/vda1"; } ]; |
||||
}; |
||||
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 |
||||
]; |
||||
|
||||
probe = { pkgs, ...}: { |
||||
environment.systemPackages = [ pkgs.netcat ]; |
||||
nix.binaryCaches = mkForce [ ]; |
||||
nix.extraOptions = '' |
||||
hashed-mirrors = |
||||
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 work around it we run a daemon which listens to a TCP connection and |
||||
# try to connect to it as a test. |
||||
# To avoid this, we install NixOS onto a temporary disk with everything we need |
||||
# included into the store. |
||||
|
||||
testScript = |
||||
'' |
||||
def create_named_machine(name): |
||||
return 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, |
||||
} |
||||
) |
||||
|
||||
|
||||
# Install NixOS |
||||
machine.start() |
||||
machine.wait_for_unit("multi-user.target") |
||||
machine.succeed("mkswap /dev/vdb") |
||||
machine.succeed("swapon -a") |
||||
machine.start_job("listener") |
||||
machine.wait_for_open_port(4444) |
||||
machine.succeed("systemctl hibernate &") |
||||
machine.wait_for_shutdown() |
||||
probe.wait_for_unit("multi-user.target") |
||||
machine.start() |
||||
probe.wait_until_succeeds("echo test | nc machine 4444 -N") |
||||
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", |
||||
) |
||||
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.succeed("systemctl hibernate &") |
||||
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") |
||||
''; |
||||
|
||||
}) |
||||
} |
||||
|
Loading…
Reference in new issue