Tag Archives: virtualization

CentOS 7.2, with added virt-v2v

CentOS 7.2 is out. New in this release, you can simply install virt-v2v and all the dependencies (including libguestfs-winsupport!) are included*.

* = except for libguestfs-xfs which you might also need for converting RHEL 7 guests.

# yum install virt-v2v
Dependencies Resolved

 Package                         Arch   Version                   Repository
 virt-v2v                        x86_64 1:1.28.1-1.55.el7.centos  base     12 M
Installing for dependencies:
 attr                            x86_64 2.4.46-12.el7             base     66 k
 augeas-libs                     x86_64 1.4.0-2.el7               base    355 k
 boost-system                    x86_64 1.53.0-25.el7             base     39 k
 boost-thread                    x86_64 1.53.0-25.el7             base     57 k
 bridge-utils                    x86_64 1.5-9.el7                 base     32 k
 bzip2                           x86_64 1.0.6-13.el7              base     52 k
 celt051                         x86_64             base     53 k
 cryptsetup                      x86_64 1.6.7-1.el7               base    119 k
 cyrus-sasl                      x86_64 2.1.26-19.2.el7           base     88 k
 cyrus-sasl-md5                  x86_64 2.1.26-19.2.el7           base     56 k
 device-mapper-event             x86_64 7:1.02.107-5.el7          base    167 k
 device-mapper-event-libs        x86_64 7:1.02.107-5.el7          base    169 k
 device-mapper-persistent-data   x86_64 0.5.5-1.el7               base    350 k
 dosfstools                      x86_64 3.0.20-9.el7              base    101 k
 flac-libs                       x86_64 1.3.0-5.el7_1             base    169 k
 fuse                            x86_64 2.9.2-6.el7               base     84 k
 fuse-libs                       x86_64 2.9.2-6.el7               base     93 k
 gdisk                           x86_64 0.8.6-5.el7               base    187 k
 genisoimage                     x86_64 1.1.11-23.el7             base    298 k
 glusterfs                       x86_64 3.7.1-16.el7              base    422 k
 glusterfs-api                   x86_64 3.7.1-16.el7              base     60 k
 glusterfs-client-xlators        x86_64 3.7.1-16.el7              base    732 k
 glusterfs-libs                  x86_64 3.7.1-16.el7              base    321 k
 gnutls-dane                     x86_64 3.3.8-12.el7_1.1          base     32 k
 gnutls-utils                    x86_64 3.3.8-12.el7_1.1          base    228 k
 gperftools-libs                 x86_64 2.4-7.el7                 base    272 k
 gsm                             x86_64 1.0.13-11.el7             base     30 k
 gtk2                            x86_64 2.24.28-8.el7             base    3.4 M
 hexedit                         x86_64 1.2.13-5.el7              base     39 k
 hivex                           x86_64 1.3.10-5.7.el7            base    100 k
 icoutils                        x86_64 0.31.0-3.el7              base     82 k
 ipxe-roms-qemu                  noarch 20130517-7.gitc4bce43.el7 base    559 k
 iscsi-initiator-utils           x86_64          base    418 k
 iscsi-initiator-utils-iscsiuio  x86_64          base     81 k
 ldns                            x86_64 1.6.16-7.el7              base    473 k
 libaio                          x86_64 0.3.109-13.el7            base     24 k
 libasyncns                      x86_64 0.8-7.el7                 base     26 k
 libcgroup                       x86_64 0.41-8.el7                base     64 k
 libconfig                       x86_64 1.4.9-5.el7               base     59 k
 libguestfs                      x86_64 1:1.28.1-1.55.el7.centos  base    1.7 M
 libguestfs-tools-c              x86_64 1:1.28.1-1.55.el7.centos  base    2.2 M
 libguestfs-winsupport           x86_64 7.2-1.el7                 base    2.1 M
 libibverbs                      x86_64 1.1.8-8.el7               base     56 k
 libicu                          x86_64 50.1.2-15.el7             base    6.9 M
 libiscsi                        x86_64 1.9.0-6.el7               base     60 k
 libogg                          x86_64 2:1.3.0-7.el7             base     24 k
 libosinfo                       x86_64 0.2.12-3.el7              base    256 k
 librados2                       x86_64 1:0.80.7-3.el7            base    1.5 M
 librbd1                         x86_64 1:0.80.7-3.el7            base    350 k
 librdmacm                       x86_64 1.0.21-1.el7              base     64 k
 libreport-filesystem            x86_64 2.1.11-32.el7.centos      base     37 k
 libseccomp                      x86_64 2.2.1-1.el7               base     49 k
 libsndfile                      x86_64 1.0.25-10.el7             base    149 k
 libunwind                       x86_64 1.1-5.el7                 base     56 k
 libusal                         x86_64 1.1.11-23.el7             base    135 k
 libvirt-client                  x86_64 1.2.17-13.el7_2.2         updates 4.3 M
 libvirt-daemon                  x86_64 1.2.17-13.el7_2.2         updates 584 k
 libvirt-daemon-driver-interface x86_64 1.2.17-13.el7_2.2         updates 161 k
 libvirt-daemon-driver-network   x86_64 1.2.17-13.el7_2.2         updates 301 k
 libvirt-daemon-driver-nodedev   x86_64 1.2.17-13.el7_2.2         updates 160 k
 libvirt-daemon-driver-nwfilter  x86_64 1.2.17-13.el7_2.2         updates 184 k
 libvirt-daemon-driver-qemu      x86_64 1.2.17-13.el7_2.2         updates 569 k
 libvirt-daemon-driver-secret    x86_64 1.2.17-13.el7_2.2         updates 154 k
 libvirt-daemon-driver-storage   x86_64 1.2.17-13.el7_2.2         updates 327 k
 libvirt-daemon-kvm              x86_64 1.2.17-13.el7_2.2         updates 117 k
 libvorbis                       x86_64 1:1.3.3-8.el7             base    204 k
 libxslt                         x86_64 1.1.28-5.el7              base    242 k
 lsof                            x86_64 4.87-4.el7                base    331 k
 lvm2                            x86_64 7:2.02.130-5.el7          base    1.0 M
 lvm2-libs                       x86_64 7:2.02.130-5.el7          base    872 k
 lzop                            x86_64 1.03-10.el7               base     54 k
 mailcap                         noarch 2.1.41-2.el7              base     31 k
 make                            x86_64 1:3.82-21.el7             base    420 k
 mdadm                           x86_64 3.3.2-7.el7               base    393 k
 mtools                          x86_64 4.0.18-5.el7              base    203 k
 netcf-libs                      x86_64 0.2.8-1.el7               base     69 k
 netpbm                          x86_64 10.61.02-9.el7            base    180 k
 netpbm-progs                    x86_64 10.61.02-9.el7            base    1.9 M
 nmap-ncat                       x86_64 2:6.40-7.el7              base    201 k
 numad                           x86_64 0.5-14.20140620git.el7    base     34 k
 openssl                         x86_64 1:1.0.1e-51.el7_2.1       updates 711 k
 perl-Business-ISBN              noarch 2.06-2.el7                base     25 k
 perl-Business-ISBN-Data         noarch 20120719.001-2.el7        base     24 k
 perl-Compress-Raw-Bzip2         x86_64 2.061-3.el7               base     32 k
 perl-Compress-Raw-Zlib          x86_64 1:2.061-4.el7             base     57 k
 perl-Digest                     noarch 1.17-245.el7              base     23 k
 perl-Digest-MD5                 x86_64 2.52-3.el7                base     30 k
 perl-Encode-Locale              noarch 1.03-5.el7                base     16 k
 perl-File-Listing               noarch 6.04-7.el7                base     13 k
 perl-HTML-Parser                x86_64 3.71-4.el7                base    115 k
 perl-HTML-Tagset                noarch 3.20-15.el7               base     18 k
 perl-HTTP-Cookies               noarch 6.01-5.el7                base     26 k
 perl-HTTP-Daemon                noarch 6.01-5.el7                base     20 k
 perl-HTTP-Date                  noarch 6.02-8.el7                base     14 k
 perl-HTTP-Message               noarch 6.06-6.el7                base     82 k
 perl-HTTP-Negotiate             noarch 6.01-5.el7                base     17 k
 perl-IO-Compress                noarch 2.061-2.el7               base    260 k
 perl-IO-HTML                    noarch 1.00-2.el7                base     23 k
 perl-IO-Socket-IP               noarch 0.21-4.el7                base     35 k
 perl-IO-Socket-SSL              noarch 1.94-3.el7                base    113 k
 perl-LWP-MediaTypes             noarch 6.02-2.el7                base     24 k
 perl-Net-HTTP                   noarch 6.06-2.el7                base     29 k
 perl-Net-LibIDN                 x86_64 0.12-15.el7               base     28 k
 perl-Net-SSLeay                 x86_64 1.55-3.el7                base    285 k
 perl-TimeDate                   noarch 1:2.30-2.el7              base     52 k
 perl-URI                        noarch 1.60-9.el7                base    106 k
 perl-WWW-RobotRules             noarch 6.02-5.el7                base     18 k
 perl-hivex                      x86_64 1.3.10-5.7.el7            base     41 k
 perl-libwww-perl                noarch 6.05-2.el7                base    205 k
 pulseaudio-libs                 x86_64 6.0-7.el7                 base    576 k
 python-chardet                  noarch 2.2.1-1.el7_1             base    227 k
 python-kitchen                  noarch 1.1.1-5.el7               base    267 k
 qemu-img                        x86_64 10:1.5.3-105.el7_2.1      updates 657 k
 qemu-kvm                        x86_64 10:1.5.3-105.el7_2.1      updates 1.8 M
 qemu-kvm-common                 x86_64 10:1.5.3-105.el7_2.1      updates 390 k
 radvd                           x86_64 1.9.2-9.el7               base     85 k
 rsyslog-mmjsonparse             x86_64 7.4.7-12.el7              base     29 k
 scrub                           x86_64 2.5.2-5.el7               base     40 k
 seabios-bin                     noarch 1.7.5-11.el7              base     74 k
 seavgabios-bin                  noarch 1.7.5-11.el7              base     32 k
 sgabios-bin                     noarch 1:0.20110622svn-4.el7     base    7.1 k
 spice-server                    x86_64 0.12.4-15.el7             base    380 k
 supermin5                       x86_64 5.1.10-1.2.el7            base    574 k
 syslinux                        x86_64 4.05-12.el7               base    990 k
 syslinux-extlinux               x86_64 4.05-12.el7               base    363 k
 unbound-libs                    x86_64 1.4.20-26.el7             base    296 k
 unzip                           x86_64 6.0-15.el7                base    166 k
 usbredir                        x86_64 0.6-7.el7                 base     44 k
 yajl                            x86_64 2.0.4-4.el7               base     39 k
 yum-utils                       noarch 1.1.31-34.el7             base    113 k

Transaction Summary
Install  1 Package (+130 Dependent packages)

Total download size: 59 M
Installed size: 172 M

Leave a comment

Filed under Uncategorized

Inspection, now with added Prolog

You can give libguestfs an unknown disk image, and it tries to guess what’s on it, in terms of operating systems, Linux distro, Windows drive letter mappings and so on, a process that we call inspection. This is an important part of many of the virt tools, because when you type a command like

$ virt-cat -a linux.img /var/log/messages

how is virt-cat to know that on this particular disk image the sysadmin put /var on a separate partition? Because, inspection.

Given that inspection is such an important part of many tools, and vital for standalone programs like virt-inspector you might wonder how it works.

The answer, right now, is 6000+ lines of hairy, intricate C code, which is difficult to maintain and a source of hard to fix bugs and hard to implement feature requests.

$ wc -l src/inspect*.c
   823 src/inspect-apps.c
   725 src/inspect.c
   777 src/inspect-fs.c
   543 src/inspect-fs-cd.c
  2092 src/inspect-fs-unix.c
   704 src/inspect-fs-windows.c
   600 src/inspect-icon.c
  6264 total

How can we make this better?

Getting back to basics, inspection is really a lot of heuristics. Things like:

  • If this filesystem contains a file /etc/fstab then it could be a Linux root filesystem. And:
  • If this thing we think is a Linux root filesystem contains /etc/debian_version then it could be a Debian root filesystem.

These heuristics can be expressed in a logic language inspired by Prolog:

LinuxRoot(fs) :-
    File(fs, "/etc/fstab").
DebianRoot(fs) :-
    File(fs, "/etc/debian_version").

What we’re doing here is collecting a set of facts (Prolog calls them “compound terms”), like:

File("/dev/sda1", "/etc/fstab").
File("/dev/sda1", "/etc/debian_version").

and deriving new facts using the rules:


(I should say at this point that I’m simplifying things a bit. If you want to get a flavour of what the inspection rules might finally look like, then take a look at this file.)

So far I have written a compiler that compiles inspection rules into fairly efficient C code (and hence to binaries), using a forward chaining strategy. It has some nice features like transparently embedding C code into the rules, allowing you to do more complicated operations directly in C:

Distro(fs, distro) :-
    LinuxRootWithOSRelease(fs), /* has /etc/os-release */
      int r;
      CLEANUP_FREE char *distro = NULL;
      if ((r = get_distro_from_os_release (fs, &distro))
           <= 0)
        return r;
      set_distro (distro);
      return 0;


BlockDevice(dev) :-
      CLEANUP_FREE_STRING_LIST char **devs =
        get_all_block_devices ();
      if (devs == NULL) return -1;
      for (size_t i = 0; devs[i] != NULL; ++i)
        set_dev (devs[i]);
      return 0;

My inspection rules run to < 500 lines of code so far, although it’s hard to compare that to the current code because (a) the inspection rules will likely double or triple in size once they are able to do everything that the current code can do, and (b) there’s a lot of supporting runtime code like get_all_block_devices above.

Nevertheless I hope the new rules system will be faster, more supportable and extensible, and easier to understand than the current code. It will also be 100% backwards compatible with existing libguestfs users (since we never break compatibility).

You can follow development in this branch on github.

Update: Hacker News discussion of this article.

Leave a comment

Filed under Uncategorized

Linux Kernel Library backend for libguestfs

For a very long time I’ve been keeping an eye on rump kernels. These are a fancy way of saying ordinary kernel code which has been ported or altered in some way so you can link it to userspace programs, usually as a library. There have been claims that rump kernels make libguestfs obsolete, which is a load of nonsense for reasons I’ll talk about in a minute. But rump kernels are interesting and finally I’ve been able to add a rump kernel library to libguestfs.

The first time I encountered rump kernels was in 2010 with Prof. Renzo Davoli’s virtualsquare View-OS project. The more recent rump kernel project was based on NetBSD. Since NetBSD doesn’t use Linux drivers, but reimplementations, it was never very interesting. We couldn’t have included it in RHEL, and it would be only a matter of time before someone found an important feature or data-corrupting difference between the real ext2/3 driver from Linux and the reimplementation in BSD. Last I looked, NetBSD didn’t even support ext4. The choice of NetBSD made it a non-starter for us.

libos arrived earlier this year and, being based on Linux, was a lot more interesting, but their aim was only the Linux network stack so it wasn’t directly relevant to libguestfs, which is only concerned with disk and filesystem access.

However last week Richard Weinberger (Linux UML maintainer) CC’d me on a much more interesting project. LKL (Linux Kernel Library) is a relatively small patchset on top of Linux that turns Linux into a library. Quite literally you just link your program with -llkl and you can start a Linux kernel and make Linux system calls. A few example programs can be found here.

Today I wrote a work-in-progress LKL backend for libguestfs. [Note for those keen to jump in and use it, it doesn’t do very much at the moment. There is a small to-do list. But it’s only a few hours more work to have it as a useful backend for libguestfs.]

What could an LKL-enabled libguestfs do? Well it could open a raw disk image that contains only a Linux filesystem, or possibly a partitioned disk image with a Linux filesystem. And it can do that very quickly – in about 0.03 seconds in my tests (compared to 2.5 seconds for the qemu-based libguestfs).

There are a long list of things that LKL cannot do however. It cannot open anything containing LVM (because LVM requires userspace tools, that would all have to be modified to use liblkl, and there would be all kinds of synchronization problems between the LVM-linked liblkl kernel and the libguestfs-linked kernel). It cannot run anything that requires a userspace tool. That includes btrfs, ntfs-3g (FUSE based), some MD devices, encrypted disks, dm-thinp and Windows Dynamic Disks.

It cannot create new LVs or filesystems or any of the other disk structures that libguestfs can create.

It cannot open disk formats like qcow2 and vmdk. The qcow2 code in particular is very specific to qemu, and cannot possibly be ported to the kernel.

It cannot open remote devices like Ceph, Gluster, https, ssh or ftp (although there is an nbd client in the kernel, so one day that may be possible).

It cannot run commands in the context of the guest.

It’s also less secure than libguestfs with the qemu backend, because it doesn’t isolate your host from exploits in the guest or filesystem using virtualization and sVirt.

All of those things can be done by libguestfs today, but may never be possible (or only in limited cases) with LKL.

But within the limits of what LKL can do, it should become an excellent choice (assuming it gets upstream). Adding an LKL backend to libguestfs brings to the table the large, but clean and well-tested libguestfs API and the language bindings and virt tools, so libguestfs gives you the best of both worlds: the performance of LKL by using that backend, or the massive feature set of libguestfs by switching over to the qemu or libvirt backend, which for most programs is a single line code change.


Filed under Uncategorized

Tip: guestmount (FUSE mount) every filesystem in a disk image

Maxim asks an interesting question which is if you’ve got a disk image, how do you mount every filesystem onto your host. Like this:

$ ./fs-mount.pl rhel-5.11.img /tmp/fs &
$ cd /tmp/fs
/tmp/fs$ ls
/tmp/fs$ cd dev
/tmp/fs/dev$ ls
sda1  sda2  sda3
/tmp/fs/dev$ cd sda2
/tmp/fs/dev/sda2$ ls
bin   dev  home  lib64       media  mnt  proc  sbin     srv  tmp  var
boot  etc  lib   lost+found  misc   opt  root  selinux  sys  usr
$ cd /tmp
$ guestunmount /tmp/fs

The answer is this surprisingly short Perl script.


use warnings;
use strict;

use Sys::Guestfs;

die "usage: $0 disk1 [disk2 ...] mountpoint\n" if @ARGV <= 1;

my $mp = pop;

my $g = Sys::Guestfs->new ();
foreach (@ARGV) {
    $g->add_drive ($_);
$g->launch ();

# Examine the filesystems.
my %fses = $g->list_filesystems ();

# Create the mountpoint directories (in the libguestfs namespace)
# and mount the filesystems on them.
foreach my $fs (sort keys %fses) {
    # mkmountpoint is really the same as mkdir.  Unfortunately there
    # is no 'mkdir -p' equivalent, so we have to do this instead:
    my @components = split ("/", $fs);
    for (my $i = 1; $i < @components; ++$i) {
        my $dir = "/" . join ("/", @components[1 .. $i]);
        eval { $g->mkmountpoint ($dir) }

    # Don't fail if the filesystem can't be mounted, eg. it's swap.
    eval { $g->mount ($fs, $fs) }

# Export the filesystem on the host.
$g->mount_local ($mp);
$g->mount_local_run ();

# Close nicely since we mounted everything writable.
$g->shutdown ();
$g->close ();

Leave a comment

Filed under Uncategorized

Virt-builder Fedora 23 image

Fedora 23 was released today. Get it through virt-builder in just two simple commands:

$ virt-builder fedora-23 \
    --root-password password:123456 \
    --size 20G
$ qemu-system-x86_64 -drive file=fedora-23,if=virtio \
    -m 2048



Filed under Uncategorized

virt-v2v, libguestfs and qemu remote drivers in RHEL 7

Upstream qemu can access a variety of remote disks, like NBD and Ceph. This feature is exposed in libguestfs so you can easily mount remote storage.

However in RHEL 7 many of these drivers are disabled, because they’re not stable enough to support. I was asked exactly how this works, and this post is my answer — as it’s not as simple as it sounds.

There are (at least) five separate layers involved:

qemu code What block drivers are compiled into qemu, and which ones are compiled out completely.
qemu block driver r/o whitelist A whitelist of drivers that qemu allows you to use read-only.
qemu block driver r/w whitelist A whitelist of drivers that qemu allows you to use for read and write.
libvirt What libvirt enables (not covered in this discussion).
libguestfs In RHEL we patch out some qemu remote storage types using a custom patch.

Starting at the bottom of the stack, in RHEL we use ./configure --disable-* flags to disable a few features: Ceph is disabled on !x86_64 and 9pfs is disabled everywhere. This means the qemu binary won’t even contain code for those features.

If you run qemu-img --help in RHEL 7, you’ll see the drivers which are compiled into the binary:

$ rpm -qf /usr/bin/qemu-img
$ qemu-img --help
Supported formats: vvfat vpc vmdk vhdx vdi ssh
sheepdog rbd raw host_cdrom host_floppy host_device
file qed qcow2 qcow parallels nbd iscsi gluster dmg
tftp ftps ftp https http cloop bochs blkverify blkdebug

Although you can use all of those in qemu-img, not all of those drivers work in qemu (the hypervisor). qemu implements two whitelists. The RHEL 7 qemu-kvm.spec file looks like this:

./configure [...]
    --block-drv-rw-whitelist=qcow2,raw,file,host_device,blkdebug,nbd,iscsi,gluster,rbd \

The --block-drv-rw-whitelist parameter configures the drivers for which full read and write access is permitted and supported in RHEL 7. It’s quite a short list!

Even shorter is the --block-drv-ro-whitelist parameter — drivers for which only read-only access is allowed. You can’t use qemu to open these files for write. You can use these as (read-only) backing files, but you can’t commit to those backing files.

In practice what happens is you get an error if you try to use non-whitelisted block drivers:

$ /usr/libexec/qemu-kvm -drive file=test.vpc
qemu-kvm: -drive file=test.vpc: could not open disk image
test.vpc: Driver 'vpc' can only be used for read-only devices
$ /usr/libexec/qemu-kvm -drive file=test.qcow1
qemu-kvm: -drive file=test.qcow1: could not open disk
image test.qcow1: Driver 'qcow' is not whitelisted

Note that’s a qcow v1 (ancient format) file, not modern qcow2.

Side note: Only qemu (the hypervisor) enforces the whitelist. Tools like qemu-img ignore it.

At the top of the stack, libguestfs has a patch which removes support for many remote protocols. Currently (RHEL 7.2/7.3) we disable: ftp, ftps, http, https, tftp, gluster, iscsi, sheepdog, ssh. That leaves only: local file, rbd (Ceph) and NBD enabled.

virt-v2v uses a mixture of libguestfs and qemu-img to convert VMware and Xen guests to run on KVM. To access VMware we need to use https and to access Xen we use ssh. Both of those drivers are disabled in libguestfs, and only available read-only in the qemu whitelist. However that’s sufficient for virt-v2v, since all it does is add the https or ssh driver as a read-only backing file. (If you are interested in finding out more about how virt-v2v works, then I gave a talk about it at the KVM Forum which is available online).

In summary — it’s complicated.


Filed under Uncategorized

Importing KVM guests to oVirt or RHEV

One of the tools I maintain is virt-v2v. It’s a program to import guests from foreign hypervisors like VMware and Xen, to KVM. It only does conversions to KVM, not the other way. And a feature I intentionally removed in RHEL 7 was importing KVM → KVM.

Why would you want to “import” KVM → KVM? Well, no reason actually. In fact it’s one of those really bad ideas for V2V. However it used to have a useful purpose: oVirt/RHEV can’t import a plain disk image, but virt-v2v knows how to import things to oVirt, so people used virt-v2v as backdoor for this missing feature.

Removing this virt-v2v feature has caused a lot of moaning, but I’m adamant it’s a very bad idea to use virt-v2v as a way to import disk images. Virt-v2v does all sorts of complex filesystem and Windows Registry manipulations, which you don’t want and don’t need if your guest already runs on KVM. Worst case, you could even end up breaking your guest.

However I have now written a replacement script that does the job: http://git.annexia.org/?p=import-to-ovirt.git

If your guest is a disk image that already runs on KVM, then you can use this script to import the guest. You’ll need to clone the git repo, read the README file, and then read the tool’s man page. It’s pretty straightforward.

There are a few shortcomings with this script to be aware of:

  1. The guest must have virtio drivers installed already, and must be able to boot off virtio-blk (default) or virtio-scsi. For virtio-scsi, you’ll need to flip the checkbox in the ‘Advanced’ section of the guest parameters in the oVirt UI.
  2. It should be possible to import guests that don’t have virtio drivers installed, but can use IDE. This is a missing feature (patches welcome).
  3. No network card is added to the guest, so it probably won’t have network when it boots. It should be possible to add a network card through the UI, but really this is something that needs to be fixed in the script (patches welcome).
  4. It doesn’t handle all the random packaging formats that guests come in, like OVA. You’ll have to extract these first and import just the disk image.
  5. It’s not in any way supported or endorsed by Red Hat.


Filed under Uncategorized