In part 1 I “exploded” a disk image into its constituent filesystems. In part 2 I “imploded” those filesystems back into a disk image without LVM. Now let’s see if we can get this thing to boot.
Since there is no boot sector nor grub, the disk image produced by virt-implode won’t boot normally. You could boot it using an external kernel and initrd, but let’s see if we can install grub first.
Using virt-rescue we can interactively run programs from the guest:
$ virt-rescue -a output.img ... ><rescue> mount /dev/sda2 /sysroot ><rescue> mount /dev/sda1 /sysroot/boot ><rescue> mount --bind /dev /sysroot/dev ><rescue> mount --bind /sys /sysroot/sys ><rescue> mount --bind /proc /sysroot/proc ><rescue> chroot /sysroot sh: no job control in this shell ><rescue> cat /etc/redhat-release Red Hat Enterprise Linux AS release 4 (Nahant Update 8) ><rescue> vi /etc/fstab
You may need to fix /etc/fstab in the guest so that it points to the new partitions. For guests using LABELs or UUIDs, this won’t be necessary.
At this point, it should be simply a matter of running grub-install. But here’s where I remember how much I hate grub, because it just throws up peculiar, non-actionable error messages for every conceivable variation in the command.
So I give up that, and decide to extract the kernel and initrd and use the external boot method after all:
$ guestfish --ro -a output.img -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: Red Hat Enterprise Linux AS release 4 (Nahant Update 8)
/dev/sda2 mounted on /
/dev/sda1 mounted on /boot
><fs> ll /boot
total 4397
drwxr-xr-x. 5 root root 1024 Nov 15 13:49 .
drwxr-xr-x. 24 root root 4096 Nov 15 13:50 ..
-rw-r--r--. 1 root root 909034 Apr 20 2009 System.map-2.6.9-89.EL
drwxr-xr-x 3 root root 1024 Nov 15 13:49 boot
-rw-r--r--. 1 root root 45145 Apr 20 2009 config-2.6.9-89.EL
drwxr-xr-x. 2 root root 1024 Nov 15 13:58 grub
-rw-r--r--. 1 root root 1546843 Oct 27 2010 initrd-2.6.9-89.EL.img
drwx------ 2 root root 12288 Oct 27 2010 lost+found
-rw-r--r--. 1 root root 23108 Aug 3 2005 message
-rw-r--r--. 1 root root 21282 Aug 3 2005 message.ja
-rw-r--r--. 1 root root 67352 Apr 20 2009 symvers-2.6.9-89.EL.gz
-rw-r--r--. 1 root root 1829516 Apr 20 2009 vmlinuz-2.6.9-89.EL
><fs> download /boot/vmlinuz-2.6.9-89.EL /tmp/vmlinuz-2.6.9-89.EL
><fs> download /boot/initrd-2.6.9-89.EL.img /tmp/initrd-2.6.9-89.EL.img
$ qemu-kvm -m 512 \ -kernel vmlinuz-2.6.9-89.EL \ -initrd initrd-2.6.9-89.EL.img \ -append 'ro root=/dev/hda2' \ -hda output.img
(I should really use libvirt, but this quick test proves that the guest works fine)

Nice writeup, and I agree that you should really use libvirt
Maybe someone should keep a bin/* of this type of “helper” script, wrapping explode, implode and grub-install all into one. All these could be distributed with guestfish.
Thanks!