mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-10-30 20:23:49 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			337 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			337 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| 
 | |
| # Copyright (C) 2009 Chris Procter All rights reserved.
 | |
| # Copyright (C) 2009-2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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"
 | |
| READLINK="readlink"
 | |
| 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
 | |
| 
 | |
|     if [ "$KEEP_TMP_LVM_SYSTEM_DIR" -eq 1 ]; then
 | |
|         echo "${SCRIPTNAME}: LVM_SYSTEM_DIR (${TMP_LVM_SYSTEM_DIR}) must be cleaned up manually."
 | |
|     else
 | |
|         "$RM" -rf -- "$TMP_LVM_SYSTEM_DIR"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| SCRIPTNAME=$("$BASENAME" "$0")
 | |
| 
 | |
| 
 | |
| if [ "$UID" != 0 ] && [ "$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)
 | |
| KEEP_TMP_LVM_SYSTEM_DIR=0
 | |
| CHANGES_MADE=0
 | |
| IMPORT=0
 | |
| DEBUG=""
 | |
| VERBOSE=""
 | |
| VERBOSE_COUNT=0
 | |
| 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 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)
 | |
|             VERBOSE_COUNT=$(( VERBOSE_COUNT + 1 ))
 | |
|             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
 | |
| 
 | |
| # turn on DEBUG (special case associated with -v use)
 | |
| if [ -z "$DEBUG" ] && [ "$VERBOSE_COUNT" -gt 3 ]; then
 | |
|     DEBUG="-d"
 | |
|     set -x
 | |
| fi
 | |
| 
 | |
| # setup LVM_OPTS
 | |
| if [ -n "$DEBUG" ] || [ -n "$VERBOSE" ]; then
 | |
|     LVM_OPTS="${LVM_OPTS} ${DEBUG} ${VERBOSE}"
 | |
| fi
 | |
| 
 | |
| # 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
 | |
| 
 | |
| ### check we have suitable values for important variables
 | |
| if [ -z "${DISKS}" ]
 | |
| then
 | |
|     usage
 | |
| fi
 | |
| 
 | |
| #####################################################################
 | |
| ### Get the existing state so we can use it later.
 | |
| ### The list of VG names is saved in this format:
 | |
| ###     :vgname1:vgname2:...:vgnameN:
 | |
| #####################################################################
 | |
| 
 | |
| OLDVGS=":$("$LVM" vgs ${LVM_OPTS} -o name --noheadings --rows --separator : --config 'log{prefix=""}'):"
 | |
| 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"
 | |
| 
 | |
| CMD_CONFIG_LINE="devices { \
 | |
|                    scan = [ \"${TMP_LVM_SYSTEM_DIR}\" ] \
 | |
|                    cache_dir = \"${TMP_LVM_SYSTEM_DIR}/cache\"
 | |
|                    global_filter = [ \"a|.*|\" ] \
 | |
|                    ${FILTER}
 | |
|                  } \
 | |
|                  global { \
 | |
|                    use_lvmetad = 0 \
 | |
|                  }"
 | |
| 
 | |
| $LVM dumpconfig ${LVM_OPTS} --file "${LVMCONF}" --mergedconfig --config "${CMD_CONFIG_LINE}"
 | |
| 
 | |
| checkvalue $? "Failed to generate ${LVMCONF}"
 | |
| # Only keep TMP_LVM_SYSTEM_DIR if it contains something worth keeping
 | |
| [ -n "${DEBUG}" ] && KEEP_TMP_LVM_SYSTEM_DIR=1
 | |
| 
 | |
| ### set to use new lvm.conf
 | |
| export LVM_SYSTEM_DIR=${TMP_LVM_SYSTEM_DIR}
 | |
| 
 | |
| # Check if there are any PVs that don't belong to any VG
 | |
| # or even if there are disks which are not PVs at all.
 | |
| NOVGDEVLIST=$("$LVM" pvs -a -o pv_name --select vg_name="" --noheadings)
 | |
| checkvalue $? "Failed to collect information for PV check"
 | |
| if [ -n "${NOVGDEVLIST}" ]; then
 | |
|     FOLLOWLIST=""
 | |
|     while read -r PVNAME; do
 | |
|         FOLLOW=$("$READLINK" "$PVNAME")
 | |
|         FOLLOWLIST="$FOLLOWLIST $FOLLOW"
 | |
|     done <<< "$(echo "$NOVGDEVLIST")"
 | |
|     die 8 "Specified devices don't belong to a VG:$FOLLOWLIST"
 | |
| fi
 | |
| 
 | |
| #####################################################################
 | |
| ### Rename the VG(s) and change the VG and PV UUIDs.
 | |
| #####################################################################
 | |
| VGLIST=$("$LVM" vgs -o vg_name,vg_exported,vg_missing_pv_count --noheadings --binary)
 | |
| checkvalue $? "Failed to collect VG information"
 | |
| 
 | |
| while read -r VGNAME VGEXPORTED VGMISSINGPVCOUNT; do
 | |
|     if [ "$VGMISSINGPVCOUNT" -gt 0 ]; then
 | |
|         echo "Volume Group ${VGNAME} has unknown PV(s), skipping."
 | |
|         echo "- Were all associated PV(s) supplied as arguments?"
 | |
|         continue
 | |
|     fi
 | |
| 
 | |
|     if [ "$VGEXPORTED" = "1" ]; 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
 | |
| 
 | |
|     "$LVM" pvchange ${LVM_OPTS} ${TEST_OPT} --uuid --config 'global{activation=0}' --select "vg_name=${VGNAME}"
 | |
|     checkvalue $? "Unable to change all PV uuids in VG ${VGNAME}"
 | |
| 
 | |
|     NEWVGNAME=$(getvgname "$OLDVGS" "$VGNAME" "$NEWVG")
 | |
| 
 | |
|     "$LVM" vgchange ${LVM_OPTS} ${TEST_OPT} --uuid --config 'global{activation=0}' "$VGNAME"
 | |
|     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
 | |
| 
 | |
|     CHANGES_MADE=1
 | |
| done <<< "$(echo "$VGLIST")"
 | |
| 
 | |
| #####################################################################
 | |
| ### Restore the old environment
 | |
| #####################################################################
 | |
| ### set to use old lvm.conf
 | |
| if [ -z "$ORIG_LVM_SYS_DIR" ]
 | |
| then
 | |
|     unset LVM_SYSTEM_DIR
 | |
| else
 | |
|     LVM_SYSTEM_DIR=$ORIG_LVM_SYS_DIR
 | |
| fi
 | |
| 
 | |
| ### update the device cache and make sure all
 | |
| ### the device nodes we need are straight
 | |
| if [ "${CHANGES_MADE}" -eq 1 ]
 | |
| then
 | |
|     # get global/use_lvmetad config and if set also notify lvmetad about changes
 | |
|     # since we were running LVM commands above with use_lvmetad=0
 | |
|     eval "$("$LVM" dumpconfig ${LVM_OPTS} global/use_lvmetad)"
 | |
|     if [ "$use_lvmetad" = 1 ]
 | |
|     then
 | |
|       echo "Notifying lvmetad about changes since it was disabled temporarily."
 | |
|       echo "(This resolves any WARNING message about restarting lvmetad that appears above.)"
 | |
|       LVM_OPTS="${LVM_OPTS} --cache"
 | |
|     fi
 | |
| 
 | |
|     "$LVM" vgscan ${LVM_OPTS} --mknodes
 | |
| fi
 | |
| 
 | |
| exit 0
 |