diff options
Diffstat (limited to 'pkgs/build-support/vm/windows/controller/default.nix')
-rw-r--r-- | pkgs/build-support/vm/windows/controller/default.nix | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/pkgs/build-support/vm/windows/controller/default.nix b/pkgs/build-support/vm/windows/controller/default.nix new file mode 100644 index 000000000000..49d6815a3dce --- /dev/null +++ b/pkgs/build-support/vm/windows/controller/default.nix @@ -0,0 +1,173 @@ +{ sshKey +, qemuArgs ? [] +, command ? "sync" +, suspendTo ? null +, resumeFrom ? null +, installMode ? false +}: + +let + inherit (import <nixpkgs> {}) lib stdenv writeScript vmTools makeInitrd; + inherit (import <nixpkgs> {}) samba vde2 busybox openssh; + inherit (import <nixpkgs> {}) socat netcat coreutils gzip; + + preInitScript = writeScript "preinit.sh" '' + #!${vmTools.initrdUtils}/bin/ash -e + export PATH=${vmTools.initrdUtils}/bin + mount -t proc none /proc + mount -t sysfs none /sys + for arg in $(cat /proc/cmdline); do + if [ "x''${arg#command=}" != "x$arg" ]; then + command="''${arg#command=}" + fi + done + + for i in $(cat ${modulesClosure}/insmod-list); do + insmod $i + done + + mkdir -p /tmp /dev + mknod /dev/null c 1 3 + mknod /dev/zero c 1 5 + mknod /dev/random c 1 8 + mknod /dev/urandom c 1 9 + mknod /dev/tty c 5 0 + + ifconfig lo up + ifconfig eth0 up 192.168.0.2 + + mkdir -p /nix/store /etc /var/run /var/log + + cat > /etc/passwd <<PASSWD + root:x:0:0::/root:/bin/false + nobody:x:65534:65534::/var/empty:/bin/false + PASSWD + + mount -t 9p \ + -o trans=virtio,version=9p2000.L,msize=262144,cache=loose \ + store /nix/store + + exec "$command" + ''; + + initrd = makeInitrd { + contents = lib.singleton { + object = preInitScript; + symlink = "/init"; + }; + }; + + initScript = writeScript "init.sh" ('' + #!${stdenv.shell} + ${coreutils}/bin/mkdir -p /etc/samba /etc/samba/private /var/lib/samba + ${coreutils}/bin/cat > /etc/samba/smb.conf <<CONFIG + [global] + security = user + map to guest = Bad User + workgroup = cygwin + netbios name = controller + server string = %h + log level = 1 + max log size = 1000 + log file = /var/log/samba.log + + [nixstore] + path = /nix/store + read only = no + guest ok = yes + CONFIG + + ${samba}/sbin/nmbd -D + ${samba}/sbin/smbd -D + ${coreutils}/bin/cp -L "${sshKey}" /ssh.key + ${coreutils}/bin/chmod 600 /ssh.key + '' + (if installMode then '' + echo -n "Waiting for Windows installation to finish..." + while ! ${netcat}/bin/netcat -z 192.168.0.1 22; do + echo -n . + # Print a dot every 10 seconds only to shorten line length. + ${coreutils}/bin/sleep 10 + done + echo " success." + # Loop forever, because this VM is going to be killed. + while :; do ${coreutils}/bin/sleep 1; done + '' else '' + echo -n "Waiting for Windows VM to become available..." + while ! ${netcat}/bin/netcat -z 192.168.0.1 22; do + echo -n . + ${coreutils}/bin/sleep 1 + done + echo " success." + + ${openssh}/bin/ssh \ + -o UserKnownHostsFile=/dev/null \ + -o StrictHostKeyChecking=no \ + -i /ssh.key \ + -l Administrator \ + 192.168.0.1 -- "${command}" + + ${busybox}/sbin/poweroff -f + '')); + + kernelAppend = lib.concatStringsSep " " [ + "panic=1" + "loglevel=4" + "console=tty1" + "console=ttyS0" + "command=${initScript}" + ]; + + controllerQemuArgs = lib.concatStringsSep " " (maybeKvm64 ++ [ + "-nographic" + "-no-reboot" + "-virtfs local,path=/nix/store,security_model=none,mount_tag=store" + "-kernel ${modulesClosure.kernel}/bzImage" + "-initrd ${initrd}/initrd" + "-append \"${kernelAppend}\"" + "-net nic,vlan=0,macaddr=52:54:00:12:01:02,model=virtio" + "-net vde,vlan=0,sock=$QEMU_VDE_SOCKET" + ]); + + maybeKvm64 = lib.optional (stdenv.system == "x86_64-linux") "-cpu kvm64"; + + cygwinQemuArgs = lib.concatStringsSep " " (maybeKvm64 ++ [ + "-monitor unix:$MONITOR_SOCKET,server,nowait" + "-nographic" + "-net nic,vlan=0,macaddr=52:54:00:12:01:01" + "-net vde,vlan=0,sock=$QEMU_VDE_SOCKET" + "-rtc base=2010-01-01,clock=vm" + ] ++ qemuArgs ++ lib.optionals (resumeFrom != null) [ + "-incoming 'exec: ${gzip}/bin/gzip -c -d \"${resumeFrom}\"'" + ]); + + modulesClosure = lib.overrideDerivation vmTools.modulesClosure (o: { + rootModules = o.rootModules ++ lib.singleton "virtio_net"; + }); + + preVM = '' + QEMU_VDE_SOCKET="$(pwd)/vde.ctl" + MONITOR_SOCKET="$(pwd)/monitor" + ${vde2}/bin/vde_switch -s "$QEMU_VDE_SOCKET" & + ''; + + vmExec = if installMode then '' + ${vmTools.qemuProg} ${controllerQemuArgs} & + ${vmTools.qemuProg} ${cygwinQemuArgs} + '' else '' + ${vmTools.qemuProg} ${cygwinQemuArgs} & + ${vmTools.qemuProg} ${controllerQemuArgs} + '' + lib.optionalString (suspendTo != null) '' + ${socat}/bin/socat - UNIX-CONNECT:$MONITOR_SOCKET <<CMD + stop + migrate_set_speed 4095m + migrate "exec:${gzip}/bin/gzip -c > '${suspendTo}'" + quit + CMD + wait %% + ''; + +in writeScript "run-cygwin-vm.sh" '' + #!${stdenv.shell} -e + ${preVM} + ${vmExec} +'' |