Tag Archives: virt-inspector

libguestfs inspection now lists Windows apps

In version ≥ 1.7.8 Windows apps can be listed from virt-inspector:

$ virt-inspector Win7.img
        <name>Mozilla Firefox (3.6.12)</name>
        <display_name>Mozilla Firefox (3.6.12)</display_name>
        <version>3.6.12 (en-GB)</version>
        <install_path>C:\Program Files\Mozilla Firefox</install_path>

or from guestfish:

$ guestfish -a Win7.img --ro -i
Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.

Type: 'help' for help on commands
      'man' to read the manual
      'quit' to quit the shell

Operating system: Windows 7 Enterprise
/dev/vda2 mounted on /

><fs> inspect-list-applications /dev/vda2
[0] = {
  app_name: Mozilla Firefox (3.6.12)
  app_display_name: Mozilla Firefox (3.6.12)
  app_epoch: 0
  app_version: 3.6.12 (en-GB)
  app_install_path: C:\Program Files\Mozilla Firefox
  app_publisher: Mozilla
  app_url: http://www.mozilla.com/en-GB/
[1] = {
  app_name: VLC media player
  app_display_name: VLC media player 1.1.5
  app_epoch: 0
  app_version: 1.1.5
  app_install_path: C:\Program Files\VideoLAN\VLC
  app_publisher: VideoLAN
  app_url: http://www.videolan.org/

The same API also works for Fedora, RHEL, Debian and Ubuntu guests, where it lists installed packages instead of “applications”.

Leave a comment

Filed under Uncategorized

Tip: Use Augeas to get the default boot kernel for a VM

Note: This requires libguestfs ≥ 1.5.23

The example below demonstrates a couple of new features of libguestfs 1.5: the core inspection API, and add_drive_opts with optional arguments. Along with the use of Augeas to parse configuration files with ease.

You can use this as a template for getting almost any information from a guest or disk image. Examples include:

  • list the user accounts in the guest
  • what repositories is it configured to use
  • what NTP servers does it connect to
  • what were the boot messages last time it booted
  • list who was logged in recently
#!/usr/bin/perl -w

use Sys::Guestfs;

die "Usage: whichboot.pl linuxdisk.img\n" if @ARGV == 0;

# Add the disk image.
my $g = Sys::Guestfs->new ();
foreach (@ARGV) {
    $g->add_drive_opts ($_, readonly => 1);
$g->launch ();

# Inspect the operating system and mount disks correctly.
my @roots = $g->inspect_os ();
die "no operating system detected, or OS is multi-boot" unless @roots == 1;
my %fses = $g->inspect_get_mountpoints ($roots[0]);
my @fses = sort { length $a <=> length $b } keys %fses;
foreach (@fses) {
    $g->mount_ro ($fses{$_}, $_);

# Use Augeas to parse configuration files.
$g->aug_init ("/", 16);

# Get GRUB default boot option.
my $grub_conf = "//files/boot/grub/menu.lst";
my $default = $g->aug_get ("$grub_conf/default");

# Add 1 because GRUB counts from 0, Augeas counts from 1.

# Get the kernel from GRUB.
my $kernel = $g->aug_get ("$grub_conf/title[$default]/kernel");

print "default boot kernel: $kernel\n"

Leave a comment

Filed under Uncategorized

New features in libguestfs 1.6: Inspect disk images from any programming language

In this series of posts I want to cover some of the upcoming features in libguestfs 1.6. Of course you don’t need to wait for 1.6 to be released, you can try them out now from the development branch (source) or in these Fedora 14 testing builds

If I give you a virtual machine (or its disk image — almost the same thing), how do you know what’s in it? Is it a copy of Windows or Linux? In libguestfs you can use virt-inspector to give you a report. But in older versions what you couldn’t do was the same thing from the API. Virt-inspector is written as a Perl library, so that information is only available to Perl tools.

In libguestfs 1.6 we have rewritten this code in C and made it available to all the language bindings.

The example below is an OCaml program that inspects a disk image to reveal the product name. You can just save it to a file, chmod +x the file, and run it from the command line like this:

$ ./inspect.ml disk.img
Fedora release 13 (Goddard)
$ sudo ./inspect.ml /dev/vg_pin/Win7x32
Windows 7 Enterprise
#!/usr/bin/ocamlrun /usr/bin/ocaml
#use "topfind";;
#require "guestfs";;
module G = Guestfs
let () =
  let filename = Sys.argv.(1) in
  let g = G.create () in
  G.add_drive_ro g filename;
  G.launch g;
  let roots = G.inspect_os g in
  print_endline (G.inspect_get_product_name g roots.(0))

Leave a comment

Filed under Uncategorized

Tip: Pack files into a new disk image

Note: This requires libguestfs ≥ 1.4

If files/ is a directory containing some files, you can create a new disk image populated with those files using the command below (virt-make-fs can also be used for this):

$ guestfish -N fs:ext2:400M -m /dev/sda1 tar-in <(tar -C files/ -cf - .) /


  1. guestfish -N fs:ext2:400M creates a prepared disk image which is 400MB in size with a single partition formatted as ext2. The new disk image is called test1.img.
  2. -m /dev/sda1 mounts the new filesystem when guestfish starts up.
  3. tar-in [...] / uploads and unpacks the tar file into the root directory of the mounted disk image.
  4. <(tar -C files/ -cf - .) is a bash process substitution which runs the tar command and supplies the output (ie. the tar file) as the input on the command line.

This is a quick way to create “appliances” using febootstrap and libguestfs, although you should note that I don’t think these appliances would really work, I just use them for testing our virtualization management tools, like the ability to detect and manage disk images:

$ febootstrap -i fedora-release -i bash -i setup -i coreutils fedora-13 f13
$ echo '/dev/sda1 / ext2 defaults 1 1' > fstab
$ febootstrap-install f13 fstab /etc 0644 root.root
$ febootstrap-minimize f13
$ guestfish -N fs:ext2:40M -m /dev/sda1 tar-in <(tar -C f13 -cf - .) /
$ guestfish --ro -i -a test1.img

Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.

Type: 'help' for a list of commands
      'man' to read the manual
      'quit' to quit the shell

Operating system: Fedora release 13 (Goddard)
/dev/vda1 mounted on /
><fs> cat /etc/fstab
/dev/sda1 / ext2 defaults 1 1


Filed under Uncategorized

libguestfs news

We rewrote the inspection code in C (originally it was Perl). One advantage to this is you can inspect unknown OS images from any language binding, not just Perl.

Another is that it makes the guestfish -i option both smarter and faster. The following will only work in the latest development version, 1.5.3:

$ guestfish -i -d Debian5x64 --ro

Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.

Type: 'help' for a list of commands
      'man' to read the manual
      'quit' to quit the shell

Operating system: squeeze/sid
/dev/mapper/debian5x64-root mounted on /
/dev/vda1 mounted on /boot
/dev/mapper/debian5x64-home mounted on /home
/dev/mapper/debian5x64-tmp mounted on /tmp
/dev/mapper/debian5x64-usr mounted on /usr
/dev/mapper/debian5x64-var mounted on /var

The inspection API is documented in the main manual.

We are also maintaining two stable branches by backporting only conservative bug fixes. libguestfs 1.2.11 is the latest old stable version along the 1.2 branch, and libguestfs 1.4.2 is the latest stable version along the 1.4 branch. (If you want to start using libguestfs and you don’t want the bleeding edge, use 1.4.x).

1 Comment

Filed under Uncategorized

guestfish -i, that’s i for “inspector” not “interactive”

I wrote this FAQ entry today …

  • What’s the deal with guestfish -i?
  • Why does virt-cat only work on a real VM image, but virt-df works on any disk image?
  • What does “no root device found in this operating system image” mean?

These questions are all related at a fundamental level which may not be immediately obvious.

At the libguestfs API and guestfish level, a “disk image” is just a pile of partitions and filesystems.

In contrast, when the virtual machine boots, it mounts those filesystems into a consistent hierarchy such as:

 /          (/dev/sda2)
 +-- /boot  (/dev/sda1)
 +-- /home  (/dev/vg_external/Homes)
 +-- /usr   (/dev/vg_os/lv_usr)
 +-- /var   (/dev/vg_os/lv_var)

(or drive letters on Windows).

The libguestfs API however knows nothing about how filesystems are mounted. In general, a disk image that we just made up might not contain an operating system or “mountpoints” at all.

Nevertheless, users expect some tools (like virt-cat) to work with VM paths:

virt-cat fedora.img /var/log/messages

How does virt-cat know that /var is a separate partition?

The trick is a large external program called virt-inspector. Virt-inspector contains all sorts of tests and heuristics, so it can take a disk image about which nothing is known beforehand and work out both what it is, and how filesystems would be mounted.

Some tools, such as virt-cat, virt-edit, virt-ls and virt-tar use the same virt-inspector code to map VM paths. Other tools, such as virt-df and virt-list-filesystems operate entirely at the raw “big pile of filesystems” level of the libguestfs API, and don’t use virt-inspector code.

guestfish is in an interesting middle ground. If you use the -a and -m command line options, then you have to tell guestfish exactly how to add disk images and where to mount partitions. This is the raw API level.

However there is also a guestfish -i (for “inspector”) mode. In this mode, guestfish runs virt-inspector, and then (if successful) virt-inspector runs guestfish a second time with the correct -a and -m options. This is much slower, but usually simpler for the user. They can just do this and it all works:

guestfish -i SomeLibvirtGuest

The error “no root device found in this operating system image” is related to this. It means virt-inspector was unable to locate an operating system within the disk image you gave it. You might see this from programs like virt-cat if you try to run them on something which is just a disk image, not a virtual machine.


Filed under Uncategorized

virt-inspector now works better with Windows guests

Yesterday we improved virt-inspector so it can now fetch information about Windows guests by reading their Registries. In the XML output, this provides the ProductName and Windows internal version:

$ virt-inspector --xml Win2003x32
    <product_name>Microsoft Windows Server 2003</product_name>

In the raw output you get even more details from the Registry:

$ virt-inspector --perl Windows7x64
'arch' => 'x86_64',
'windows_registered_owner' => 'rjones',
'windows_current_type' => 'Multiprocessor Free',
'windows_system_hive' => '/Windows/System32/config/SYSTEM',
'windows_installation_type' => 'Client',
'os_major_version' => '6',
'os_minor_version' => '1',
'systemroot' => '/Windows',
'windows_software_hive' => '/Windows/System32/config/SOFTWARE',
'windows_software_type' => 'System',
'windows_registered_organization' => '',
'windows_current_build' => '7600',
'windows_edition_id' => 'Enterprise',
'product_name' => 'Windows 7 Enterprise',

1 Comment

Filed under Uncategorized

Ubuntu 9.10 packages for libguestfs

By popular demand, I’ve built Ubuntu packages for the latest libguestfs, guestfish, virt-inspector, virt-cat and virt-df:


These are experimental. If they break, you get to keep both pieces.

One point in particular is there is no Perl Sys::Virt package in Ubuntu, which means you have to supply this yourself, else virt-inspector etc. won’t work.


Filed under Uncategorized

Display an XML doc from the command line

Leading me down the garden path today, how to quickly display an XML document … graphically, from the command line?

This doesn’t work:

$ virt-inspector --xml RHEL54.img | firefox -

Creating a temporary file is possible, but ugly.

Then I was tipped off that you can create and pass a data: URI to Firefox.

There is no existing command line tool to generate data URIs, but we can write one in 3 lines of shell script:

#!/bin/sh -
echo -n data:$1\;
uuencode -m notused | tail -n +2 | tr -d '\n'


$ cat > /tmp/test.html
$ datauri text/html < /tmp/test.html

This also doesn’t work. There are two problems: the XML generated by virt-inspector is too long for a data URI, and in any case Firefox seems to ignore the data URI although I’m sure I’m constructing it correctly. Maybe it’s a security or configuration issue?

Well, good idea, but let’s go back to the temporary file idea. Bash process substitution might have worked:

$ firefox <(virt-inspector --xml RHEL54.img)

but Firefox’s frankly stupid session management crap gets in the way because this command expands to something like:

$ firefox /proc/self/fd/123

and the new firefox process passes the non-portable /proc/self path to the currently running instance of Firefox which doesn’t have the same view of /proc/self.

So we are finally left with:

$ firefox $(f=`mktemp -u`;
            virt-inspector --xml RHEL54.img > $f.xml;
            echo $f.xml)

which is fugly and unsafe.

If only there was a less insane tool to display XML, but being XML I guess insane goes with the territory.


Filed under Uncategorized

Examine VMWare ESX with libguestfs

We worked out yesterday (thanks Matthias Bolte) how to use the libguestfs tools like virt-inspector and guestfish to examine VMWare VMs.

VMWare’s native disk format is VMDK, which is only partially understood by free tools like qemu-img. qemu-img breaks quite badly on the newer variant that ESX 4 uses. Then there’s the issue of how you get the VMDK file from VMWare’s storage. Use their proprietary storage APIs?

Well it turned out both problems could be solved easily. VMWare ESX servers make the storage available over https connections, so you can use a URL like https://root:password@esxserver/folder/ to browse available storage on the server. And VMWare also makes the raw (“flat”) disk images available in the same way.

libvirt has supported ESX management for a while (thanks again to Matthias Bolte), so you can do:

$ sudo virsh -c esx:// list --all
Enter username for [root]:
Enter root password for
 Id Name                 State
  - TestLinux            shut off
  - TestWin              shut off

(Note that the domains must be shut off before VMWare will allow you to access the flat disk images).

Then we can get the storage URL:

$ sudo virsh -c esx:// dumpxml TestLinux > /tmp/xml
$ grep '<source file' /tmp/xml
      <source file='[Storage1] TestLinux/TestLinux.vmdk'/>

And from that storage URL you can grab the disk image directly:

$ wget --no-check-certificate 'https://root:password@'

The large flat file downloaded is a straight raw disk image that can be examined directly in programs like guestfish and virt-inspector:

$ virt-list-filesystems -al TestLinux-flat.vmdk
/dev/sda1 ext4
/dev/vg_testlinux/lv_root ext4
/dev/vg_testlinux/lv_swap swap

$ guestfish --ro -a TestLinux-flat.vmdk -m /dev/vg_testlinux/lv_root

Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.

Type: 'help' for help with commands
      'quit' to quit the shell

><fs> ll /
total 116
dr-xr-xr-x.  23 root root  4096 Dec 30 06:27 .
dr-xr-xr-x   29 root root     0 Dec 21 07:59 ..
-rw-r--r--.   1 root root     0 Dec 30 06:27 .autofsck
drwx------.   3 root root  4096 Dec 17 11:58 .dbus
-rw-r--r--.   1 root root     0 Dec 17 12:50 .readahead_collect
dr-xr-xr-x.   2 root root  4096 Dec 17 12:11 bin

It’s probably also possible to avoid the download step, since libguestfs is built on qemu which should support http(s) connections directly, but I didn’t try this yet.


Filed under Uncategorized