diff --git a/nixos/release.nix b/nixos/release.nix index 12dd81f8970..0694c52a430 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -306,6 +306,7 @@ in rec { tests.simple = callTest tests/simple.nix {}; tests.tomcat = callTest tests/tomcat.nix {}; tests.udisks2 = callTest tests/udisks2.nix {}; + tests.virtualbox = callTest tests/virtualbox.nix {}; tests.xfce = callTest tests/xfce.nix {}; diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix new file mode 100644 index 00000000000..c8912760f3d --- /dev/null +++ b/nixos/tests/virtualbox.nix @@ -0,0 +1,250 @@ +import ./make-test.nix ({ pkgs, ... }: let + + testVMConfig = { config, pkgs, ... }: { + boot.kernelParams = [ + "console=tty0" "console=ttyS0" "ignore_loglevel" + "boot.trace" "panic=1" "boot.panic_on_fail" + ]; + + fileSystems."/" = { + device = "vboxshare"; + fsType = "vboxsf"; + }; + + services.virtualboxGuest.enable = true; + + boot.initrd.kernelModules = [ "vboxsf" ]; + + boot.initrd.extraUtilsCommands = '' + cp -av -t "$out/bin/" \ + "${pkgs.linuxPackages.virtualboxGuestAdditions}/sbin/mount.vboxsf" + ''; + + boot.initrd.postMountCommands = '' + touch /mnt-root/boot-done + + i=0 + while [ ! -e /mnt-root/shutdown ]; do + sleep 10 + i=$(($i + 10)) + [ $i -le 120 ] || fail + done + + rm -f /mnt-root/boot-done /mnt-root/shutdown + poweroff -f + ''; + + system.requiredKernelConfig = with config.lib.kernelConfig; [ + (isYes "SERIAL_8250_CONSOLE") + (isYes "SERIAL_8250") + ]; + }; + + testVM = let + cfg = (import ../lib/eval-config.nix { + system = "i686-linux"; + modules = [ + ../modules/profiles/minimal.nix + testVMConfig + ]; + }).config; + in pkgs.vmTools.runInLinuxVM (pkgs.runCommand "virtualbox-image" { + preVM = '' + mkdir -p "$out" + diskImage="$(pwd)/qimage" + ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw "$diskImage" 100M + ''; + + postVM = '' + echo "creating VirtualBox disk image..." + ${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -O vdi \ + "$diskImage" "$out/disk.vdi" + ''; + + buildInputs = [ pkgs.utillinux pkgs.perl ]; + } '' + ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos + ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s + . /sys/class/block/vda1/uevent + mknod /dev/vda1 b $MAJOR $MINOR + + ${pkgs.e2fsprogs}/sbin/mkfs.ext4 /dev/vda1 + ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 + mkdir /mnt + mount /dev/vda1 /mnt + cp "${cfg.system.build.kernel}/bzImage" /mnt/linux + cp "${cfg.system.build.initialRamdisk}/initrd" /mnt/initrd + + ${pkgs.grub2}/bin/grub-install --boot-directory=/mnt /dev/vda + + cat > /mnt/grub/grub.cfg <execute(ru( + 'set -e; i=0; '. + 'while ! test -e /home/alice/vboxshare/boot-done; do '. + 'sleep 10; i=$(($i + 10)); [ $i -le 3600 ]; '. + 'VBoxManage list runningvms | grep -qF test; '. + 'done' + )); + } + + sub checkRunning { + my $checkrunning = ru "VBoxManage list runningvms | grep -qF test"; + my ($status, $out) = $machine->execute($checkrunning); + return $status == 0; + } + + sub waitForStartup { + for (my $i = 0; $i <= 120; $i += 10) { + $machine->sleep(10); + return if checkRunning; + } + die "VirtualBox VM didn't start up within 2 minutes"; + } + + sub waitForShutdown { + for (my $i = 0; $i <= 120; $i += 10) { + $machine->sleep(10); + return unless checkRunning; + } + die "VirtualBox VM didn't shut down within 2 minutes"; + } + + sub shutdownVM { + $machine->succeed(ru "touch /home/alice/vboxshare/shutdown"); + $machine->waitUntilSucceeds( + "test ! -e /home/alice/vboxshare/shutdown ". + " -a ! -e /home/alice/vboxshare/boot-done" + ); + waitForShutdown; + } + + sub cleanup { + $machine->execute(ru "VBoxManage controlvm test poweroff") + if checkRunning; + $machine->succeed("rm -rf /home/alice/vboxshare"); + $machine->succeed("mkdir -p /home/alice/vboxshare"); + $machine->succeed("chown alice.users /home/alice/vboxshare"); + } + + $machine->waitForX; + + $machine->succeed(ru "VBoxManage createvm --name test ${createFlags}"); + $machine->succeed(ru "VBoxManage modifyvm test ${vmFlags}"); + + $machine->fail("test -e '/root/VirtualBox VMs'"); + $machine->succeed("test -e '/home/alice/VirtualBox VMs'"); + + $machine->succeed(ru "VBoxManage storagectl test ${controllerFlags}"); + $machine->succeed(ru "VBoxManage storageattach test ${diskFlags}"); + + $machine->succeed(ru "VBoxManage sharedfolder add test ${sharedFlags}"); + + $machine->succeed(ru "VBoxManage showvminfo test >&2"); + + cleanup; + + subtest "virtualbox-gui", sub { + $machine->succeed(ru "VirtualBox &"); + $machine->waitForWindow(qr/Oracle VM VirtualBox Manager/); + $machine->sleep(5); + $machine->screenshot("gui_manager_started"); + $machine->sendKeys("ret"); + $machine->screenshot("gui_manager_sent_startup"); + waitForStartup; + $machine->screenshot("gui_started"); + waitForVMBoot; + $machine->screenshot("gui_booted"); + shutdownVM; + $machine->sleep(5); + $machine->screenshot("gui_stopped"); + $machine->sendKeys("ctrl-q"); + $machine->sleep(5); + $machine->screenshot("gui_manager_stopped"); + }; + + cleanup; + + subtest "virtualbox-cli", sub { + $machine->succeed(ru "VBoxManage startvm test"); + waitForStartup; + $machine->screenshot("cli_started"); + waitForVMBoot; + $machine->screenshot("cli_booted"); + shutdownVM; + }; + + $machine->fail("test -e '/root/VirtualBox VMs'"); + $machine->succeed("test -e '/home/alice/VirtualBox VMs'"); + ''; +})