Tuesday, July 24, 2012

Linux Howto: Clone your active system to get a N-1 OS version available in case of update troubles or instability




If you are in the same situation as i am, your Linux XBMC Box became the Multimedia center for all the family, let's say it's now in "production" and as any client would, they won't accept any downtime due to system or application upgrade issue :-)

There is off course several solutions you may use to backup and restore your system if required, in my opinion the easiest is to have a secondary N-1 version system available and ready to run in case the last update you absolutely had to applied (because you're such a geek you cannot keep running an outdated system ^^) broke your nice and stable installation!

Naturally, this will be applicable for any Linux installation.


************************ CAUTION ***************************************************************

These operations may easily break your system if you don't pay attention, 
please follow this Howto with many cautions and very carefully!


*************************************************************************************************


Methods and requirements:


I recommend the following method using "partclone" to clone your system.

First and in any case, ensure you have a secondary partition with a size strictly identical to your base system. (obligatory for partclone)

This secondary partition will be uased by our cloned system.

Also, i would recommend you install "/home"' under a dedicated third partition.

So, let's say as an example you installation is partitioned that way (all formatted in ext4) :

  • "/dev/sda1" is your main OS installation
  • "/dev/sda2" will be your N-1 OS version
  • "/dev/sda3" is your "/home" partition

Note: With partclone, your 2 system partitions must have strictly the same size, use Gparted when you are in your Live OS to modify your partitions as required, you resize, create move and so on.
But be careful, you can easily break everything if you don't pay attention ^^


Clone your system with partclone


Limitations and constraints:

You can't clone a partition being used and mounted, so the easiest method is to use a USB Live Distribution you will use to boot and clone your system.

This is very easy, just download any Linux distribution (i recommend Xubuntu) and use "Unetbootin" to create the Live USB key.

Also, ensure your live system will be able to access to Internet as you will need to install some packages.

Step 1: Boot to Live OS


Insert your Live USB Key and boot the system, when the system is ready install some requirements:
sudo apt-get install partclone
Notes: Ensure you are connected to Internet before the apt-get, no need to update first but you also can do it if you want


Step 2: Clone the system


Recommended:

I recommend to first backup the partition to an external image you may need later and after that restoring it to the secondary partition:

First check and correct the filesystem if required:
sudo fsck.ext4 -yf /dev/sda1

Clone sda1 to an external image:
sudo partclone.ext4 -c -d -s /dev/sda1 -o <MY DESTINATION FOLDER>/sda1_partclone_ext4_MMDDYYYY.img

Restore sda1 image to sda2 partition:
sudo partclone.ext4 -r -d -s <MY DESTINATION FOLDER>/sda1_partclone_ext4_MMDDYYYY.img -o /dev/sda2

Step 3: Update secondary partition UUID and Label



This a very important operation, i you don't update the secondary partition UUID, it will have the same than your first OS and you can be sure you're going into big troubles!

Install requirements:
sudo apt-get install uuid e2label

List actual UUID, sda1 and sda2 have the same UUID and same label which is really is bad thing:

sudo blkid
Note: You can also use the command "sudo tune2fs -l /dev/sda1 | grep UUID"

Output example before update:
/dev/sda1: LABEL="SYSTEM1" UUID="affe0f48-6b88-43a5-b131-20a58cd776b8" TYPE="ext4"                                                          
/dev/sda2: LABEL="SYSTEM1" UUID="affe0f48-6b88-43a5-b131-20a58cd776b8" TYPE="ext4"

Update "/dev/sda2" UUID:
sudo tune2fs -U `uuid` /dev/sda2

Update "/dev/sda2" Label:
sudo e2label /dev/sda2 SYSTEM2

Check and note the new configuration:
sudo blkid
/dev/sda1: LABEL="SYSTEM1" UUID="affe0f48-6b88-43a5-b131-20a58cd776b8" TYPE="ext4"                                                          
/dev/sda2: LABEL="SYSTEM2" UUID="8e1e225a-d51e-11e1-b5aa-00012e409020" TYPE="ext4"

Everything is fine, we have different UUID and Labels for both partitions, let's mount the secondary partition and update "/etc/fstab" with this new information:

Mount the partition:
sudo mkdir /mnt/sda2 && sudo mount -t ext4 /dev/sda2 /mnt/sda2

Edit "/mnt/sda2/etc/fstab" and replace initial UUID by the new one, in this example we replace:
UUID=affe0f48-6b88-43a5-b131-20a58cd776b8 /               ext4    errors=remount-ro,noatime 0       1                                       

By:
UUID=8e1e225a-d51e-11e1-b5aa-00012e409020 /               ext4    errors=remount-ro,noatime 0       1                                       

Save and umount the partition:
sudo umount /dev/sda2 && sudo rm -rf /mnt/sda2


Step 4: Reboot to main system and update grub


Notes: Os prober from Grub should be able to generate a functional boot configuration finding our cloned system in "/dev/sda2", for an unknown reason this doesn't work so i recommend a manual operation which will be more reliable.


Leave the Live USB system and reboot to the main system, then open "/boot/grub/grub.cfg" and copy main system boot lines to clipboard or a temporary text editor, in our example we will find the original kernel lines:
menuentry 'Ubuntu, avec Linux 3.2.0-26-generic' --class ubuntu --class gnu-linux --class gnu --class os {                                   
        recordfail                                                                                                                          
        gfxmode $linux_gfx_mode                                                                                                             
        insmod gzio                                                                                                                         
        insmod part_msdos                                                                                                                   
        insmod ext2                                                                                                                         
        set root='(hd0,msdos1)'                                                                                                             
        search --no-floppy --fs-uuid --set=root affe0f48-6b88-43a5-b131-20a58cd776b8                                                        
        linux   /boot/vmlinuz-3.2.0-26-generic root=UUID=affe0f48-6b88-43a5-b131-20a58cd776b8 ro   quiet splash $vt_handoff                 
        initrd  /boot/initrd.img-3.2.0-26-generic                                                                                           
}                                                                                                                                           
menuentry 'Ubuntu, avec Linux 3.2.0-26-generic (mode de dépannage)' --class ubuntu --class gnu-linux --class gnu --class os {               
        recordfail                                                                                                                          
        insmod gzio                                                                                                                         
        insmod part_msdos                                                                                                                   
        insmod ext2                                                                                                                         
        set root='(hd0,msdos1)'                                                                                                             
        search --no-floppy --fs-uuid --set=root affe0f48-6b88-43a5-b131-20a58cd776b8                                                        
        echo    'Chargement de Linux 3.2.0-26-generic ...'                                                                                  
        linux   /boot/vmlinuz-3.2.0-26-generic root=UUID=affe0f48-6b88-43a5-b131-20a58cd776b8 ro recovery nomodeset                         
        echo    'Chargement du disque mémoire initial ...'                                                                                  
        initrd  /boot/initrd.img-3.2.0-26-generic                                                                                           
} 


Add "(on /dev/sda2) behind the kernel version in "menuentry" and replace "msdos1" by "msdos2" and the old UUID by the new one and put these lines into "/etc/grub.d/40_custom", in our example our new lines will be:
menuentry "Ubuntu, avec Linux 3.2.0-26-generic (on /dev/sda2)" --class gnu-linux --class gnu --class os {                                   
        recordfail                                                                                                                          
        gfxmode $linux_gfx_mode                                                                                                             
        insmod gzio                                                                                                                         
        insmod part_msdos                                                                                                                   
        insmod ext2                                                                                                                         
        set root='(hd0,msdos2)'                                                                                                             
        search --no-floppy --fs-uuid --set=root 8e1e225a-d51e-11e1-b5aa-00012e409020                                                        
        linux /boot/vmlinuz-3.2.0-26-generic root=UUID=8e1e225a-d51e-11e1-b5aa-00012e409020 ro quiet splash $vt_handoff                     
        initrd /boot/initrd.img-3.2.0-26-generic                                                                                            
}                                                                                                                                           
menuentry "Ubuntu, avec Linux 3.2.0-26-generic (mode de dépannage) (on /dev/sda2)" --class gnu-linux --class gnu --class os {               
        recordfail                                                                                                                          
        insmod gzio                                                                                                                         
        insmod part_msdos                                                                                                                   
        insmod ext2                                                                                                                         
        set root='(hd0,msdos2)'                                                                                                             
        search --no-floppy --fs-uuid --set=root 8e1e225a-d51e-11e1-b5aa-00012e409020                                                        
        linux /boot/vmlinuz-3.2.0-26-generic root=UUID=8e1e225a-d51e-11e1-b5aa-00012e409020 ro recovery nomodeset                           
        initrd /boot/initrd.img-3.2.0-26-generic                                                                                            
}  

Update grub:
sudo update-grub 


Reboot from your main system and test booting to the secondary OS, it should boot with no problem and you will get exactly the same system than the main one.

You can test whatever you need in the secondary system such as important system and application upgrade without the risk of breaking down your main system.

Therefore, don't forget that if you have a third partition for "/home", any issue not related to the system partition but related to the home partition (such as deleting user's files) will off course exist in both systems!

So a best practice will always be to also backup the /home partition ^^

As now you have 2 systems available, if you want to update the secondary system, you don't have to boot again with a Live OS:

  • Boot to secondary system
  • Create the partclone image from primary system to an external image
  • Boot to primary system
  • Restore the external image to secondary partition
  • Re do UUID change and fstab correction


Step 5: Optional - Home Directory


If you want to be completely independent of your first installation, you may also copy your initial main user home directory, example to "/home/user_system2".

Then just ensure to change the home directory in your second system by editing "/etc/passwd". (remember to adapt from where you edit it)





Feel free to comment :-)