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.
2017-06-28 21:05:42 +03:00
# Copyright (C) 2009-2017 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
2021-04-23 00:22:01 +03:00
RM = "rm"
BASENAME = "basename"
MKTEMP = "mktemp"
READLINK = "readlink"
GETOPT = "getopt"
2009-05-14 20:46:12 +04:00
# user may override lvm location by setting LVM_BINARY
2017-07-04 12:55:17 +03:00
LVM = ${ LVM_BINARY :- lvm }
2009-05-14 20:46:12 +04:00
die( ) {
code = $1 ; shift
2017-06-28 20:40:34 +03:00
echo "Fatal:" " $@ " 1>& 2
2017-06-28 21:05:42 +03:00
exit " $code "
2009-05-14 20:46:12 +04:00
}
" $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 } } "
2017-07-04 12:55:17 +03:00
NAME = ${ BNAME }
2009-05-14 20:46:12 +04:00
I = 0
2017-06-29 19:54:26 +03:00
while [ [ " ${ VGLIST } " = ~ :${ NAME } : ] ]
2009-05-14 20:46:12 +04:00
do
2017-06-28 21:31:09 +03:00
I = $(( I + 1 ))
2009-05-14 20:46:12 +04:00
NAME = " ${ BNAME } $I "
done
echo " ${ NAME } "
}
function checkvalue {
### check return value and error if non zero
2017-06-28 21:05:42 +03:00
if [ " $1 " -ne 0 ] ; then
die " $1 " " $2 , error: $1 "
2009-05-14 20:46:12 +04:00
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
2017-10-25 18:02:31 +03:00
LVM_SYSTEM_DIR = $ORIG_LVM_SYS_DIR
2009-05-14 20:46:12 +04:00
2017-06-28 21:05:42 +03:00
if [ " $KEEP_TMP_LVM_SYSTEM_DIR " -eq 1 ] ; then
2009-06-17 19:47:01 +04:00
echo " ${ SCRIPTNAME } : LVM_SYSTEM_DIR ( ${ TMP_LVM_SYSTEM_DIR } ) must be cleaned up manually. "
else
2017-10-25 18:02:31 +03:00
" $RM " -rf -- " $TMP_LVM_SYSTEM_DIR "
2009-06-17 19:47:01 +04:00
fi
2009-05-14 20:46:12 +04:00
}
2017-06-28 21:20:15 +03:00
SCRIPTNAME = $( " $BASENAME " " $0 " )
2009-05-14 20:46:12 +04:00
2017-06-28 21:35:34 +03:00
if [ " $UID " != 0 ] && [ " $EUID " != 0 ] ; then
2009-05-14 20:46:12 +04:00
die 3 " ${ SCRIPTNAME } must be run as root. "
fi
LVM_OPTS = ""
TEST_OPT = ""
DISKS = ""
# for compatibility: using mktemp -t rather than --tmpdir
2017-06-28 21:20:15 +03:00
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
2017-06-28 21:06:59 +03:00
trap cleanup 0 1 2 3 4 5 6 7 8 10 11 12 13 14 15 16 17 18
2009-05-14 20:46:12 +04:00
#####################################################################
### Get and check arguments
#####################################################################
2017-06-28 21:20:15 +03:00
OPTIONS = $( " $GETOPT " -o n:dhitv \
2009-05-14 20:46:12 +04:00
-l basevgname:,debug,help,import,quiet,test,verbose,version \
2017-06-28 21:20:15 +03:00
-n " ${ SCRIPTNAME } " -- " $@ " )
2009-05-14 20:46:12 +04:00
[ $? -ne 0 ] && usage
eval set -- " $OPTIONS "
while true
do
case $1 in
-n| --basevgname)
2017-07-04 12:55:17 +03:00
NEWVG = $2 ; shift; shift
2009-05-14 20:46:12 +04:00
; ;
-i| --import)
IMPORT = 1; shift
; ;
-t| --test)
TEST_OPT = "-t"
shift
; ;
--quiet)
LVM_OPTS = " --quiet ${ LVM_OPTS } "
shift
; ;
-v| --verbose)
2021-04-23 00:22:01 +03:00
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)
2017-06-28 21:35:34 +03:00
if [ -z " $DEBUG " ] && [ " $VERBOSE_COUNT " -gt 3 ] ; then
2009-06-17 19:47:01 +04:00
DEBUG = "-d"
set -x
fi
# setup LVM_OPTS
2017-06-28 21:35:34 +03:00
if [ -n " $DEBUG " ] || [ -n " $VERBOSE " ] ; then
2009-06-17 19:47:01 +04:00
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
2017-06-28 21:05:42 +03:00
ln -s " $ARG " " ${ TMP_LVM_SYSTEM_DIR } /vgimport ${ DEVNO } "
2009-05-14 20:46:12 +04:00
DISKS = " ${ DISKS } ${ TMP_LVM_SYSTEM_DIR } /vgimport ${ DEVNO } "
2017-06-28 21:31:09 +03:00
DEVNO = $(( DEVNO + 1 ))
2009-05-14 20:46:12 +04:00
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
#####################################################################
2017-06-28 21:20:15 +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|.*|\" ] "
2017-07-04 12:55:17 +03:00
LVMCONF = " ${ TMP_LVM_SYSTEM_DIR } /lvm.conf "
2009-05-14 20:46:12 +04:00
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 \
} "
2017-06-28 21:05:42 +03:00
$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.
2017-06-28 21:20:15 +03:00
NOVGDEVLIST = $( " $LVM " pvs -a -o pv_name --select vg_name = "" --noheadings)
2015-10-09 17:26:27 +03:00
checkvalue $? "Failed to collect information for PV check"
if [ -n " ${ NOVGDEVLIST } " ] ; then
FOLLOWLIST = ""
2017-06-28 21:26:23 +03:00
while read -r PVNAME; do
2017-06-28 21:20:15 +03:00
FOLLOW = $( " $READLINK " " $PVNAME " )
2015-10-09 17:26:27 +03:00
FOLLOWLIST = " $FOLLOWLIST $FOLLOW "
2017-06-28 21:20:15 +03:00
done <<< " $( echo " $NOVGDEVLIST " ) "
2015-10-09 17:26:27 +03:00
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.
#####################################################################
2017-06-28 21:20:15 +03:00
VGLIST = $( " $LVM " vgs -o vg_name,vg_exported,vg_missing_pv_count --noheadings --binary)
2015-10-09 17:26:27 +03:00
checkvalue $? "Failed to collect VG information"
2009-05-14 20:46:12 +04:00
2017-06-28 21:26:23 +03:00
while read -r VGNAME VGEXPORTED VGMISSINGPVCOUNT; do
2017-06-28 21:05:42 +03:00
if [ " $VGMISSINGPVCOUNT " -gt 0 ] ; then
2015-10-09 17:26:27 +03:00
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
2017-07-04 12:55:17 +03:00
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
2017-06-28 21:20:15 +03:00
NEWVGNAME = $( getvgname " $OLDVGS " " $VGNAME " " $NEWVG " )
2009-05-14 20:46:12 +04:00
2017-06-28 21:05:42 +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
2017-06-28 21:20:15 +03:00
done <<< " $( echo " $VGLIST " ) "
2009-05-14 20:46:12 +04:00
#####################################################################
### Restore the old environment
#####################################################################
### set to use old lvm.conf
2017-10-25 18:02:31 +03:00
if [ -z " $ORIG_LVM_SYS_DIR " ]
2009-06-17 19:47:01 +04:00
then
unset LVM_SYSTEM_DIR
else
2017-10-25 18:02:31 +03:00
LVM_SYSTEM_DIR = $ORIG_LVM_SYS_DIR
2009-06-17 19:47:01 +04:00
fi
2009-05-14 20:46:12 +04:00
### update the device cache and make sure all
### the device nodes we need are straight
2017-07-04 12:55:17 +03:00
if [ " ${ CHANGES_MADE } " -eq 1 ]
2009-06-17 19:47:01 +04:00
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
2017-06-28 21:05:42 +03:00
eval " $( " $LVM " dumpconfig ${ LVM_OPTS } global/use_lvmetad) "
2017-07-04 12:55:17 +03:00
if [ " $use_lvmetad " = 1 ]
2014-12-10 15:43:54 +03:00
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