From b2dff45423ec768f7ad6c4f85db99d5835941ee1 Mon Sep 17 00:00:00 2001 From: James Laska Date: Wed, 22 Sep 2010 16:28:59 +0200 Subject: [PATCH] lvm: support for dynamic LVM SNAPSHOT root volume I'm looking for a way to have a system with disposable storage that can be rebooted and all filesystem changes are thrown away. After reboot, the system starts with a fresh root volume again. The use case is for automated testing. We run test scripts that could potentially not clean up after themselves. This is almost like stateless, but the storage is local to the system (not iSCSI, NFS or NBB). 1. Install Fedora 13 using default partition layout NOTE: modify the layout to leave extra room in the LVM volume group 2. Apply attached patch 3. Update grub.conf to enable dracut LVM snapshot support. Add the following boot arguments rd_LVM_SNAPSHOT=vg_test1055/lv_snap (note the VG name will depend on your system). rd_LVM_SNAPSIZE= (optional, defaults to size of volume specified with by rd_LVM_SNAPSHOT) 4. Adjust grub.conf and fstab to use LVM snapshot $ sed -i -e 's|lv_root|lv_snap|' /boot/grub/grub.conf $ sed -i -e 's|lv_root|lv_snap|' /etc/fstab 5. Reboot system Expected results (no value provided for rd_LVM_SNAPSIZE): dracut: Starting plymouth daemon dracut: rd_NO_DM: removing DM RAID activation dracut: rd_NO_MD: removing MD RAID activation dracut: Removing existing LVM snapshot vg_test1055/lv_snap dracut: Logical volume "lv_snap" successfully removed dracut: No LVM snapshot size provided, using size of vg_test1055/lv_root ( 9024.00m) dracut: Creating LVM snapshot vg_test1055/lv_snap ( 9024.00m) dracut: Logical volume "lv_snap" created dracut: Scanning devices sda2 for LVM logical volumes vg_test1055/lv_root vg_test1055/lv_swap dracut: inactive Original '/dev/vg_test1055/lv_root' [8.81 GiB] inherit dracut: inactive '/dev/vg_test1055/lv_swap' [1.00 GiB] inherit dracut: inactive Snapshot '/dev/vg_test1055/lv_snap' [8.81 GiB] inherit dracut: Mounted root filesystem /dev/mapper/vg_test1055-lv_snap dracut: Loading SELinux policy dracut: Switching root Expected results (rd_LVM_SNAPSIZE=100m): dracut: Starting plymouth daemon dracut: rd_NO_DM: removing DM RAID activation dracut: rd_NO_MD: removing MD RAID activation dracut: Removing existing LVM snapshot vg_test1055/lv_snap dracut: Logical volume "lv_snap" successfully removed dracut: Creating LVM snapshot vg_test1055/lv_snap (100m ) dracut: Rounding up size to full physical extent 128.00 MiB dracut: Logical volume "lv_snap" created dracut: Scanning devices sda2 for LVM logical volumes vg_test1055/lv_root vg_test1055/lv_swap dracut: inactive Original '/dev/vg_test1055/lv_root' [8.81 GiB] inherit dracut: inactive '/dev/vg_test1055/lv_swap' [1.00 GiB] inherit dracut: inactive Snapshot '/dev/vg_test1055/lv_snap' [128.00 MiB] inherit dracut: Mounted root filesystem /dev/mapper/vg_test1055-lv_snap dracut: Loading SELinux policy dracut: Switching root --- modules.d/90lvm/lvm_scan.sh | 82 +++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/modules.d/90lvm/lvm_scan.sh b/modules.d/90lvm/lvm_scan.sh index 0a8a6e3..5c3fb5c 100755 --- a/modules.d/90lvm/lvm_scan.sh +++ b/modules.d/90lvm/lvm_scan.sh @@ -8,6 +8,8 @@ VGS=$(getargs rd_LVM_VG=) LVS=$(getargs rd_LVM_LV=) +SNAPSHOT=$(getargs rd_LVM_SNAPSHOT=) +SNAPSIZE=$(getargs rd_LVM_SNAPSIZE=) [ -d /etc/lvm ] || mkdir -p /etc/lvm # build a list of devices to scan @@ -27,10 +29,17 @@ if [ ! -e /etc/lvm/lvm.conf ]; then done; echo '"r/.*/" ]'; echo '}'; - # establish read-only locking - echo 'global {'; - echo ' locking_type = 4'; - echo '}'; + + # establish LVM locking + if [ -n $SNAPSHOT ]; then + echo 'global {'; + echo ' locking_type = 1'; + echo '}'; + else + echo 'global {'; + echo ' locking_type = 4'; + echo '}'; + fi } > /etc/lvm/lvm.conf lvmwritten=1 fi @@ -51,29 +60,52 @@ check_lvm_ver() { nopoll=$( # hopefully this output format will never change, e.g.: # LVM version: 2.02.53(1) (2009-09-25) - lvm version 2>/dev/null | \ - ( + lvm version 2>/dev/null | ( \ IFS=. read maj min sub; maj=${maj##*:}; - sub=${sub%% *}; sub=${sub%%\(*}; - check_lvm_ver $maj $min $sub && \ - echo " --poll n ") 2>/dev/null ) - - if [ -n "$LVS" ] ; then - info "Scanning devices $lvmdevs for LVM logical volumes $LVS" - lvm lvscan --ignorelockingfailure 2>&1 | vinfo - lvm lvchange -ay --ignorelockingfailure $nopoll --ignoremonitoring $LVS 2>&1 | vinfo - fi + sub=${sub%% *}; sub=${sub%%\(*}; + check_lvm_ver $maj $min $sub && \ + echo " --poll n "; + ) 2>/dev/null +) - if [ -z "$LVS" -o -n "$VGS" ]; then - info "Scanning devices $lvmdevs for LVM volume groups $VGS" - lvm vgscan --ignorelockingfailure 2>&1 | vinfo - lvm vgchange -ay --ignorelockingfailure $nopoll --ignoremonitoring $VGS 2>&1 | vinfo - fi +if [ -n "$SNAPSHOT" ] ; then + # HACK - this should probably be done elsewhere or turned into a function + # Enable read-write LVM locking + sed -i -e 's/\(^[[:space:]]*\)locking_type[[:space:]]*=[[:space:]]*[[:digit:]]/\1locking_type = 1/' ${initdir}/etc/lvm/lvm.conf - if [ "$lvmwritten" ]; then - rm -f /etc/lvm/lvm.conf - ln -s /sbin/lvm-cleanup /pre-pivot/30-lvm-cleanup.sh 2>/dev/null - ln -s /sbin/lvm-cleanup /pre-pivot/31-lvm-cleanup.sh 2>/dev/null + # Expected SNAPSHOT format ":" + ORIG_LV=${SNAPSHOT%%:*} + SNAP_LV=${SNAPSHOT##*:} + + info "Removing existing LVM snapshot $SNAP_LV" + lvm lvremove --force $SNAP_LV 2>&1| vinfo + + # Determine snapshot size + if [ -z "$SNAPSIZE" ] ; then + SNAPSIZE=$(lvm lvs --noheadings --units m --options lv_size $ORIG_LV) + info "No LVM snapshot size provided, using size of $ORIG_LV ($SNAPSIZE)" fi - unset lvmwritten + + info "Creating LVM snapshot $SNAP_LV ($SNAPSIZE)" + lvm lvcreate -s -n $SNAP_LV -L $SNAPSIZE $ORIG_LV 2>&1| vinfo +fi + +if [ -n "$LVS" ] ; then + info "Scanning devices $lvmdevs for LVM logical volumes $LVS" + lvm lvscan --ignorelockingfailure 2>&1 | vinfo + lvm lvchange -ay --ignorelockingfailure $nopoll --ignoremonitoring $LVS 2>&1 | vinfo +fi + +if [ -z "$LVS" -o -n "$VGS" ]; then + info "Scanning devices $lvmdevs for LVM volume groups $VGS" + lvm vgscan --ignorelockingfailure 2>&1 | vinfo + lvm vgchange -ay --ignorelockingfailure $nopoll --ignoremonitoring $VGS 2>&1 | vinfo +fi + +if [ "$lvmwritten" ]; then + rm -f /etc/lvm/lvm.conf + ln -s /sbin/lvm-cleanup /pre-pivot/30-lvm-cleanup.sh 2>/dev/null + ln -s /sbin/lvm-cleanup /pre-pivot/31-lvm-cleanup.sh 2>/dev/null +fi +unset lvmwritten -- 2.7.4