[linux-lvm] Script to import hardware snapshoted VGs
chris procter
chris-procter at talk21.com
Thu May 7 22:05:17 UTC 2009
Hi,
After getting kicking from Alasdair at a conference a few weeks ago for asking him about Netapp snapshots I decided it would by useful to implement http://sources.redhat.com/lvm2/wiki/HardwareSnapshotRestore (step 5 onwards) as a script. I've tested it on RHEL 5 and it seems pretty solid but I don't quite know the best way to release it to the world so here it is, all comments and advice gratefully received :)
I will get around to writing a man page, but in the meantime
1) present in your clone luns
2) figure out what devices they appear as
3) run importclone /dev/sda /dev/sdb /dev/sdc (replacing /dev/sda etc by your clone luns obviously)
If your VG is called myvg you should now also have a new vg called myvg.1 with different uuids. It will ignore incomplete volume groups, or exported volume groups unless the -i flag is used.
chris
P.S. I'm using ascii 001 and 002 characters as seperators which might get mangled by email sorry :(
################# importclone #############################
!/bin/sh
# Copyright (C) 2009 Chris Procter All rights reserved.
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
exec 2> ./$0.log
set -x
function appenddisk {
### add a blockdevice path (/dev/sda etc) to a list if its valid
LIST=$1
DISK=$2
if [ ! -b "${DISK}" ]
then
echo " ${DISK} not a valid block device - ignoring" >&2
echo "${LIST}"
return
fi
if [ -z "${LIST}" ]
then
LIST="${DISK}"
else
LIST="${LIST} ${DISK}"
fi
echo ${LIST}
}
function getvgname {
### get a unique vg name
### $1 = list of exists VGs
### $2 = the name we want
VGLIST=$1
VG=$2
NEWVG=$3
BASENAME="${NEWVG:-${VG}}"
NAME="${BASENAME}"
I=0
while [[ "${VGLIST}" =~ "${NAME}" ]]
do
I=$(($I+1))
NAME="${BASENAME}.$I"
done
echo "${NAME}"
}
function checkvalue {
### check return value and error if non zero
if [ $1 -ne 0 ]
then
echo "FAIL!: $2 value: $1"
exit $1
fi
}
function usage {
### display usage message
SCRIPT=`basename $0`
echo "${SCRIPT} - Restore LVM data from a hardware snapshot"
echo -e "Usage: ${SCRIPT} [disk1...]"
echo -e "\t\t-h\t\t- Display this usage message"
echo -e "\t\t-i\t\t- Import any exported volume groups found"
echo -e "\t\t-n\t\t- Name for the new volume group(s)"
echo -e "\t\t-l [path]\t - location of lvm.conf (default ${LVMCONF})"
echo -e "\t\t-t [path]\t - directory for temporary lvm directory (default ${TMPDIR})"
exit 0
}
function cleanup {
#set to use old lvm.conf
LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR}
}
SHOW=0
DISKS=""
LVMCONF="/etc/lvm/lvm.conf"
TMPDIR="/tmp/lvm"
NOVGFLAG=0
IMPORT=0
export ORIG_LVM_SYS_DIR=${LVM_SYSTEM_DIR}
trap cleanup 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#####################################################################
### Get and check arguments
#####################################################################
while [ $# -ne 0 ]
do
case $1 in
-h) usage
shift
;;
-i) IMPORT=1
shift
;;
-l) LVMCONF="$2"
shift
shift
;;
-t) TMPDIR="$2"
shift
shift
;;
-n) NEWVG="$2"
shift
shift
;;
*)
DISKS=`appenddisk "${DISKS}" "$1"`;
shift
;;
esac
done
### check we have suitable values for important variables
if [ -z "${DISKS}" ]
then
usage
fi
#####################################################################
### Get the existing state so we can use it later
#####################################################################
#pvs --noheadings --trustcache 2>/dev/null
OLDVGS=`pvs --noheadings --trustcache 2>/dev/null | awk '(NF==6){printf("%s ",$2)}'`
#####################################################################
### Prepare the temporay lvm environment
#####################################################################
if [ ! -d "${TMPDIR}" ]
then
mkdir "${TMPDIR}"
checkvalue $? "Unable to create ${TMPDIR}"
fi
###create filter
for BLOCK in ${DISKS}
do
FILTER="\"a|^${BLOCK}$|\",${FILTER}"
done
FILTER="filter=[ ${FILTER} \"r|.*|\" ]"
awk -v var="${FILTER}" '/^[[:space:]]*filter/{print var;next};{print $0}' < ${LVMCONF} > ${TMPDIR}/lvm.conf
### set to use new lvm.conf
export LVM_SYSTEM_DIR=${TMPDIR}
#####################################################################
### Change the uuids.
#####################################################################
PVSCAN=`pvscan`
VGS=`echo "${PVSCAN}" |awk '$1~/PV/{for(i=1;i<=NF;i++){if($i=="VG"){vg[$(i+1)]=vg[$(i+1)]""$2}if($i=="exported"){x[$(i+2)]="x"}}}END{for(k in vg){printf k""x[k]""vg[k]" "}}'`
echo "$VGS"
for VG in ${VGS}
do
VGNAME=`echo -e "${VG}" |cut -d -f1`
EXPORTED=`echo -e "${VG}" | cut -d -f2`
PVLIST=`echo -e "${VG}" | cut -d -f3`
if [ -n "${EXPORTED}" ]
then
if [ ${IMPORT} -eq 1 ]
then
vgimport ${VGNAME}
else
echo "Volume Group ${VGNAME} exported, skipping."
continue
fi
fi
### change the pv uuids
BLOCKDEVS=`echo ${PVLIST} | tr '' ' '`
if [ "${PVLIST}" =~ "unknown" ]
then
echo "Volume Group ${VGNAME} incomplete, skipping."
continue
fi
for BLOCKDEV in ${BLOCKDEVS}
do
pvchange --uuid ${BLOCKDEV} --config 'global{activation=0}'
checkvalue $? "Unable to change pvuuid for ${BLOCKDEV}"
done
NEWVGNAME=`getvgname "${OLDVGS}" "${VGNAME}" "${NEWVG}"`
vgchange --uuid ${VGNAME} --config 'global{activation=0}'
checkvalue $? "Unable to change vguuid for ${VGNAME}"
## if the name isn't going to get changed dont even try.
if [ "${VGNAME}" != "${NEWVGNAME}" ]
then
vgrename "${VGNAME}" "${NEWVGNAME}"
checkvalue $? "Unable to rename ${VGNAME} to ${NEWVGNAME}"
fi
done
#####################################################################
### Restore the old environment
#####################################################################
### set to use old lvm.conf
LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR}
### make sure all the device nodes we need are straight
vgmknodes >/dev/null
### sort out caches.
pvscan
exit 0
More information about the linux-lvm
mailing list