Tag Archives: virt-inspector

Tip: Run virt-inspector on a compressed disk (with nbdkit)

virt-inspector is a very convenient tool to examine a disk image and find out if it contains an operating system, what applications are installed and so on.

If you have an xz-compressed disk image, you can run virt-inspector on it without uncompressing it, using the magic of captive nbdkit. Here’s how:

nbdkit xz file=win7.img.xz \
    -U - \
    --run 'virt-inspector --format=raw -a nbd://?socket=$unixsocket'

What’s happening here is we run nbdkit with the xz plugin, and tell it to serve NBD over a randomly named Unix domain socket (-U -).

We then run virt-inspector as a sub-process. This is called “captive nbdkit”. (Nbdkit is “captive” here, because it will exit as soon as virt-inspector exits, so there’s no need to clean anything up.)

The $unixsocket variable expands to the name of the randomly generated Unix domain socket, forming a libguestfs NBD URL which allows virt-inspector to examine the raw uncompressed data exported by nbdkit.

The nbdkit xz plugin only uncompresses those blocks of the data which are actually accessed, so this is quite efficient.

3 Comments

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) :-
    Filesystem(fs),
    File(fs, "/etc/fstab").
DebianRoot(fs) :-
    LinuxRoot(fs),
    File(fs, "/etc/debian_version").

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

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

and deriving new facts using the rules:

LinuxRoot("/dev/sda1").
DebianRoot("/dev/sda1").

(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 */
    (distro)?={{
      int r;
      CLEANUP_FREE char *distro = NULL;
      if ((r = get_distro_from_os_release (fs, &distro))
           <= 0)
        return r;
      set_distro (distro);
      return 0;
    }}.

and

BlockDevice(dev) :-
    (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

New tool: virt-customize

The final big feature of libguestfs 1.26 has arrived. Virt-customize is the customization bits from virt-builder, in a separate program. This lets you take any virtual machine and install packages, edit configuration files, run scripts, set passwords and so on.

One of the most requested features for virt-builder is the ability to customize templates while keeping a shared backing file, and virt-customize lets you do this.

Here’s how to use virt-customize:

$ virt-customize -a fedora-20.img \
    --update --install gcc
[   0.0] Examining the guest ...
[  37.0] Setting a random seed
[  37.0] Updating core packages
[ 238.0] Installing packages: gcc

virt-inspector has a way to list out the packages installed in a virtual machine disk image, and we can use it to show that gcc was installed:

$ virt-inspector -a fedora-20.img |
    xmlstarlet sel -t -c '//application[name="gcc"]'
<application>
        <name>gcc</name>
        <version>4.8.2</version>
        <release>7.fc20</release>
        <arch>x86_64</arch>
</application>

5 Comments

Filed under Uncategorized

ReactOS installed on KVM

Unfortunately a few things don’t work:

3 Comments

Filed under Uncategorized

Inspection in virt-manager #4

Listing the installed applications in virt-manager:

7 Comments

Filed under Uncategorized

Inspection in virt-manager #3

This is how it looks when the OS inspection icons are added to the main VM list:

4 Comments

Filed under Uncategorized

Inspection in virt-manager #2

Do right button -> View image. This free wordpress theme appears to truncate the right hand side of images.

Leave a comment

Filed under Uncategorized

Inspection in virt-manager

Using a background thread, inspect the virt-manager VMs and (just for a quick example) add the hostname to the user interface. I’m hoping in future that we can do things like changing those boring generic computer icons into operating system logos, displaying disk usage, and lots more.

Patch

8 Comments

Filed under Uncategorized

virt-inspector now supports Slackware

# virt-inspector Slackware13x64
<?xml version="1.0"?>
<operatingsystems>
  <operatingsystem>
    <root>/dev/sda3</root>
    <name>linux</name>
    <arch>x86_64</arch>
    <distro>slackware</distro>
    <product_name>Slackware 13.1.0</product_name>
    <major_version>13</major_version>
    <minor_version>1</minor_version>
    <format>installed</format>
[etc]

So now virt-inspector is known to detect: ArchLinux, CentOS, Debian, Fedora, FreeBSD, Gentoo, Linux Mint, Mandriva, Meego, Pardus, Red Hat Enterprise Linux, Scientific Linux, Slackware, Ubuntu, Windows XP through 7.

Leave a comment

Filed under Uncategorized

libguestfs: Live CD inspection

New in libguestfs 1.9.4, you can now run virt-inspector on some types of installer CD and live CD. The output tells you what type of operating system is on the CD:

$ virt-inspector cd.iso
<?xml version="1.0"?>
<operatingsystems>
  <operatingsystem>
    <root>/dev/sda</root>
    <name>windows</name>
    <arch>x86_64</arch>
    <distro>windows</distro>
    <product_name>Windows Server 2003 Enterprise x64 Edition</product_name>
    <major_version>5</major_version>
    <minor_version>2</minor_version>
    <windows_systemroot>\WINDOWS</windows_systemroot>
    <format>installer</format>
    <mountpoints>
      <mountpoint dev="/dev/sda">/</mountpoint>
    </mountpoints>
    <filesystems>
      <filesystem dev="/dev/sda">
        <type>iso9660</type>
        <label>CRMEXFPP_EN</label>
      </filesystem>
    </filesystems>
    <applications/>
  </operatingsystem>
</operatingsystems>

Update

On IRC someone asked me how long this takes. Here is the time to run the above command on my laptop:

real	0m4.736s
user	0m1.134s
sys	0m2.897s

The use case is in tools like virt-manager where we would like to detect what sort of ISO a user is installing from so that we can set the OS hints correctly. 5 seconds is just about acceptable as long as this happens in the background and doesn’t disturb the UI.

Leave a comment

Filed under Uncategorized