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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s