Create an Ubuntu/Xen Virtual Machine

Create an Ubuntu/Xen Virtual Machine

Install Ubuntu into a virtual-machine image and boot it using Xen.

The previous hack showed you how to set up a Xen server [Hack #90]. To make use of your newly Xen-enabled host, you need to create some domU virtual machines to run on it. In this hack, you'll set up a basic Dapper virtual machine (VM).

Prepare VM Filesystems

The VM needs both root and swap filesystems. In a production environment, these would most likely be stored on some form of shared-access filesystem, such as a SAN or similar, but, to keep things simple, for now you should create them as loopback disk images on the local disk. So start by making a couple of directories to store them in:

$ sudo mkdir -p /vm/vm_base
$ sudo mkdir /vm/images

Root filesystem

The root filesystem will be a 2 GB image, so first use dd to create a disk image and then use mkfs to set up a filesystem in it. 2 GB should be enough space for initial testing, but if you want to vary the size, just change the count argument, which, when multiplied by the bs (block size) argument, determines the total disk size.

While mkfs is running, it will complain that vm_base.img is not a special block device and ask if you want to proceed anyway. Say y:

$ sudo dd if=/dev/zero of=/vm/images/vm_base.img bs=1024k count=2000
$ sudo mkfs.ext3 /vm/images/vm_base.img

Swap filesystem

You can create a 200 MB swap image in a similar way:

$ sudo dd if=/dev/zero of=/vm/images/vm_base-swap.img bs=1024k count=200
$ sudo mkswap /vm/images/vm_base-swap.img

Mount the root filesystem image

Mount the root filesystem image as a loopback device, allowing it to appear as a separate volume, even though it's only an image stored on the local disk:

$ sudo mount -o loop /vm/images/vm_base.img /vm/vm_base

Install Ubuntu into the Root Filesystem

Now you have the equivalent of a blank disk just waiting to have Linux installed on it. The system you install will become the domU virtual machine that is booted by Xen. Installing into a different volume can be a tricky exercise, but luckily Debian provides an extremely useful tool called debootstrap that takes care of all the hard work for you. First, grab debootstrap:

$ sudo apt-get install debootstrap

Then, use it to build a new Breezy base system into the root filesystem. The installation process has been radically overhauled for Dapper, so for now it's easier to install Breezy first and dist-upgrade to Dapper afterwards:

$ sudo debootstrap --arch i386 breezy /vm/vm_base/ \\

If you're wondering why you're installing Breezy, it's because base-config no longer exists in Dapper (the install process has been largely rewritten into a single-stage system, and we haven't yet figured out exactly how the initial configuration takes place). A simple workaround is to do a Breezy bootstrap and then update it to Dapper.

The preceding example specifies the architecture as i386 (32-bit Intel). You may need to specify an alternative, such as powerpc or amd64, depending on your system architecture.

Running debootstrap can take quite a long time because it needs to download all the packages, and if you need to go through this process several times, you may want to set up a local package cache [Hack #61] or replace the mirror address with a reference to file:///media/cdrom and use an Ubuntu install CD. If you have a local apt-cacher running already, you can include the cache address like so:

$ sudo debootstrap --arch i386 breezy /vm/vm_base/  \\

Configure the Virtual Machine

At this point, you have a basic Ubuntu install, but it's totally unconfigured. If your host machine is running Ubuntu, you can save yourself some effort by copying in your /etc/apt/sources.list file:

$ sudo cp -a /etc/apt/sources.list /vm/vm_base/etc/apt/

Then edit /vm/vm_base/etc/apt/sources.list and change any references from dapper to breezy, since you are starting with a base Breezy install.

Now edit /vm/vm_base/etc/network/interfaces and set up the loopback address and a virtual eth0 interface. You will need to adjust these values to suit your own network. The address allocated to eth0 needs to be one that's not in use yet:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static

Edit /vm/vm_base/etc/hostname and set it to vm01.

Edit /vm/vm_base/etc/hosts and put in some basic entries: localhost.localdomain   localhost  vm01

# The following lines are desirable for IPv6 capable hosts
::1    ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

The VM also needs to be given a filesystem configuration. Note that this is not necessarily the same as the configuration of the host, and the volume names have nothing to do with your actual local disk. The volumes that the VM will see when it starts up are virtual volumes that will be determined by the Xen configuration, so for now just edit /vm/vm_base/etc/fstab and set it up like this:

/dev/hda1       /           ext3    defaults  1   2
/dev/hda5       none        swap    sw        0   0
/dev/pts        devpts      gid=5,mode=620    0   0
none            /dev/shm    tmpfs   defaults  0   0

Run Setup Within the VM Image

Use chroot to switch into the root of the VM filesystem:

$ sudo chroot /vm/vm_base

From now on, everything you do will be within the context of the VM, so you can manually invoke the tools that are normally run in the last stages of the regular Ubuntu installer. Make sure the universe repository [Hack #60] is enabled in sources.list (Breezy has a universe repository as well), and tell apt to update the package list and then set up locales:

# apt-get update
# apt-get install localeconf
# dpkg-reconfigure localeconf

You will then be asked a series of questions when the localeconf package is installed and then additional questions when you reconfigure it:

Manage locale configuration files with debconf?

Answer Yes.

Replace existing locale configuration files?

Answer Yes.

Default system locale

Select the applicable default, such as en_US ISO-8859-1.

Environment settings that should override the default locale

Don't select any options; just select OK to proceed.

At this point, many of the standard devices don't exist and locale generation won't be working, so mount the proc virtual filesystem and create the default devices:

# mount -t proc proc /proc
# cd /dev
# ./MAKEDEV generic

When MAKEDEV finishes, run base-config to bootstrap the system:

# base-config

base-config will ask you all the usual questions that you normally see when running the Ubuntu Breezy installer, so answer all the questions as normal, with one exception: when asked to specify an access method for apt, select "edit sources list by hand," which will then put you into the vim editor with the sources.list file open. Since it's already set up correctly, just type ZZ to save and exit vim, and let apt run through the process of verifying the repositories and installing all the base packages.

Once the Breezy installer has finished, edit the /etc/apt/sources.list again, and this time change all references from breezy to dapper. Then update the package list again and dist-upgrade to Dapper:

# apt-get update
# apt-get dist-upgrade

You now have a basic Dapper install inside the loopback filesystem, so finally you can exit the chroot:

# exit

Get Ready to Crank Up the VM

The domU virtual machine will be booted using the Xen kernel installed on the dom0 host, so copy the kernel modules into its filesystem, disable TLS, and unmount the image:

$ sudo cp -dpR /lib/modules/ /vm/vm_base/lib/modules/
$ sudo mv /vm/vm_base/lib/tls /vm/vm_base/lib/tls.disabled
$ sudo umount /vm/vm_base

It's quite likely that umount will complain that the device is busy even though nothing is using it anymore, so ignore the warning.

You now have one complete, functional domU virtual machine, but it's quite likely that you will ultimately want to create a few of them, so rather than boot the image you just created, it's best to treat it as a template and make copies of it to play with.

Copy the disk image to create a new VM:

$ sudo cp -a /vm/images/vm_base.img /vm/images/vm01.img
$ sudo cp -a /vm/images/vm_base-swap.img /vm/images/vm01-swap.img

Configure the VM in Xen

You need to create a configuration file for each domU virtual machine so that Xen will know how to boot it. Start by copying the sample configuration file into place:

$ sudo cp /etc/xen/xmexample1 /etc/xen/vm01.conf

The sample config file is very well commented, and most of the defaults are fine as a starting point, so open /etc/xen/vm01.conf in your favorite editor and start working through it. Highlights to pay attention to include:


The kernel parameter specifies the path to the domU kernel in the host system. Note that the dom0 and domU kernels are almost identical, so you can use the dom0 kernel image to boot the domU guest if you prefer. The domU kernel is basically just the dom0 kernel, but with most of the modules stripped out because networking and many other services are supplied by the dom0 host and the virtual machine doesn't need to manage such things itself. This makes the domU kernel about 30 percent smaller than the dom0 kernel.


The dom0 host preallocates RAM to each virtual machine using the memory parameter in the config file, so set it to some sensible value to start with, such as 128. You need to make sure you leave enough memory for the dom0 host after all the domU guests have claimed their allocated address space; so if, for example, you have 512 MB RAM in the host, you could run three guests with 128 MB allocated each and still have 128 MB available for the host.


Each domU host needs a unique name that will be used to identify it. Set it to vm01 for now.

Virtual network interfaces

You can specify virtual network interface settings directly in the config file or leave a blank value to have the guest specify its own settings. For now, just leave this blank because you configured a virtual eth0 interface earlier: vif = [ '' ].


The dom0 host exposes real filesystems to the domU guest as if they were real filesystems, so the disk parameter allows you to specify what will be seen by the guest. For now, you should use the loopback disk images that were created earlier, so if you set up the guest's /etc/fstab in the way suggested earlier, you should set the disk parameter to:

disk = [ 'file:/vm/images/vm01.img,hda1,w','file:/vm/images/vm01-swap. 
img,hda5,w' ]

The disk images don't have to be mounted: the file argument tells Xen that it has to treat the target as a loopback disk image, and takes care of everything for you.

Boot Your Virtual Machine

Virtual machines are managed using xm, the Xen Manager, which allows you to boot, shut down, list, and migrate them to other physical hosts. Start up your newly created VM:

$ sudo xm create -c /etc/xen/vm01.conf

If all goes well, you will see Linux run through its boot sequence all the way up to a login prompt into your virtual machine. Log in as the user you created during the setup process and poke around. Try a few things like:

$ cat /proc/cpuinfo
$ cat /proc/meminfo
$ uname -r

It should look exactly as if you're in a totally separate machine, and the network interface will be functional, with packets bridged to the physical Ethernet through the kernel in the dom0 host so you can even apt-get install some packages or do whatever else you need to do to set up the virtual machine just the way you want it.

While your virtual machine is still running, open another terminal session onto the dom0 host and try running:

$ sudo xm list

to see a list of currently running guests. You can also view a dynamically updated list of hosts along with resource utilization:

$ sudo xm top

If you want to nicely bring down a VM without logging in to it, you can do so through xm:

$ sudo xm shutdown vm01

When you've finished playing around in your new VM, you can either shut it down from the dom0 host using xm or shut it down from inside just like any other machine using sudo shutdown.

Create Additional Guests

To create additional guests, you need to repeat a number of the previous steps. Copy the templates again:

$ sudo cp -a /vm/images/vm_base.img /vm/images/vm02.img
$ sudo cp -a /vm/images/vm_base-swap.img /vm/images/vm02-swap.img

Mount the base image:

$ sudo mount -o loop /vm/images/vm02.img /vm/vm_base

Edit /vm/vm_base/etc/network/interfaces, /vm/vm_base/etc/network/hostname, and /vm/vm_base/etc/network/hosts to set appropriate values for the hostname and IP address.

Unmount the base image:

$ sudo umount /vm/vm_base

Copy the Xen configuration:

$ sudo cp /etc/xen/vm01.conf /etc/xen/vm02.conf

Then edit it to change the paths to the disk images and the machine name, and you're ready to start up a second VM.

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows