From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29153 invoked by alias); 14 May 2009 16:46:17 -0000 Received: (qmail 29133 invoked by uid 9805); 14 May 2009 16:46:16 -0000 Date: Thu, 14 May 2009 16:46:00 -0000 Message-ID: <20090514164616.29131.qmail@sourceware.org> From: snitzer@sourceware.org To: lvm-devel@redhat.com, lvm2-cvs@sourceware.org Subject: LVM2 ./WHATS_NEW man/Makefile.in man/lvm.8.in ... Mailing-List: contact lvm2-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: lvm2-cvs-owner@sourceware.org X-SW-Source: 2009-05/txt/msg00029.txt.bz2 CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: snitzer@sourceware.org 2009-05-14 16:46:13 Modified files: . : WHATS_NEW man : Makefile.in lvm.8.in scripts : Makefile.in Added files: man : vgimportclone.8.in scripts : vgimportclone.sh Log message: Add vgimportclone and install it and the man page by default. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1111&r2=1.1112 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/vgimportclone.8.in.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/Makefile.in.diff?cvsroot=lvm2&r1=1.26&r2=1.27 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvm.8.in.diff?cvsroot=lvm2&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/scripts/vgimportclone.sh.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/scripts/Makefile.in.diff?cvsroot=lvm2&r1=1.8&r2=1.9 --- LVM2/WHATS_NEW 2009/05/13 21:29:10 1.1111 +++ LVM2/WHATS_NEW 2009/05/14 16:46:12 1.1112 @@ -1,5 +1,6 @@ Version 2.02.46 - ================================ + Add vgimportclone and install it and the man page by default. Force max_lv restriction only for newly created LV. Remove unneeded import parameter from lv_create_empty. Merge lv_is_displayable and lv_is_visible functions. /cvs/lvm2/LVM2/man/vgimportclone.8.in,v --> standard output revision 1.1 --- LVM2/man/vgimportclone.8.in +++ - 2009-05-14 16:46:15.152373000 +0000 @@ -0,0 +1,58 @@ +.TH VGIMPORTCLONE 8 "LVM TOOLS #VERSION#" "Red Hat, Inc." \" -*- nroff -*- +.SH NAME +vgimportclone \- import and rename duplicated volume group (e.g. a hardware snapshot) +.SH SYNOPSIS +.B vgimportclone +[\-n|\-\-basevgname VolumeGroupName] +[\-i|\-\-import] +PhysicalVolume [PhysicalVolume...] +.SH DESCRIPTION +.B vgimportclone +is used to import a duplicated VG (e.g. hardware snapshot). Duplicate VG(s) +and PV(s) are not able to be used until they are made to coexist with +the origin VG(s) and PV(s). +.B vgimportclone +renames the VG associated with the specified PV(s) and changes the +associated VG and PV UUIDs. +.SH OPTIONS +See \fBlvm\fP for common options. +.TP +.I \-n|\-\-basevgname VolumeGroupName +By default the snapshot VG will be renamed to the original name plus a +numeric suffix to avoid duplicate naming (e.g. 'test_vg' would be renamed +to 'test_vg1'). This option will override the base VG name that is +used for all VG renames. If a VG already exists with the specified name +a numeric suffix will be added (like the previous example) to make it unique. +.TP +.I \-i|\-\-import +Import exported Volume Groups. Otherwise VGs that have been exported +will not be changed (nor will their associated PVs). +.SH ENVIRONMENT VARIABLES +.TP +\fBLVM_BINARY\fP +The LVM2 binary to use. +Defaults to "lvm". +.SH EXAMPLES +If origin VG +.B test_vg +has PVs +.BR /dev/loop0 " and " /dev/loop1 +and +.BR /dev/loop2 " and " /dev/loop3 +are respective snapshot PVs of the origin PVs. +To rename the VG +associated with +.BR /dev/loop2 " and " /dev/loop3 +from +.B test_vg +to +.B test_vg_snap +(and change associated VG and PV UUIDs): +.nf + +\ vgimportclone --basevgname test_vg_snap /dev/loop2 /dev/loop3 + +.fi +.SH SEE ALSO +.BR lvm (8) + --- LVM2/man/Makefile.in 2009/05/11 10:28:46 1.26 +++ LVM2/man/Makefile.in 2009/05/14 16:46:13 1.27 @@ -29,8 +29,8 @@ lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \ pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \ vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \ - vgimport.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 vgrename.8 \ - vgs.8 vgscan.8 vgsplit.8 $(FSADMMAN) + vgimport.8 vgimportclone.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 \ + vgrename.8 vgs.8 vgscan.8 vgsplit.8 $(FSADMMAN) MAN8CLUSTER=clvmd.8 MAN8DM=dmsetup.8 MAN5DIR=${mandir}/man5 --- LVM2/man/lvm.8.in 2009/02/20 01:47:02 1.2 +++ LVM2/man/lvm.8.in 2009/05/14 16:46:13 1.3 @@ -95,6 +95,8 @@ .TP \fBvgimport\fP \(em Make exported volume groups known to the system. .TP +\fBvgimportclone\fP \(em Import and rename duplicated volume group (e.g. a hardware snapshot). +.TP \fBvgmerge\fP \(em Merge two volume groups. .TP \fBvgmknodes\fP \(em Recreate volume group directory and logical volume special files @@ -307,6 +309,7 @@ .BR vgdisplay (8), .BR vgextend (8), .BR vgimport (8), +.BR vgimportclone (8), .BR vgmerge (8), .BR vgmknodes (8), .BR vgreduce (8), /cvs/lvm2/LVM2/scripts/vgimportclone.sh,v --> standard output revision 1.1 --- LVM2/scripts/vgimportclone.sh +++ - 2009-05-14 16:46:16.074811000 +0000 @@ -0,0 +1,334 @@ +#!/bin/sh + +# Copyright (C) 2009 Chris Procter All rights reserved. +# Copyright (C) 2009 Red Hat, Inc. All rights reserved. +# +# This file is part of LVM2. +# +# 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 +# +# vgimportclone: This script is used to rename the VG and change the associated +# VG and PV UUIDs (primary application being HW snapshot restore) + +# following external commands are used throughout the script +# echo and test are internal in bash at least +RM=rm +BASENAME=basename +MKTEMP=mktemp +AWK=awk +CUT=cut +TR=tr +READLINK=readlink +GREP=grep +GETOPT=getopt + +# user may override lvm location by setting LVM_BINARY +LVM="${LVM_BINARY:-lvm}" + +die() { + code=$1; shift + echo "Fatal: $@" 1>&2 + exit $code +} + +"$LVM" version >& /dev/null || die 2 "Could not run lvm binary '$LVM'" + + +function getvgname { +### get a unique vg name +### $1 = list of exists VGs +### $2 = the name we want + VGLIST=$1 + VG=$2 + NEWVG=$3 + + BNAME="${NEWVG:-${VG}}" + NAME="${BNAME}" + I=0 + + while [[ "${VGLIST}" =~ "${NAME}" ]] + do + I=$(($I+1)) + NAME="${BNAME}$I" + done + echo "${NAME}" +} + + +function checkvalue { +### check return value and error if non zero + if [ $1 -ne 0 ] + then + die $1 "$2, error: $1" + fi +} + + +function usage { +### display usage message + echo "Usage: ${SCRIPTNAME} [options] PhysicalVolume [PhysicalVolume...]" + echo " -n|--basevgname - Base name for the new volume group(s)" + echo " -i|--import - Import any exported volume groups found" + echo " -t|--test - Run in test mode" + echo " --quiet - Suppress output" + echo " -v|--verbose - Set verbose level" + echo " -d|--debug - Set debug level" + echo " --version - Display version information" + echo " -h|--help - Display this help message" + echo "" + exit 1 +} + + +function cleanup { + #set to use old lvm.conf + LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR} + + "$RM" -rf -- "${TMP_LVM_SYSTEM_DIR}" +} + +SCRIPTNAME=`"$BASENAME" $0` + + +if [ "$UID" != "0" -a "$EUID" != "0" ] +then + die 3 "${SCRIPTNAME} must be run as root." +fi + +LVM_OPTS="" +TEST_OPT="" +DISKS="" +# for compatibility: using mktemp -t rather than --tmpdir +TMP_LVM_SYSTEM_DIR=`"$MKTEMP" -d -t snap.XXXXXXXX` +IMPORT=0 +DEBUG="" +VERBOSE="" +DEVNO=0 + +if [ -n "${LVM_SYSTEM_DIR}" ]; then + export ORIG_LVM_SYS_DIR="${LVM_SYSTEM_DIR}" +fi + +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 +##################################################################### +OPTIONS=`"$GETOPT" -o n:dhitv \ + -l basevgname:,debug,help,import,quiet,test,verbose,version \ + -n "${SCRIPTNAME}" -- "$@"` +[ $? -ne 0 ] && usage +eval set -- "$OPTIONS" + +while true +do + case $1 in + -n|--basevgname) + NEWVG="$2"; shift; shift + ;; + -i|--import) + IMPORT=1; shift + ;; + -t|--test) + TEST_OPT="-t" + shift + ;; + --quiet) + LVM_OPTS="--quiet ${LVM_OPTS}" + shift + ;; + -v|--verbose) + if [ -z "$VERBOSE" ] + then + VERBOSE="-v" + else + VERBOSE="${VERBOSE}v" + fi + shift + ;; + -d|--debug) + if [ -z "$DEBUG" ] + then + DEBUG="-d" + set -x + else + DEBUG="${DEBUG}d" + fi + shift + ;; + --version) + "$LVM" version + shift + exit 0 + ;; + -h|--help) + usage; shift + ;; + --) + shift; break + ;; + *) + usage + ;; + esac +done + +# process remaining arguments (which should be disks) +for ARG +do + if [ -b "$ARG" ] + then + ln -s "$ARG" ${TMP_LVM_SYSTEM_DIR}/vgimport${DEVNO} + DISKS="${DISKS} ${TMP_LVM_SYSTEM_DIR}/vgimport${DEVNO}" + DEVNO=$((${DEVNO}+1)) + else + die 3 "$ARG is not a block device." + fi +done + +# setup LVM_OPTS +if [ -n "${DEBUG}" -o -n "${VERBOSE}" ] +then + LVM_OPTS="${LVM_OPTS} ${DEBUG} ${VERBOSE}" +fi + +### check we have suitable values for important variables +if [ -z "${DISKS}" ] +then + usage +fi + +##################################################################### +### Get the existing state so we can use it later +##################################################################### + +OLDVGS=`"${LVM}" vgs ${LVM_OPTS} -o name --noheadings 2>/dev/null` +checkvalue $? "Current VG names could not be collected without errors" + +##################################################################### +### Prepare the temporary lvm environment +##################################################################### + +for BLOCK in ${DISKS} +do + FILTER="\"a|^${BLOCK}$|\", ${FILTER}" +done +export FILTER="filter=[ ${FILTER} \"r|.*|\" ]" + +LVMCONF=${TMP_LVM_SYSTEM_DIR}/lvm.conf + +"$LVM" dumpconfig ${LVM_OPTS} | \ +"$AWK" -v DEV=${TMP_LVM_SYSTEM_DIR} -v CACHE=${TMP_LVM_SYSTEM_DIR}/.cache \ + -v CACHE_DIR=${TMP_LVM_SYSTEM_DIR}/cache \ + '/^[[:space:]]*filter[[:space:]]*=/{print ENVIRON["FILTER"];next} \ + /^[[:space:]]*scan[[:space:]]*=/{print "scan = [ \"" DEV "\" ]";next} \ + /^[[:space:]]*cache[[:space:]]*=/{print "cache = \"" CACHE "\"";next} \ + /^[[:space:]]*cache_dir[[:space:]]*=/{print "cache_dir = \"" CACHE_DIR "\"";next} \ + {print $0}' > ${LVMCONF} + +checkvalue $? "Failed to generate ${LVMCONF}" + +# verify the config contains the filter, scan and cache_dir (or cache) config keywords +"$GREP" -q '^[[:space:]]*filter[[:space:]]*=' ${LVMCONF} || \ + die 5 "Temporary lvm.conf must contain 'filter' config." +"$GREP" -q '^[[:space:]]*scan[[:space:]]*=' ${LVMCONF} || \ + die 6 "Temporary lvm.conf must contain 'scan' config." + +# check for either 'cache' or 'cache_dir' config values +"$GREP" -q '[[:space:]]*cache[[:space:]]*=' ${LVMCONF} +CACHE_RET=$? +"$GREP" -q '^[[:space:]]*cache_dir' ${LVMCONF} +CACHE_DIR_RET=$? +[ $CACHE_RET -eq 0 -o $CACHE_DIR_RET -eq 0 ] || \ + die 7 "Temporary lvm.conf must contain 'cache' or 'cache_dir' config." + +### set to use new lvm.conf +export LVM_SYSTEM_DIR=${TMP_LVM_SYSTEM_DIR} + + +##################################################################### +### Rename the VG(s) and change the VG and PV UUIDs. +##################################################################### + +PVINFO=`"${LVM}" pvs ${LVM_OPTS} -o pv_name,vg_name,vg_attr --noheadings --separator : 2>/dev/null` +checkvalue $? "PV info could not be collected without errors" + +# output VG info so each line looks like: name:exported?:disk1,disk2,... +VGINFO=`echo "${PVINFO}" | \ + "$AWK" -F : '{{sub(/^[[:space:]]*/,"")} \ + {vg[$2]=$1","vg[$2]} if($3 ~ /^..x/){x[$2]="x"}} \ + END{for(k in vg){printf("%s:%s:%s\n", k, x[k], vg[k])}}'` +checkvalue $? "PV info could not be parsed without errors" + +for VG in ${VGINFO} +do + VGNAME=`echo "${VG}" | "$CUT" -d: -f1` + EXPORTED=`echo "${VG}" | "$CUT" -d: -f2` + PVLIST=`echo "${VG}" | "$CUT" -d: -f3- | "$TR" , ' '` + + if [ -z "${VGNAME}" ] + then + FOLLOWLIST="" + for DEV in $PVLIST; do + FOLLOW=`"$READLINK" $DEV` + FOLLOWLIST="$FOLLOW $FOLLOWLIST" + done + die 8 "Specified PV(s) ($FOLLOWLIST) don't belong to a VG." + fi + + if [ -n "${EXPORTED}" ] + then + if [ ${IMPORT} -eq 1 ] + then + "$LVM" vgimport ${LVM_OPTS} ${TEST_OPT} "${VGNAME}" + checkvalue $? "Volume Group ${VGNAME} could not be imported" + else + echo "Volume Group ${VGNAME} exported, skipping." + continue + fi + fi + + ### change the pv uuids + if [[ "${PVLIST}" =~ "unknown" ]] + then + echo "Volume Group ${VGNAME} incomplete, skipping." + continue + fi + + for BLOCKDEV in ${PVLIST} + do + "$LVM" pvchange ${LVM_OPTS} ${TEST_OPT} --uuid ${BLOCKDEV} --config 'global{activation=0}' + checkvalue $? "Unable to change PV uuid for ${BLOCKDEV}" + done + + NEWVGNAME=`getvgname "${OLDVGS}" "${VGNAME}" "${NEWVG}"` + + "$LVM" vgchange ${LVM_OPTS} ${TEST_OPT} --uuid "${VGNAME}" --config 'global{activation=0}' + checkvalue $? "Unable to change VG uuid for ${VGNAME}" + + ## if the name isn't going to get changed dont even try. + if [ "${VGNAME}" != "${NEWVGNAME}" ] + then + "$LVM" vgrename ${LVM_OPTS} ${TEST_OPT} "${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} + +### update the device cache and make sure all +### the device nodes we need are straight +"$LVM" vgscan ${LVM_OPTS} --mknodes + +exit 0 --- LVM2/scripts/Makefile.in 2009/05/11 10:35:00 1.8 +++ LVM2/scripts/Makefile.in 2009/05/14 16:46:13 1.9 @@ -20,6 +20,8 @@ install: $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) lvm_dump.sh \ $(sbindir)/lvmdump + $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) vgimportclone.sh \ + $(sbindir)/vgimportclone ifeq ("@FSADM@", "yes") $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) fsadm.sh \ $(sbindir)/fsadm