]> sourceware.org Git - lvm2.git/blame - scripts/vgimportclone.sh
Refer to details of snapshot of raid problem.
[lvm2.git] / scripts / vgimportclone.sh
CommitLineData
75153387 1#!/bin/bash
761e5741
MS
2
3# Copyright (C) 2009 Chris Procter All rights reserved.
4# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
5#
6# This file is part of LVM2.
7#
8# This copyrighted material is made available to anyone wishing to use,
9# modify, copy, or redistribute it subject to the terms and conditions
10# of the GNU General Public License v.2.
11#
12# You should have received a copy of the GNU General Public License
13# along with this program; if not, write to the Free Software Foundation,
14# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15#
16# vgimportclone: This script is used to rename the VG and change the associated
17# VG and PV UUIDs (primary application being HW snapshot restore)
18
19# following external commands are used throughout the script
20# echo and test are internal in bash at least
21RM=rm
22BASENAME=basename
23MKTEMP=mktemp
24AWK=awk
25CUT=cut
26TR=tr
27READLINK=readlink
28GREP=grep
29GETOPT=getopt
30
31# user may override lvm location by setting LVM_BINARY
32LVM="${LVM_BINARY:-lvm}"
33
34die() {
35 code=$1; shift
36 echo "Fatal: $@" 1>&2
37 exit $code
38}
39
40"$LVM" version >& /dev/null || die 2 "Could not run lvm binary '$LVM'"
41
42
43function getvgname {
44### get a unique vg name
45### $1 = list of exists VGs
46### $2 = the name we want
47 VGLIST=$1
48 VG=$2
49 NEWVG=$3
50
51 BNAME="${NEWVG:-${VG}}"
52 NAME="${BNAME}"
53 I=0
54
55 while [[ "${VGLIST}" =~ "${NAME}" ]]
56 do
57 I=$(($I+1))
58 NAME="${BNAME}$I"
59 done
60 echo "${NAME}"
61}
62
63
64function checkvalue {
65### check return value and error if non zero
66 if [ $1 -ne 0 ]
67 then
68 die $1 "$2, error: $1"
69 fi
70}
71
72
73function usage {
74### display usage message
75 echo "Usage: ${SCRIPTNAME} [options] PhysicalVolume [PhysicalVolume...]"
76 echo " -n|--basevgname - Base name for the new volume group(s)"
77 echo " -i|--import - Import any exported volume groups found"
78 echo " -t|--test - Run in test mode"
79 echo " --quiet - Suppress output"
80 echo " -v|--verbose - Set verbose level"
81 echo " -d|--debug - Set debug level"
82 echo " --version - Display version information"
83 echo " -h|--help - Display this help message"
84 echo ""
85 exit 1
86}
87
88
89function cleanup {
90 #set to use old lvm.conf
91 LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR}
92
87422138
MS
93 if [ $KEEP_TMP_LVM_SYSTEM_DIR -eq 1 ]; then
94 echo "${SCRIPTNAME}: LVM_SYSTEM_DIR (${TMP_LVM_SYSTEM_DIR}) must be cleaned up manually."
95 else
96 "$RM" -rf -- "${TMP_LVM_SYSTEM_DIR}"
97 fi
761e5741
MS
98}
99
100SCRIPTNAME=`"$BASENAME" $0`
101
102
103if [ "$UID" != "0" -a "$EUID" != "0" ]
104then
105 die 3 "${SCRIPTNAME} must be run as root."
106fi
107
108LVM_OPTS=""
109TEST_OPT=""
110DISKS=""
111# for compatibility: using mktemp -t rather than --tmpdir
112TMP_LVM_SYSTEM_DIR=`"$MKTEMP" -d -t snap.XXXXXXXX`
87422138
MS
113KEEP_TMP_LVM_SYSTEM_DIR=0
114CHANGES_MADE=0
761e5741
MS
115IMPORT=0
116DEBUG=""
117VERBOSE=""
87422138 118VERBOSE_COUNT=0
761e5741
MS
119DEVNO=0
120
121if [ -n "${LVM_SYSTEM_DIR}" ]; then
122 export ORIG_LVM_SYS_DIR="${LVM_SYSTEM_DIR}"
123fi
124
125trap cleanup 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
126
127#####################################################################
128### Get and check arguments
129#####################################################################
130OPTIONS=`"$GETOPT" -o n:dhitv \
131 -l basevgname:,debug,help,import,quiet,test,verbose,version \
132 -n "${SCRIPTNAME}" -- "$@"`
133[ $? -ne 0 ] && usage
134eval set -- "$OPTIONS"
135
136while true
137do
138 case $1 in
139 -n|--basevgname)
140 NEWVG="$2"; shift; shift
141 ;;
142 -i|--import)
143 IMPORT=1; shift
144 ;;
145 -t|--test)
146 TEST_OPT="-t"
147 shift
148 ;;
149 --quiet)
150 LVM_OPTS="--quiet ${LVM_OPTS}"
151 shift
152 ;;
153 -v|--verbose)
87422138 154 let VERBOSE_COUNT=VERBOSE_COUNT+1
761e5741
MS
155 if [ -z "$VERBOSE" ]
156 then
157 VERBOSE="-v"
158 else
159 VERBOSE="${VERBOSE}v"
160 fi
161 shift
162 ;;
163 -d|--debug)
164 if [ -z "$DEBUG" ]
165 then
166 DEBUG="-d"
167 set -x
168 else
169 DEBUG="${DEBUG}d"
170 fi
171 shift
172 ;;
173 --version)
174 "$LVM" version
175 shift
176 exit 0
177 ;;
178 -h|--help)
179 usage; shift
180 ;;
181 --)
182 shift; break
183 ;;
184 *)
185 usage
186 ;;
187 esac
188done
189
87422138
MS
190# turn on DEBUG (special case associated with -v use)
191if [ -z "$DEBUG" -a $VERBOSE_COUNT -gt 3 ]; then
192 DEBUG="-d"
193 set -x
194fi
195
196# setup LVM_OPTS
197if [ -n "${DEBUG}" -o -n "${VERBOSE}" ]
198then
199 LVM_OPTS="${LVM_OPTS} ${DEBUG} ${VERBOSE}"
200fi
201
761e5741
MS
202# process remaining arguments (which should be disks)
203for ARG
204do
205 if [ -b "$ARG" ]
206 then
87422138
MS
207 PVS_OUT=`"${LVM}" pvs ${LVM_OPTS} --noheadings -o vg_name "$ARG" 2>/dev/null`
208 checkvalue $? "$ARG is not a PV."
209 PV_VGNAME=$(echo $PVS_OUT | $GREP -v '[[:space:]]+$')
210 [ -z "$PV_VGNAME" ] && die 3 "$ARG is not in a VG."
211
761e5741
MS
212 ln -s "$ARG" ${TMP_LVM_SYSTEM_DIR}/vgimport${DEVNO}
213 DISKS="${DISKS} ${TMP_LVM_SYSTEM_DIR}/vgimport${DEVNO}"
214 DEVNO=$((${DEVNO}+1))
215 else
216 die 3 "$ARG is not a block device."
217 fi
218done
219
761e5741
MS
220### check we have suitable values for important variables
221if [ -z "${DISKS}" ]
222then
223 usage
224fi
225
226#####################################################################
227### Get the existing state so we can use it later
228#####################################################################
229
230OLDVGS=`"${LVM}" vgs ${LVM_OPTS} -o name --noheadings 2>/dev/null`
231checkvalue $? "Current VG names could not be collected without errors"
232
233#####################################################################
234### Prepare the temporary lvm environment
235#####################################################################
236
237for BLOCK in ${DISKS}
238do
239 FILTER="\"a|^${BLOCK}$|\", ${FILTER}"
240done
241export FILTER="filter=[ ${FILTER} \"r|.*|\" ]"
242
243LVMCONF=${TMP_LVM_SYSTEM_DIR}/lvm.conf
244
77f771eb 245# FIXME convert to cmdline override
761e5741
MS
246"$LVM" dumpconfig ${LVM_OPTS} | \
247"$AWK" -v DEV=${TMP_LVM_SYSTEM_DIR} -v CACHE=${TMP_LVM_SYSTEM_DIR}/.cache \
248 -v CACHE_DIR=${TMP_LVM_SYSTEM_DIR}/cache \
77f771eb
ZK
249 '/^[ \t]*filter[ \t]*=/{print ENVIRON["FILTER"];next} \
250 /^[ \t]*scan[ \t]*=/{print "scan = [ \"" DEV "\" ]";next} \
251 /^[ \t]*cache[ \t]*=/{print "cache = \"" CACHE "\"";next} \
dae08226 252 /^[ \t]*use_lvmetad[ \t]*=/{print "use_lvmetad = 0";next} \
77f771eb 253 /^[ \t]*cache_dir[ \t]*=/{print "cache_dir = \"" CACHE_DIR "\"";next} \
761e5741
MS
254 {print $0}' > ${LVMCONF}
255
256checkvalue $? "Failed to generate ${LVMCONF}"
87422138
MS
257# Only keep TMP_LVM_SYSTEM_DIR if it contains something worth keeping
258[ -n "${DEBUG}" ] && KEEP_TMP_LVM_SYSTEM_DIR=1
761e5741
MS
259
260# verify the config contains the filter, scan and cache_dir (or cache) config keywords
261"$GREP" -q '^[[:space:]]*filter[[:space:]]*=' ${LVMCONF} || \
262 die 5 "Temporary lvm.conf must contain 'filter' config."
263"$GREP" -q '^[[:space:]]*scan[[:space:]]*=' ${LVMCONF} || \
264 die 6 "Temporary lvm.conf must contain 'scan' config."
265
266# check for either 'cache' or 'cache_dir' config values
267"$GREP" -q '[[:space:]]*cache[[:space:]]*=' ${LVMCONF}
268CACHE_RET=$?
269"$GREP" -q '^[[:space:]]*cache_dir' ${LVMCONF}
270CACHE_DIR_RET=$?
271[ $CACHE_RET -eq 0 -o $CACHE_DIR_RET -eq 0 ] || \
272 die 7 "Temporary lvm.conf must contain 'cache' or 'cache_dir' config."
273
274### set to use new lvm.conf
275export LVM_SYSTEM_DIR=${TMP_LVM_SYSTEM_DIR}
276
277
278#####################################################################
279### Rename the VG(s) and change the VG and PV UUIDs.
280#####################################################################
281
282PVINFO=`"${LVM}" pvs ${LVM_OPTS} -o pv_name,vg_name,vg_attr --noheadings --separator : 2>/dev/null`
283checkvalue $? "PV info could not be collected without errors"
284
285# output VG info so each line looks like: name:exported?:disk1,disk2,...
286VGINFO=`echo "${PVINFO}" | \
77f771eb 287 "$AWK" -F : '{{sub(/^[ \t]*/,"")} \
87422138 288 {sub(/unknown device/,"unknown_device")} \
761e5741
MS
289 {vg[$2]=$1","vg[$2]} if($3 ~ /^..x/){x[$2]="x"}} \
290 END{for(k in vg){printf("%s:%s:%s\n", k, x[k], vg[k])}}'`
291checkvalue $? "PV info could not be parsed without errors"
292
293for VG in ${VGINFO}
294do
295 VGNAME=`echo "${VG}" | "$CUT" -d: -f1`
296 EXPORTED=`echo "${VG}" | "$CUT" -d: -f2`
297 PVLIST=`echo "${VG}" | "$CUT" -d: -f3- | "$TR" , ' '`
298
299 if [ -z "${VGNAME}" ]
300 then
301 FOLLOWLIST=""
302 for DEV in $PVLIST; do
303 FOLLOW=`"$READLINK" $DEV`
304 FOLLOWLIST="$FOLLOW $FOLLOWLIST"
305 done
306 die 8 "Specified PV(s) ($FOLLOWLIST) don't belong to a VG."
307 fi
308
309 if [ -n "${EXPORTED}" ]
310 then
311 if [ ${IMPORT} -eq 1 ]
312 then
313 "$LVM" vgimport ${LVM_OPTS} ${TEST_OPT} "${VGNAME}"
314 checkvalue $? "Volume Group ${VGNAME} could not be imported"
315 else
316 echo "Volume Group ${VGNAME} exported, skipping."
317 continue
318 fi
319 fi
320
321 ### change the pv uuids
322 if [[ "${PVLIST}" =~ "unknown" ]]
323 then
87422138
MS
324 echo "Volume Group ${VGNAME} has unknown PV(s), skipping."
325 echo "- Were all associated PV(s) supplied as arguments?"
761e5741
MS
326 continue
327 fi
328
329 for BLOCKDEV in ${PVLIST}
330 do
331 "$LVM" pvchange ${LVM_OPTS} ${TEST_OPT} --uuid ${BLOCKDEV} --config 'global{activation=0}'
332 checkvalue $? "Unable to change PV uuid for ${BLOCKDEV}"
333 done
334
335 NEWVGNAME=`getvgname "${OLDVGS}" "${VGNAME}" "${NEWVG}"`
336
337 "$LVM" vgchange ${LVM_OPTS} ${TEST_OPT} --uuid "${VGNAME}" --config 'global{activation=0}'
338 checkvalue $? "Unable to change VG uuid for ${VGNAME}"
339
340 ## if the name isn't going to get changed dont even try.
341 if [ "${VGNAME}" != "${NEWVGNAME}" ]
342 then
343 "$LVM" vgrename ${LVM_OPTS} ${TEST_OPT} "${VGNAME}" "${NEWVGNAME}"
344 checkvalue $? "Unable to rename ${VGNAME} to ${NEWVGNAME}"
345 fi
346
87422138 347 CHANGES_MADE=1
761e5741
MS
348done
349
350#####################################################################
351### Restore the old environment
352#####################################################################
353### set to use old lvm.conf
87422138
MS
354if [ -z "${ORIG_LVM_SYS_DIR}" ]
355then
356 unset LVM_SYSTEM_DIR
357else
358 LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR}
359fi
761e5741
MS
360
361### update the device cache and make sure all
362### the device nodes we need are straight
87422138
MS
363if [ ${CHANGES_MADE} -eq 1 ]
364then
365 "$LVM" vgscan ${LVM_OPTS} --mknodes
366fi
761e5741
MS
367
368exit 0
This page took 0.082618 seconds and 5 git commands to generate.