Merge pull request #5995 from ts468/qemu-vm

Update QEMU Nixos Virtual Machine
This commit is contained in:
James Cook 2015-02-16 13:13:26 -08:00
commit 6daf9aa922
4 changed files with 144 additions and 23 deletions

View File

@ -36,13 +36,28 @@ let
${toString config.virtualisation.diskSize}M || exit 1
fi
# Create a directory for exchanging data with the VM.
# Create a directory for storing temporary data of the running VM.
if [ -z "$TMPDIR" -o -z "$USE_TMPDIR" ]; then
TMPDIR=$(mktemp -d nix-vm.XXXXXXXXXX --tmpdir)
fi
cd $TMPDIR
# Create a directory for exchanging data with the VM.
mkdir -p $TMPDIR/xchg
${if cfg.useBootLoader then ''
# Create a writable copy/snapshot of the boot disk
# A writable boot disk can be booted from automatically
${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 -b ${bootDisk}/disk.img $TMPDIR/disk.img || exit 1
${if cfg.useEFIBoot then ''
# VM needs a writable flash BIOS
cp ${bootDisk}/bios.bin $TMPDIR || exit 1
chmod 0644 $TMPDIR/bios.bin || exit 1
'' else ''
''}
'' else ''
''}
cd $TMPDIR
idx=2
extraDisks=""
${flip concatMapStrings cfg.emptyDiskImages (size: ''
@ -52,7 +67,6 @@ let
'')}
# Start QEMU.
# "-boot menu=on" is there, because I don't know how to make qemu boot from 2nd hd.
exec ${pkgs.qemu_kvm}/bin/qemu-kvm \
-name ${vmName} \
-m ${toString config.virtualisation.memorySize} \
@ -63,8 +77,11 @@ let
-virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \
${if cfg.useBootLoader then ''
-drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
-drive index=1,id=drive2,file=${bootDisk}/disk.img,if=virtio,readonly \
-boot menu=on \
-drive index=1,id=drive2,file=$TMPDIR/disk.img,media=disk \
${if cfg.useEFIBoot then ''
-pflash $TMPDIR/bios.bin \
'' else ''
''}
'' else ''
-drive file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
-kernel ${config.system.build.toplevel}/kernel \
@ -74,7 +91,8 @@ let
$extraDisks \
${qemuGraphics} \
${toString config.virtualisation.qemu.options} \
$QEMU_OPTS
$QEMU_OPTS \
$@
'';
@ -98,23 +116,44 @@ let
''
mkdir $out
diskImage=$out/disk.img
${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 $diskImage "32M"
bootFlash=$out/bios.bin
${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 $diskImage "40M"
${if cfg.useEFIBoot then ''
cp ${pkgs.OVMF-CSM}/FV/OVMF.fd $bootFlash
chmod 0644 $bootFlash
'' else ''
''}
'';
buildInputs = [ pkgs.utillinux ];
QEMU_OPTS = if cfg.useEFIBoot
then "-pflash $out/bios.bin -nographic -serial pty"
else "-nographic -serial pty";
}
''
# 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
# Create a /boot EFI partition with 40M
${pkgs.gptfdisk}/sbin/sgdisk -G /dev/vda
${pkgs.gptfdisk}/sbin/sgdisk -a 1 -n 1:34:2047 -c 1:"BIOS Boot Partition" -t 1:ef02 /dev/vda
${pkgs.gptfdisk}/sbin/sgdisk -a 512 -N 2 -c 2:"EFI System" -t 2:ef00 /dev/vda
${pkgs.gptfdisk}/sbin/sgdisk -A 1:set:1 /dev/vda
${pkgs.gptfdisk}/sbin/sgdisk -A 2:set:2 /dev/vda
${pkgs.gptfdisk}/sbin/sgdisk -h 2 /dev/vda
${pkgs.gptfdisk}/sbin/sgdisk -C /dev/vda
${pkgs.utillinux}/bin/sfdisk /dev/vda -A 2
. /sys/class/block/vda2/uevent
mknod /dev/vda2 b $MAJOR $MINOR
. /sys/class/block/vda/uevent
${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L boot /dev/vda1
${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1
${pkgs.dosfstools}/bin/mkfs.fat -F16 /dev/vda2
export MTOOLS_SKIP_CHECK=1
${pkgs.mtools}/bin/mlabel -i /dev/vda2 ::boot
# Mount /boot.
# Mount /boot; load necessary modules first.
${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/nls/nls_cp437.ko || true
${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/nls/nls_iso8859-1.ko || true
${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/fat/fat.ko || true
${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/fat/vfat.ko || true
${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/efivarfs/efivarfs.ko || true
mkdir /boot
mount /dev/vda1 /boot
mount /dev/vda2 /boot
# This is needed for GRUB 0.97, which doesn't know about virtio devices.
mkdir /boot/grub
@ -287,6 +326,17 @@ in
'';
};
virtualisation.useEFIBoot =
mkOption {
default = false;
description =
''
If enabled, the virtual machine will provide a EFI boot
manager.
useEFIBoot is ignored if useBootLoader == false.
'';
};
};
config = {
@ -379,8 +429,8 @@ in
};
} // optionalAttrs cfg.useBootLoader
{ "/boot" =
{ device = "/dev/disk/by-label/boot";
fsType = "ext4";
{ device = "/dev/vdb2";
fsType = "vfat";
options = "ro";
noCheck = true; # fsck fails on a r/o filesystem
};
@ -413,6 +463,7 @@ in
# Wireless won't work in the VM.
networking.wireless.enable = mkVMOverride false;
networking.connman.enable = mkVMOverride false;
# Speed up booting by not waiting for ARP.
networking.dhcpcd.extraConfig = "noarp";

View File

@ -1,4 +1,4 @@
{ stdenv, edk2, nasm, iasl }:
{ stdenv, edk2, nasm, iasl, seabios, openssl, secureBoot ? false }:
let
@ -14,14 +14,36 @@ in
stdenv.mkDerivation (edk2.setup "OvmfPkg/OvmfPkg${targetArch}.dsc" {
name = "OVMF-2014-12-10";
buildInputs = [nasm iasl];
# TODO: properly include openssl for secureBoot
buildInputs = [nasm iasl] ++ stdenv.lib.optionals (secureBoot == true) [ openssl ];
unpackPhase = ''
for file in \
"${edk2.src}"/{OvmfPkg,UefiCpuPkg,MdeModulePkg,IntelFrameworkModulePkg,PcAtChipsetPkg,FatBinPkg,EdkShellBinPkg,MdePkg,ShellPkg,OptionRomPkg,IntelFrameworkPkg};
"${edk2.src}"/{UefiCpuPkg,MdeModulePkg,IntelFrameworkModulePkg,PcAtChipsetPkg,FatBinPkg,EdkShellBinPkg,MdePkg,ShellPkg,OptionRomPkg,IntelFrameworkPkg};
do
ln -sv "$file" .
done
'';
${if (seabios == false) then ''
ln -sv ${edk2.src}/OvmfPkg .
'' else ''
cp -r ${edk2.src}/OvmfPkg .
chmod +w OvmfPkg/Csm/Csm16
cp ${seabios}/Csm16.bin OvmfPkg/Csm/Csm16/Csm16.bin
''}
${if (secureBoot == true) then ''
ln -sv ${edk2.src}/SecurityPkg .
ln -sv ${edk2.src}/CryptoPkg .
'' else ''
''}
'';
buildPhase = if (seabios == false) then ''
build ${if secureBoot then "-DSECURE_BOOT_ENABLE=TRUE" else ""}
'' else ''
build -D CSM_ENABLE -D FD_SIZE_2MB ${if secureBoot then "-DSECURE_BOOT_ENABLE=TRUE" else ""}
'';
meta = {
description = "Sample UEFI firmware for QEMU and KVM";

View File

@ -0,0 +1,44 @@
{ stdenv, fetchurl, iasl, python }:
stdenv.mkDerivation rec {
name = "seabios-${version}";
version = "1.7.5.2";
src = fetchurl {
url = "http://code.coreboot.org/p/seabios/downloads/get/${name}.tar.gz";
sha256 = "1syd3gi5gq0gj2pjvmdis64xc3j1xf0jgy49ngymap0pdpm0cmh0";
};
buildInputs = [ iasl python ];
configurePhase = ''
# build SeaBIOS for CSM
cat > .config << EOF
CONFIG_CSM=y
CONFIG_QEMU_HARDWARE=y
CONFIG_PERMIT_UNALIGNED_PCIROM=y
EOF
make olddefconfig
'';
installPhase = ''
mkdir $out
cp out/Csm16.bin $out/Csm16.bin
'';
meta = with stdenv.lib; {
description = "Open source implementation of a 16bit X86 BIOS";
longDescription = ''
SeaBIOS is an open source implementation of a 16bit X86 BIOS.
It can run in an emulator or it can run natively on X86 hardware with the use of coreboot.
SeaBIOS is the default BIOS for QEMU and KVM.
'';
homepage = http://www.seabios.org;
license = licenses.lgpl3;
maintainers = [ maintainers.tstrobel ];
platforms = platforms.linux;
};
}

View File

@ -8133,7 +8133,11 @@ let
oracleXE = callPackage ../servers/sql/oracle-xe { };
OVMF = callPackage ../applications/virtualization/OVMF { };
OVMF = callPackage ../applications/virtualization/OVMF { seabios=false; openssl=null; };
OVMF-CSM = callPackage ../applications/virtualization/OVMF { openssl=null; };
#WIP: OVMF-secureBoot = callPackage ../applications/virtualization/OVMF { seabios=false; secureBoot=true; };
seabios = callPackage ../applications/virtualization/seabios { };
pgpool92 = callPackage ../servers/sql/pgpool/default.nix {
postgresql = postgresql92;