mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
feature #3782: live snapshots for qcow2
This commit is contained in:
parent
77a72e9d33
commit
5af9499101
src
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/bash -ex
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs #
|
||||
@ -62,7 +62,7 @@ SNAP_PATH="${SNAP_DIR}/${SNAP_ID}"
|
||||
SNAP_PATH_RELATIVE=$(basename ${SNAP_PATH})
|
||||
CURRENT_PATH=${DISK_PATH}
|
||||
|
||||
rm ${DISK_PATH}
|
||||
qemu-img convert -O qcow2 ${SNAP_PATH} ${CURRENT_PATH}
|
||||
qemu-img convert -O qcow2 ${SNAP_PATH} ${CURRENT_PATH}.tmp
|
||||
mv "${CURRENT_PATH}.tmp" "${CURRENT_PATH}"
|
||||
rm -rf ${SNAP_DIR}
|
||||
|
||||
|
@ -96,9 +96,11 @@ http://*)
|
||||
RESIZE_CMD="; qemu-img resize ${DST_PATH} ${SIZE}M"
|
||||
fi
|
||||
|
||||
CLONE_CMD="cd $DST_DIR; \
|
||||
rm -f $DST_PATH; $QEMU_IMG create -b $SRC_PATH -f qcow2 $DST_PATH \
|
||||
CLONE_CMD="cd $DST_DIR; rm -f $DST_PATH; \
|
||||
$QEMU_IMG create -b $SRC_PATH -f qcow2 ${DST_PATH}.orig; \
|
||||
ln -s ${DST_PATH}.orig ${DST_PATH}; \
|
||||
${RESIZE_CMD}"
|
||||
|
||||
ssh_exec_and_log "$DST_HOST" "$CLONE_CMD" "Error copying $SRC to $DST"
|
||||
;;
|
||||
esac
|
||||
|
@ -52,27 +52,89 @@ while IFS= read -r -d '' element; do
|
||||
XPATH_ELEMENTS[i++]="$element"
|
||||
done < <(onevm show -x $VMID| $XPATH \
|
||||
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SOURCE \
|
||||
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/CLONE)
|
||||
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/CLONE \
|
||||
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/TARGET \
|
||||
"/VM/SNAPSHOTS[DISK_ID=$DISK_ID]/SNAPSHOT[last()]/ID" \
|
||||
/VM/HISTORY_RECORDS/HISTORY/VMMMAD \
|
||||
/VM/STATE \
|
||||
/VM/LCM_STATE \
|
||||
'%m%/VM/TEMPLATE/DISK/TARGET')
|
||||
|
||||
DISK_SRC="${XPATH_ELEMENTS[j++]}"
|
||||
CLONE="${XPATH_ELEMENTS[j++]}"
|
||||
TARGET="${XPATH_ELEMENTS[j++]}"
|
||||
LAST_SNAP_ID="${XPATH_ELEMENTS[j++]}"
|
||||
VMMAD="${XPATH_ELEMENTS[j++]}"
|
||||
STATE="${XPATH_ELEMENTS[j++]}"
|
||||
LCM_STATE="${XPATH_ELEMENTS[j++]}"
|
||||
ALL_DISKS="${XPATH_ELEMENTS[j++]}"
|
||||
|
||||
if [ -z "$LAST_SNAP_ID" ]; then
|
||||
LAST_SNAP_ID=0
|
||||
fi
|
||||
|
||||
|
||||
SYSTEM_DS_PATH=$(dirname ${SRC_PATH})
|
||||
IMAGE_DS_PATH=$(dirname ${DISK_SRC})
|
||||
|
||||
SYSTEM_DS_DISK_PATH="${SYSTEM_DS_PATH}/disk.${DISK_ID}"
|
||||
|
||||
if [ "$CLONE" = "YES" ]; then
|
||||
DISK_PATH="${SYSTEM_DS_PATH}/disk.${DISK_ID}"
|
||||
DISK_PATH="${SYSTEM_DS_DISK_PATH}"
|
||||
DISK_PATH_ORIG="${DISK_PATH}.orig"
|
||||
else
|
||||
DISK_PATH=$DISK_SRC
|
||||
DISK_PATH_ORIG=$DISK_PATH
|
||||
fi
|
||||
|
||||
SNAP_ID=$(( $LAST_SNAP_ID + 1 ))
|
||||
|
||||
SNAP_DIR="${DISK_PATH}.snap"
|
||||
SNAP_PATH="${SNAP_DIR}/${SNAP_ID}"
|
||||
LAST_SNAP_PATH="${SNAP_DIR}/${LAST_SNAP_ID}"
|
||||
SNAP_PATH_RELATIVE=$(basename ${SNAP_PATH})
|
||||
CURRENT_PATH=${DISK_PATH}
|
||||
|
||||
# virsh snapshot-create by default creates snapshots for all the disks that
|
||||
# are not read only. To be able to make a snapshot in only one of the disks
|
||||
# an xml must be created describing all of the disks and setting the value
|
||||
# snapshot='no' to the disks that are not going to be snapshotted.
|
||||
|
||||
# <domainsnapshot>
|
||||
# <name>1</name>
|
||||
# <description>snap 1</description>
|
||||
# <disks>
|
||||
# <disk name='vda' snapshot='no'/>
|
||||
# <disk name='vdb'>
|
||||
# <source file='/var/lib/one/datastores/1/09eec196c67b38dea41048a628978600.snap/1'/>
|
||||
# </disk>
|
||||
# <disk name='vdc' snapshot='no'/>
|
||||
# </disks>
|
||||
# </domainsnapshot>
|
||||
|
||||
|
||||
DOC="
|
||||
<domainsnapshot>
|
||||
<name>${SNAP_ID}</name>
|
||||
<description>snap ${SNAP_ID}</description>
|
||||
<disks>"
|
||||
|
||||
for disk in $ALL_DISKS; do
|
||||
if [ "$disk" = "$TARGET" ]; then
|
||||
DOC="$DOC
|
||||
<disk name='$disk' snapshot='external'>
|
||||
<source file='$SNAP_PATH'/>
|
||||
</disk>"
|
||||
else
|
||||
DOC="$DOC
|
||||
<disk name='$disk' snapshot='no'/>"
|
||||
fi
|
||||
done
|
||||
|
||||
DOC="$DOC
|
||||
</disks>
|
||||
</domainsnapshot>"
|
||||
|
||||
CMD=$(cat <<EOT
|
||||
set -ex
|
||||
|
||||
@ -80,28 +142,43 @@ if [ ! -d "${SNAP_DIR}" ]; then
|
||||
mkdir "${SNAP_DIR}"
|
||||
fi
|
||||
|
||||
# Move save current snapshot and create a new one. The snapshot uses
|
||||
# absolute path name as the qemu-img has problems with relative backing
|
||||
# file paths and symlinks
|
||||
mv "${CURRENT_PATH}" "${SNAP_PATH}"
|
||||
qemu-img create -f qcow2 -b "${SNAP_PATH}" "${CURRENT_PATH}"
|
||||
# 57 is DISK_SNAPSHOT. When the snapshot is done with the VM in running state
|
||||
if [ "$LCM_STATE" = "57" ] && [ "$VMMMAD" = "kvm" ] ; then
|
||||
# The file must be created beforehand or libvirt complains with
|
||||
# "permission denied"
|
||||
touch $SNAP_PATH
|
||||
|
||||
# TODO: Check that the new snapshot can be created. Roll back in case
|
||||
# of error
|
||||
# Temporary xml file
|
||||
FILENAME="/tmp/snapshot-\$(date +%s)"
|
||||
echo -e "$DOC" > \$FILENAME
|
||||
|
||||
# Convert backing file absolute path to relative path so it works outside
|
||||
# the system directory. Do not do this for snapshot one as:
|
||||
# * It could be a non backed file (persistent)
|
||||
# * The backing file is in images directory, is not relative
|
||||
if [ "$SNAP_ID" != "0" ]; then
|
||||
BACKING_FILE=\$(qemu-img info ${SNAP_PATH} | grep '^backing file:' | \
|
||||
cut -d: -f2 | sed 's/^ //')
|
||||
virsh -c qemu:///system snapshot-create one-$VMID --disk-only --atomic \
|
||||
--xmlfile \$FILENAME --quiesce
|
||||
|
||||
if [ -n "\$BACKING_FILE" ]; then
|
||||
RELATIVE_BACKING_FILE="\$(basename \${BACKING_FILE})"
|
||||
ln -sf $SNAP_PATH $SYSTEM_DS_DISK_PATH
|
||||
|
||||
qemu-img rebase -u -b "\${RELATIVE_BACKING_FILE}" "${SNAP_PATH}"
|
||||
rm \$FILENAME
|
||||
else
|
||||
if [ "$SNAP_ID" = "1" ]; then
|
||||
ORIG="$DISK_PATH_ORIG"
|
||||
else
|
||||
ORIG="$LAST_SNAP_PATH"
|
||||
fi
|
||||
|
||||
qemu-img create -f qcow2 -b "\${ORIG}" "${SNAP_PATH}"
|
||||
ln -sf $SNAP_PATH $SYSTEM_DS_DISK_PATH
|
||||
fi
|
||||
|
||||
if [ "$SNAP_ID" = "1" ] && [ "$CLONE" != "YES" ]; then
|
||||
ln -sf "${DISK_PATH_ORIG}" "${SNAP_DIR}/0"
|
||||
fi
|
||||
|
||||
BACKING_FILE=\$(qemu-img info ${SNAP_PATH} | grep '^backing file:' | \
|
||||
cut -d: -f2 | sed 's/^ //')
|
||||
|
||||
if [ "\${BACKING_FILE}" = "${SYSTEM_DS_DISK_PATH}" ]; then
|
||||
REAL_BACKING_FILE="${DISK_PATH_ORIG}"
|
||||
qemu-img rebase -u -b "\${REAL_BACKING_FILE}" "${SNAP_PATH}"
|
||||
fi
|
||||
EOT
|
||||
)
|
||||
|
@ -67,13 +67,16 @@ else
|
||||
DISK_PATH=$DISK_SRC
|
||||
fi
|
||||
|
||||
NEXT_ID=$(( $SNAP_ID + 1 ))
|
||||
SNAP_DIR="${DISK_PATH}.snap"
|
||||
SNAP_PATH="${SNAP_DIR}/${SNAP_ID}"
|
||||
SNAP_PATH_NEXT="${SNAP_DIR}/${NEXT_ID}"
|
||||
SNAP_PATH_RELATIVE=$(basename ${SNAP_PATH})
|
||||
CURRENT_PATH=${DISK_PATH}
|
||||
|
||||
CMD="rm \"${CURRENT_PATH}\" ; \
|
||||
qemu-img create -f qcow2 -b \"${SNAP_PATH}\" \"${CURRENT_PATH}\""
|
||||
CMD="set -ex ; \
|
||||
qemu-img create -f qcow2 -b \"${SNAP_PATH}\" \"${CURRENT_PATH}\"; \
|
||||
"
|
||||
|
||||
ssh_exec_and_log "${SRC_HOST}" "${CMD}" \
|
||||
"Error reverting snapshot to ${SNAP_PATH}"
|
||||
|
@ -63,8 +63,21 @@ ssh_make_path $DST_HOST $DST_DIR
|
||||
#-------------------------------------------------------------------------------
|
||||
log "Linking $SRC_PATH in $DST"
|
||||
|
||||
ssh_exec_and_log $DST_HOST \
|
||||
"cd $DST_DIR; rm -f $DST_PATH ; ln -s $SRC_PATH $DST_PATH" \
|
||||
"Error linking $SRC to $DST"
|
||||
CMD=$(cat <<EOT
|
||||
set -ex
|
||||
|
||||
SRC="$SRC_PATH"
|
||||
SNAP_DIR="${SRC_PATH}.snap"
|
||||
|
||||
if [ -d "\${SNAP_DIR}" ]; then
|
||||
SNAP="\$(ls \${SNAP_DIR} | sort -n | tail -n 1)"
|
||||
SRC="\${SNAP_DIR}/\${SNAP}"
|
||||
fi
|
||||
|
||||
ln -sf "\$SRC" "$DST_PATH"
|
||||
EOT
|
||||
)
|
||||
|
||||
ssh_exec_and_log $DST_HOST "$CMD" \
|
||||
"Error linking $SRC to $DST"
|
||||
exit 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user