Browse Source

* 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
nsd-state-dir
Eelco Dolstra 12 years ago
parent
commit
c1295661c4
  1. 15
      default.nix
  2. 31
      doc/manual/man-nixos-rebuild.xml
  3. 9
      modules/installer/tools/nixos-rebuild.sh
  4. 2
      modules/system/activation/switch-to-configuration.sh
  5. 92
      modules/virtualisation/qemu-vm.nix

15
default.nix

@ -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;

31
doc/manual/man-nixos-rebuild.xml

@ -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 doesn’t reconfigure the
system at all.</para>
</listitem>
</varlistentry>
</variablelist>
</para>

9
modules/installer/tools/nixos-rebuild.sh

@ -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

2
modules/system/activation/switch-to-configuration.sh

@ -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

92
modules/virtualisation/qemu-vm.nix

@ -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.

Loading…
Cancel
Save