virt-v2v: better living through new technology

If you ever used the old version of virt-v2v, our software that converts guests to run on KVM, then you probably found it slow, but worse still it was slow and could fail at the end of the conversion (after possibly an hour or more). No one liked that, least of all the developers and support people who had to help people use it.

A V2V conversion is intrinsically going to take a long time, because it always involves copying huge disk images around. These can be gigabytes or even terabytes in size.

My main aim with the rewrite was to do all the work up front (and if the conversion is going to fail, then fail early), and leave the huge copy to the last step. The second aim was to work much harder to minimize the amount of data that we need to copy, so the copy is quicker. I achieved both of these aims using a lot of new technology that we developed for qemu in RHEL 7.

Virt-v2v works (now) by putting an overlay on top of the source disk. This overlay protects the source disk from being modified. All the writes done to the source disk during conversion (eg. modifying config files and adding device drivers) are saved into the overlay. Then we qemu-img convert the overlay to the final target. Although this sounds simple and possibly obvious, none of this could have been done when we wrote old virt-v2v. It is possible now because:

  • qcow2 overlays can now have virtual backing files that come from HTTPS or SSH sources. This allows us to place the overlay on top of (eg) a VMware vCenter Server source without having to copy the whole disk from the source first.
  • qcow2 overlays can perform copy-on-read. This means you only need to read each block of data from the source once, and then it is cached in the overlay, making things much faster.
  • qemu now has excellent discard and trim support. To minimize the amount of data that we copy, we first fstrim the filesystems. This causes the overlay to remember which bits of the filesystem are used and only copy those bits.
  • I added support for fstrim to ntfs-3g so this works for Windows guests too.
  • libguestfs has support for remote storage, cachemode, discard, copy-on-read and more, meaning we can use all these features in virt-v2v.
  • We use OCaml — not C, and not type-unsafe languages — to ensure that the compiler is helping us to find bugs in the code that we write, and also to ensure that we end up with an optimized, standalone binary that requires no runtime support/interpreters and can be shipped everywhere.

3 Comments

Filed under Uncategorized

New in libguestfs 1.27.34 – virt-v2v and virt-p2v

There haven’t been too many updates around here for a while, and that’s for a very good reason: I’ve been “heads down” writing the new versions of virt-v2v and virt-p2v, our tools for converting VMware and Xen virtual machines, or physical machines, to run on KVM.

The new virt-v2v [manual page] can slurp in a guest from a local disk image, local Xen, VMware vCenter, or (soon) an OVA file — convert it to run on KVM — and write it out to RHEV-M, OpenStack Glance, local libvirt or as a plain disk image.

It’s easy to use too. Unlike the old virt-v2v there are no hairy configuration files to edit or complicated preparations. You simply do:

$ virt-v2v -i disk xen_disk.img -o local -os /tmp

That command (which doesn’t need root, naturally) takes the Xen disk image, which could be any supported Windows or Enterprise Linux distro, converts it to run on KVM (eg. installing virtio drivers, adjusting dozens of configuration files), and writes it out to /tmp.

To connect to a VMware vCenter server, change the -i options to:

$ virt-v2v -ic vpx://vcenter/Datacenter/esxi "esx guest name" [-o ...]

To output the converted disk image to OpenStack glance, change the -o options to:

$ virt-v2v [-i ...] -o glance [-on glance_image_name]

Coming up: The new technology we’ve used to make virt-v2v much faster.

1 Comment

Filed under Uncategorized

ARM Server Update on Fedora and RHEL

A talk by Jon Masters:

All the Fedora Flock 2014 talks are here: https://www.youtube.com/channel/UCQIXiF6fxPCtHw_XwHFq6nA

2 Comments

Filed under Uncategorized

Use libguestfs to mount arbitrary disk images with FUSE

You can use guestmount to mount most virtual machine disk images on the host using FUSE.

However guestmount doesn’t work well for disk images that just consist of a pile of partitions.

But libguestfs at the API level has no problem, and we can write a script using the mount-local API to expose it, like this one:


#!/usr/bin/perl -w

use strict;
use Sys::Guestfs;

if (@ARGV != 2) {
    print "$0 disk-image mount-point\n";
    exit 1
}

die "$ARGV[1] must be a directory (mount point)" unless -d $ARGV[1];

print "Examining the disk $ARGV[0].\n";
print "Please wait a moment ...\n";
my $g = Sys::Guestfs->new ();
$g->add_drive ($ARGV[0]);
$g->launch ();

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

my $mounts = 0;

# Mount them on mountpoints in the libguestfs namespace.
foreach my $dev (sort keys %fses) {
    my $t = $fses{$dev};
    if ($t eq "unknown" || $t eq "swap") {
        print "ignored $t partition $dev\n";
    }
    else {
        # Make a mountpoint.
        my $mp = $dev;
        $mp =~ s{^/}{};
        $mp =~ s{/}{_}g;
        $g->mkmountpoint ("/" . $mp);
        eval { $g->mount ($dev, "/" . $mp); };
        if ($@) {
            print "ignored unmountable partition $dev\n";
        } else {
            print "mounted $dev on $ARGV[1]/$mp\n";
            $mounts++;
        }
    }
}

if ($mounts == 0) {
    print "No mountable filesystems were found in this disk image.\n";
    print "Suggest using `guestfish' or `virt-filesystems' on the disk image.\n";
    exit 1;
}

# Now start the FUSE service.
$g->mount_local ($ARGV[1]);

print "\n";
print "Mounted on $ARGV[1] ...\n";
print "Run the following command to end the FUSE service:\n";
print "    guestunmount $ARGV[1]\n";

$g->mount_local_run ();

# Unmounted ...
$g->shutdown ();
$g->close ();

When you run this you will see each partition, logical volume or other mountable filesystem from the disk image exposed as a separate directory under the mountpoint, like this:

$ ls
dev_VG_LV1            # this is /dev/VG/LV1
$ cd dev_VG_LV1
$ ls -ltr
total 12
drwx------. 2 root root 12288 Aug  8 18:15 lost+found
-rw-r--r--. 1 root root     0 Aug  8 18:34 foo
-rw-r--r--. 1 root root     0 Aug  8 18:35 hello

Leave a comment

Filed under Uncategorized

libguestfs now works on 64 bit ARM

arm

Pictured above is my 64 bit ARM server. It’s under NDA so I cannot tell you who supplied it or even show you a proper photo.

However it runs Fedora 21 & Rawhide:

Linux arm64.home.annexia.org 3.16.0-0.rc6.git1.1.efirtcfix1.fc22.aarch64 #1 SMP Wed Jul 23 12:15:58 BST 2014 aarch64 aarch64 aarch64 GNU/Linux

libvirt and libguestfs run fine, with full KVM acceleration, although right now you have to use qemu from git as the Rawhide version of qemu is not new enough.

Also OCaml 4.02.0 beta works (after we found and fixed a few bugs in the arm64 native code generator last week).

2 Comments

Filed under Uncategorized

New(ish) in libguestfs 1.27.23 — add firstboot batch files to Windows guests

You’ve been able to do this for a while by hand but now virt-sysprep & virt-customize ≥ 1.27.23 let you easily install firstboot scripts into Windows guests:

$ cat /tmp/test.bat
echo Hello I am a batch file
$ virt-customize -a win7.qcow2 --firstboot /tmp/test.bat

Next time the guest boots, check the log file in C:\Program Files\Red Hat\Firstboot\log.txt

This works well for me in Windows 7 guests. It ought to work in other Windows guests too. So far the only other Windows flavour I tested was W2K3 where the service crashed for some unfathomable reason (I’m not very patient with debugging Windows problems).

So let us know how it goes and we’ll try to fix the bugs as we go along.

Leave a comment

Filed under Uncategorized

Tip: Use gdbserver to debug qemu running under libguestfs

If qemu crashes or fails when run under libguestfs, it can be a bit hard to debug things. However a small qemu wrapper and gdbserver can help.

Create a file called qemu-wrapper chmod +x and containing:

#!/bin/bash -

if ! echo "$@" | grep -sqE -- '-help|-version|-device \?' ; then
  gdbserver="gdbserver :1234"
fi

exec $gdbserver /usr/bin/qemu-system-x86_64 "$@"

Set your environment variables so libguestfs will use the qemu wrapper instead of running qemu directly:

$ export LIBGUESTFS_BACKEND=direct
$ export LIBGUESTFS_HV=/path/to/qemu-wrapper

Now we run guestfish or another virt tool as normal:

$ guestfish -a /dev/null -v -x run

When qemu starts up, gdbserver will run and halt the process, printing:

Listening on port 1234

At this point you can connect gdb:

$ gdb
(gdb) file /usr/bin/qemu-system-x86_64
(gdb) target remote tcp::1234
set breakpoints etc here
(gdb) cont

Leave a comment

Filed under Uncategorized