2010-05-14 15:33:20 +04:00
#!/bin/bash
2009-05-14 20:46:12 +04:00
# Copyright (C) 2009 Chris Procter All rights reserved.
2015-09-14 10:24:15 +03:00
# Copyright (C) 2009-2015 Red Hat, Inc. All rights reserved.
2009-05-14 20:46:12 +04:00
#
# 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,
2016-01-21 13:49:46 +03:00
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2009-05-14 20:46:12 +04:00
#
# 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
2015-10-12 12:11:34 +03:00
while [ [ " ${ VGLIST } " = ~ " : ${ NAME } : " ] ]
2009-05-14 20:46:12 +04:00
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 }
2009-06-17 19:47:01 +04:00
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
2009-05-14 20:46:12 +04:00
}
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`
2009-06-17 19:47:01 +04:00
KEEP_TMP_LVM_SYSTEM_DIR = 0
CHANGES_MADE = 0
2009-05-14 20:46:12 +04:00
IMPORT = 0
DEBUG = ""
VERBOSE = ""
2009-06-17 19:47:01 +04:00
VERBOSE_COUNT = 0
2009-05-14 20:46:12 +04:00
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)
2009-06-17 19:47:01 +04:00
let VERBOSE_COUNT = VERBOSE_COUNT+1
2009-05-14 20:46:12 +04:00
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
2009-06-17 19:47:01 +04:00
# turn on DEBUG (special case associated with -v use)
if [ -z " $DEBUG " -a $VERBOSE_COUNT -gt 3 ] ; then
DEBUG = "-d"
set -x
fi
# setup LVM_OPTS
if [ -n " ${ DEBUG } " -o -n " ${ VERBOSE } " ]
then
LVM_OPTS = " ${ LVM_OPTS } ${ DEBUG } ${ VERBOSE } "
fi
2009-05-14 20:46:12 +04:00
# 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
#####################################################################
2015-10-12 12:11:34 +03:00
### Get the existing state so we can use it later.
### The list of VG names is saved in this format:
### :vgname1:vgname2:...:vgnameN:
2009-05-14 20:46:12 +04:00
#####################################################################
2015-10-12 13:51:13 +03:00
OLDVGS = ":`" ${ LVM } " vgs ${ LVM_OPTS } -o name --noheadings --rows --separator : --config 'log{prefix= " "}'`:"
2009-05-14 20:46:12 +04:00
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
2014-12-10 15:25:23 +03:00
CMD_CONFIG_LINE = " devices { \
scan = [ \" ${ TMP_LVM_SYSTEM_DIR } \" ] \
2015-09-14 10:24:15 +03:00
cache_dir = \" ${ TMP_LVM_SYSTEM_DIR } /cache\"
2014-12-10 15:25:23 +03:00
global_filter = [ \" a| .*| \" ] \
${ FILTER }
} \
global { \
use_lvmetad = 0 \
} "
$LVM dumpconfig ${ LVM_OPTS } --file ${ LVMCONF } --mergedconfig --config " ${ CMD_CONFIG_LINE } "
2009-05-14 20:46:12 +04:00
checkvalue $? " Failed to generate ${ LVMCONF } "
2009-06-17 19:47:01 +04:00
# Only keep TMP_LVM_SYSTEM_DIR if it contains something worth keeping
[ -n " ${ DEBUG } " ] && KEEP_TMP_LVM_SYSTEM_DIR = 1
2009-05-14 20:46:12 +04:00
### set to use new lvm.conf
export LVM_SYSTEM_DIR = ${ TMP_LVM_SYSTEM_DIR }
2015-10-09 17:26:27 +03:00
# 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 PVNAME; do
FOLLOW = ` $READLINK $PVNAME `
FOLLOWLIST = " $FOLLOWLIST $FOLLOW "
done <<< "`echo " ${ NOVGDEVLIST } "`"
die 8 " Specified devices don't belong to a VG: $FOLLOWLIST "
fi
2009-05-14 20:46:12 +04:00
#####################################################################
### Rename the VG(s) and change the VG and PV UUIDs.
#####################################################################
2015-10-09 17:26:27 +03:00
VGLIST = ` ${ LVM } vgs -o vg_name,vg_exported,vg_missing_pv_count --noheadings --binary`
checkvalue $? "Failed to collect VG information"
2009-05-14 20:46:12 +04:00
2015-10-09 17:26:27 +03:00
while read 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
2009-05-14 20:46:12 +04:00
fi
2015-10-09 17:26:27 +03:00
if [ " $VGEXPORTED " = "1" ] ; then
if [ ${ IMPORT } -eq 1 ] ; then
2009-05-14 20:46:12 +04:00
" $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
2015-10-09 17:26:27 +03:00
" $LVM " pvchange ${ LVM_OPTS } ${ TEST_OPT } --uuid --config 'global{activation=0}' --select " vg_name= ${ VGNAME } "
2016-01-21 16:47:48 +03:00
checkvalue $? " Unable to change all PV uuids in VG ${ VGNAME } "
2009-05-14 20:46:12 +04:00
NEWVGNAME = ` getvgname " ${ OLDVGS } " " ${ VGNAME } " " ${ NEWVG } " `
2015-10-09 17:26:27 +03:00
" $LVM " vgchange ${ LVM_OPTS } ${ TEST_OPT } --uuid --config 'global{activation=0}' ${ VGNAME }
2009-05-14 20:46:12 +04:00
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
2009-06-17 19:47:01 +04:00
CHANGES_MADE = 1
2015-10-09 17:26:27 +03:00
done <<< "`echo " ${ VGLIST } "`"
2009-05-14 20:46:12 +04:00
#####################################################################
### Restore the old environment
#####################################################################
### set to use old lvm.conf
2009-06-17 19:47:01 +04:00
if [ -z " ${ ORIG_LVM_SYS_DIR } " ]
then
unset LVM_SYSTEM_DIR
else
LVM_SYSTEM_DIR = ${ ORIG_LVM_SYS_DIR }
fi
2009-05-14 20:46:12 +04:00
### update the device cache and make sure all
### the device nodes we need are straight
2009-06-17 19:47:01 +04:00
if [ ${ CHANGES_MADE } -eq 1 ]
then
2014-12-10 15:43:54 +03:00
# 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."
2015-01-17 14:29:38 +03:00
echo "(This resolves any WARNING message about restarting lvmetad that appears above.)"
2014-12-10 15:43:54 +03:00
LVM_OPTS = " ${ LVM_OPTS } --cache "
fi
2009-06-17 19:47:01 +04:00
" $LVM " vgscan ${ LVM_OPTS } --mknodes
fi
2009-05-14 20:46:12 +04:00
exit 0