Ubuntu QEMU VM
So far I installed operating systems in virtual machines to its virtual hard disk using a CD or DVD image (an ISO file), similar to what I would do on a real PC. Some years ago I noticed that Qemu has options to directly load a kernel and initial ramdisk (initrd) into the virtual ROM of the virtual computer, so it can directly start the kernel without needing a firmware to detect hard disks, seek for boot loader and the like (similar to what many embedded systems do as well, PCs normally don't do that). It's quite clear that this reduces the time for the machine to come up and also reduces the complexity and number of things that could go wrong. So I decided to make an experiment and see which steps are necessary to get such a virtual machine running.
Creating files for VM
First, I created a directory that contains all the files needed and copied my currently used kernel and initrd to that directory.
mkdir ubuntu_qemu cp -v /boot/*$(uname -r)* ubuntu_qemu/ cd ubuntu_qemu
Next, I created a file that would represent the virtual hard disk (a raw image) and formatted that file with an ext3 file system. The size of that virtual hard disk is just 512 MiB, which would be enough for that experiment. For real world scenarios I strongly recommend a larger file!
dd if=/dev/zero of=testimage bs=1048576 count=512 # create 512 MiB image mkfs.ext4 -L testpart testimage # format image with ext4
An alternative is to create an QCOW image and format it:
qemu-img create -f qcow2 drive0.img 1G modprobe nbd max_part=16 qemu-nbd -c /dev/nbd0 drive0.img partprobe /dev/nbd0 mkfs.ext4 -L label /dev/nbd0
If you want to have some spare disks, let them create in a batch:
for i in $(seq 1 4); do echo "Creating spare disk $i"; dd if=/dev/zero of=sparedisk$i bs=1048576 count=128; done
Installing Ubuntu
Ubuntu won't be installed using ubiquity as usual, but just by using "debootstrap" on my host system (which is Xubuntu 14.04 x64 with Linux 4.2.0-36 at time of writing).
dnsmasq on host
My bridge "br0" has an IP address of 10.92.92.253 and dnsmasq is listening on that address. YMMV - change as needed.
dnsmasq --interface=br0 --bind-interfaces --dhcp-range=10.92.92.1,10.92.92.128 # on host, start dnsmasq
debootstrap and network configuration
So we install Ubuntu using debootstrap and configure the installation.
mkdir mnt mount testimage mnt/ debootstrap --arch=amd64 trusty mnt/ http://archive.ubuntu.com/ubuntu/ # downloads about 40 MiB; takes about 30 min echo "/dev/sda / ext4 errors=remount-ro 0 1" > mnt/etc/fstab echo "ubuntu_qemu" > mnt/etc/hostname # set a meaningful hostname echo "auto eth0" > mnt/etc/network/interfaces
If dnsmasq (or some other DHCP server) is running on the host and listening on the bridge used, use this line
echo "iface eth0 inet dhcp" >> mnt/etc/network/interfaces
Otherwise, use a static configuration:
echo "iface eth0 inet static" >> mnt/etc/network/interfaces echo " address 10.92.92.123" >> mnt/etc/network/interfaces echo " netmask 255.255.255.0" >> mnt/etc/network/interfaces echo " gateway 10.92.92.253" >> mnt/etc/network/interfaces
For more information on network configuration, see NetworkConfiguration in Debian Wiki.
Tell the system which DNS resolver you would like to use:
echo "nameserver 10.92.92.253" > mnt/etc/resolv.conf
Setting passwords
Next, we'll chroot into the system:
chroot mnt/
In the chrooted environment:
passwd # set root password useradd someuser # add a user passwd someuser # set user's password
Then leave with Ctrl+D.
Booting the VM
qemu-system-x86_64 -kernel vmlinuz-4.2.0-36-generic -initrd initrd.img-4.2.0-36-generic \ -boot d testimage -net nic,macaddr=52:54:e:2:11:10 -enable-kvm -name ubuntu1404qemu -net none -net bridge,br=br0 -m 512
Statistics
Disk usage
Right after the installation, df reported this:
Filesystem Size Used Avail Use% Mounted on /dev/sda 488M 253M 210M 55% /
Then I installed the openssh server, which loaded a bunch of dependencies on the system:
Filesystem Size Used Avail Use% Mounted on /dev/sda 488M 319M 144M 69% /
Memory
With 512 MiB RAM, /proc/meminfo reported this:
MemTotal: 500844 kB MemFree: 408108 kB MemAvailable: 464828 kB Buffers: 5936 kB Cached: 51096 kB SwapCached: 0 kB Active: 40088 kB Inactive: 25776 kB Active(anon): 8868 kB Inactive(anon): 264 kB Active(file): 31220 kB Inactive(file): 25512 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 0 kB SwapFree: 0 kB Dirty: 0 kB Writeback: 0 kB AnonPages: 8856 kB Mapped: 9200 kB Shmem: 304 kB Slab: 17504 kB SReclaimable: 10548 kB SUnreclaim: 6956 kB KernelStack: 1040 kB PageTables: 1212 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 250420 kB Committed_AS: 38900 kB VmallocTotal: 34359738367 kB VmallocUsed: 3304 kB VmallocChunk: 34359730020 kB HardwareCorrupted: 0 kB AnonHugePages: 0 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 36856 kB DirectMap2M: 487424 kB
Boot time
6 seconds after starting Qemu, Linux starts writing its output. After 20, I see the login prompt.
On my host, btrfs-tools is installed, so the initrd contains the code to seek for btrfs partitions, which takes about 3 seconds. Apparently, the boot time could be improved if btrfs was not used in the VM and the code was removed.
Outlook
This can be done also with a virtual machine using ARM architecture. Further information can be found here: