Skip to content

Commit

Permalink
CP-46179 update metadata backup/restore to use deterministic UUID
Browse files Browse the repository at this point in the history
We introduce deterministic UUID for backup VDIs to avoid searching for
VDIs. Add this capability to the scripts that create and restore
backups. In case the VDI with the expected UUID does not exist, let the
user confirm probing for it.

Signed-off-by: Christian Lindig <[email protected]>
  • Loading branch information
Christian Lindig authored and lindig committed Mar 25, 2024
1 parent bbc5a1f commit 65f152d
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 15 deletions.
44 changes: 40 additions & 4 deletions scripts/xe-backup-metadata
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
44 changes: 33 additions & 11 deletions scripts/xe-restore-metadata
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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=
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand All @@ -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 <enter> to continue."
echo "Please type in 'yes' and <enter> to continue."
read response
if [ "$response" != "yes" ]; then
echo Aborting metadata restore.
Expand Down Expand Up @@ -297,30 +319,30 @@ 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
good_count=$(( $good_count + 1 ))
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
fi

echo "Restored ${good_count} VM(s), and ${error_count} error(s)"
cleanup
exit ${error_count}
exit "${error_count}"

0 comments on commit 65f152d

Please sign in to comment.