* Added a command `nixos-rebuild build-vm-with-bootloader'. This is

like `build-vm', but boots using the regular boot loader (i.e. GRUB
  1 or 2) rather than booting directly from the kernel/initrd.  Thus
  it allows testing of GRUB.

svn path=/nixos/trunk/; revision=23747
gstqt5
Eelco Dolstra 2010-09-13 12:34:58 +00:00
parent b756a1ee81
commit c1295661c4
5 changed files with 137 additions and 12 deletions

View File

@ -11,11 +11,22 @@ let
inherit (eval) config pkgs;
# This is for `nixos-rebuild build-vm'.
vmConfig = (import ./lib/eval-config.nix {
inherit system;
modules = [ configuration ./modules/virtualisation/qemu-vm.nix ];
}).config;
# This is for `nixos-rebuild build-vm-with-bootloader'.
vmWithBootLoaderConfig = (import ./lib/eval-config.nix {
inherit system;
modules =
[ configuration
./modules/virtualisation/qemu-vm.nix
{ virtualisation.useBootLoader = true; }
];
}).config;
in
{
@ -25,6 +36,8 @@ in
vm = vmConfig.system.build.vm;
vmWithBootLoader = vmWithBootLoaderConfig.system.build.vm;
# The following are used by nixos-rebuild.
nixFallback = pkgs.nixUnstable;
manifests = config.installer.manifests;

View File

@ -24,6 +24,8 @@
<arg choice='plain'><option>build</option></arg>
<arg choice='plain'><option>dry-run</option></arg>
<arg choice='plain'><option>build-vm</option></arg>
<arg choice='plain'><option>build-vm-with-bootloader</option></arg>
<arg choice='plain'><option>pull</option></arg>
</group>
<sbr />
<arg><option>--install-grub</option></arg>
@ -151,6 +153,35 @@ $ ./result/bin/run-*-vm
</listitem>
</varlistentry>
<varlistentry>
<term><option>build-vm-with-bootloader</option></term>
<listitem>
<para>Like <option>build-vm</option>, but boots using the
regular boot loader of your configuration (e.g., GRUB 1 or 2),
rather than booting directly into the kernel and initial ramdisk
of the system. This allows you to test whether the boot loader
works correctly. However, it does not guarantee that your NixOS
configuration will boot successfully on the host hardware (i.e.,
after running <command>nixos-rebuild switch</command>), because
the hardware and boot loader configuration in the VM are
different. The boot loader is installed on an automatically
generated virtual disk containing a <filename>/boot</filename>
partition, which is mounted read-only in the VM.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>pull</option></term>
<listitem>
<para>This operation merely fetches the latest manifest in the
Nixpkgs channel to speed up subsequent
<command>nix-env</command> operations. This is useful if you
are not using <command>nix-channel</command> but still want to
use pre-built binary packages. It doesnt reconfigure the
system at all.</para>
</listitem>
</varlistentry>
</variablelist>
</para>

View File

@ -22,6 +22,8 @@ The operation is one of the following:
activate it
build-vm: build a virtual machine containing the configuration
(useful for testing)
build-vm-with-bootloader:
like build-vm, but include a boot loader in the VM
dry-run: just show what store paths would be built/downloaded
pull: just pull the Nixpkgs channel manifest and exit
@ -64,7 +66,7 @@ while test "$#" -gt 0; do
--help)
showSyntax
;;
switch|boot|test|build|dry-run|build-vm|pull)
switch|boot|test|build|dry-run|build-vm|build-vm-with-bootloader|pull)
action="$i"
;;
--install-grub)
@ -171,9 +173,12 @@ if test -z "$rollback"; then
elif test "$action" = test -o "$action" = build -o "$action" = dry-run; then
nix-build $NIXOS -A system -K -k $extraBuildFlags > /dev/null
pathToConfig=./result
elif test "$action" = build-vm; then
elif [ "$action" = build-vm ]; then
nix-build $NIXOS -A vm -K -k $extraBuildFlags > /dev/null
pathToConfig=./result
elif [ "$action" = build-vm-with-bootloader ]; then
nix-build $NIXOS -A vmWithBootLoader -K -k $extraBuildFlags > /dev/null
pathToConfig=./result
else
showSyntax
fi

View File

@ -38,7 +38,7 @@ if [ "$action" = "switch" -o "$action" = "boot" ]; then
if [ "$NIXOS_INSTALL_GRUB" = 1 -o "$oldGrubVersion" != "$newGrubVersion" ]; then
echo "installing the GRUB bootloader..."
@grub@/sbin/grub-install "@grubDevice@" --no-floppy --recheck
@grub@/sbin/grub-install "@grubDevice@" --no-floppy
echo "$newGrubVersion" > /boot/grub/version
fi
fi

View File

@ -110,7 +110,24 @@ let
example = "-vga std";
description = "Options passed to QEMU.";
};
virtualisation.useBootLoader =
mkOption {
default = true;
description =
''
If enabled, the virtual machine will be booted using the
regular boot loader (i.e., GRUB 1 or 2). This allows
testing of the boot loader. However, it does not
guarantee that your NixOS configuration will boot
successfully on the host hardware, because the hardware
and boot loader configuration in the VM are different. If
disabled (the default), the VM directly boots the NixOS
kernel and initial ramdisk, bypassing the boot loader
altogether.
'';
};
};
cfg = config.virtualisation;
@ -146,12 +163,17 @@ let
-net nic,vlan=0,model=virtio \
-chardev socket,id=samba,path=./samba \
-net user,vlan=0,guestfwd=tcp:10.0.2.4:139-chardev:samba''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS} \
-drive file=$NIX_DISK_IMAGE,if=virtio,boot=on,cache=writeback,werror=report \
-kernel ${config.system.build.toplevel}/kernel \
-initrd ${config.system.build.toplevel}/initrd \
${if cfg.useBootLoader then ''
-drive index=0,file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
-drive index=1,file=${bootDisk}/disk.img,if=virtio,boot=on \
'' else ''
-drive file=$NIX_DISK_IMAGE,if=virtio,boot=on,cache=writeback,werror=report \
-kernel ${config.system.build.toplevel}/kernel \
-initrd ${config.system.build.toplevel}/initrd \
-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.bootStage2} systemConfig=${config.system.build.toplevel} regInfo=${regInfo} ${kernelConsole} $QEMU_KERNEL_PARAMS" \
''}
${qemuGraphics} \
$QEMU_OPTS \
-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.bootStage2} systemConfig=${config.system.build.toplevel} regInfo=${regInfo} ${kernelConsole} $QEMU_KERNEL_PARAMS" \
${config.virtualisation.qemu.options}
'';
@ -165,11 +187,54 @@ let
printRegistration=1 perl ${pkgs.pathsFromGraph} closure-* > $out
'';
# Generate a hard disk image containing a /boot partition and GRUB
# in the MBR. Used when the `useBootLoader' option is set.
bootDisk =
pkgs.vmTools.runInLinuxVM (
pkgs.runCommand "nixos-boot-disk"
{ preVM =
''
mkdir $out
diskImage=$out/disk.img
${pkgs.vmTools.kvm}/bin/qemu-img create -f qcow2 $diskImage "32M"
'';
buildInputs = [ pkgs.utillinux ];
}
''
# Create a single /boot partition.
${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
. /sys/class/block/vda/uevent
${pkgs.e2fsprogs}/sbin/mkfs.ext3 -L boot /dev/vda1
${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1
# Mount /boot.
mkdir /boot
mount /dev/vda1 /boot
# This is needed for GRUB 0.97, which doesn't know about virtio devices.
mkdir /boot/grub
echo '(hd0) /dev/vda' > /boot/grub/device.map
# Install GRUB and generate the GRUB boot menu.
touch /etc/NIXOS
mkdir -p /nix/var/nix/profiles
${config.system.build.toplevel}/bin/switch-to-configuration boot
umount /boot
''
);
in
{
require = options;
boot.loader.grub.device = mkOverride 50 "/dev/vda";
# All the modules the initrd needs to mount the host filesystem via
# CIFS. Also use paravirtualised network and block devices for
# performance.
@ -207,6 +272,7 @@ in
boot.initrd.postMountCommands =
''
mkdir -p $targetRoot/boot
mount -o remount,ro $targetRoot/nix/store
${optionalString cfg.writableStore ''
mkdir /mnt-store-tmpfs
@ -225,7 +291,9 @@ in
boot.postBootCommands =
''
( source /proc/cmdline
${config.environment.nix}/bin/nix-store --load-db < $regInfo
if [ -n "$regInfo" ]; then
${config.environment.nix}/bin/nix-store --load-db < $regInfo
fi
)
'';
@ -237,7 +305,7 @@ in
# where the regular value for the `fileSystems' attribute should be
# disregarded for the purpose of building a VM test image (since
# those filesystems don't exist in the VM).
fileSystems = mkOverride 50
fileSystems = mkOverride 50 (
[ { mountPoint = "/";
device = "/dev/vda";
}
@ -253,7 +321,15 @@ in
options = "bind";
neededForBoot = true;
}
];
] ++ optional cfg.useBootLoader
{ mountPoint = "/boot";
device = "/dev/disk/by-label/boot";
fsType = "ext3";
options = "ro";
noCheck = true; # fsck fails on a r/o filesystem
});
swapDevices = mkOverride 50 [ ];
# Starting DHCP brings down eth0, which kills the connection to the
# host filesystem and thus deadlocks the system.