Can’t boot properly after moving all files off then back on the VM drive

bootgrub2virtual machinevirtualbox

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:

  1. 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.
  2. Boot to a blank purple screen. Freeze. On subsequent resets, boot to a blinking text cursor.
  3. 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):

  1. Create a VM in VirtualBox using an 8GB .vdi virtual disk (called ub.vdi, for the purposes of the rest of the question)
  2. Boot with the Ubuntu 12.04.3 32-bit install ISO
  3. "Try Ubuntu".
  4. Set up an MSDOS partition table and two primary partitions, a 2048MiB swap space, the rest an ext4 partition. (Used gparted).
  5. Install Ubuntu on the ext4 partition
  6. Shut down the VM
  7. 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):

/usr/sbin/grub-install --root-directory="$MNT_DIR" /dev/nbd

and make sure that /boot/grub/device.map contains

(hd0) /dev/nbd

Note that this device.map will not work if you run grub-install in the VM. If that matters, either save and restore device.map around the grub-install invocation or manually invoke the low-level command that grub-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).

Related Question