There are lots of cloud disk images floating around. They are designed to run in clouds where there is a boot-time network service called cloud-init available that provides initial configuration. If that’s not present, or you’re just trying to boot these images in KVM/libvirt directly without any cloud, then things can go wrong.
Luckily it’s fairly easy to create a config disk (aka “seed disk”) which you attach to the guest and then let cloud-init in the guest get its configuration from there. No cloud, or even network, required.
I’m going to use a tool called virt-make-fs to make the config disk, as it’s easy to use and doesn’t require root. There are other tools around, eg. make-seed-disk which do a similar job. (NB: You might hit this bug in virt-make-fs, which should be fixed in the latest version).
I’m also using a cloud image downloaded from the Fedora project, but any cloud image should work.
First I create my cloud-init metadata. This consists of two files. meta-data
contains host and network configuration:
instance-id: iid-123456
local-hostname: cloudy
user-data
contains other custom configuration (note #cloud-config
is
not a comment, it’s a directive to tell cloud-init the format of the file):
#cloud-config
password: 123456
runcmd:
- [ useradd, -m, -p, "", rjones ]
- [ chage, -d, 0, rjones ]
(The idea behind this split is probably not obvious, but apparently it’s because the meta-data
is meant to be supplied by the Cloud, and the user-data
is meant to be supplied by the Cloud’s customer. In this case, no cloud, so we’re going to supply both!)
I put these two files into a directory, and run virt-make-fs
to create the config disk:
$ ls
meta-data user-data
$ virt-make-fs --type=msdos --label=cidata . /tmp/seed.img
$ virt-filesystems -a /tmp/seed.img --all --long -h
Name Type VFS Label MBR Size Parent
/dev/sda filesystem vfat cidata - 286K -
/dev/sda device - - - 286K -
Now I need to pass some kernel options when booting the Fedora cloud image, and the only way to do that is if I boot from an external kernel & initrd. This is not as complicated as it sounds, and virt-builder has an option to get the kernel and initrd that I’m going to need:
$ virt-builder --get-kernel Fedora-cloud.raw
download: /boot/vmlinuz-3.9.5-301.fc19.x86_64 -> ./vmlinuz-3.9.5-301.fc19.x86_64
download: /boot/initramfs-3.9.5-301.fc19.x86_64.img -> ./initramfs-3.9.5-301.fc19.x86_64.img
Finally I’m going to boot the guest using KVM (you could also use libvirt with a little extra effort):
$ qemu-kvm -m 1024 \
-drive file=Fedora-cloud.raw,if=virtio \
-drive file=seed.img,if=virtio \
-kernel ./vmlinuz-3.9.5-301.fc19.x86_64 \
-initrd ./initramfs-3.9.5-301.fc19.x86_64.img \
-append 'root=/dev/vda1 ro ds=nocloud-net'
You’ll be able to log in either as fedora/123456 or rjones (no password), and you should see that the hostname has been set to cloudy
.