I have created an Ubuntu 12.04 32-bit VM in VirtualBox with a .vdi disk. I then mount this disk with qemu-nbd and move all the files off it; then back onto it. When I boot the VM again I get varying results:
- Ubuntu tells me there has been an error and asks if I would like to fix/skip/ignore/manual fix. If I fix, it will restart and boot to a tty. If I ignore it will boot to a tty. I haven't tried skip/manual fix yet.
- Boot to a blank purple screen. Freeze. On subsequent resets, boot to a blinking text cursor.
- Boot to the Ubuntu splash screen, freeze. On reset, see number 1 in this list.
My question is: why does this happen? Is there some disk hardware address in Grub referencing /boot/? Is there a way to remove and replace files in the VHD without having this problem?
How to reproduce this result (I hope):
- Create a VM in VirtualBox using an 8GB .vdi virtual disk (called ub.vdi, for the purposes of the rest of the question)
- Boot with the Ubuntu 12.04.3 32-bit install ISO
- "Try Ubuntu".
- Set up an MSDOS partition table and two primary partitions, a 2048MiB swap space, the rest an ext4 partition. (Used gparted).
- Install Ubuntu on the ext4 partition
- Shut down the VM
- Navigate to your VM directory and run the following script:
#!bin/bash
# load the nbd module
sudo modprobe nbd
# make a folder for our virtual disk files
mkdir os_files
# load the virtual disk as a device (nbd0)
sudo qemu-nbd -c /dev/nbd0 ub.vdi
sleep 1
# create a directory and mount the os partition to it
MNT_DIR=$(mktemp -d)
sudo mount /dev/nbd0p2 $MNT_DIR
# move the os files off, then back onto the virtual disk
find $MNT_DIR -maxdepth 1 -mindepth 1 | xargs -I{} sudo mv {} os_files/
find os_files/ -maxdepth 1 -mindepth 1 | xargs -I{} sudo mv {} $MNT_DIR
# clean up
sudo umount $MNT_DIR
sudo qemu-nbd -d /dev/nbd0
rm os_files/ $MNT_DIR -r
unset MNT_DIR
Why are you doing this?
As part of a contractual requirement, I need to store the virtual disk in version control. Having an enormous binary blob (virtual disk) in version control is a pain, mostly for clone(git)/checkout(svn), but also for diffs. I have considered splitting to multiple files, but I need to be able to manipulate the OS/data extracted in (5) above. Note that my VCS repository still needs all the information required to build a complete VM.
See also: https://superuser.com/questions/641971/manual-clone-recreate-virtual-disk. Apologies if posting again seems untoward/ungrateful/not-idiomatic/rude whatever; the answers I received at SU, while useful, simply lacked the expertise to actually solve my problem. Please do note that the question I've asked here is a little more specific than the linked one, but any ideas that circumvent the problem entirely are more than welcome.
Best Answer
The bootloader needs to find some file in a specific place. Ubuntu uses Grub as its default bootloader, and Grub contains a filesystem driver that it uses to load the Linux kernel, but Grub needs to find its filesystem driver. Furthermore, the
If you try to recreate the VM from scratch by creating a blank disk and partitioning it, it's even worse: the disk won't contain a bootloader.
As an additional restore step, you need to reinstall the bootloader. I think the following command should do it (you may need a few other options to make sure that Grub includes the necessary device drivers):
and make sure that
/boot/grub/device.map
containsNote that this
device.map
will not work if you rungrub-install
in the VM. If that matters, either save and restoredevice.map
around thegrub-install
invocation or manually invoke the low-level command thatgrub-install
eventually runs.An alternative approach would be to set up your VM with a tiny boot disk that only contains the bootloader, which you won't mind building from scratch all the time (or you could cache a built copy every time the bootloader changes, which should happen rarely).