Clone Physical to Virtual and Back, Revisited2018-06-212019-05-14Richard Ketcham

Our beta-test kiosk-workstation is now tested and so this system is ready to clone to our other workstation.

The following procedures take off from where, in my previous article, I created a tar backup of system root filesystem (i.e. ‘/’).

In the mean time, the buzzard learned how to attach a physical disk to a VirtualBox VM.

#mount a physical disk
 VBoxManage internalcommands createrawvmdk -filename "</path/to/file>.vmdk" -rawdisk /dev/sda

This will be useful, because I can clone directly to a harddrive and boot it in a VM to test and configure, and then pop the HD into the physical machine, thereby minimizing downtime of the target workstation, with one less step where things could go wrong.

I start by creating a VM with my physical disk attached, and pxe booting it from my CentOS 7 kickstart server.  My kickstart configuration partitions the physical drive with a boot partition,  and an LVM PV with a VG on the remainder of the physical drive, from which I carve a small LV, onto which I will install a minimal bootable OS, which, as I will show, comes in handy as I get the cloned system up and running.

After the kickstart installation, I reboot my VM into this minimal CentOS 7 and I carve off another LV into which I will untar my clone backup.  This will become my new, cloned, slash (/) filesystem.

[root@C7-64-minimus ~]# lvcreate -a y -n avrootvol --size 20G -v vg_01
[root@C7-64-minimus ~]# mkfs.ext4 -L avsysroot /dev/mapper/vg_01-avrootvol
[root@C7-64-minimus ~]# mkdir /mnt/avrootvol
[root@C7-64-minimus ~]# mount /dev/mapper/vg_01-avrootvol /mnt/avrootvol

(I prefer to create my LVM volumes small, because I can easily grow them later, as needed.)

I now need my backup tar file.  I have copied it to my VirtualBox host machine and I will use the VirtualBox file share feature to make it accessible from my booted VM.  First I need to install VirtualBox Guest Additions to enable this feature. and then create my vbox share in the “devices” menu.

[root@C7-64-minimus ~]# mkdir /mnt/shared
[root@C7-64-minimus ~]# mount -t vboxsf Shared /mnt/shared

Now I am set to untar:

[root@C7-64-minimus ~]# cd /mnt/avrootvol
[root@C7-64-minimus avrootvol]# tar xzf /mnt/shared/2018.06.19/av301_root.tgz --numeric-owner

The –numeric-owner flag prevents tar from resetting file uid and gid numbers as it does by default, by matching names from /etc/passwd and /etc/group.  These would then no longer match after I reboot into the cloned OS.

Now I need to make changes in my boot partition so that I can boot my newly cloned system.  This will require recreating /boot/grub/grub.cfg and also /boot/initramfs-*.  In particular, the existing initramfs contains references by UUID to the kickstart-installed root filesystem (what was installed on the currently booted (/) root partition) and so , short of cloning the UUID, it is tied to that partition.  In my previous article, I took a quick-and-dirty shortcut around this problem by untarring the cloned system onto, and thus overwriting, that existing root filesystem, so that I could reuse the existing initramfs as-is.   Now, instead, I am going to fully recreate that initramfs, starting by chrooting into the new root filesystem.

 [root@C7-64-minimus avrootvol]# mount --bind /proc ./proc
 [root@C7-64-minimus avrootvol]# mount --bind /sys ./sys
 [root@C7-64-minimus avrootvol]# mount --bind /dev ./dev
 [root@C7-64-minimus avrootvol]# chroot /mnt/avrootvol
 bash-4.2#

As I will be rebooting between different OS installation instances, I want to use human-friendly partition labels instead of the default UUID labels (actually, these are file system labels correctly speaking, not partition labels) . Labels will keep things portable and less confusing to a buzzard like Ricky.

 bash-4.2# e2label /dev/sda1 boot
 bash-4.2# e2label /dev/mapper/vg_01-avrootvol avsysroot
 bash-4.2# e2label /dev/mapper/vg_01-homevol home
 bash-4.2# e2label /dev/mapper/vg_01-optvol opt
 bash-4.2# swaplabel -L swap1 /dev/mapper/vg_01-swapvol

I am going to edit the /etc/fstab to use these labels (note that I am now working in my chrooted environment):

 bash-4.2# vi /etc/fstab
 bash-4.2# cat /etc/fstab
 LABEL=boot /boot ext3 defaults 0 0
 LABEL=avsysroot / ext4 defaults 0 0
 LABEL=home /home ext4 defaults 0 0
 LABEL=opt /opt ext4 defaults 0 0
 LABEL=swap1 swap swap defaults 0 0
 ## brukerdata disk
 #LABEL=brukerdata2011 /brukerdata2011 ext3 defaults,usrquota 1 2
 ## bind mount for export
 #/brukerdata2011 /export/avxxx bind bind,auto 0 0

The last two, commented out, lines are for an external hard drive that will be installed later and will be nfs4 exported.

I am ready now to make changes to /boot.

Recall that I am operating on my physical disk that is booted as a VirtualBox VM and I have created a new partition into which and I have untarred the filesystem I am cloning, that I want to become my new system partition after I reboot.  I am chrooted into this new system partition.  My /boot partition on  /dev/sda1 will remain the same, so now I need to create a new initial ramdisk there and also a new grub configuration file, which will boot to my new system partition. I could, straightforwardly, mount the /boot partition first:

bash-4.2# mount LABEL=boot /boot

and write directly to it.  But to be timidly cautious, I will leave my functional /boot on /dev/sda1 unchanged for now and make a copy of it in the  /boot directory of my chrooted system filesystem.  Then after I have created my new initramfs and grub.cfg in this copied /boot directory I will copy these back to the /boot  filesystem on /dev/sda1:

bash-4.2# mkdir /mnt/boot
bash-4.2# mount LABEL=boot /mnt/boot
bash-4.2# cp -a /mnt/boot/* /boot/

A less obvious advantage to this method is that a redundant copy of the boot system is created in the boot directory of the system partition, which will be safely hidden when it is over-mounted with the /boot partition, but will be there in case needed for boot recovery emergency.

The next steps are the same either way.

Before recreating the boot system, I need to update my kernel so that the version of kernel modules in /lib/modules matches the version installed in /boot.

bash-4.2# yum --disableexcludes=all update kernel\*

(‘–disableexcludes’ because I have kernel updates excluded in /etc/yum.conf out of concern for system stability)

Now create a new initramfs:

bash-4.2# dracut --force --no-hostonly --persistent-policy by-label

The –persistent-policy by-label flag should configure the new initramfs to use my human-friendly labels instead of UUIDs.

and also re-create grub.cfg:

bash-4.2# grub2-mkconfig -o /boot/grub2/grub.cfg

I shouldn’t need to reinstall grub because it is already installed onto my /dev/sda hard drive and /dev/sda1 boot partition, which recall, was created by my kickstart.  That’s one less thing that could go wrong.

So now I would have everything in place to reboot into the cloned  system.  Or, since I chose the timidly cautious method, there is the final step of copying  my changes back to the real boot partition:

[CTRL-D] (exit chroot)

Recall that my new system partition is still mounted as /mnt/avrootvol.  I am going to cautiously save my old initramfs vmlinuzes, and grub.cfg, leaving a trail of bread crumbs, just in case things go sideways when I attempt to reboot my new system.

cd /mnt/avrootvol/boot
mkdir -p /boot.save/grub2
mv /boot/vmlinuz* /boot.save
mv /boot/initramfs-* /boot.save
mv /boot/grub2/grub.* /boot.save/grub2/
rsync -av /mnt/avrootvol/boot/ /boot

And now just

bash-4.2# reboot