| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  | { system ? builtins.currentSystem, debug ? false }: | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  | with import ../lib/testing.nix { inherit system; }; | 
					
						
							|  |  |  | with pkgs.lib; | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  | let | 
					
						
							| 
									
										
										
										
											2016-08-23 13:05:14 +02:00
										 |  |  |   testVMConfig = vmName: attrs: { config, pkgs, lib, ... }: let | 
					
						
							| 
									
										
										
										
											2015-09-17 11:02:43 +02:00
										 |  |  |     guestAdditions = pkgs.linuxPackages.virtualboxGuestAdditions; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     miniInit = ''
 | 
					
						
							|  |  |  |       #!${pkgs.stdenv.shell} -xe | 
					
						
							| 
									
										
										
										
											2016-08-23 13:05:14 +02:00
										 |  |  |       export PATH="${lib.makeBinPath [ pkgs.coreutils pkgs.utillinux ]}" | 
					
						
							| 
									
										
										
										
											2015-09-17 11:02:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-24 12:43:42 +02:00
										 |  |  |       mkdir -p /run/dbus | 
					
						
							| 
									
										
										
										
											2015-09-17 11:02:43 +02:00
										 |  |  |       cat > /etc/passwd <<EOF | 
					
						
							|  |  |  |       root:x:0:0::/root:/bin/false | 
					
						
							| 
									
										
										
										
											2016-10-24 12:43:42 +02:00
										 |  |  |       messagebus:x:1:1::/run/dbus:/bin/false | 
					
						
							| 
									
										
										
										
											2015-09-17 11:02:43 +02:00
										 |  |  |       EOF | 
					
						
							|  |  |  |       cat > /etc/group <<EOF | 
					
						
							|  |  |  |       root:x:0: | 
					
						
							|  |  |  |       messagebus:x:1: | 
					
						
							|  |  |  |       EOF | 
					
						
							| 
									
										
										
										
											2016-05-26 16:45:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       "${pkgs.dbus.daemon}/bin/dbus-daemon" --fork \ | 
					
						
							|  |  |  |         --config-file="${pkgs.dbus.daemon}/share/dbus-1/system.conf" | 
					
						
							| 
									
										
										
										
											2015-09-17 11:02:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       ${guestAdditions}/bin/VBoxService | 
					
						
							|  |  |  |       ${(attrs.vmScript or (const "")) pkgs} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       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 | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  |   in { | 
					
						
							|  |  |  |     boot.kernelParams = [ | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |       "console=tty0" "console=ttyS0" "ignore_loglevel" | 
					
						
							|  |  |  |       "boot.trace" "panic=1" "boot.panic_on_fail" | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       "init=${pkgs.writeScript "mini-init.sh" miniInit}" | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 21:42:50 +01:00
										 |  |  |     # XXX: Remove this once TSS location detection has been fixed in VirtualBox | 
					
						
							|  |  |  |     boot.kernelPackages = pkgs.linuxPackages_4_9; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     fileSystems."/" = { | 
					
						
							|  |  |  |       device = "vboxshare"; | 
					
						
							|  |  |  |       fsType = "vboxsf"; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-13 12:17:32 +02:00
										 |  |  |     virtualisation.virtualbox.guest.enable = true; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |     boot.initrd.kernelModules = [ | 
					
						
							|  |  |  |       "af_packet" "vboxsf" | 
					
						
							|  |  |  |       "virtio" "virtio_pci" "virtio_ring" "virtio_net" "vboxguest" | 
					
						
							|  |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     boot.initrd.extraUtilsCommands = ''
 | 
					
						
							| 
									
										
										
										
											2015-09-17 11:02:43 +02:00
										 |  |  |       copy_bin_and_libs "${guestAdditions}/bin/mount.vboxsf" | 
					
						
							| 
									
										
										
										
											2015-03-28 17:15:41 -07:00
										 |  |  |       copy_bin_and_libs "${pkgs.utillinux}/bin/unshare" | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       ${(attrs.extraUtilsCommands or (const "")) pkgs} | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     boot.initrd.postMountCommands = ''
 | 
					
						
							|  |  |  |       touch /mnt-root/boot-done | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       hostname "${vmName}" | 
					
						
							|  |  |  |       mkdir -p /nix/store | 
					
						
							| 
									
										
											  
											
												nixos/tests/virtualbox: Fix @shell@ expansion
This has surfaced since f803270b7e00fa7124282809838d5652083b6aad.
The commit bumped bash to version 4.4, which caused to change the order
of --subst-var flags in substituteAll, which this test was relying on,
because it added a @shell@ to boot.initrd.postMountCommands.
Our substituter is currently working a bit like this:
original.replace('@var1@', 'val1').replace('@var2@', 'val2')...
Unfortunately, this means that if @var2@ occurs within @var1@ it is
replaced by the new value, so the order of the substvars actually
matter. I highly doubt that we want a behaviour like this and I'm
wondering why it didn't occur to me as a problem while writing the
initial implementation of the VirtualBox tests.
Whether to get rid of this and disallowing substitution of substvars
within substvars is another topic which I think needs discussion in a
different place.
As for now, I'm using stdenv.shell, because the closure size of this
should fit within the initrd, so it's fine especially because it's just
a test.
Tested with the net-hostonlyif and systemd-detect-virt tests and they
both succeed with this change.
Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Reported-by: @globin on IRC
											
										 
											2017-03-27 04:15:44 +02:00
										 |  |  |       unshare -m ${escapeShellArg pkgs.stdenv.shell} -c ' | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |         mount -t vboxsf nixstore /nix/store | 
					
						
							|  |  |  |         exec "$stage2Init" | 
					
						
							|  |  |  |       ' | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |       poweroff -f | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     system.requiredKernelConfig = with config.lib.kernelConfig; [ | 
					
						
							|  |  |  |       (isYes "SERIAL_8250_CONSOLE") | 
					
						
							|  |  |  |       (isYes "SERIAL_8250") | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 19:17:38 +01:00
										 |  |  |   mkLog = logfile: tag: let | 
					
						
							|  |  |  |     rotated = map (i: "${logfile}.${toString i}") (range 1 9); | 
					
						
							|  |  |  |     all = concatMapStringsSep " " (f: "\"${f}\"") ([logfile] ++ rotated); | 
					
						
							|  |  |  |     logcmd = "tail -F ${all} 2> /dev/null | logger -t \"${tag}\""; | 
					
						
							| 
									
										
										
										
											2014-12-18 13:43:18 +01:00
										 |  |  |   in optionalString debug "$machine->execute(ru '${logcmd} & disown');"; | 
					
						
							| 
									
										
										
										
											2014-12-15 19:17:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |   testVM = vmName: vmScript: let | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     cfg = (import ../lib/eval-config.nix { | 
					
						
							|  |  |  |       system = "i686-linux"; | 
					
						
							|  |  |  |       modules = [ | 
					
						
							|  |  |  |         ../modules/profiles/minimal.nix | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |         (testVMConfig vmName vmScript) | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |       ]; | 
					
						
							|  |  |  |     }).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 ]; | 
					
						
							|  |  |  |   } ''
 | 
					
						
							| 
									
										
										
										
											2017-10-08 15:35:47 +02:00
										 |  |  |     ${pkgs.parted}/sbin/parted --script /dev/vda mklabel msdos | 
					
						
							|  |  |  |     ${pkgs.parted}/sbin/parted --script /dev/vda -- mkpart primary ext2 1M -1s | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     ${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 <<GRUB | 
					
						
							|  |  |  |     set root=hd0,1 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |     linux /linux ${concatStringsSep " " cfg.boot.kernelParams} | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     initrd /initrd | 
					
						
							|  |  |  |     boot | 
					
						
							|  |  |  |     GRUB | 
					
						
							|  |  |  |     umount /mnt | 
					
						
							|  |  |  |   '');
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |   createVM = name: attrs: let | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |     mkFlags = concatStringsSep " "; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |     sharePath = "/home/alice/vboxshare-${name}"; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     createFlags = mkFlags [ | 
					
						
							|  |  |  |       "--ostype Linux26" | 
					
						
							|  |  |  |       "--register" | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |     vmFlags = mkFlags ([ | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |       "--uart1 0x3F8 4" | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |       "--uartmode1 client /run/virtualbox-log-${name}.sock" | 
					
						
							| 
									
										
										
										
											2015-09-22 09:24:10 +02:00
										 |  |  |       "--memory 768" | 
					
						
							| 
									
										
										
										
											2016-09-13 23:17:47 +02:00
										 |  |  |       "--audio none" | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |     ] ++ (attrs.vmFlags or [])); | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     controllerFlags = mkFlags [ | 
					
						
							|  |  |  |       "--name SATA" | 
					
						
							|  |  |  |       "--add sata" | 
					
						
							|  |  |  |       "--bootable on" | 
					
						
							|  |  |  |       "--hostiocache on" | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     diskFlags = mkFlags [ | 
					
						
							|  |  |  |       "--storagectl SATA" | 
					
						
							|  |  |  |       "--port 0" | 
					
						
							|  |  |  |       "--device 0" | 
					
						
							|  |  |  |       "--type hdd" | 
					
						
							|  |  |  |       "--mtype immutable" | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       "--medium ${testVM name attrs}/disk.vdi" | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sharedFlags = mkFlags [ | 
					
						
							|  |  |  |       "--name vboxshare" | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |       "--hostpath ${sharePath}" | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     nixstoreFlags = mkFlags [ | 
					
						
							|  |  |  |       "--name nixstore" | 
					
						
							|  |  |  |       "--hostpath /nix/store" | 
					
						
							|  |  |  |       "--readonly" | 
					
						
							|  |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |   in { | 
					
						
							|  |  |  |     machine = { | 
					
						
							| 
									
										
										
										
											2015-09-17 11:25:37 +02:00
										 |  |  |       systemd.sockets."vboxtestlog-${name}" = { | 
					
						
							| 
									
										
										
										
											2015-09-17 11:32:05 +02:00
										 |  |  |         description = "VirtualBox Test Machine Log Socket For ${name}"; | 
					
						
							| 
									
										
										
										
											2015-09-17 11:25:37 +02:00
										 |  |  |         wantedBy = [ "sockets.target" ]; | 
					
						
							|  |  |  |         before = [ "multi-user.target" ]; | 
					
						
							|  |  |  |         socketConfig.ListenStream = "/run/virtualbox-log-${name}.sock"; | 
					
						
							|  |  |  |         socketConfig.Accept = true; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       systemd.services."vboxtestlog-${name}@" = { | 
					
						
							| 
									
										
										
										
											2015-09-17 11:32:05 +02:00
										 |  |  |         description = "VirtualBox Test Machine Log For ${name}"; | 
					
						
							| 
									
										
										
										
											2015-09-17 11:25:37 +02:00
										 |  |  |         serviceConfig.StandardInput = "socket"; | 
					
						
							|  |  |  |         serviceConfig.StandardOutput = "syslog"; | 
					
						
							|  |  |  |         serviceConfig.SyslogIdentifier = "GUEST-${name}"; | 
					
						
							|  |  |  |         serviceConfig.ExecStart = "${pkgs.coreutils}/bin/cat"; | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |     testSubs = ''
 | 
					
						
							| 
									
										
										
										
											2015-09-17 14:12:24 +02:00
										 |  |  |       my ${"$" + name}_sharepath = '${sharePath}'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       sub checkRunning_${name} { | 
					
						
							|  |  |  |         my $cmd = 'VBoxManage list runningvms | grep -q "^\"${name}\""'; | 
					
						
							|  |  |  |         my ($status, $out) = $machine->execute(ru $cmd); | 
					
						
							|  |  |  |         return $status == 0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sub cleanup_${name} { | 
					
						
							|  |  |  |         $machine->execute(ru "VBoxManage controlvm ${name} poweroff") | 
					
						
							|  |  |  |           if checkRunning_${name}; | 
					
						
							|  |  |  |         $machine->succeed("rm -rf ${sharePath}"); | 
					
						
							|  |  |  |         $machine->succeed("mkdir -p ${sharePath}"); | 
					
						
							|  |  |  |         $machine->succeed("chown alice.users ${sharePath}"); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |       sub createVM_${name} { | 
					
						
							|  |  |  |         vbm("createvm --name ${name} ${createFlags}"); | 
					
						
							|  |  |  |         vbm("modifyvm ${name} ${vmFlags}"); | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |         vbm("setextradata ${name} VBoxInternal/PDM/HaltOnReset 1"); | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |         vbm("storagectl ${name} ${controllerFlags}"); | 
					
						
							|  |  |  |         vbm("storageattach ${name} ${diskFlags}"); | 
					
						
							|  |  |  |         vbm("sharedfolder add ${name} ${sharedFlags}"); | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |         vbm("sharedfolder add ${name} ${nixstoreFlags}"); | 
					
						
							|  |  |  |         cleanup_${name}; | 
					
						
							| 
									
										
										
										
											2014-12-15 19:17:38 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ${mkLog "$HOME/VirtualBox VMs/${name}/Logs/VBox.log" "HOST-${name}"} | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sub destroyVM_${name} { | 
					
						
							|  |  |  |         cleanup_${name}; | 
					
						
							|  |  |  |         vbm("unregistervm ${name} --delete"); | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |       sub waitForVMBoot_${name} { | 
					
						
							|  |  |  |         $machine->execute(ru( | 
					
						
							|  |  |  |           'set -e; i=0; '. | 
					
						
							|  |  |  |           'while ! test -e ${sharePath}/boot-done; do '. | 
					
						
							|  |  |  |           'sleep 10; i=$(($i + 10)); [ $i -le 3600 ]; '. | 
					
						
							|  |  |  |           'VBoxManage list runningvms | grep -q "^\"${name}\""; '. | 
					
						
							|  |  |  |           'done' | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       sub waitForIP_${name} ($) { | 
					
						
							|  |  |  |         my $property = "/VirtualBox/GuestInfo/Net/$_[0]/V4/IP"; | 
					
						
							|  |  |  |         my $getip = "VBoxManage guestproperty get ${name} $property | ". | 
					
						
							|  |  |  |                     "sed -n -e 's/^Value: //p'"; | 
					
						
							|  |  |  |         my $ip = $machine->succeed(ru( | 
					
						
							|  |  |  |           'for i in $(seq 1000); do '. | 
					
						
							|  |  |  |           'if ipaddr="$('.$getip.')" && [ -n "$ipaddr" ]; then '. | 
					
						
							|  |  |  |           'echo "$ipaddr"; exit 0; '. | 
					
						
							|  |  |  |           'fi; '. | 
					
						
							|  |  |  |           'sleep 1; '. | 
					
						
							|  |  |  |           'done; '. | 
					
						
							|  |  |  |           'echo "Could not get IPv4 address for ${name}!" >&2; '. | 
					
						
							|  |  |  |           'exit 1' | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |         chomp $ip; | 
					
						
							|  |  |  |         return $ip; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |       sub waitForStartup_${name} { | 
					
						
							|  |  |  |         for (my $i = 0; $i <= 120; $i += 10) { | 
					
						
							|  |  |  |           $machine->sleep(10); | 
					
						
							|  |  |  |           return if checkRunning_${name}; | 
					
						
							| 
									
										
										
										
											2015-04-04 07:51:46 +02:00
										 |  |  |           eval { $_[0]->() } if defined $_[0]; | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         die "VirtualBox VM didn't start up within 2 minutes"; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |       sub waitForShutdown_${name} { | 
					
						
							|  |  |  |         for (my $i = 0; $i <= 120; $i += 10) { | 
					
						
							|  |  |  |           $machine->sleep(10); | 
					
						
							|  |  |  |           return unless checkRunning_${name}; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         die "VirtualBox VM didn't shut down within 2 minutes"; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |       sub shutdownVM_${name} { | 
					
						
							|  |  |  |         $machine->succeed(ru "touch ${sharePath}/shutdown"); | 
					
						
							| 
									
										
										
										
											2016-09-13 14:52:49 +02:00
										 |  |  |         $machine->execute( | 
					
						
							|  |  |  |           'set -e; i=0; '. | 
					
						
							|  |  |  |           'while test -e ${sharePath}/shutdown '. | 
					
						
							|  |  |  |           '        -o -e ${sharePath}/boot-done; do '. | 
					
						
							|  |  |  |           'sleep 1; i=$(($i + 1)); [ $i -le 3600 ]; '. | 
					
						
							|  |  |  |           'done' | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  |         ); | 
					
						
							|  |  |  |         waitForShutdown_${name}; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     '';
 | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |   hostonlyVMFlags = [ | 
					
						
							|  |  |  |     "--nictype1 virtio" | 
					
						
							|  |  |  |     "--nictype2 virtio" | 
					
						
							|  |  |  |     "--nic2 hostonly" | 
					
						
							|  |  |  |     "--hostonlyadapter2 vboxnet0" | 
					
						
							|  |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dhcpScript = pkgs: ''
 | 
					
						
							|  |  |  |     ${pkgs.dhcp}/bin/dhclient \ | 
					
						
							|  |  |  |       -lf /run/dhcp.leases \ | 
					
						
							|  |  |  |       -pf /run/dhclient.pid \ | 
					
						
							|  |  |  |       -v eth0 eth1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-30 02:52:47 +02:00
										 |  |  |     otherIP="$(${pkgs.netcat}/bin/nc -l 1234 || :)" | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |     ${pkgs.iputils}/bin/ping -I eth1 -c1 "$otherIP" | 
					
						
							| 
									
										
										
										
											2016-10-30 02:52:47 +02:00
										 |  |  |     echo "$otherIP reachable" | ${pkgs.netcat}/bin/nc -l 5678 || : | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |   '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-17 14:12:24 +02:00
										 |  |  |   sysdDetectVirt = pkgs: ''
 | 
					
						
							|  |  |  |     ${pkgs.systemd}/bin/systemd-detect-virt > /mnt-root/result | 
					
						
							|  |  |  |   '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |   vboxVMs = mapAttrs createVM { | 
					
						
							|  |  |  |     simple = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-17 14:12:24 +02:00
										 |  |  |     detectvirt.vmScript = sysdDetectVirt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |     test1.vmFlags = hostonlyVMFlags; | 
					
						
							|  |  |  |     test1.vmScript = dhcpScript; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     test2.vmFlags = hostonlyVMFlags; | 
					
						
							|  |  |  |     test2.vmScript = dhcpScript; | 
					
						
							| 
									
										
										
										
											2016-09-01 18:54:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     headless.virtualisation.virtualbox.headless = true; | 
					
						
							|  |  |  |     headless.services.xserver.enable = false; | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |   mkVBoxTest = name: testScript: makeTest { | 
					
						
							|  |  |  |     name = "virtualbox-${name}"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     machine = { lib, config, ... }: { | 
					
						
							|  |  |  |       imports = let | 
					
						
							|  |  |  |         mkVMConf = name: val: val.machine // { key = "${name}-config"; }; | 
					
						
							|  |  |  |         vmConfigs = mapAttrsToList mkVMConf vboxVMs; | 
					
						
							|  |  |  |       in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs; | 
					
						
							|  |  |  |       virtualisation.memorySize = 2048; | 
					
						
							|  |  |  |       virtualisation.virtualbox.host.enable = true; | 
					
						
							| 
									
										
										
										
											2016-05-26 15:03:01 +02:00
										 |  |  |       services.xserver.displayManager.auto.user = "alice"; | 
					
						
							| 
									
										
										
										
											2018-06-30 01:55:42 +02:00
										 |  |  |       users.users.alice.extraGroups = let | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |         inherit (config.virtualisation.virtualbox.host) enableHardening; | 
					
						
							|  |  |  |       in lib.mkIf enableHardening (lib.singleton "vboxusers"); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     testScript = ''
 | 
					
						
							|  |  |  |       sub ru ($) { | 
					
						
							|  |  |  |         my $esc = $_[0] =~ s/'/'\\${"'"}'/gr; | 
					
						
							|  |  |  |         return "su - alice -c '$esc'"; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |       sub vbm { | 
					
						
							|  |  |  |         $machine->succeed(ru("VBoxManage ".$_[0])); | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |       sub removeUUIDs { | 
					
						
							|  |  |  |         return join("\n", grep { $_ !~ /^UUID:/ } split(/\n/, $_[0]))."\n"; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |       ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vboxVMs)} | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |       $machine->waitForX; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |       ${mkLog "$HOME/.config/VirtualBox/VBoxSVC.log" "HOST-SVC"} | 
					
						
							| 
									
										
										
										
											2014-12-15 19:17:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |       ${testScript} | 
					
						
							|  |  |  |     '';
 | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     meta = with pkgs.stdenv.lib.maintainers; { | 
					
						
							|  |  |  |       maintainers = [ aszlig wkennington ]; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  | in mapAttrs mkVBoxTest { | 
					
						
							|  |  |  |   simple-gui = ''
 | 
					
						
							|  |  |  |     createVM_simple; | 
					
						
							|  |  |  |     $machine->succeed(ru "VirtualBox &"); | 
					
						
							| 
									
										
										
										
											2016-05-26 16:27:16 +02:00
										 |  |  |     $machine->waitUntilSucceeds( | 
					
						
							|  |  |  |       ru "xprop -name 'Oracle VM VirtualBox Manager'" | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     $machine->sleep(5); | 
					
						
							|  |  |  |     $machine->screenshot("gui_manager_started"); | 
					
						
							|  |  |  |     $machine->sendKeys("ret"); | 
					
						
							|  |  |  |     $machine->screenshot("gui_manager_sent_startup"); | 
					
						
							|  |  |  |     waitForStartup_simple (sub { | 
					
						
							|  |  |  |       $machine->sendKeys("ret"); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     $machine->screenshot("gui_started"); | 
					
						
							|  |  |  |     waitForVMBoot_simple; | 
					
						
							|  |  |  |     $machine->screenshot("gui_booted"); | 
					
						
							|  |  |  |     shutdownVM_simple; | 
					
						
							|  |  |  |     $machine->sleep(5); | 
					
						
							|  |  |  |     $machine->screenshot("gui_stopped"); | 
					
						
							|  |  |  |     $machine->sendKeys("ctrl-q"); | 
					
						
							|  |  |  |     $machine->sleep(5); | 
					
						
							|  |  |  |     $machine->screenshot("gui_manager_stopped"); | 
					
						
							| 
									
										
										
										
											2016-09-14 02:12:16 +02:00
										 |  |  |     destroyVM_simple; | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |   '';
 | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |   simple-cli = ''
 | 
					
						
							|  |  |  |     createVM_simple; | 
					
						
							|  |  |  |     vbm("startvm simple"); | 
					
						
							|  |  |  |     waitForStartup_simple; | 
					
						
							|  |  |  |     $machine->screenshot("cli_started"); | 
					
						
							|  |  |  |     waitForVMBoot_simple; | 
					
						
							|  |  |  |     $machine->screenshot("cli_booted"); | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     $machine->nest("Checking for privilege escalation", sub { | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       $machine->fail("test -e '/root/VirtualBox VMs'"); | 
					
						
							| 
									
										
										
										
											2014-12-15 19:12:58 +01:00
										 |  |  |       $machine->fail("test -e '/root/.config/VirtualBox'"); | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  |       $machine->succeed("test -e '/home/alice/VirtualBox VMs'"); | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     shutdownVM_simple; | 
					
						
							| 
									
										
										
										
											2016-09-14 02:12:16 +02:00
										 |  |  |     destroyVM_simple; | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |   '';
 | 
					
						
							| 
									
										
										
										
											2015-09-17 23:47:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-01 18:54:58 +00:00
										 |  |  |   headless = ''
 | 
					
						
							|  |  |  |     createVM_headless; | 
					
						
							|  |  |  |     $machine->succeed(ru("VBoxHeadless --startvm headless & disown %1")); | 
					
						
							|  |  |  |     waitForStartup_headless; | 
					
						
							|  |  |  |     waitForVMBoot_headless; | 
					
						
							|  |  |  |     shutdownVM_headless; | 
					
						
							| 
									
										
										
										
											2016-09-14 02:12:16 +02:00
										 |  |  |     destroyVM_headless; | 
					
						
							| 
									
										
										
										
											2016-09-01 18:54:58 +00:00
										 |  |  |   '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |   host-usb-permissions = ''
 | 
					
						
							|  |  |  |     my $userUSB = removeUUIDs vbm("list usbhost"); | 
					
						
							|  |  |  |     print STDERR $userUSB; | 
					
						
							|  |  |  |     my $rootUSB = removeUUIDs $machine->succeed("VBoxManage list usbhost"); | 
					
						
							|  |  |  |     print STDERR $rootUSB; | 
					
						
							| 
									
										
										
										
											2015-09-17 23:47:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     die "USB host devices differ for root and normal user" | 
					
						
							|  |  |  |       if $userUSB ne $rootUSB; | 
					
						
							|  |  |  |     die "No USB host devices found" if $userUSB =~ /<none>/; | 
					
						
							|  |  |  |   '';
 | 
					
						
							| 
									
										
										
										
											2015-09-17 23:47:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |   systemd-detect-virt = ''
 | 
					
						
							|  |  |  |     createVM_detectvirt; | 
					
						
							|  |  |  |     vbm("startvm detectvirt"); | 
					
						
							|  |  |  |     waitForStartup_detectvirt; | 
					
						
							|  |  |  |     waitForVMBoot_detectvirt; | 
					
						
							|  |  |  |     shutdownVM_detectvirt; | 
					
						
							|  |  |  |     my $result = $machine->succeed("cat '$detectvirt_sharepath/result'"); | 
					
						
							|  |  |  |     chomp $result; | 
					
						
							|  |  |  |     destroyVM_detectvirt; | 
					
						
							|  |  |  |     die "systemd-detect-virt returned \"$result\" instead of \"oracle\"" | 
					
						
							|  |  |  |       if $result ne "oracle"; | 
					
						
							|  |  |  |   '';
 | 
					
						
							| 
									
										
										
										
											2015-09-17 14:12:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |   net-hostonlyif = ''
 | 
					
						
							|  |  |  |     createVM_test1; | 
					
						
							|  |  |  |     createVM_test2; | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     vbm("startvm test1"); | 
					
						
							|  |  |  |     waitForStartup_test1; | 
					
						
							|  |  |  |     waitForVMBoot_test1; | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     vbm("startvm test2"); | 
					
						
							|  |  |  |     waitForStartup_test2; | 
					
						
							|  |  |  |     waitForVMBoot_test2; | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     $machine->screenshot("net_booted"); | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     my $test1IP = waitForIP_test1 1; | 
					
						
							|  |  |  |     my $test2IP = waitForIP_test2 1; | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-21 02:38:52 +02:00
										 |  |  |     $machine->succeed("echo '$test2IP' | nc -N '$test1IP' 1234"); | 
					
						
							|  |  |  |     $machine->succeed("echo '$test1IP' | nc -N '$test2IP' 1234"); | 
					
						
							| 
									
										
										
										
											2014-12-13 12:13:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-21 02:38:52 +02:00
										 |  |  |     $machine->waitUntilSucceeds("nc -N '$test1IP' 5678 < /dev/null >&2"); | 
					
						
							|  |  |  |     $machine->waitUntilSucceeds("nc -N '$test2IP' 5678 < /dev/null >&2"); | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     shutdownVM_test1; | 
					
						
							|  |  |  |     shutdownVM_test2; | 
					
						
							| 
									
										
										
										
											2014-12-15 08:58:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  |     destroyVM_test1; | 
					
						
							|  |  |  |     destroyVM_test2; | 
					
						
							| 
									
										
										
										
											2014-12-13 11:15:48 +01:00
										 |  |  |   '';
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:15:36 +01:00
										 |  |  | } |