idupree ([personal profile] idupree) wrote2013-08-30 11:12 am

Some Linux virtual machines

(The canonical location of this blog post is now Some Linux virtual machines on my web site.)

I run Linux. Sometimes it's helpful to use a different Linux distro installation than my main one. For example:

  • For building Lasercake, I test building on both 32- and 64-bit Debian installations with only the necessary packages installed. This helps test that Lasercake doesn't accidentally depend on one of the thousands of packages installed in my main system.

  • I had to use OpenModelica. It didn't work right on my main Linux system at the time[1]. It did work right in Debian Stable, so I used it there.

  • For running software that might be malicious (e.g. random programs off the Internet) or vulnerable (e.g. old browser versions I'm using to test websites), certain virtual-machine configurations can prevent that software from compromising my main account.

  • Familiarity with virtual machines is also helpful for servers and for deterministic builds.

Some methods I've used:

For installation:
  • Debootstrap. When this works, it works well. It is specific to Debian guests. Example: sudo debootstrap --arch=amd64 wheezy ./debootstrap-amd64-wheezy

  • Running a distro's install CD in QEMU and installing it onto a disk image. This often works, though it is odd deciding whether the disk image should be partitioned or be just a filesystem.

  • Using an online service or piece of software that is already set up to create VMs for you. (Not discussed here.)

For running:
  • chroot. I made a script for setting up a useful Linux chroot environment, superchroot. This provides no security. If the distro installation is inside a disk image, you'll need to mount it first. This relies on the kernel and basic runtime services of the host distro being similar enough to the guest distro. For example, running 'startx' in the guest didn't work while I was running host X11, and after I closed host X11, guest X11 worked but I got a kernel panic after a few minutes. (In theory kernel panics shouldn't happen but other problems might.) Example: superchroot ./debootstrap-amd64-wheezy /bin/bash

  • QEMU/KVM. QEMU emulates many hardware architectures. For (at least) x86 emulating x86, pass -enable-kvm and the emulated code will run at native speed. Specifically:


QEMU of a system installed on a disk image does not require root. (Unless you use `sudo mount -o loop` to help create your disk image.) Regular disk images are fixed-size and can thus waste space and/or run out of space if you install things on the guest system. (QEMU's qcow2 disk image can allocate storage as-needed for the guest, but, since it's emulating a block device, I don't believe it can shrink unless it listens to guest TRIM requests. `qemu-img` can create these.)

One way:
# Setup (if you have already created a debootstrap as above)
# Make sure a kernel is installed in the debootstrap
# e.g.: (superchroot as mentioned above)
sudo superchroot ./debootstrap-amd64-wheezy \
    /usr/bin/aptitude install linux-image-3.2.0-4-amd64
sudo dd if=/dev/zero of=./deb-amd64-wheezy.img bs=1M count=5000
sudo mkfs.ext4 ./deb-amd64-wheezy.img
# If necessary, sudo mkdir /media/x or any dir name you like in /media/
sudo mount -o loop ./deb-amd64-wheezy.img /media/x
# If you've chrooted to the copy source before, make sure to
# unmount its dev, dev/pts, proc, sys before copying: we want to copy
# the physical files that are present before special filesystems are
# mounted, not the special filesystems' contents! :
sudo umount ./debootstrap-amd64-wheezy/{dev/pts,dev,proc,sys}
# Warning: this glob would miss top-level dot files if there were any.
sudo cp -a ./debootstrap-amd64-wheezy/* /media/x
# Warning: make sure to unmount before using the image!
# Otherwise host and/or guest kernels might panic by both thinking
# they have exclusive modification rights to this ext4 filesystem
# (if you're unlucky).
sudo umount /media/x

# Running
# This method uses the kernel/initrd from the original debootstrap
# rather than the disk image.
# Optional flags: -enable-kvm makes it run much faster. -m 1500 gives
# it up to 1.5 GB of RAM.  -cpu core2duo is a workaround to prevent
# guest `gcc -march=native` mis-detecting the emulated CPU as 32-bit
# even though QEMU is emulating a 64-bit CPU.
sudo qemu-system-x86_64 -enable-kvm -m 1500 -cpu core2duo \
    -kernel ./debootstrap-amd64-wheezy/boot/vmlinuz-3.2.0-4-amd64 \
    -initrd ./debootstrap-amd64-wheezy/boot/initrd.img-3.2.0-4-amd64 \
    -hda ./deb-amd64-wheezy-openmo.img \
    -append 'root=/dev/sda'

QEMU of a host filesystem tree that's not encapsulated in a disk image:

Apparently 9p, the filesystem protocol originally created for Plan 9, is the way to run QEMU on a guest stored in a host-mounted filesystem. The guest's kernel must support 9p (e.g. 9p kernel modules must be loaded before any 9p filesystems need to be mounted). For my Debian guest, I had to edit its etc/initramfs-tools/modules to include

and then run update-initramfs -u in the chroot. 9p is the filesystem and 9pnet_virtio is the "transport" that lets it connect to QEMU-provided 9p filesystems. The host kernel does not need to understand 9p: QEMU uses the regular filesystem interface on the host, and creates a virtual 9p interface for the guest.

Then, to run,
sudo qemu-system-x86_64 -enable-kvm -m 1500 -cpu core2duo \
    -kernel ./debootstrap-amd64-wheezy/boot/vmlinuz-3.2.0-4-amd64 \Some 
    -initrd ./debootstrap-amd64-wheezy/boot/initrd.img-3.2.0-4-amd64 \
    -fsdev local,id=test_dev,path=./debootstrap-amd64-wheezy,security_model=none \
    -device virtio-9p-pci,fsdev=test_dev,mount_tag=test_mount \
    -append 'rootfstype=9p rootflags=trans=virtio root=test_mount console=ttyS0'

Without 'sudo', it will run but then fail to access files such as etc/shadow that non-root can't access. You won't be able to log in and you'll have no idea why. The flags `-enable-kvm -m 1500 -cpu core2duo` are optional as described above. -virtfs can be used as a shorthand for -fsdev + -device. The names 'test_dev' and 'test_mount' are arbitrary but used as names: if you rename one instance of either, rename all instances of it. console=ttyS0 changes which guest debug messages and interactive prompts you can get: add/remove it freely while debugging this setup.

Warning: Don't start a VM while the VM's disk image is loop-mounted or while you're chrooted to it with dev/proc/sys mounted on the host system. Weird things can happen, including kernel panics. However, the host editing the files within a guest 9p filesystem should work (provided 9p caching isn't turned on in the guest kernel mount options).

[1] Perhaps because of a GCC or toolchain version incompatibility. Error message "Simulation execution failed for model" when trying to run the "Hello World" model in OMNotebook or OMShell. The only relevant search result was a Gentoo user trying to install OpenModelica. I use Arch Linux, which can be similarly cutting-edge. OpenModelica provides Debian binaries and I chose to see if those worked on Debian rather than try to debug further on Arch Linux. They worked fine.