mercoledì 13 febbraio 2013

Physical to virtual (P2V) GNU/Linux step by step

Hi,
I'm trying to migrate from physical machine to virtual machine GNU/Linux with KVM, continuing keeping running the physical machine during the virtualization (and thus minimization the downtime).
(still working in progress, but...)

Script to create the virtual disk with 2 partitions:

#!/bin/bash
set -e
if [ ! $UID -eq 0 ] ; then
 echo "You are not root"
 exit 1
fi
DEFAULT=5 # GB
ROOTSIZEGB=${1:-$DEFAULT}
ROOTSIZEB=$((ROOTSIZEGB * 1024 * 1024 * 1024 )) # bytes
ROOTSIZEs=$((ROOTSIZEB  / 512                )) # sector

SWAPSIZEGB=4 # GB
SWAPSIZEB=$((SWAPSIZEGB * 1024 * 1024 * 1024 )) # bytes
SWAPSIZEs=$((SWAPSIZEB  / 512                )) # sector

# 4K alignment:
#OFFSETKB=64 # KB
OFFSETKB=1024 # KB
OFFSETB=$((OFFSETKB * 1024 )) # bytes
OFFSETs=$((OFFSETB  / 512  )) # sector

DEFAULT=1
N=${2:-$DEFAULT}
LOOP=/dev/loop$N
VDISK=disk-0$N.bin
LOGFILE=$VDISK.log

if [ -f $VDISK ] ; then
   echo "$VDISK already exists!"
   echo "usage: $0 GBsize LOOPdevice"
   ls -lh $VDISK
   mount | grep $LOOP
   echo "# umount /mnt/$VDISK"
   losetup -a
   echo "# losetup -d $LOOP"
   exit 1
fi

echo "Virtual file system : $VDISK : $ROOTSIZEGB GB / + $SWAPSIZEGB swap mounted on $LOOP"
echo "Ok? (CTRL-C to quit, ENTER to continue)"
read ANSWER

CMD="qemu-img create -f raw $VDISK $((OFFSETB + ROOTSIZEB + SWAPSIZEB))"
echo "--------" | tee -a $LOGFILE
echo $CMD | tee -a $LOGFILE
echo "--------" | tee -a $LOGFILE
$CMD

#CMD="$OFFSETs,$ROOTSIZEs,83\n$((OFFSETs + ROOTSIZEs)),$((SWAPSIZEs - OFFSETs)),82"
CMD="$OFFSETs,$ROOTSIZEs,83\n$((OFFSETs + ROOTSIZEs)),,82"
echo "--------" | tee -a $LOGFILE
echo -e "$CMD  | sfdisk -S 32 -uS $VDISK" | tee -a $LOGFILE
echo "--------" | tee -a $LOGFILE
echo -e "$CMD" | sfdisk -S 32 -uS $VDISK  > /dev/null 2>&1

# check:
echo "--------" | tee -a $LOGFILE
sfdisk -l -S 32 -uS $VDISK | tee -a $LOGFILE
echo "--------" | tee -a $LOGFILE

LOOPSWAP=/dev/loop7
CMD="losetup --offset $(( OFFSETB + ROOTSIZEB )) $LOOPSWAP $VDISK"
echo -e "--------\n$CMD\n--------" | tee -a $LOGFILE
$CMD
mkswap $LOOPSWAP
sleep 1
losetup -d $LOOPSWAP

mkdir -p /mnt/$VDISK
CMD="losetup --offset $OFFSETB $LOOP $VDISK"
echo -e "--------\n$CMD\n--------" | tee -a $LOGFILE
$CMD

CMD="mkfs.ext4 -O uninit_bg,filetype,extent,dir_index -L KVM $LOOP"
echo -e "--------\n$CMD\n--------" | tee -a $LOGFILE
$CMD > /dev/null 2>&1

CMD="mount $LOOP /mnt/$VDISK"
echo -e "--------\n$CMD\n--------" | tee -a $LOGFILE
$CMD

#grub-install --force --boot-directory=/mnt/test-sda/ --no-floppy $LOOP
echo "At the end...:"
echo "umount $LOOP ; losetup -d $LOOP" | tee -a $LOGFILE

Clone physical machine:

cd /mnt/$VDISK
rsync -e ssh -au -numeric-ids --stats -h --exclude /proc --exclude /tmp --exclude /dev --exclude /sys root@REMOTEHOST:/ /mnt/$VDISK/

Chroot to VM:

mount --bind /dev/ /mnt/$VDISK/dev/
mount -t devpts pts /mnt/$VDISK/dev/pts/
mount -t tmpfs none /mnt/$VDISK/dev/shm/
mount -t proc none /mnt/$VDISK/proc/
mount -t sysfs sys /mnt/$VDISK/sys/
chroot /mnt/test/sda

Fix mtab and fstab:

vim /etc/mtab
vim /etc/fstab

Rebuild initramdisk:

mkinitrd ...

Install grub:

grub-install $LOOP

Umounting virtual image:

exit
cd ..
umount /mnt/$VDISK/sys/
umount /mnt/$VDISK/proc/
umount /mnt/$VDISK/dev/shm
umount /mnt/$VDISK/dev/pts
umount /mnt/$VDISK/dev/
umount /mnt/$VDISK/
losetup -d $LOOP

Run virtual machine:

kvm -name VMclone -m 4096 -cpu kvm32 -monitor stdio -kernel boot/vmlinuz -append "root=/dev/sda1" -initrd initrd.img $VDISK

grub:

linux /boot/vmlinux... root=/dev/sda1
initrd /boot/initrd....
boot



All correct?
pastebin link: physical2virtual.sh

Problems:
  1. PROBLEM:
    mount: could not find filesystem '/dev/root'
    kernel panic - not syncing: attempted to kill init!
    REASON: Your kernel didn't find the root partition.
    SOLUTION: still working on... :-(
    (the original Linux installation was on a LVM partition over MD-raid ...)
  2. ...

1 commento:

  1. You're creating a raw image but then you mkfs.ext4 on that file, instead of creating a partition table on it. Afterwards, you try to "boot=/dev/sda1" (I think you mean "root=/dev/sda1") which will fail because you don't have any partiton on sda.

    RispondiElimina