home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / sbin / vgimportclone < prev    next >
Encoding:
Text File  |  2011-01-23  |  10.1 KB  |  367 lines

  1. #!/bin/bash
  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
  21. RM=rm
  22. BASENAME=basename
  23. MKTEMP=mktemp
  24. AWK=awk
  25. CUT=cut
  26. TR=tr
  27. READLINK=readlink
  28. GREP=grep
  29. GETOPT=getopt
  30.  
  31. # user may override lvm location by setting LVM_BINARY
  32. LVM="${LVM_BINARY:-lvm}"
  33.  
  34. die() {
  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.  
  43. function 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.  
  64. function 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.  
  73. function 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.  
  89. function cleanup {
  90.     #set to use old lvm.conf
  91.     LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR}
  92.  
  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
  98. }
  99.  
  100. SCRIPTNAME=`"$BASENAME" $0`
  101.  
  102.  
  103. if [ "$UID" != "0" -a "$EUID" != "0" ]
  104. then
  105.     die 3 "${SCRIPTNAME} must be run as root."
  106. fi
  107.  
  108. LVM_OPTS=""
  109. TEST_OPT=""
  110. DISKS=""
  111. # for compatibility: using mktemp -t rather than --tmpdir
  112. TMP_LVM_SYSTEM_DIR=`"$MKTEMP" -d -t snap.XXXXXXXX`
  113. KEEP_TMP_LVM_SYSTEM_DIR=0
  114. CHANGES_MADE=0
  115. IMPORT=0
  116. DEBUG=""
  117. VERBOSE=""
  118. VERBOSE_COUNT=0
  119. DEVNO=0
  120.  
  121. if [ -n "${LVM_SYSTEM_DIR}" ]; then
  122.     export ORIG_LVM_SYS_DIR="${LVM_SYSTEM_DIR}"
  123. fi
  124.  
  125. trap  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. #####################################################################
  130. OPTIONS=`"$GETOPT" -o n:dhitv \
  131.     -l basevgname:,debug,help,import,quiet,test,verbose,version \
  132.     -n "${SCRIPTNAME}" -- "$@"`
  133. [ $? -ne 0 ] && usage
  134. eval set -- "$OPTIONS"
  135.  
  136. while true
  137. do
  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)
  154.             let VERBOSE_COUNT=VERBOSE_COUNT+1
  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
  188. done
  189.  
  190. # turn on DEBUG (special case associated with -v use)
  191. if [ -z "$DEBUG" -a $VERBOSE_COUNT -gt 3 ]; then
  192.     DEBUG="-d"
  193.     set -x
  194. fi
  195.  
  196. # setup LVM_OPTS
  197. if [ -n "${DEBUG}" -o -n "${VERBOSE}" ]
  198. then
  199.     LVM_OPTS="${LVM_OPTS} ${DEBUG} ${VERBOSE}"
  200. fi
  201.  
  202. # process remaining arguments (which should be disks)
  203. for ARG
  204. do
  205.     if [ -b "$ARG" ]
  206.     then
  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.  
  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
  218. done
  219.  
  220. ### check we have suitable values for important variables
  221. if [ -z "${DISKS}" ]
  222. then
  223.     usage
  224. fi
  225.  
  226. #####################################################################
  227. ### Get the existing state so we can use it later
  228. #####################################################################
  229.  
  230. OLDVGS=`"${LVM}" vgs ${LVM_OPTS} -o name --noheadings 2>/dev/null`
  231. checkvalue $? "Current VG names could not be collected without errors"
  232.  
  233. #####################################################################
  234. ### Prepare the temporary lvm environment
  235. #####################################################################
  236.  
  237. for BLOCK in ${DISKS}
  238. do
  239.     FILTER="\"a|^${BLOCK}$|\", ${FILTER}"
  240. done
  241. export FILTER="filter=[ ${FILTER} \"r|.*|\" ]"
  242.  
  243. LVMCONF=${TMP_LVM_SYSTEM_DIR}/lvm.conf
  244.  
  245. "$LVM" dumpconfig ${LVM_OPTS} | \
  246. "$AWK" -v DEV=${TMP_LVM_SYSTEM_DIR} -v CACHE=${TMP_LVM_SYSTEM_DIR}/.cache \
  247.     -v CACHE_DIR=${TMP_LVM_SYSTEM_DIR}/cache \
  248.     '/^[[:space:]]*filter[[:space:]]*=/{print ENVIRON["FILTER"];next} \
  249.      /^[[:space:]]*scan[[:space:]]*=/{print "scan = [ \"" DEV "\" ]";next} \
  250.      /^[[:space:]]*cache[[:space:]]*=/{print "cache = \"" CACHE "\"";next} \
  251.      /^[[:space:]]*cache_dir[[:space:]]*=/{print "cache_dir = \"" CACHE_DIR "\"";next} \
  252.      {print $0}' > ${LVMCONF}
  253.  
  254. checkvalue $? "Failed to generate ${LVMCONF}"
  255. # Only keep TMP_LVM_SYSTEM_DIR if it contains something worth keeping
  256. [ -n "${DEBUG}" ] && KEEP_TMP_LVM_SYSTEM_DIR=1
  257.  
  258. # verify the config contains the filter, scan and cache_dir (or cache) config keywords
  259. "$GREP" -q '^[[:space:]]*filter[[:space:]]*=' ${LVMCONF} || \
  260.     die 5 "Temporary lvm.conf must contain 'filter' config."
  261. "$GREP" -q '^[[:space:]]*scan[[:space:]]*=' ${LVMCONF} || \
  262.     die 6 "Temporary lvm.conf must contain 'scan' config."
  263.  
  264. # check for either 'cache' or 'cache_dir' config values
  265. "$GREP" -q '[[:space:]]*cache[[:space:]]*=' ${LVMCONF}
  266. CACHE_RET=$?
  267. "$GREP" -q '^[[:space:]]*cache_dir' ${LVMCONF}
  268. CACHE_DIR_RET=$?
  269. [ $CACHE_RET -eq 0 -o $CACHE_DIR_RET -eq 0 ] || \
  270.     die 7 "Temporary lvm.conf must contain 'cache' or 'cache_dir' config."
  271.  
  272. ### set to use new lvm.conf
  273. export LVM_SYSTEM_DIR=${TMP_LVM_SYSTEM_DIR}
  274.  
  275.  
  276. #####################################################################
  277. ### Rename the VG(s) and change the VG and PV UUIDs.
  278. #####################################################################
  279.  
  280. PVINFO=`"${LVM}" pvs ${LVM_OPTS} -o pv_name,vg_name,vg_attr --noheadings --separator : 2>/dev/null`
  281. checkvalue $? "PV info could not be collected without errors"
  282.  
  283. # output VG info so each line looks like: name:exported?:disk1,disk2,...
  284. VGINFO=`echo "${PVINFO}" | \
  285.     "$AWK" -F : '{{sub(/^[[:space:]]*/,"")} \
  286.     {sub(/unknown device/,"unknown_device")} \
  287.     {vg[$2]=$1","vg[$2]} if($3 ~ /^..x/){x[$2]="x"}} \
  288.     END{for(k in vg){printf("%s:%s:%s\n", k, x[k], vg[k])}}'`
  289. checkvalue $? "PV info could not be parsed without errors"
  290.  
  291. for VG in ${VGINFO}
  292. do
  293.     VGNAME=`echo "${VG}" | "$CUT" -d: -f1`
  294.     EXPORTED=`echo "${VG}" | "$CUT" -d: -f2`
  295.     PVLIST=`echo "${VG}" | "$CUT" -d: -f3- | "$TR" , ' '`
  296.  
  297.     if [ -z "${VGNAME}" ]
  298.     then
  299.         FOLLOWLIST=""
  300.         for DEV in $PVLIST; do
  301.             FOLLOW=`"$READLINK" $DEV`
  302.             FOLLOWLIST="$FOLLOW $FOLLOWLIST"
  303.         done
  304.         die 8 "Specified PV(s) ($FOLLOWLIST) don't belong to a VG."
  305.     fi
  306.  
  307.     if [ -n "${EXPORTED}" ]
  308.     then
  309.         if [ ${IMPORT} -eq 1 ]
  310.         then
  311.             "$LVM" vgimport ${LVM_OPTS} ${TEST_OPT} "${VGNAME}"
  312.             checkvalue $? "Volume Group ${VGNAME} could not be imported"
  313.         else
  314.             echo "Volume Group ${VGNAME} exported, skipping."
  315.             continue
  316.         fi
  317.     fi
  318.  
  319.     ### change the pv uuids
  320.     if [[ "${PVLIST}" =~ "unknown" ]]
  321.     then
  322.         echo "Volume Group ${VGNAME} has unknown PV(s), skipping."
  323.         echo "- Were all associated PV(s) supplied as arguments?"
  324.         continue
  325.     fi
  326.  
  327.     for BLOCKDEV in ${PVLIST}
  328.     do
  329.         "$LVM" pvchange ${LVM_OPTS} ${TEST_OPT} --uuid ${BLOCKDEV} --config 'global{activation=0}'
  330.         checkvalue $? "Unable to change PV uuid for ${BLOCKDEV}"
  331.     done
  332.  
  333.     NEWVGNAME=`getvgname "${OLDVGS}" "${VGNAME}" "${NEWVG}"`
  334.  
  335.     "$LVM" vgchange ${LVM_OPTS} ${TEST_OPT} --uuid "${VGNAME}" --config 'global{activation=0}'
  336.     checkvalue $? "Unable to change VG uuid for ${VGNAME}"
  337.  
  338.     ## if the name isn't going to get changed dont even try.
  339.     if [ "${VGNAME}" != "${NEWVGNAME}" ]
  340.     then
  341.         "$LVM" vgrename ${LVM_OPTS} ${TEST_OPT} "${VGNAME}" "${NEWVGNAME}"
  342.         checkvalue $? "Unable to rename ${VGNAME} to ${NEWVGNAME}"
  343.     fi
  344.  
  345.     CHANGES_MADE=1
  346. done
  347.  
  348. #####################################################################
  349. ### Restore the old environment
  350. #####################################################################
  351. ### set to use old lvm.conf
  352. if [ -z "${ORIG_LVM_SYS_DIR}" ]
  353. then
  354.     unset LVM_SYSTEM_DIR
  355. else
  356.     LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR}
  357. fi
  358.  
  359. ### update the device cache and make sure all
  360. ### the device nodes we need are straight
  361. if [ ${CHANGES_MADE} -eq 1 ]
  362. then
  363.     "$LVM" vgscan ${LVM_OPTS} --mknodes
  364. fi
  365.  
  366. exit 0
  367.