Debian Wheezy: Split and resize Xen disk image
Background
One of my Xen virtual servers needed to have its 400G disk split and resized over the weekend, and I wanted to keep downtime to a minimal. The disk had 240G used, 235G of which was a /backup directory, and the remaining 5G dedicated to a regular Debian Linux installation. I wanted to split the disk into a two disks - a 20GB disk containing the Linux system, and a 300G disk to mount as /backup. Then I could apply my DRBD setup to replicate that 300G backup partition to a separate 2nd backup machine.
I didn't want to end up in a situation of having to copy a load of data on the physical host, and I certainly didn't want the virtual machine down while I did it.
Set up images
The virtual machine has its disk image located in /vm/domains/b1/disk.img and an accompanying swap.img that we don't need to worry about.
Issue:
losetup -a
To locate all used loop devices. In my case, /dev/loop20 was the first free device. Next, I'll set up a loopback device for the image, and then mount it:
mkdir -p /mnt/loop-copy-from /mnt/loop-copy-to
losetup /dev/loop20 /vm/domains/b1/disk.img
mount /dev/loop20 /mnt/loop-copy-from
Create a new empty sparse image
Now, we're not going to move /backup, instead, we're going to move everything else to the new 20G image. We'll create a sparse image file of 20G with:
dd if=/dev/zero of=/vm/domains/b1/disk-root.img bs=1k count=1 seek=$(((20*1024*1024)-1))
Next, we'll need to set up a new loop device, create a filesystem and finally mount this new image
losetup /dev/loop21 /vm/domains/b1/disk-root.img
mkfs.ext3 /dev/loop21
mount /dev/loop21 /mnt/loop-copy-to
Copy root filesystem
Now, I'll copy everything from /mnt/loop-copy-from to /mnt/loop-copy-to aside from the 235G backup directory:
rsync -arplogu --exclude "/backup" --stats --progress /mnt/loop-copy-from/ /mnt/loop-copy-to
Clean up existing filesystem
I want to remove everything on /mnt/loop-copy-from except the backup directory:
cd /mnt/loop-copy-from; ls | grep -v 'backup' | xargs rm -rf
We'll then unmount both devices:
umount /mnt/loop-copy-from
umount /mnt/loop-copy-to
Shrink existing filesystem
I'll now need to shrink /dev/loop20 from 400G to 300G:
e2fsck -f /dev/loop20
resize2fs /dev/loop20 300G
Copy boot data
And then, copy the boot data before destroying the loopback devices:
dd if=/dev/loop20 of=/dev/loop21 bs=1 count=512
losetup -d /dev/loop20
losetup -d /dev/loop21
Xen configuration and VM boot
Now edit the Xen VM configuration file, in my case, /etc/xen/b1.cfg, changing:
disk = [ 'file:/vm/domains/b1/disk.img,xvda2,w', 'file:/vm/domains/b1/swap.img,xvda1,w', ]
With:
disk = [ 'file:/vm/domains/b1/disk-root.img,xvda2,w', 'file:/vm/domains/b1/disk.img,xvda3,w', 'file:/vm/domains/b1/swap.img,xvda1,w', ]
And finally:
xm create b1.cfg