From 401fd84ae156531b53cd8732fe1fa432a312684f Mon Sep 17 00:00:00 2001 From: Marc Weber Date: Tue, 15 Dec 2009 06:37:32 +0000 Subject: [PATCH] kvm installation test update + NixOS installation archive You can run the kvm nixos installation test by: nix-build --no-out-link tests/test-nixos-install-from-cd.nix It boots the installed system. It still fails sshd isn't started (yet) adding nixos-bootstrapping-archive: You can install NixOS easily using any live cd now. See README-BOOTSTRAP-NIXOS svn path=/nixos/trunk/; revision=18950 --- .../installation-cd-minimal-test-insecure.nix | 1 + .../test-nixos-install-from-cd-config.nix | 4 +- .../tools/installer2/nixos-bootstrap.sh | 134 +++++++++++ .../tools/installer2/nixos-prepare-install.sh | 227 ++++++++++++++++++ .../tools/installer2/run-in-chroot.sh | 93 +++++++ .../README-BOOTSTRAP-NIXOS | 16 ++ .../tools/nixos-bootstrap-archive/default.nix | 20 ++ modules/installer/tools/nixos-install.sh | 2 + modules/installer/tools/tools.nix | 51 +++- tests/test-nixos-install-from-cd.nix | 124 +++++++--- tests/test-nixos-installer2.nix | 71 ++++++ 11 files changed, 711 insertions(+), 32 deletions(-) rename {tests => modules/installer/cd-dvd}/test-nixos-install-from-cd-config.nix (80%) create mode 100644 modules/installer/tools/installer2/nixos-bootstrap.sh create mode 100644 modules/installer/tools/installer2/nixos-prepare-install.sh create mode 100644 modules/installer/tools/installer2/run-in-chroot.sh create mode 100644 modules/installer/tools/nixos-bootstrap-archive/README-BOOTSTRAP-NIXOS create mode 100644 modules/installer/tools/nixos-bootstrap-archive/default.nix create mode 100644 tests/test-nixos-installer2.nix diff --git a/modules/installer/cd-dvd/installation-cd-minimal-test-insecure.nix b/modules/installer/cd-dvd/installation-cd-minimal-test-insecure.nix index e25e2e72129..b531ccaaf3d 100644 --- a/modules/installer/cd-dvd/installation-cd-minimal-test-insecure.nix +++ b/modules/installer/cd-dvd/installation-cd-minimal-test-insecure.nix @@ -26,6 +26,7 @@ in boot.loader.grub.timeout = doOverride 0; boot.loader.grub.default = 2; + boot.loader.grub.version = doOverride 2; # FIXME: rewrite pam.services the to be an attr list # I only want to override sshd diff --git a/tests/test-nixos-install-from-cd-config.nix b/modules/installer/cd-dvd/test-nixos-install-from-cd-config.nix similarity index 80% rename from tests/test-nixos-install-from-cd-config.nix rename to modules/installer/cd-dvd/test-nixos-install-from-cd-config.nix index 758ab2328da..e0dcea6e061 100644 --- a/tests/test-nixos-install-from-cd-config.nix +++ b/modules/installer/cd-dvd/test-nixos-install-from-cd-config.nix @@ -4,11 +4,11 @@ {pkgs, config, ...}: { # make system boot and accessible: - require = [ ../modules/installer/cd-dvd/installation-cd-minimal-test-insecure.nix ]; + require = [ ./installation-cd-minimal-test-insecure.nix ]; boot.loader.grub = { device = "/dev/sda"; - copyKernels = true; + copyKernels = false; bootDevice = "(hd0,0)"; }; diff --git a/modules/installer/tools/installer2/nixos-bootstrap.sh b/modules/installer/tools/installer2/nixos-bootstrap.sh new file mode 100644 index 00000000000..97e66bc88ed --- /dev/null +++ b/modules/installer/tools/installer2/nixos-bootstrap.sh @@ -0,0 +1,134 @@ +#! @shell@ +# runs in chroot +# creates mandatory directories such as /var +# finally runs switch-to-configuration optionally registering grub +set -e + +usage(){ + cat << EOF + script --install [--fast] [--no-grub] + + --no-pull: don't do a nix-pull to get the latest Nixpkgs + channel manifest + + --no-grub: don't install grub ( you don't want this ..) + + --debug: set -x + + -j n : will be passed to nix-env = number of build tasks done simultaniously + + Description: + This scripts installs NixOS and should be run within the target chroot. + + The minimal nix system must have been installed previously. + Eg nixos-prepare-install.sh does this for you. + + Probably this script is distributed along with the minimal nix closure used + for bootstrapping +EOF + exit 1 +} + +die(){ echo "!>> " $@; exit 1; } + +check(){ + [ -e "$1" ] || die "$1 not found $2" +} +WARN(){ echo "WARNING: $@"; } +INFO(){ echo "INFO: " $@; } + +# == configuration == + +HOME=${HOME:-/root} +NIXOS=${NIXOS:-/etc/nixos/nixos} +NIXPKGS=${NIXPKGS:-/etc/nixos/nixpkgs} +NIXOS_CONFIG=${NIXOS_CONFIG:-/etc/nixos/configuration.nix} +NIXOS_PULL=${NIXOS_PULL:-1} +NIXOS_INSTALL_GRUB=${NIXOS_INSTALL_GRUB:-1} + +ps="with-prepared-chroot.sh" + +check "$NIXOS_CONFIG" +check "$NIXOS/modules" "nixos repo not found" +check "$NIXPKGS/pkgs/top-level/all-packages.nix" "nixpgks repo not found" +for d in /dev /sys /proc; do + check "$d" "It should have been mounted by $ps" +done + +# try reusing binaries from host system (which is most likely an installation CD) +if [ -d /host-system/nix ]; then + export NIX_OTHER_STORES=/host-system/nix${NIX_OTHER_STORES:+:}$NIX_OTHER_STORES +else + WARN "/host-system/nix not found. It should have been --bind mounted by $ps. + I won't be able to take binaries from the installation media. + " +fi + +# == configuration end == + +INSTALL= + +for arg in $@; do + case $arg in + --no-pull) NIXOS_PULL=0;; + --install) INSTALL=1;; + --no-grub) NIXOS_INSTALL_GRUB=;; + --debug) set -x;; + -j*) NIX_ENV_ARGS="$NIX_ENV_ARGS $arg";; + *) usage; + esac +done + +if [ "$INSTALL" != 1 ]; then + usage +fi + + +# We don't have locale-archive in the chroot, so clear $LANG. +export LANG= + +export PATH=@coreutils@/bin + +mkdir -m 01777 -p /tmp +mkdir -m 0755 -p /var + +# Create the necessary Nix directories on the target device, if they +# don't already exist. +mkdir -m 0755 -p \ + /nix/var/nix/gcroots \ + /nix/var/nix/temproots \ + /nix/var/nix/manifests \ + /nix/var/nix/userpool \ + /nix/var/nix/profiles \ + /nix/var/nix/db \ + /nix/var/log/nix/drvs + +# Do a nix-pull to speed up building. +if test -n "@nixpkgsURL@" -a ${NIXOS_PULL} != 0; then + @nix@/bin/nix-pull @nixpkgsURL@/MANIFEST || true +fi + +# Build the specified Nix expression in the target store and install +# it into the system configuration profile. +INFO "building the system configuration..." +@nix@/bin/nix-env \ + -p /nix/var/nix/profiles/system \ + -f "$NIXOS" \ + --arg configuration "import $NIXOS_CONFIG" \ + --set -A system \ + $NIX_ENV_ARGS + +# Mark the target as a NixOS installation, otherwise +# switch-to-configuration will chicken out. +touch /etc/NIXOS + +# Grub needs an mtab. +ln -sfn /proc/mounts /etc/mtab + + +# Switch to the new system configuration. This will install Grub with +# a menu default pointing at the kernel/initrd/etc of the new +# configuration. +INFO "finalising the installation..." +export NIXOS_INSTALL_GRUB +/nix/var/nix/profiles/system/bin/switch-to-configuration boot diff --git a/modules/installer/tools/installer2/nixos-prepare-install.sh b/modules/installer/tools/installer2/nixos-prepare-install.sh new file mode 100644 index 00000000000..b85ef2b9eaa --- /dev/null +++ b/modules/installer/tools/installer2/nixos-prepare-install.sh @@ -0,0 +1,227 @@ +#!/bin/sh + +# prepare installation by putting in place unless present: +# /etc/nixos/nixpkgs +# /etc/nixos/nixos +# /etc/nixos/configuration.nix + + +set -e + +usage(){ + cat << EOF + script options [list of actions] + + actions: + + guess-config: run nixos-hardware-scan > T/configuration.nix + copy-nix: copy minimal nix system which can bootstrap the whole system + This creates the $mountPoint/bin/sh symlink + If you're bootstrapping from an archive store paths are registered valid only + copy-nixos-bootstrap: + copy the nixos-bootstrap script to /nix/store where it will be + garbage collected later + copy-sources: copy repos into T/ + checkout-sources: svn checkout official repos into T/ + + + where T=$T + and repos = $ALL_REPOS + + options: + --force: If targets exist no action will taken unless you use --force + in which case target is renamed before action is run + --dir-ok: allow installing into directory (omits is mount point check) + + --debug: set -x + + + default list of actions: $DEFAULTS +EOF + exit 1 +} + + +INFO(){ echo "INFO: " $@; } + +# = configuration = + +FORCE_ACTIONS=${FORCE_ACTIONS:-} +ALL_REPOS="nixpkgs nixos" +mountPoint=${mountPoint:-/mnt} + +if [ -e $mountPoint/README-BOOTSTRAP-NIXOS ]; then + INFO "$mountPoint/README-BOOTSTRAP-NIXOS found, assuming your're bootstrapping from an archive. Nix files should be in place" + FROM_ARCHIVE=1 + DEFAULTS="guess-config copy-nix" +else + FROM_ARCHIVE=0 + DEFAULTS="guess-config copy-nixos-bootstrap copy-nix copy-sources" +fi + +backupTimestamp=$(date "+%Y%m%d%H%M%S") +SRC_BASE=${SRC_BASE:-"/etc/nixos"} +SVN_BASE="https://svn.nixos.org/repos/nix" +MUST_BE_MOUNTPOINT=${MUST_BE_MOUNTPOINT:-1} +T="$mountPoint/etc/nixos" + +NIX_CLOSURE=${NIX_CLOSURE:-@nixClosure@} + +die(){ echo "!>> " $@; exit 1; } + +## = read options = +# actions is used by main loop at the end +ACTIONS="" +# check and handle options: +for a in $@; do + case "$a" in + copy-nix|copy-nixos-bootstrap|guess-config|copy-sources|checkout-sources) + ACTIONS="$ACTIONS $a" + ;; + --dir-ok) + MUST_BE_MOUNTPOINT=false + ;; + --force) + FORCE_ACTIONS=1 + ;; + --debug) + set -x + ;; + *) + echo "unkown option: $a" + usage + ;; + esac +done +[ -n "$ACTIONS" ] || ACTIONS="$DEFAULTS" + + +if ! grep -F -q " $mountPoint " /proc/mounts && [ "$MUST_BE_MOUNTPOINT" = 1 ]; then + die "$mountPoint doesn't appear to be a mount point" +fi + +# Get the store paths to copy from the references graph. +storePaths=$(@perl@/bin/perl @pathsFromGraph@ @nixClosure@) +# = utils = + +backup(){ + local dst="$(dirname "$1")/$(basename "$1")-$backupTimestamp" + INFO "backing up: $1 -> $dst" + mv "$1" "$dst" +} + +# = implementation = + +# exit status = 0: target exists +# exti status != 0: target must be rebuild either because --force was given or +# because it didn't exist yet +target_realised(){ + if [ -e "$1" ] && [ "$FORCE_ACTIONS" = 1 ]; then + backup "$1" + fi + + [ -e "$1" ] && { + INFO "not realsing $1. Target already exists. Use --force to force." + } +} + +createDirs(){ + mkdir -m 0755 -p $mountPoint/etc/nixos + mkdir -m 1777 -p $mountPoint/nix/store +} + + +realise_repo(){ + local action=$1 + local repo=$2 + + createDirs + + if [ "$action" == "copy-sources" ]; then + + local repo_sources="${repo}_SOURCES" + rsync -a -r "${SRC_BASE}/$repo" "$T" + + else + + INFO "checking out $repo" + svn co "$SVN_BASE/$repo/trunk" "$T/$repo" + + fi + +} + +# = run actions: = +for a in $ACTIONS; do + case "$a" in + + guess_config) + local config="$T/configuration.nix" + target_realised "$config" || { + INFO "creating simple configuration file" + nixos-hardware-scan > "$config" + echo + INFO "Note: you can start customizing $config while remaining actions will are being executed" + echo + } + ;; + + copy-nixos-bootstrap) + createDirs + # this script will be garbage collected somewhen: + cp @nixosBootstrap@/bin/nixos-bootstrap $mountPoint/nix/store/ + ;; + + copy-nix) + if [ -n "$FROM_ARCHIVE" ]; then + NIX_CLOSURE=${mountPoint}@nixClosure@ + else + INFO "Copy Nix to the Nix store on the target device." + createDirs + echo "copying Nix to $mountPoint...." + for i in $storePaths; do + echo " $i" + rsync -a $i $mountPoint/nix/store/ + done + + fi + + [ -e "$NIX_CLOSURE" ] || die "Couldn't find nixClosure $NIX_CLOSURE anywhere. Can't register inital store paths valid. Exiting" + + # Create the required /bin/sh symlink; otherwise lots of things + # (notably the system() function) won't work. + mkdir -m 0755 -p $mountPoint/bin + ln -sf @shell@ $mountPoint/bin/sh + + INFO "registering bootstrapping store paths as valid so that they won't be rebuild" + # Register the paths in the Nix closure as valid. This is necessary + # to prevent them from being deleted the first time we install + # something. (I.e., Nix will see that, e.g., the glibc path is not + # valid, delete it to get it out of the way, but as a result nothing + # will work anymore.) + # TODO: check permissions so that paths can't be changed later? + chroot "$mountPoint" @nix@/bin/nix-store --register-validity < $NIX_CLOSURE + + ;; + + copy-sources|checkout-sources) + + for repo in $ALL_REPOS; do + target_realised "$T/$repo" || realise_repo $a $repo + done + + ;; + esac +done + +if [ -e "$T/nixos" ] && [ -e "$T/nixpkgs" ] && [ -e "$T/configuration.nix" ]; then + cat << EOF + To realise your NixOS installtion execute: + + run-in-chroot "/nix/store/nixos-bootstrap --install" +EOF +else + for t in "$T/configuration.nix" "$T/nixpkgs" "$T/configuration.nix"; do + INFO "you can't start because $t is missing" + done +fi diff --git a/modules/installer/tools/installer2/run-in-chroot.sh b/modules/installer/tools/installer2/run-in-chroot.sh new file mode 100644 index 00000000000..1d4deb921ee --- /dev/null +++ b/modules/installer/tools/installer2/run-in-chroot.sh @@ -0,0 +1,93 @@ +#!/bin/sh +# helper script preparing chroot by mounting /dev /proc /sys etc + +set -e + +usage(){ + cat << EOF + $SCRIPT OPTS or cmd + OPTS: + --prepare : only mount + --unprepare : only unmount + --debug : set -x + + requisites: perl + + $SCRIPT --prepare: prepare chroot only + $SCRIPT --unprepare: unprepare chroot only + $SCRIPT command: run /bin/sh command in chroot + + usage example run a shell in chroot: + $SCRIPT path-to-sh + +EOF + exit 1 +} + +die(){ echo "!>> " $@; exit 1; } +INFO(){ echo "INFO: " $@; } + +# this is no longer needed because umount -l unmounts rescursive --rbound mounts as well +#umountUnder() { +# local dir="$1" +# for i in $(grep -F " $dir" /proc/mounts \ +# | perl -e 'while (<>) { /^\S+\s+(\S+)\s+/; print "$1\n"; }' \ +# | sort -r); +# do +# echo umount $i || true +# done +#} + + +prepare(){ + INFO "Enable networking: copying /etc/resolv.conf" + mkdir -m 0755 -p $mountPoint/etc + touch /etc/resolv.conf + cp /etc/resolv.conf $mountPoint/etc/ + + INFO "mounting /proc /sys /dev and / to /host-system" + mkdir -m 0755 -p $mountPoint/{dev,proc,sys,host-system} + mount --bind /dev $mountPoint/dev + mount --bind /proc $mountPoint/proc + mount --bind /sys $mountPoint/sys + mount --rbind / $mountPoint/host-system +} + +unprepare(){ + INFO "unmounting /proc /sys /dev and removing /host-system if empty" + for d in $mountPoint/{host-system,dev,proc,sys}; do + umount -l "$d" + done + # no -fr !! + rmdir $mountPoint/host-system +} + +run_cmd(){ + prepare + trap "unprepare" EXIT + chroot $mountPoint $@ +} + + +SCRIPT="$(basename "$0")" +mountPoint=${mountPoint:-/mnt} + +[ -d $mountPoint ] || die "$mountPoint is not a directory" + +while [ "$#" > 0 ]; do + case $1 in + + --debug) shift; set -x;; + + -h|--help) shift; usage;; + + --prepare) shift; prepare;; + + --unprepare) shift; unprepare;; + + *) + run_cmd "$@" + exit 0 + ;; + esac +done diff --git a/modules/installer/tools/nixos-bootstrap-archive/README-BOOTSTRAP-NIXOS b/modules/installer/tools/nixos-bootstrap-archive/README-BOOTSTRAP-NIXOS new file mode 100644 index 00000000000..041588bb7e4 --- /dev/null +++ b/modules/installer/tools/nixos-bootstrap-archive/README-BOOTSTRAP-NIXOS @@ -0,0 +1,16 @@ +HOWTO install NixOS from a bootstrap archive +============================================= + +export mountPoint=$target # defaults to /mnt +tar xfj $ARCHIV -C $mountPoint + +bash $mountPoint/nix/store/nixos-prepare-install # see --help + +$EDITOR $mountPoint/etc/nixos/configuration.nix + +# you can replace --install by --help to get more info +bash $mountPoint/nix/store/run-in-chroot "/nix/store/nixos-bootstrap --install" + + +This archive is create by +nix-build $NIXOS -A config.system.build.minimalInstaller diff --git a/modules/installer/tools/nixos-bootstrap-archive/default.nix b/modules/installer/tools/nixos-bootstrap-archive/default.nix new file mode 100644 index 00000000000..d383ad081e1 --- /dev/null +++ b/modules/installer/tools/nixos-bootstrap-archive/default.nix @@ -0,0 +1,20 @@ +args: with args; + +# TODO add revision number or such +runCommand "nixos-bootstrap-archive" { } '' + PATH=${perl}/bin:${coreutils}/bin:${gnutar}/bin:${bzip2}/bin + storePaths=$(perl ${pathsFromGraph} ${nixClosure}) + + s(){ echo -C $(dirname $1) $(basename $1); } + + mkdir $out + tar cf tmp.tar ${nixClosure} $storePaths + cp ${./README-BOOTSTRAP-NIXOS} README-BOOTSTRAP-NIXOS + tar --append -f tmp.tar README-BOOTSTRAP-NIXOS + tar --append -f tmp.tar --transform 's@^@/nix/store/@' \ + $(s ${nixosPrepareInstall}/bin/nixos-prepare-install ) \ + $(s ${runInChroot}/bin/run-in-chroot ) \ + $(s ${nixosBootstrap}/bin/nixos-bootstrap ) + + cat tmp.tar | bzip2 > $out/nixos-install-archive.tar.bz2 +'' diff --git a/modules/installer/tools/nixos-install.sh b/modules/installer/tools/nixos-install.sh index bc935f7c8e3..5ae1a89b52f 100644 --- a/modules/installer/tools/nixos-install.sh +++ b/modules/installer/tools/nixos-install.sh @@ -60,6 +60,8 @@ mount --bind /proc $mountPoint/proc mount --bind /sys $mountPoint/sys mount --rbind / $mountPoint/mnt +# Note: probably umount -l is enough. It umounts recursive mount points having been mounted by --rbind! +# Probably umountUnder can be removed ? umountUnder() { local dir="$1" for i in $(grep -F " $dir" /proc/mounts \ diff --git a/modules/installer/tools/tools.nix b/modules/installer/tools/tools.nix index 45df2a50e92..f9027c3448f 100644 --- a/modules/installer/tools/tools.nix +++ b/modules/installer/tools/tools.nix @@ -53,6 +53,47 @@ let "cp refs $out"; }; + # rewrite of nixosInstall: each tool does exactly one job. + # So they get more useful. + installer2 = + let nixClosure = pkgs.runCommand "closure" + {exportReferencesGraph = ["refs" config.environment.nix];} + "cp refs $out"; + + nix = config.environment.nix; + in rec { + + nixosPrepareInstall = makeProg { + name = "nixos-prepare-install"; + src = ./installer2/nixos-prepare-install.sh; + + inherit (pkgs) perl pathsFromGraph; + inherit nix nixClosure nixosBootstrap; + }; + + runInChroot = makeProg { + name = "run-in-chroot"; + src = ./installer2/run-in-chroot.sh; + }; + + nixosBootstrap = makeProg { + name = "nixos-bootstrap"; + src = ./installer2/nixos-bootstrap.sh; + + inherit (pkgs) coreutils; + inherit nixClosure nix; + + # TODO shell ? + nixpkgsURL = config.installer.nixpkgsURL; + }; + + # see ./nixos-bootstrap-archive/README + minimalInstaller = import ./nixos-bootstrap-archive { + inherit (pkgs) stdenv runCommand perl pathsFromGraph gnutar coreutils bzip2; + inherit nixosPrepareInstall runInChroot nixosBootstrap nixClosure; + }; + }; + nixosRebuild = makeProg { name = "nixos-rebuild"; src = ./nixos-rebuild.sh; @@ -79,7 +120,15 @@ in nixosRebuild nixosHardwareScan nixosGenSeccureKeys + + installer2.runInChroot + installer2.nixosPrepareInstall ]; - system.build = { inherit nixosInstall; }; + system.build = { + inherit nixosInstall; + + # expose scripts + inherit (installer2) nixosPrepareInstall runInChroot nixosBootstrap minimalInstaller; + }; } diff --git a/tests/test-nixos-install-from-cd.nix b/tests/test-nixos-install-from-cd.nix index d654cdbd69f..f832d6d464f 100644 --- a/tests/test-nixos-install-from-cd.nix +++ b/tests/test-nixos-install-from-cd.nix @@ -29,7 +29,7 @@ let # passed system = systom of iso (isos.iso_minimal_test_insecure { inherit system; }).iso; - configuration = /pr/system_nixos_installer/nixos/tests/test-nixos-install-from-cd-config.nix; + configuration = ../modules/installer/cd-dvd/test-nixos-install-from-cd-config.nix; eval = import ../lib/eval-config.nix { inherit system nixpkgs; @@ -46,6 +46,8 @@ let # the iso is only build when this suceeds (?) systemDerivation = builtins.addErrorContext "while building system" config.system.build.toplevel; + # TODO test both: copyKernels = true and false. true doesn't work ? + in rec { @@ -57,69 +59,133 @@ rec { # Would using uml provide any advantages? pkgs.runCommand "nixos-installation-test" { inherit systemDerivation; } '' + INFO(){ echo $@; } + + die(){ echo $@; exit 1; } + + if ${pkgs.procps}/bin/ps aux | grep -v grep | grep sbin/nmbd ; then + die "!! aborting: -smb won't work when host is running samba!" + fi + + [ -e /dev/kvm ] || die "modprobe a kvm-* module /dev/kvm not present. You want it for speed reasons!" + for path in ${pkgs.socat} ${pkgs.openssh} ${qemu_kvm}; do PATH=$path/bin:$PATH done - echo "creating image file" - qemu-img create -f qcow2 image 512M + # without samba -smb doesn't work + PATH=${pkgs.samba}/sbin:$PATH # install the system export DISPLAY=localhost:0.0 + SOCKET_NAME=65535.socket + + # creating shell script for debugging purposes cat >> run-kvm.sh << EOF - #!/bin/sh - qemu-system-x86_64 -m 620 \ + #!/bin/sh -e + # maybe swap should be used ? + exec qemu-system-x86_64 -m 2048 \ -no-kvm-irqchip \ - -net nic -net user -smb \ + -net nic,model=virtio -net user -smb /nix \ -hda image \ - -cdrom $(echo ${isoFile}/iso/*.iso) \ + -redir tcp:''${SOCKET_NAME/.socket/}::22 \ "\$@" EOF chmod +x run-kvm.sh - SOCKET_NAME=65535.socket - - # run qemu-kvm in a background process - { ./run-kvm.sh -boot d -redir tcp:''${SOCKET_NAME/.socket/}::22 \ - || { echo "starting kvm failed, exiting" 1>&2; pkill -9 $$; } - } & - - # check that vm is still running - checkVM(){ [ -n "$(jobs -l)" ] || { echo "kvm died!?"; exit 1; }; } + RUN_KVM(){ + INFO "launching qemu-kvm in a background process" + { ./run-kvm.sh "$@" \ + || { echo "starting kvm failed, exiting" 1>&2; kill -9 $$; } + } & + } waitTill(){ echo $1 - while ! eval "$2"; do sleep 1; checkVM; done + while ! eval "$2"; do sleep 1; done } SSH(){ - ssh -v -o UserKnownHostsFile=/dev/null \ + ssh -o UserKnownHostsFile=/dev/null \ -o StrictHostKeyChecking=no \ -o ProxyCommand="socat stdio ./$SOCKET_NAME" \ root@127.0.0.1 \ "$@"; } + SSH_STDIN_E(){ { echo "set -e;"; cat; } | SSH; } + + SHUTDOWN_VM(){ + SSH 'shutdown -h now'; + INFO "waiting for kvm to shutown" + wait + } # wait for socket - waitTill "waiting for socket in $TMP" '[ ! -e ./$SOCKET_NAME ]' - waitTill "waiting for sshd job" "SSH 'echo Hello > /dev/tty1'" + waitForSSHD(){ + waitTill "waiting for socket in $TMP" '[ ! -e ./$SOCKET_NAME ]' + waitTill "waiting for sshd job" "SSH 'echo Hello > /dev/tty1' &> /dev/null" + } + + + + ### test installting NixOS: install system then reboot + + + INFO "creating image file" + qemu-img create -f qcow2 image 2G + + RUN_KVM -boot d -cdrom $(echo ${isoFile}/iso/*.iso) + + waitForSSHD # INSTALLATION - echo "installation should take place" + INFO "creating filesystem .." + SSH_STDIN_E << EOF + parted /dev/sda mklabel msdos + parted /dev/sda mkpart primary 0 2G + while [ ! -e /dev/sda1 ]; do + echo "waiting for /dev/sda1 to appear" + sleep 1; + done + mkfs.ext3 /dev/sda1 + mount /dev/sda1 /mnt + mkdir -p /mnt/nix-on-host + mount //10.0.2.4/qemu -oguest,username=nobody,noperm -tcifs /mnt/nix-on-host + EOF - # REBOOT - echo "rebooting should take place" - # CHECK - echo "verify system is up and running" + SSH_STDIN_E << EOF + # simple nixos-hardware-scan syntax check: + nixos-hardware-scan > /tmp/test.nix + EOF - # SHUTDOWN - SSH "shutdown -h now" + INFO "copying sources and Nix, preparing configuration, starting installation" + SSH_STDIN_E << EOF - echo waiting for kvm to shutdown.. - wait + nixos-prepare-install + + # has the generated configuration.nix file syntax errors? + nix-instantiate --eval-only /tmp/test.nix + + # NixOS sources are in /etc/nixos, copy those configuration files. + cp /etc/nixos/nixos/modules/installer/cd-dvd/test-nixos-install-from-cd-config.nix /mnt/etc/nixos/configuration.nix + # the configuration file is referencing additional files: + cp -r /etc/nixos/nixos/modules/installer/cd-dvd/*.nix /mnt/etc/nixos/ + export NIX_OTHER_STORES=/nix-on-host + run-in-chroot "/nix/store/nixos-bootstrap --install" + #nixos-install + EOF + + SHUTDOWN_VM + + INFO "booting installed system" + RUN_KVM -boot c + waitForSSHD + SHUTDOWN_VM + + echo "$(date) success" > $out ''; } diff --git a/tests/test-nixos-installer2.nix b/tests/test-nixos-installer2.nix new file mode 100644 index 00000000000..7afb9cd892e --- /dev/null +++ b/tests/test-nixos-installer2.nix @@ -0,0 +1,71 @@ +# A test script is created testing the installer2 scripts +# This can't be a build job because chroot is required - sudo is used +# +# # build test script: +# nix-build tests/test-nixos-installer2.nix -A test +# +# # run: +# sudo result/bin/test + +{ nixos ? ./.. +, nixpkgs ? ../../nixpkgs +, services ? ../../nixos/services +, system ? builtins.currentSystem +, configPath ? ./test-nixos-install-from-cd.nix +}: + +let + + isos = (import ../release.nix) { inherit nixpkgs; }; + + # using same configuration as ased by kvm test. + configuration = ../modules/installer/cd-dvd/test-nixos-install-from-cd-config.nix; + + eval = import ../lib/eval-config.nix { + inherit system nixpkgs; + modules = [ configuration ]; + }; + + + inherit (eval) pkgs config; + + inherit (pkgs) qemu_kvm; + + # prebuild system which will be installed for two reasons: + # build derivations are in store and can be reused + # the iso is only build when this suceeds (?) + systemDerivation = builtins.addErrorContext "while building system" config.system.build.toplevel; + + + tools = config.system.build; + +in + +rec { + + test = pkgs.writeScriptBin "test" '' + #!/bin/sh -e + # DEBUG can be set to --debug to force set -x in scripts + + export mountPoint=''${mountPoint:-`pwd`/mountPoint} + if [ -e "$mountPoint" ]; then + echo "mountPoint $mountPoint exists, delete? [y] | other key: continue" + read -n1 delete + if [ "$delete" == "y" ]; then + rm -fr $mountPoint + fi + fi + mkdir -p $mountPoint + + set -x + + ${tools.nixosPrepareInstall}/bin/nixos-prepare-install $DEBUG --dir-ok copy-nixos-bootstrap copy-nix copy-sources + + cp ${configuration} $mountPoint/etc/nixos/configuration.nix + + # at least one of those files is referenced. So copy all - they don't hurt + cp -r ${builtins.dirOf (builtins.toString configuration)}/* $mountPoint/etc/nixos + + ${tools.runInChroot}/bin/run-in-chroot $DEBUG "/nix/store/nixos-bootstrap $DEBUG --install --no-grub" + ''; +}