First I created a created a loopback (/dev/loop0) device from a 25GB blank raw disk image and partitioned it into a 20GB partition for the filesystem and the remainder for swap.
Remember to use kpartx on the loopback device to 'find' the new partitions:
# kpartx -a /dev/loop0
# ls /dev/mapper/
control loop0p1 loop0p2
I wasn't sure which file system to use so I conservatively chose to make an ext2 file system on the first partition:
# mkfs.ext2 /dev/mapper/loop0p1
mke2fs 1.41.12 (17-May-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1313760 inodes, 5245214 blocks
262260 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
161 block groups
32768 blocks per group, 32768 fragments per group
8160 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 23 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
Create a mount point and mount the loopback device partition:
# mkdir /mnt/disk
# mount /dev/mapper/loop0p1 /mnt/disk
Change to the mount directory and untar the archive:
# cd /mnt/disk
# tar xzvf /path/to/disk_archive.tar.gz
Use chroot to mount the new disk image as a root filesystem:
# mount -t proc none /mnt/disk/proc
# mount -o bind /dev /mnt/disk/dev
# chroot /mnt/disk /bin/bash
Make any required changes to the file system (like installing the grub packages!)
Exit chroot and unmount and unloop everything:
# umount /mnt/disk/dev
# umount /mnt/disk/proc
# umount /mnt/disk
# kpartx -d /dev/loop0
# losetup -d /dev/loop0
Finally I created a VM with this as its hard drive. I used Super Grub2 Disk to resolve any further issues with the bootloader.