diff --git a/scripts/xe-backup-metadata b/scripts/xe-backup-metadata index 4aa09b7f74c..c67f04a0b4c 100755 --- a/scripts/xe-backup-metadata +++ b/scripts/xe-backup-metadata @@ -48,6 +48,29 @@ function usage { exit 1 } +function uuid5 { + # could use a modern uuidgen but it's not on XS 8 + # should work with Python 2 and 3 + python -c "import uuid; print (uuid.uuid5(uuid.UUID('$1'), '$2'))" +} + +function validate_vdi_uuid { + # we check that vdi has the expected UUID which depends on the UUID of + # the SR. This is a deterministic hash of the SR UUID and the + # namespace UUID $NS. This UUID must match what Xapi's Uuidx module is using. + local NS="e93e0639-2bdb-4a59-8b46-352b3f408c19" + local sr="$1" + local vdi="$2" + local uuid + + uuid=$(uuid5 "$NS" "$sr") + if [ "$vdi" != "$uuid" ]; then + return 1 + else + return 0 + fi +} + function test_sr { sr_uuid_found=$(${XE} sr-list uuid="$1" --minimal) if [ "${sr_uuid_found}" != "$1" ]; then @@ -93,7 +116,7 @@ if [ -z "${sr_uuid}" ]; then fi test_sr "${sr_uuid}" -sr_name=$(${XE} sr-param-get uuid=${sr_uuid} param-name=name-label) +sr_name=$(${XE} sr-param-get uuid="${sr_uuid}" param-name=name-label) # see if a backup VDI already exists on the selected SR vdi_uuid=$(${XE} vdi-list other-config:ctxs-pool-backup=true sr-uuid=${sr_uuid} params=uuid --minimal) @@ -134,11 +157,24 @@ function cleanup { fi } -echo Using SR: ${sr_name} +# if we can't validate the UUID of the VDI, prompt the user +if [ -n "${vdi_uuid}" ]; then + if ! validate_vdi_uuid "${sr_uuid}" "${vdi_uuid}"; then + echo "Backup VDI $vdi_uuid was most likley create by an earlier" + echo "version of this code. Make sure this is a VDI that you" + echo "created as we can't validate it without mounting it." + read -p "Continue? [Y/N]" -n 1 -r; echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi + fi +fi + +echo "Using SR: ${sr_name}" if [ -z "${vdi_uuid}" ]; then if [ "${create_vdi}" -gt 0 ]; then echo -n "Creating new backup VDI: " - vdi_uuid=$(${XE} vdi-create virtual-size=500MiB sr-uuid=${sr_uuid} type=user name-label="Pool Metadata Backup") + label="Pool Metadata Backup" + # the label must match what xapi_vdi.ml is using for backup VDIs + vdi_uuid=$(${XE} vdi-create virtual-size=500MiB sr-uuid="${sr_uuid}" type=user name-label="${label}") init_fs=1 if [ $? -ne 0 ]; then echo failed @@ -225,7 +261,7 @@ if [ ${leave_mounted} -eq 0 ]; then usage=`cd ${mnt} && df . | sed -n "2p" | awk '{ print $5 }' | tr -d '%'` echo "Checking backup VDI space usage: $usage%" if [ $usage -gt $usage_alert ] && [ ${force_backup} -eq 0 ]; then - echo "Running out of space, you can use "-d" option to attach VDI and free more space, exit now." + echo "Running out of space, you can use '-d' option to attach VDI and free more space, exit now." cleanup exit 1 fi diff --git a/scripts/xe-restore-metadata b/scripts/xe-restore-metadata index 81beb51b704..6c2018ccb54 100755 --- a/scripts/xe-restore-metadata +++ b/scripts/xe-restore-metadata @@ -52,6 +52,13 @@ function test_sr { fi } +# name space to hash SRs for a deterministic VDI UUID +NS="e93e0639-2bdb-4a59-8b46-352b3f408c19" +function uuid5 { + # could use a modern uuidgen but it's not on XS 8 + python -c "import uuid; print (uuid.uuid5(uuid.UUID('$1'), '$2'))" +} + dry_run=0 sr_uuid= yes=0 @@ -100,9 +107,16 @@ test_sr "${sr_uuid}" sr_name=$(${XE} sr-param-get uuid=${sr_uuid} param-name=name-label) +# probe first for a VDI with known UUID derived from the SR to avoid +# scanning for a VDI +backup_vdi=$(uuid5 "${NS}" "${sr_uuid}") +if [ -z "${vdis}" ]; then + vdis=$(${XE} vdi-list uuid="${backup_vdi}" sr-uuid="${sr_uuid}" read-only=false --minimal) +fi + # get a list of all VDIs if an override has not been provided on the cmd line if [ -z "${vdis}" ]; then - vdis=$(${XE} vdi-list params=uuid sr-uuid=${sr_uuid} read-only=false --minimal) + vdis=$(${XE} vdi-list params=uuid sr-uuid="${sr_uuid}" read-only=false --minimal) fi mnt= @@ -149,6 +163,14 @@ fi trap cleanup SIGINT ERR for vdi_uuid in ${vdis}; do + if [ "${vdi_uuid}" != "${backup_vdi}" ]; then + echo "Probing VDI ${vdi_uuid}." + echo "This VDI was created with a prior version of XenServer." + echo "Its validity can't be checked without mounting it first." + read -p "Continue? [Y/N]" -n 1 -r; echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi + fi + ${debug} echo -n "Creating VBD: " >&2 vbd_uuid=$(${XE} vbd-create vm-uuid=${CONTROL_DOMAIN_UUID} vdi-uuid=${vdi_uuid} device=autodetect 2>/dev/null) @@ -253,7 +275,7 @@ all) ;; esac -if [ ! -d ${full_dir} ]; then +if [ ! -d "${full_dir}" ]; then echo No VM metadata exports were found for the selected SR >&2 cleanup exit 1 @@ -266,9 +288,9 @@ ${debug} echo "" >&2 ${debug} echo Latest VM metadata found is: >&2 ${debug} ls >&2 -if [ $yes -eq 0 ]; then +if [ "$yes" -eq 0 ]; then echo "Do you wish to reimport all VM metadata?" - echo "Please type in "yes" and to continue." + echo "Please type in 'yes' and to continue." read response if [ "$response" != "yes" ]; then echo Aborting metadata restore. @@ -297,8 +319,8 @@ else fi shopt -s nullglob for meta in *.vmmeta; do - echo xe vm-import filename=${meta} sr-uuid=${sr_uuid} --metadata --preserve${force_flag}${dry_run_flag} - "@OPTDIR@/bin/xe" vm-import filename="${full_dir}/${meta}" sr-uuid=${sr_uuid} --metadata --preserve${force_flag}${dry_run_flag} + echo xe vm-import filename="${meta}" sr-uuid="${sr_uuid}" --metadata --preserve"${force_flag}""${dry_run_flag}" + "@OPTDIR@/bin/xe" vm-import filename="${full_dir}/${meta}" sr-uuid="${sr_uuid}" --metadata --preserve"${force_flag}""${dry_run_flag}" if [ $? -gt 0 ]; then error_count=$(( $error_count + 1 )) else @@ -306,16 +328,16 @@ for meta in *.vmmeta; do fi done -smmeta_file=${mnt}/metadata/${chosen_metadata_dir}/SRMETA.xml +smmeta_file="${mnt}/metadata/${chosen_metadata_dir}/SRMETA.xml" if [ "$restore_mode" == "all" ]; then cmd="@LIBEXECDIR@/restore-sr-metadata.py -f ${smmeta_file}" else cmd="@LIBEXECDIR@/restore-sr-metadata.py -u ${sr_uuid} -f ${smmeta_file}" fi -if [ -e ${smmeta_file} ]; then - if [ ${dry_run} -gt 0 ]; then - echo ${cmd} +if [ -e "${smmeta_file}" ]; then + if [ "${dry_run}" -gt 0 ]; then + echo "${cmd}" else ${cmd} fi @@ -323,4 +345,4 @@ fi echo "Restored ${good_count} VM(s), and ${error_count} error(s)" cleanup -exit ${error_count} +exit "${error_count}"