Tag Archives: guestmount

Tip: FUSE-mount a disk image with Windows drive letters

guestmount is the libguestfs tool for taking a disk image and mounting it under the host filesystem. This works great for Linux disk images:

$ virt-builder centos-7.2
$ mkdir /tmp/mnt
$ guestmount -a centos-7.2.img -i /tmp/mnt
$ ls /tmp/mnt
bin   dev  home  lib64       media  opt   root  sbin  sys  usr
boot  etc  lib   lost+found  mnt    proc  run   srv   tmp  var
$ guestunmount /tmp/mnt

Those files under /tmp/mnt are inside the centos-7.2.img disk image file, and you can read and write them.

guestmount is fine for Windows disk images too, except when Windows has multiple drives, C:, D:, etc., because in that case you’ll only “see” the contents of the C: drive.

But guestmount is nowadays just a wrapper around the “mount-local” API in libguestfs, and you can use that API directly if you want to do anything a bit more complicated … such as exposing Windows drive letters.

Here is a Perl script which uses the mount-local API directly to do this:

#!/usr/bin/perl -w
use strict;
use Sys::Guestfs;
$| = 1;
die "usage: $0 mountpoint disk.img" if @ARGV < 2;
my $mp = shift @ARGV;
my $g = new Sys::Guestfs;
$g->add_drive_opts ($_) foreach @ARGV;
my @roots = $g->inspect_os;
die "$0: no operating system found" if @roots != 1;
my $root = $roots[0];
die "$0: not Windows" if $g->inspect_get_type ($root) ne "windows";
my %map = $g->inspect_get_drive_mappings ($root);
foreach (keys %map) {
    $g->mkmountpoint ("/$_");
    eval { $g->mount ($map{$_}, "/$_") };
    warn "$@ (ignored)\n" if $@;
$g->mount_local ($mp);
print "filesystem mounted on $mp\n";

You can use it like this:

$ mkdir /tmp/mnt
$ ./drive-letters.pl /tmp/mnt windows7.img
filesystem ready on /tmp/mnt

in another window:

$ cd /tmp/mnt
$ ls
C  D
$ cd C
$ ls
Documents and Settings
Program Files
$ cd ../..
$ guestunmount /tmp/mnt

(Thanks to Pino Toscano for working out the details)

Leave a comment

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

Why has the libguestfs appliance grown by 281 MB?

a.k.a guestmount + filelight are awesome!

Click to see the full image


If you want to reproduce the same diagrams yourself, just do:

$ mkdir /tmp/mp
$ guestmount --ro \
    -a /var/tmp/.guestfs-1000/appliance.d/root \
    -m /dev/sda /tmp/mp
$ filelight /tmp/mp


Filed under Uncategorized

Tip: Custom guestmount in Perl

Since libguestfs 1.18 guestmount has just been a slim wrapper around the libguestfs guestfs_mount_local API. You can replace guestmount with a small custom script if you want to do tricky/non-standard stuff like setting filesystem mount options, as in the example below.

$ ./mount-local.pl --ro -a /tmp/f17x64.img --mountopts=noatime /tmp/mount
mounting disk on /tmp/mount
to unmount: fusermount -u /tmp/mount
#!/usr/bin/perl -w

use strict;
use Getopt::Long;
use Sys::Guestfs;

my $readonly = 0;
my @drives;
my $mountopts;
my $trace = 0;

GetOptions ("ro|r" => \$readonly,
            "add|a=s" => \@drives,
            "mountopts=s" => \$mountopts,
            "trace|x" => \$trace)
    or die "$0 [--ro] [--add drive] [--mountopts mountopts] mountpoint\n";

die "$0: no drives (-a) were specified\n"
    unless @drives > 0;
die "$0: no mountpoint was specified\n"
    unless @ARGV == 1;

my $g = Sys::Guestfs->new ();
$g->set_trace (1) if $trace;
foreach (@drives) {
    $g->add_drive_opts ($_, readonly => $readonly)
$g->launch ();

# Inspect the disk to find OSes.
my @roots = $g->inspect_os ();
unless (@roots == 1) {
    die "$0: no operating systems found\n";
my $root = $roots[0];

# Mount up the disks like using the -i option.
my %mps = $g->inspect_get_mountpoints ($root);
my @mps = sort { length $a <=> length $b } (keys %mps);
foreach (@mps) {
    my $options = $readonly ? "ro" : "rw";
    $options .= "," . $mountopts if defined $mountopts;
    eval { $g->mount_options ($options, $mps{$_}, $_) };
    if ($@) {
        print "$@ (ignored)\n"

# Export the filesystem using FUSE.
$g->mount_local ($ARGV[0]);

print "mounting disk on $ARGV[0]\n";
print "to unmount: fusermount -u $ARGV[0]\n";
$g->mount_local_run ();
# This returns when the filesystem is unmounted.

$g->shutdown ();
$g->close ();

Leave a comment

Filed under Uncategorized

Scanning offline guests using OpenSCAP and guestmount

OpenSCAP is a project that lets you scan physical machines looking for known vulnerabilities or configuration problems (like public-writable directories).

Obviously it would be good to use this to scan guests, especially in a cloud scenario where you want to help naive users not to deploy guests that are just going to get pwned the minute they go online.

New upstream in OpenSCAP is the ability to scan chroots. You can use this to scan containers, or using guestmount, scan offline guests.

Usage with guestmount is described here or here.

(Thanks Daniel Kopecek and Peter Vrabec)

Leave a comment

Filed under Uncategorized

Use guestfish, virt tools with remote disks

New in libguestfs ≥ 1.21.30 is the ability to use guestfish and some of the virt tools with remote disks.

Currently you can use remote disks over NBD, GlusterFS, Ceph, Sheepdog and (recently upstream) SSH.

For this example I’ll use SSH because it needs no setup, although this requires absolutely the latest qemu and libguestfs (both from git).

Since we don’t have libvirt support for ssh yet, so this only works with the direct backend:

$ export LIBGUESTFS_BACKEND=direct

I can use a ssh:// URI to add disks with guestfish, guestmount and most of the virt tools. For example:

$ virt-rescue -a ssh://localhost/tmp/f17x64.img
[... lots of boot messages ...]
Welcome to virt-rescue, the libguestfs rescue shell.

Note: The contents of / are the rescue appliance.
You have to mount the guest's partitions under /sysroot
before you can examine them.

><rescue> mount /dev/vg_f17x64/lv_root /sysroot
><rescue> cat /sysroot/etc/redhat-release
Fedora release 17 (Beefy Miracle)

Apart from being a tiny bit slower, it just works as if the disk was local:

$ virt-df -a ssh://localhost/tmp/f17x64.img
Filesystem                           1K-blocks       Used  Available  Use%
f17x64.img:/dev/sda1                    487652      63738     398314   14%
f17x64.img:/dev/vg_f17x64/lv_root     28316680    4285576   22586036   16%
$ guestmount -a ssh://localhost/tmp/f17x64.img -i /tmp/mnt
$ ls /tmp/mnt
bin   dev  home  lib64       media  opt   root  sbin  sys  usr
boot  etc  lib   lost+found  mnt    proc  run   srv   tmp  var
$ cat /tmp/mnt/etc/redhat-release
Fedora release 17 (Beefy Miracle)
$ guestunmount /tmp/mnt

Leave a comment

Filed under Uncategorized

Cool new bash-completions of libguestfs tools

Starting in libguestfs ≥ 1.21.23-2, bash tab completions of guestfish, guestmount and virt-* tools have been rewritten and greatly improved.

Note you will need to install the libguestfs-bash-completion package to enable this feature.

You can now tab complete all long options on most tools:

$ virt-df --[tab]
--add             --domain          --human-readable  --uuid
--connect         --format          --inodes          --verbose
--csv             --help            --one-per-guest   --version
$ virt-resize --[tab]
--align-first          --help                 --no-extra-partition
--alignment            --ignore               --ntfsresize-force
--debug                --lvexpand             --output-format
--debug-gc             --lv-expand            --quiet
--delete               --LVexpand             --resize
--dryrun               --LV-expand            --resize-force
--dry-run              --machine-readable     --shrink
--expand               --no-copy-boot-loader  --version
--format               --no-expand-content    

Where appropriate, the -d option will now expand to the list of libvirt domains:

# virt-df -d [tab]
archlinux20121201x64  f19rawhidex32
f18x64                f19rawhidex64

Finally, guestfish commands are expanded on the command line:

$ guestfish add /tmp/disk : run : list-[tab]
list-9p              list-events          list-md-devices
list-devices         list-filesystems     list-partitions
list-disk-labels     list-ldm-partitions  
list-dm-devices      list-ldm-volumes     

To make this less intrusive, so you can really use it daily, I left the default readline expansions enabled. This means that filenames and so on can continue to be used in every position on the command line, and should mean that bash completions won’t try to be cleverer than the user.

Libguestfs bash completions are also demand-loaded now, so that if you’re not using them, they don’t consume any resources in the shell.

Leave a comment

Filed under Uncategorized