Saturday, September 10, 2011

Xen - Creating a PV domU guest

In this article we will explain how to create a new Xen unprivileged guest (domU). A Xen guest can be one of the following two types:
  • HVM Guest – Fully virtualized guest by using hardware assisted virtualization. The guest’s kernel needs no modifications but our CPU must include virtualization technology to support hardware assisted virtualization.
  • PV Guest – Paravirtualized guest. The guest’s kernel needs some modifications.
The first thing to do when creating a domU Linux guest is to decide what kernel we will use. On the one hand, we can use the existing dom0 kernel. However, because the dom0 kernel is full of unwanted stuff for a guest, like backend drivers we can build a new lightweight kernel for a domU guest. The next step after deciding what kernel to use is to create and configure the root file system for our domU guest. The guest’s root file system can reside in a file which acts as a virtual disk, in a physical partition or even in a remote NFS server. Finally, the last step is to create a configuration file to inform Xen about our new guest.



1. Building a domU kernel

As we said in section 4, there are two different types of Xen dom0 capable kernels available today: pvops and xenlinux. Pvops support for a domU guest has been in mainline Linux kernel since 2.6.23. In this guide we will use the latest stable Linux kernel which is 3.0.4. The first thing to do is to grab the kernel from kernel.org:

user@dom0$ cd /home/giorgos/xen
user@dom0$ tar xvf linux-3.0.4.tar.gz
user@dom0$ cd linux-3.0.4

Now, we can configure our new kernel by running:

user@dom0$ make menuconfig

We must be sure that we have a correct processor family set in the kernel configuration. Xen options won’t show up at all if we have too old CPU selected. If we are building a 32 bit version of the kernel, we first need to enable PAE support:

Processor type and features →
         High memory support (64GB)
         PAE (Physical Address Extension) Support - enabled

PAE is not needed for 64 bit kernels. Also, if we are building a 32 bit kernel we need to set the option ‘CONFIG_HIGHPTE=n’:

 Processor type and features →
         Allocate 2nd-level pagetables from highmem - disabled


Below, is a list of options needed to compile Linux kernel with domU support. It’s important to mention that we prefer to select all the options below as build in, not as modules:
  • CONFIG_XEN=y
  • CONFIG_PARAVIRT_GUEST=y
  • CONFIG_PARAVIRT=y
  • CONFIG_XEN_PVHVM=y
  • CONFIG_XEN_MAX_DOMAIN_MEMORY=128
  • CONFIG_XEN_SAVE_RESTORE=y
  • CONFIG_PCI_XEN=y
  • CONFIG_XEN_PCIDEV_FRONTEND=y
  • CONFIG_XEN_BLKDEV_FRONTEND=y
  • CONFIG_XEN_NETDEV_FRONTEND=y
  • CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y
  • CONFIG_HVC_XEN=y
  • CONFIG_XEN_FBDEV_FRONTEND=y
  • CONFIG_XEN_DEV_EVTCHN=y
  • CONFIG_XEN_XENBUS_FRONTEND=y
Now, we can build the kernel:

root@dom0$ make

When the build process is complete, we will have a file called ‘vmlinux’ on the top-level directory. We can copy this file to our working directory:

root@dom0$ cp vmlinux /home/giorgos/xen/vmlinux-3.0.4-domU

When we will create the guest’s file system later, we will come back to install the necessary kernel modules.

2. Creating guest’s file system

In order for our new domU kernel to be functional we have to supply it with a root file system. We will create a disk image which will contain the root file system for our domU guest. This image will act as a hard disk for our guest system. In order to create an empty disk image we will use the ‘dd’ (man 1 dd) utility:

user@dom0$ dd if=/dev/zero of=/home/giorgos/xen/domu1.img bs=1024K count=1024

With the above command we created an empty disk image with 1GB free space. Now, we must initialize the file system inside of the image file. We will use ext4 as our root file system:

user@dom0$ /sbin/mkfs.ext4 /home/giorgos/xen/domu1.img

If we would like to provide a swap space to our guest we can create a second image and initialize it with the swap file system:

user@dom0$ dd if=/dev/zero of=/home/giorgos/xen/swap.img bs=1024K count=256
user@dom0$ /sbin/mkfs.swap /home/giorgos/xen/swap.img

At this point we have two disk images, one formatted with ext4 and one formatted as swap space. The next step is to populate the file system with a copy of the host’s root or with a base system of our favorite Linux distribution. Here we choose to install a Debian Squeeze base system. To achieve this, we first mount the disk image to a new directory on the host and then we use the ‘debootstrap’ (man 8 debootstrap) utility to populate the image with a Debian Squeeze base system:

root@dom0$ mount –o loop /home/giorgos/xen/domu1.img /mnt/
root@dom0$ debootstrap --arch i386 squeeze /mnt/ http://ftp.us.debian.org/debian

In the above example we chose i386 as the architecture of our new system. We can specify a different architecture by changing the argument after ‘arch’ parameter. However, it’s important to select the same architecture with the kernel we built earlier.
Alternatively, we can populate the guest’s root file system by copying from the host’s root:

root@dom0$ cp –ax /{root,dev,var,etc,usr,bin,sbin,lib} /mnt.
root@dom0$ mkdir /mnt/{proc,sys,home,tmp}

3. Guest system configuration

After populating the disk image we need to edit some files in order to have our guest system in a valid configuration:

/etc/fstab
The ‘/etc/fstab’ file is a system configuration file that lists all available disks and disk partitions and indicates how they are to be initialized or otherwise integrated into the overall system’s file system. Here we mount the virtual disk device ‘/dev/xvda1’ on the root specifying ‘ext4’ as the file system and the virtual disk device ‘/dev/xvda2’ for swap space. Also, we mount the proc file system on ‘/proc’ directory:

/dev/xvda1     /                ext4    defaults         0        1
/dev/xvda2   none            swap   sw                0        0
proc             /proc           proc    defaults         0        0

/etc/hostname
The hostname file contains the host name of the guest system. We add the name:

domu1

/etc/network/interfaces
This file contains network interface configuration information for the ifup(8) and ifdown(8) commands. This is where you configure how your system is connected to the network. At this point we will add the loopback interface to this file. Later on this guide we will add some more network interfaces to provide a fully functional networking on the domU guest. So, we open this file with an editor and we add the following values:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

#
# The loopback network interface
#
auto lo
iface lo inet loopback

Note that the lines beginning with # are comments.

 /etc/securetty
The ‘/etc/securetty’ file allows you to specify which TTY devices the root user is allowed to login on. The ‘/etc/securetty’ file is read by the login program usually ‘/bin/login’. Its format is a list of the tty devices’ names allowed, and for all others that are commented out or do not appear in this file, root login is disallowed. We append this file with the following values:

hvc0

/dev
The ‘/dev’ directory contains the special device files for all the available devices. If the virtual block devices ‘xvda1’ and ‘xvda2’ does not exist there we have to create them manually. We run the following commands as root:

root@dom0$ chroot /mnt
root@dom0$ mknod /dev/xvda1 b 202 1
root@dom0$ mknod /dev/xvda2 b 202 2
root@dom0$ chown root:disk /dev/xvda1 /dev/xvda2
root@dom0$ exit

/etc/inittab
The ‘/etc/inittab’ file describes which processes are started at boot up and during normal operation. To login immediately after the boot messages comment out the following lines:

# 2:23:respawn:/sbin/getty 38400 tty2
# 3:23:respawn:/sbin/getty 38400 tty3
# 4:23:respawn:/sbin/getty 38400 tty4
# 5:23:respawn:/sbin/getty 38400 tty5
# 6:23:respawn:/sbin/getty 38400 tty6

And modify the line starting with ‘1:’ as follows:

hvc0:2345:respawn:/sbin/agetty -L 9600 hvc0

Now, it’s time to add a new user to the domU guest. To do this we run the following commands as root:

root@dom0$ chroot /mnt
root@dom0$ adduser xen
root@dom0$ exit

Instead of using the tool ‘adduser’, we can add a new user by hand, by adding an entry to ‘/etc/passwd’ and ‘/etc/shadow’ files. After adding the new user we can specify a password for the root user. We run the following commands as root:

root@dom0$ chroot /mnt
root@dom0$ passwd
root@dom0$ exit

Remember the kernel we compiled earlier? Now it’s time to install the kernel modules to the appropriate location. To do this we run the following:

root@dom0$ cd /home/giorgos/xen/linux-3.0.4
root@dom0$ make modules_install INSTALL_MOD_PATH=/mnt

Now, we can create an initramfs image for the guest kernel. To do this we run the following commands:

root@dom0$ cp /home/giorgos/xen/linux-3.0.4/.config /mnt/boot/config-3.0.4
root@dom0$ chroot /mnt
root@dom0$ mkinitramfs -o initrd.img-3.0.4-domU 3.0.4
root@dom0$ exit
root@dom0$ mv /mnt/initrd.img-3.0.4-domU /home/giorgos/xen/.

At this point the root file system for our domU guest is ready. We can unmount it from ‘/mnt’:

root@dom0$ umount /mnt

4. Creating a domain configuration file

Before we can boot the new domU guest, we must create a configuration file. Below, we provide an example file which you can use as a starting point:

#  -*- mode: python; -*-
#=========================================
# Python configuration setup for 'xm create'.
# This script sets the parameters used when a domain is created using 'xm create'.
# You use a separate script for each domain you want to create, or
# you can set the parameters for the domain on the xm command line.
#=========================================

# Kernel image file.
kernel = "/home/giorgos/xen/vmlinux-3.0.4-domU"

# Optional ramdisk.
ramdisk = "/home/giorgos/xen/initrd.img-3.0.4-domU"

# Initial memory allocation (in megabytes) for the new domain
memory = 128

# A name for your domain. All domains must have different names.
name = "domu1"

# Define network interfaces.
vif = [ '' ]

# Define the disk devices you want the domain to have access to.
disk = [  ‘file:/home/giorgos/xen/domu1.img,xvda1,w’,
             ‘file:/home/giorgos/xen/swap.img,xvda2,w’ ]

# Set if you want dhcp to allocate the IP address.
#dhcp="dhcp"
# Set root device.
root = "/dev/xvda1 ro"

# Sets runlevel 4.
extra = "4"
#=========================================

You can find additional templates in ‘/etc/xen’ directory. Let’s explain the basic options we use above:
  • kernel: Set this to the path of the domU kernel you compiled for use with Xen.
  • ramdisk: Set this to the path of the initramfs you created for the above domU kernel.
  • memory: Set this to the size of domain’s memory in megabytes.
  • name: Give a unique name to the new domain.
  • vif: Define network interfaces. The syntax of this option is: vif = [ ‘mac=MAC_ADDRESS’, ‘bridge=BRIDGE’ ] where MAC_ADDRESS is a valid MAC address for the new virtual interface and BRIDGE is a valid BRIDGE on dom0. You can also specify only the bridge: vif = [‘’, ‘bridge=BRIDGE’ ] or let the system to choose the defaults: vif = [ ‘’ ]
  • disk: Define the disk devices you want the domain to have access to and what you want them accessible as. Each disk entry is of the form phy:UNAME,DEV,MODE where UNAME is the device, DEV is the device name the domain will see, and MODE is ‘r’ for read-only, ‘w’ for read-write.
  • dhcp: Uncomment the dhcp variable, so that the domain will receive its IP address from a DHCP server.
  • root: Set the root device. The guest will use this device to mount its root file system.
  • extra: Set extra kernel parameters (e.g. runlevels).

We name the above file ‘domu1’. If we would like this guest to start automatically when dom0 boots we can copy it to the directory ‘/etc/auto/’ or just create a link there:

root@dom0$ ln –s /etc/xen/domu1 /etc/xen/auto/domu1

To start the new domU guest we can type:

root@dom0$ xm create –c domu1


The ‘-c’ switch causes xm to turn into the domain’s console after creation. We should see the console boot messages from the new domain appearing in the terminal in which we typed the command, culminating in a login prompt.


No comments:

Post a Comment