summary refs log tree commit diff
path: root/pkgs/build-support/vm/windows/default.nix
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2014-02-15 23:23:47 +0100
committeraszlig <aszlig@redmoonstudios.org>2014-02-26 04:51:56 +0100
commitc731467e2c83f3df0b59c44575616e6241a63c7d (patch)
treed86cba504d645898458142bd425980c8d7ebafb3 /pkgs/build-support/vm/windows/default.nix
parent5105e7f0bfc3a9131df5a8f3bf4d899a01b0106b (diff)
downloadnixpkgs-c731467e2c83f3df0b59c44575616e6241a63c7d.tar
nixpkgs-c731467e2c83f3df0b59c44575616e6241a63c7d.tar.gz
nixpkgs-c731467e2c83f3df0b59c44575616e6241a63c7d.tar.bz2
nixpkgs-c731467e2c83f3df0b59c44575616e6241a63c7d.tar.lz
nixpkgs-c731467e2c83f3df0b59c44575616e6241a63c7d.tar.xz
nixpkgs-c731467e2c83f3df0b59c44575616e6241a63c7d.tar.zst
nixpkgs-c731467e2c83f3df0b59c44575616e6241a63c7d.zip
vm/windows: Split install into several stages.
These stages are in particular:

 * Install of the bare Windows VM with Cygwin and shut down.
 * Boot up the same VM again without the installation media and dump the
   VMs memory to state.gz.
 * Resume from state.gz and build whatever we want to build.

Every single stage involves a new "controller", which is more like an
abstraction on the Nix side that constructs the madness described in
276b72fb93d60ae0e59088ea0e0029da87e6f31c.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Diffstat (limited to 'pkgs/build-support/vm/windows/default.nix')
-rw-r--r--pkgs/build-support/vm/windows/default.nix175
1 files changed, 32 insertions, 143 deletions
diff --git a/pkgs/build-support/vm/windows/default.nix b/pkgs/build-support/vm/windows/default.nix
index 470fac0437d..2ecadbae7cf 100644
--- a/pkgs/build-support/vm/windows/default.nix
+++ b/pkgs/build-support/vm/windows/default.nix
@@ -1,160 +1,49 @@
-with import <nixpkgs> {};
-
-with import <nixpkgs/nixos/lib/build-vms.nix> {
-  inherit system;
-  minimal = false;
-};
-
 let
+  inherit (import <nixpkgs> {}) lib stdenv requireFile writeText qemu;
+
   winISO = /path/to/iso/XXX;
 
-  base = import ./install {
+  installedVM = import ./install {
     isoFile = winISO;
     productKey = "XXX";
   };
 
-  maybeKvm64 = lib.optional (stdenv.system == "x86_64-linux") "-cpu kvm64";
-
-  cygwinQemuArgs = lib.concatStringsSep " " (maybeKvm64 ++ [
-    "-monitor unix:$MONITOR_SOCKET,server,nowait"
-    "-nographic"
-    "-boot order=c,once=d"
-    "-drive file=${base.floppy},readonly,index=0,if=floppy"
-    "-drive file=winvm.img,index=0,media=disk"
-    "-drive file=${winISO},index=1,media=cdrom"
-    "-drive file=${base.iso}/iso/cd.iso,index=2,media=cdrom"
-    "-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"
-  ]);
-
-  modulesClosure = lib.overrideDerivation vmTools.modulesClosure (o: {
-    rootModules = o.rootModules ++ lib.singleton "virtio_net";
+  runInVM = img: attrs: import ./controller (attrs // {
+    inherit (installedVM) sshKey;
+    qemuArgs = attrs.qemuArgs or [] ++ [
+      "-boot order=c"
+      "-drive file=${img},index=0,media=disk"
+    ];
   });
 
-  controllerQemuArgs = cmd: let
-    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 "${base.sshKey}" /ssh.key
-      ${coreutils}/bin/chmod 600 /ssh.key
-
-      echo -n "Waiting for Windows VM to become ready"
-      while ! ${netcat}/bin/netcat -z 192.168.0.1 22; do
-        echo -n .
-        ${coreutils}/bin/sleep 1
-      done
-      echo " ready."
-
-      ${openssh}/bin/ssh \
-        -o UserKnownHostsFile=/dev/null \
-        -o StrictHostKeyChecking=no \
-        -i /ssh.key \
-        -l Administrator \
-        192.168.0.1 -- "${cmd}"
+  runAndSuspend = runInVM "winvm.img" {
+    suspendTo = "state.gz";
+  };
 
-      ${busybox}/sbin/poweroff -f
+  suspendedVM = stdenv.mkDerivation {
+    name = "cygwin-suspended-vm";
+    buildCommand = ''
+      ${qemu}/bin/qemu-img create \
+        -b "${installedVM}/disk.img" \
+        -f qcow2 winvm.img
+      ${runAndSuspend}
+      ensureDir "$out"
+      cp winvm.img "$out/disk.img"
+      cp state.gz "$out/state.gz"
     '';
-    kernelAppend = lib.concatStringsSep " " [
-      "panic=1"
-      "loglevel=4"
-      "console=tty1"
-      "console=ttyS0"
-      "command=${initScript}"
-    ];
-  in 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"
-  ]);
+  };
 
-  bootstrap = stdenv.mkDerivation {
-    name = "windown-vm";
+  resumeAndRun = command: runInVM "${suspendedVM}/disk.img" {
+    resumeFrom = "${suspendedVM}/state.gz";
+    qemuArgs = lib.singleton "-snapshot";
+    inherit command;
+  };
 
+  runFromSuspended = command: stdenv.mkDerivation {
+    name = "cygwin-vm-run";
     buildCommand = ''
-      ${qemu}/bin/qemu-img create -f qcow2 winvm.img 2G
-      QEMU_VDE_SOCKET="$(pwd)/vde.ctl"
-      MONITOR_SOCKET="$(pwd)/monitor"
-      ${vde2}/bin/vde_switch -s "$QEMU_VDE_SOCKET" &
-      ${vmTools.qemuProg} ${cygwinQemuArgs} &
-      ${vmTools.qemuProg} ${controllerQemuArgs "sync"}
-
-      ensureDir "$out"
-      ${socat}/bin/socat - UNIX-CONNECT:$MONITOR_SOCKET <<CMD
-      stop
-      migrate_set_speed 4095m
-      migrate "exec:${gzip}/bin/gzip -c > '$out/state.gz'"
-      CMD
-      cp winvm.img "$out/disk.img"
+      ${resumeAndRun command}
     '';
   };
 
-in bootstrap
+in runFromSuspended "uname -a"