Skip to content

Live P2V migration, on the cheap

Last week I performed a live physical to virtual migration for a customer. Ghetto style.
I was actually surprised by it’s simplicity and how well it turned out in the end.

Basically what I did was boot the target server to a live environment in order to be able to have raw access to the disk. In this case I’ve used FAI’s Sysinfo mode, but booting any Linux Live CD would have worked equally well. After it’s booted I’ve created the the necessary partitions, created filesytems and mounted them. When those steps were done it was time to sync data and make the virtual system bootable.

Usually I would advise against this kind of migration but in this case there was only static data involved.
It worked out well for me, but your mileage may vary.

Alright here’s what I did step by step…

1. Backup partition layout and MBR

source:~ # sfdisk -d /dev/sda > /tmp/source-partitions
source:~ # dd if=/dev/sda of=/tmp/source-mbr.img bs=512 count=1
source:~ # scp /tmp/source-* target:/tmp/

2. Restore partition layout and MBR

target:~ # dd if=/tmp/source-mbr.img of=/dev/sda bs=446 count=1
target:~ # sfdisk /dev/xvda < /tmp/source-partitions

3. Create a filesystem on each partition

target:~ # for partition in xvda1 xvda6 xvda7 xvda8 xvda9 xvda10; do mkfs.ext4 /dev/$partition; done

4. Create a swap space

mkswap /dev/xvda2
swapon /dev/xvda2

5. Mount the newly created partitions

target:~ # mount /dev/xvda1 /mnt/tmp/
target:~ # mount /dev/xvda6 /mnt/tmp/var/
target:~ # mount /dev/xvda7 /mnt/tmp/tmp/
target:~ # mount /dev/xvda8 /mnt/tmp/usr
target:~ # mount /dev/xvda9 /mnt/tmp/home/
target:~ # mount /dev/xvda10 /mnt/tmp/data/

6. Synchronise data from source to target

target:~ # for i in $(seq 1 10);
rsync -av --delete --progress \
--exclude=/dev \
--exclude=/sys \
--exclude=/proc \
--exclude=/mnt/ \
--exclude=/media/ \
source:/* /mnt/tmp/;
target:~ #

Repeat this step until you’re confident nothing has changed anymore.

7. Enter the synchronized environment

target:~ # mount -t proc none /mnt/tmp/proc
target:~ # mount --rbind /dev /mnt/tmp/dev

target:~ # chroot /mnt/tmp /bin/bash
chroot:~ # source /etc/profile

8. Fix fstab entries

(only for Xen vm’s)

chroot:~ # sed -i 's+/dev/sda+/dev/xvda+g' /etc/fstab
chroot:~ # vim /etc/fstab

9. Fix network settings

chroot:~ # vim /etc/network/interfaces

10. Make the system bootable

chroot:~ # grep -v rootfs /proc/mounts > /etc/mtab
chroot:~ # grub-install --no-floppy /dev/xvda
chroot:~ # update-grub

Once you’ve run the above commands it’s time to exit the chroot, unmount all partitions and reboot
into your migrated environment. Enjoy!

“Dynamic lookup is deprecated. Support will be removed in Puppet 2.8.” when using facts in templates

Recently ran into some of these when running Puppet 2.7.x:

warning: Dynamic lookup of $variable is deprecated. Support 
will be removed in Puppet 2.8.  Use a fully-qualified variable
name (e.g., $classname::variable) or parameterized classes.

The solution was pretty obvious and it’s easy to fix because the solution is mentioned in the warning. However the warning fails to mention what to do with Facter facts inside ERB templates. Figuring out how to fix this took me quite a while although it’s easy too.

Let’s start by taking a look at this snippet:

NameVirtualHost <%= 'ipaddress' %>:80
< VirtualHost <%= 'ipaddress' %>:80 >
	DocumentRoot /var/www/vhosts/

If we’d apply this template in a manifest using Puppet 2.7.x we would run into the warning mentioned above because the IP address fact is out of scope. In order to avoid this we use lookupvar for Facter facts:

NameVirtualHost <%= scope.lookupvar('ipaddress') %>:80
< VirtualHost <%= scope.lookupvar('ipaddress') %>:80 >
	DocumentRoot /var/www/vhosts/