Extracting filesystems from guest images, reconstructing guest images from filesystems, part 2

As discussed previously you can use libguestfs to extract raw filesystem content from a disk image.

The second part of our LVM to non-LVM converter involves a utility called virt-implode which takes the filesystem images and creates a new disk image with partitions containing the image content. It’s best to run this program using LIBGUESTFS_TRACE=1 so you can easily see what it’s doing.

$ LIBGUESTFS_TRACE=1 ./virt-implode.pl \
    sda1.img VolGroup00_LogVol00.img VolGroup00_LogVol01.img \
    output.img
libguestfs: trace: add_drive "output.img" "format:raw"
libguestfs: trace: add_drive = 0
libguestfs: trace: launch
libguestfs: trace: get_tmpdir
libguestfs: trace: get_tmpdir = "/tmp"
libguestfs: trace: get_cachedir
libguestfs: trace: get_cachedir = "/var/tmp"
libguestfs: trace: get_cachedir
libguestfs: trace: get_cachedir = "/var/tmp"
libguestfs: trace: launch = 0
libguestfs: trace: part_init "/dev/sda" "gpt"
libguestfs: trace: part_init = 0
libguestfs: trace: part_add "/dev/sda" "p" 2048 210943
libguestfs: trace: part_add = 0
libguestfs: trace: part_add "/dev/sda" "p" 210944 14694399
libguestfs: trace: part_add = 0
libguestfs: trace: part_add "/dev/sda" "p" 14694400 16726015
libguestfs: trace: part_add = 0
libguestfs: trace: upload "sda1.img" "/dev/sda1"
libguestfs: trace: upload = 0
libguestfs: trace: upload "VolGroup00_LogVol00.img" "/dev/sda2"
libguestfs: trace: upload = 0
libguestfs: trace: upload "VolGroup00_LogVol01.img" "/dev/sda3"
libguestfs: trace: upload = 0
libguestfs: trace: shutdown
libguestfs: trace: internal_autosync
libguestfs: trace: internal_autosync = 0
libguestfs: trace: shutdown = 0
libguestfs: trace: close

Use virt-filesystems to examine the result:

$ virt-filesystems -a output.img --all --long -h
Name       Type        VFS   Label  MBR  Size  Parent
/dev/sda1  filesystem  ext3  /boot  -    102M  -
/dev/sda2  filesystem  ext3  -      -    6.9G  -
/dev/sda3  filesystem  swap  -      -    992M  -
/dev/sda1  partition   -     -      -    102M  /dev/sda
/dev/sda2  partition   -     -      -    6.9G  /dev/sda
/dev/sda3  partition   -     -      -    992M  /dev/sda
/dev/sda   device      -     -      -    8.0G  -

Here is the virt-implode script:

#!/usr/bin/perl -w

use strict;
use Sys::Guestfs;

die "$0 *.img output.img" unless @ARGV >= 2;

my $output = pop @ARGV;

# Work out how we'll partition the output image.
# Assumes that the input filesystem images are
# in raw format, and therefore size == file size.
my $fs;
my $size = 1024*1024;
my @start_sectors = ();
foreach $fs (@ARGV) {
    push @start_sectors, $size / 512;
    $size += (-s $fs);
    # Round up to next 1MB boundary.
    $size = round_up ($size, 1024*1024);
}
push @start_sectors, $size / 512;
$size += 1024 * 1024;

open FILE, ">$output" or die "$output: $!";
truncate FILE, $size or die "$output: truncate: $!";
close FILE or die "$output: close: $!";

my $g = Sys::Guestfs->new ();
$g->add_drive_opts ($output, format => "raw");
$g->launch ();

$g->part_init ("/dev/sda", "gpt");
my $i;
for (my $i = 0; $i < @start_sectors-1; ++$i) {
    $g->part_add ("/dev/sda", "p", $start_sectors[$i], $start_sectors[$i+1]-1);
}

$i = 1;
foreach $fs (@ARGV) {
    $g->upload ($fs, "/dev/sda$i");
    $i++;
}

$g->shutdown ();

sub round_up
{
    my $n = shift;
    my $r = shift;

    $n += $r-1;
    $n &= ~($r-1);
    $n
}

Next time I’ll see if I can get this guest to boot …

About these ads

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