Installer tests: Don't use the ISO

We already have separate tests for checking whether the ISO boots
correctly, so it's not necessary to do that here. So now
tests/installer.nix just tests nixos-install, from a regular NixOS VM
that uses the host's Nix store. This makes running the tests more
convenient because we don't have to build a new ISO after every
change.
This commit is contained in:
Eelco Dolstra 2015-06-10 13:14:40 +02:00
parent e5db79a859
commit d906939e74
3 changed files with 85 additions and 158 deletions

View File

@ -61,8 +61,8 @@ let
idx=2
extraDisks=""
${flip concatMapStrings cfg.emptyDiskImages (size: ''
${pkgs.qemu_kvm}/bin/qemu-img create -f raw "empty$idx" "${toString size}M"
extraDisks="$extraDisks -drive index=$idx,file=$(pwd)/empty$idx,if=virtio,werror=report"
${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 "empty$idx.qcow2" "${toString size}M"
extraDisks="$extraDisks -drive index=$idx,file=$(pwd)/empty$idx.qcow2,if=virtio,werror=report"
idx=$((idx + 1))
'')}
@ -83,7 +83,7 @@ let
'' else ''
''}
'' else ''
-drive file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
-drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
-kernel ${config.system.build.toplevel}/kernel \
-initrd ${config.system.build.toplevel}/initrd \
-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo} ${kernelConsole} $QEMU_KERNEL_PARAMS" \
@ -165,7 +165,7 @@ let
${config.system.build.toplevel}/bin/switch-to-configuration boot
umount /boot
''
'' # */
);
in
@ -204,17 +204,25 @@ in
'';
};
virtualisation.bootDevice =
mkOption {
type = types.str;
default = "/dev/vda";
description =
''
The disk to be used for the root filesystem.
'';
};
virtualisation.emptyDiskImages =
mkOption {
default = [];
type = types.listOf types.int;
description =
''
Additional disk images to provide to the VM, the value is a list of
sizes in megabytes the empty disk should be.
These disks are writeable by the VM and will be thrown away
afterwards.
Additional disk images to provide to the VM. The value is
a list of size in megabytes of each disk. These disks are
writeable by the VM.
'';
};
@ -341,7 +349,7 @@ in
config = {
boot.loader.grub.device = mkVMOverride "/dev/vda";
boot.loader.grub.device = mkVMOverride cfg.bootDevice;
boot.initrd.extraUtilsCommands =
''
@ -353,9 +361,9 @@ in
''
# If the disk image appears to be empty, run mke2fs to
# initialise.
FSTYPE=$(blkid -o value -s TYPE /dev/vda || true)
FSTYPE=$(blkid -o value -s TYPE ${cfg.bootDevice} || true)
if test -z "$FSTYPE"; then
mke2fs -t ext4 /dev/vda
mke2fs -t ext4 ${cfg.bootDevice}
fi
'';
@ -396,7 +404,7 @@ in
# attribute should be disregarded for the purpose of building a VM
# test image (since those filesystems don't exist in the VM).
fileSystems = mkVMOverride (
{ "/".device = "/dev/vda";
{ "/".device = cfg.bootDevice;
${if cfg.writableStore then "/nix/.ro-store" else "/nix/store"} =
{ device = "store";
fsType = "9p";

View File

@ -256,7 +256,6 @@ in rec {
tests.installer.grub1 = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).grub1.test);
tests.installer.lvm = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).lvm.test);
tests.installer.luksroot = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).luksroot.test);
tests.installer.rebuildCD = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).rebuildCD.test);
tests.installer.separateBoot = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).separateBoot.test);
tests.installer.simple = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simple.test);
tests.installer.simpleLabels = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simpleLabels.test);

View File

@ -6,45 +6,8 @@ with pkgs.lib;
let
# Build the ISO. This is the regular minimal installation CD but
# with test instrumentation.
iso =
(import ../lib/eval-config.nix {
inherit system;
modules =
[ ../modules/installer/cd-dvd/installation-cd-minimal.nix
../modules/testing/test-instrumentation.nix
{ key = "serial";
boot.loader.grub.timeout = mkOverride 0 0;
# The test cannot access the network, so any sources we
# need must be included in the ISO.
isoImage.storeContents =
[ pkgs.glibcLocales
pkgs.sudo
pkgs.docbook5
pkgs.docbook5_xsl
pkgs.unionfs-fuse
# Bootloader support
pkgs.grub
pkgs.grub2
pkgs.grub2_efi
pkgs.gummiboot
pkgs.perlPackages.XMLLibXML
pkgs.perlPackages.ListCompare
];
# Don't use https://cache.nixos.org since the fake
# cache.nixos.org doesn't do https.
nix.binaryCaches = [ http://cache.nixos.org/ ];
}
];
}).config.system.build.isoImage;
# The configuration to install.
makeConfig = { testChannel, grubVersion, grubDevice, grubIdentifier
makeConfig = { grubVersion, grubDevice, grubIdentifier
, extraConfig, readOnly ? true, forceGrubReinstallCount ? 0
}:
pkgs.writeText "configuration.nix" ''
@ -53,7 +16,6 @@ let
{ imports =
[ ./hardware-configuration.nix
<nixpkgs/nixos/modules/testing/test-instrumentation.nix>
<nixpkgs/nixos/modules/profiles/minimal.nix>
];
boot.loader.grub.version = ${toString grubVersion};
@ -68,94 +30,39 @@ let
${optionalString (!readOnly) "nix.readOnlyStore = false;"}
environment.systemPackages = [ ${optionalString testChannel "pkgs.rlwrap"} ];
hardware.enableAllFirmware = lib.mkForce false;
nix.binaryCaches = [ http://cache.nixos.org/ ];
${replaceChars ["\n"] ["\n "] extraConfig}
}
'';
# Configuration of a web server that simulates the Nixpkgs channel
# distribution server.
webserver =
{ config, lib, pkgs, ... }:
{ services.httpd.enable = true;
services.httpd.adminAddr = "foo@example.org";
services.httpd.servedDirs = singleton
{ urlPath = "/";
dir = "/tmp/channel";
};
virtualisation.writableStore = true;
virtualisation.pathsInNixDB = channelContents ++ [ pkgs.hello.src ];
virtualisation.memorySize = 768;
networking.firewall.allowedTCPPorts = [ 80 ];
};
channelContents = [ pkgs.rlwrap ];
# The test script boots the CD, installs NixOS on an empty hard
# The test script boots a NixOS VM, installs NixOS on an empty hard
# disk, and then reboot from the hard disk. It's parameterized with
# a test script fragment `createPartitions', which must create
# partitions and filesystems.
testScriptFun = { createPartitions, testChannel, grubVersion, grubDevice
testScriptFun = { createPartitions, grubVersion, grubDevice
, grubIdentifier, preBootCommands, extraConfig
}:
let
# FIXME: OVMF doesn't boot from virtio http://www.mail-archive.com/edk2-devel@lists.sourceforge.net/msg01501.html
iface = if grubVersion == 1 then "scsi" else "virtio";
qemuFlags =
(if iso.system == "x86_64-linux" then "-m 768 " else "-m 512 ") +
(optionalString (iso.system == "x86_64-linux") "-cpu kvm64 ");
hdFlags =''hda => "harddisk", hdaInterface => "${iface}", '';
(if system == "x86_64-linux" then "-m 768 " else "-m 512 ") +
(optionalString (system == "x86_64-linux") "-cpu kvm64 ");
hdFlags = ''hda => "vm-state-machine/machine.qcow2", hdaInterface => "${iface}", '';
in
''
createDisk("harddisk", 8 * 1024);
my $machine = createMachine({ ${hdFlags}
cdrom => glob("${iso}/iso/*.iso"),
qemuFlags => "${qemuFlags} " . '${optionalString testChannel (toString (qemuNICFlags 1 1 2))}' });
$machine->start;
${optionalString testChannel ''
# Create a channel on the web server containing a few packages
# to simulate the Nixpkgs channel.
$webserver->start;
$webserver->waitForUnit("httpd");
$webserver->succeed(
"nix-push --bzip2 --dest /tmp/channel --manifest --url-prefix http://nixos.org/channels/nixos-unstable " .
"${toString channelContents} >&2");
$webserver->succeed("mkdir /tmp/channel/sha256");
$webserver->succeed("cp ${pkgs.hello.src} /tmp/channel/sha256/${pkgs.hello.src.outputHash}");
''}
# Make sure that we get a login prompt etc.
$machine->succeed("echo hello");
#$machine->waitForUnit('getty@tty2');
$machine->waitForUnit("rogue");
$machine->waitForUnit("nixos-manual");
${optionalString testChannel ''
$machine->waitForUnit("dhcpcd");
# Allow the machine to talk to the fake nixos.org.
$machine->succeed(
"rm /etc/hosts",
"echo 192.168.1.1 nixos.org cache.nixos.org tarballs.nixos.org > /etc/hosts",
"ifconfig eth1 up 192.168.1.2",
);
# Test nix-env.
$machine->fail("hello");
$machine->succeed("nix-env -i hello");
$machine->succeed("hello") =~ /Hello, world/
or die "bad `hello' output";
''}
# Wait for hard disks to appear in /dev
$machine->succeed("udevadm settle");
@ -163,14 +70,12 @@ let
${createPartitions}
# Create the NixOS configuration.
$machine->succeed(
"nixos-generate-config --root /mnt",
);
$machine->succeed("nixos-generate-config --root /mnt");
$machine->succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2");
$machine->copyFileFromHost(
"${ makeConfig { inherit testChannel grubVersion grubDevice grubIdentifier extraConfig; } }",
"${ makeConfig { inherit grubVersion grubDevice grubIdentifier extraConfig; } }",
"/mnt/etc/nixos/configuration.nix");
# Perform the installation.
@ -188,7 +93,7 @@ let
# Now see if we can boot the installation.
$machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}" });
# For example to enter LUKS passphrase
# For example to enter LUKS passphrase.
${preBootCommands}
# Did /boot get mounted?
@ -209,9 +114,9 @@ let
$machine->succeed("type -tP ls | tee /dev/stderr") =~ /.nix-profile/
or die "nix-env failed";
# We need to a writable nix-store on next boot
# We need to a writable nix-store on next boot.
$machine->copyFileFromHost(
"${ makeConfig { inherit testChannel grubVersion grubDevice grubIdentifier extraConfig; readOnly = false; forceGrubReinstallCount = 1; } }",
"${ makeConfig { inherit grubVersion grubDevice grubIdentifier extraConfig; readOnly = false; forceGrubReinstallCount = 1; } }",
"/etc/nixos/configuration.nix");
# Check whether nixos-rebuild works.
@ -220,7 +125,7 @@ let
# Test nixos-option.
$machine->succeed("nixos-option boot.initrd.kernelModules | grep virtio_console");
$machine->succeed("nixos-option boot.initrd.kernelModules | grep 'List of modules'");
$machine->succeed("nixos-option boot.initrd.kernelModules | grep qemu-guest.nix");
$machine->succeed("nixos-option boot.initrd.kernelModules | grep qemu-guest.nix");
$machine->shutdown;
@ -229,7 +134,7 @@ let
${preBootCommands}
$machine->waitForUnit("multi-user.target");
$machine->copyFileFromHost(
"${ makeConfig { inherit testChannel grubVersion grubDevice grubIdentifier extraConfig; readOnly = false; forceGrubReinstallCount = 2; } }",
"${ makeConfig { inherit grubVersion grubDevice grubIdentifier extraConfig; readOnly = false; forceGrubReinstallCount = 2; } }",
"/etc/nixos/configuration.nix");
$machine->succeed("nixos-rebuild boot >&2");
$machine->shutdown;
@ -245,16 +150,60 @@ let
makeInstallerTest = name:
{ createPartitions, preBootCommands ? "", extraConfig ? ""
, testChannel ? false, grubVersion ? 2, grubDevice ? "/dev/vda"
, grubVersion ? 2, grubDevice ? "/dev/vda"
, grubIdentifier ? "uuid", enableOCR ? false
}:
makeTest {
inherit iso;
name = "installer-" + name;
nodes = if testChannel then { inherit webserver; } else { };
inherit enableOCR;
name = "installer-" + name;
nodes = {
# The configuration of the machine used to run "nixos-install". It
# also has a web server that simulates cache.nixos.org.
machine =
{ config, lib, pkgs, ... }:
{ imports =
[ ../modules/profiles/installation-device.nix
../modules/profiles/base.nix
];
virtualisation.diskSize = 8 * 1024;
virtualisation.memorySize = 768;
virtualisation.writableStore = true;
# Use a small /dev/vdb as the root disk for the
# installer. This ensures the target disk (/dev/vda) is
# the same during and after installation.
virtualisation.emptyDiskImages = [ 512 ];
virtualisation.bootDevice = "/dev/vdb";
hardware.enableAllFirmware = mkForce false;
# The test cannot access the network, so any packages we
# need must be included in the VM.
system.extraDependencies =
[ pkgs.sudo
pkgs.docbook5
pkgs.docbook5_xsl
pkgs.unionfs-fuse
pkgs.ntp
pkgs.nixos-artwork
pkgs.gummiboot
pkgs.perlPackages.XMLLibXML
pkgs.perlPackages.ListCompare
]
++ optional (grubVersion == 1) pkgs.grub
++ optionals (grubVersion == 2) [ pkgs.grub2 pkgs.grub2_efi ];
nix.binaryCaches = mkForce [ ];
};
};
testScript = testScriptFun {
inherit createPartitions preBootCommands testChannel grubVersion
inherit createPartitions preBootCommands grubVersion
grubDevice grubIdentifier extraConfig;
};
};
@ -281,7 +230,6 @@ in {
"mount LABEL=nixos /mnt",
);
'';
testChannel = true;
};
# Same as the previous, but now with a separate /boot partition.
@ -413,40 +361,11 @@ in {
"mkfs.ext3 -L nixos /dev/sda2",
"mount LABEL=nixos /mnt",
);
'';
grubVersion = 1;
grubDevice = "/dev/sda";
};
# Rebuild the CD configuration with a little modification.
rebuildCD = makeTest
{ inherit iso;
name = "rebuild-cd";
nodes = { };
testScript =
''
my $machine = createMachine({ cdrom => glob("${iso}/iso/*.iso"), qemuFlags => '-m 768' });
$machine->start;
# Enable sshd service.
$machine->succeed(
"sed -i 's,^}\$,systemd.services.sshd.wantedBy = pkgs.lib.mkOverride 0 [\"multi-user.target\"]; },' /etc/nixos/configuration.nix"
);
$machine->succeed("cat /etc/nixos/configuration.nix >&2");
# Apply the new CD configuration.
$machine->succeed("nixos-rebuild test");
# Connect to it-self.
$machine->waitForUnit("sshd");
$machine->waitForOpenPort(22);
$machine->shutdown;
'';
};
# Test using labels to identify volumes in grub
simpleLabels = makeInstallerTest "simpleLabels" {
createPartitions = ''
@ -545,4 +464,5 @@ in {
);
'';
};
}