diff --git a/install.sh b/install.sh index 7325a5f90a3..6a3cbe65493 100755 --- a/install.sh +++ b/install.sh @@ -353,6 +353,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \ $VAR_LOCATION/remotes/datastore/dummy \ $VAR_LOCATION/remotes/datastore/fs \ $VAR_LOCATION/remotes/datastore/ceph \ + $VAR_LOCATION/remotes/datastore/qcow2 \ $VAR_LOCATION/remotes/datastore/dev \ $VAR_LOCATION/remotes/datastore/vcenter \ $VAR_LOCATION/remotes/market \ @@ -1289,6 +1290,7 @@ TM_QCOW2_FILES="src/tm_mad/qcow2/clone \ src/tm_mad/qcow2/mkswap \ src/tm_mad/qcow2/mkimage \ src/tm_mad/qcow2/mv \ + src/tm_mad/qcow2/mv.ssh \ src/tm_mad/qcow2/context \ src/tm_mad/qcow2/premigrate \ src/tm_mad/qcow2/postmigrate \ @@ -1296,9 +1298,13 @@ TM_QCOW2_FILES="src/tm_mad/qcow2/clone \ src/tm_mad/qcow2/mvds \ src/tm_mad/qcow2/mvds.ssh \ src/tm_mad/qcow2/snap_create \ + src/tm_mad/qcow2/snap_create.ssh \ src/tm_mad/qcow2/snap_create_live \ + src/tm_mad/qcow2/snap_create_live.ssh \ src/tm_mad/qcow2/snap_delete \ + src/tm_mad/qcow2/snap_delete.ssh \ src/tm_mad/qcow2/snap_revert \ + src/tm_mad/qcow2/snap_revert.ssh \ src/tm_mad/qcow2/cpds \ src/tm_mad/qcow2/cpds.ssh \ src/tm_mad/qcow2/resize" diff --git a/src/datastore_mad/remotes/libfs.sh b/src/datastore_mad/remotes/libfs.sh index eb10478907c..3cdd9318521 100644 --- a/src/datastore_mad/remotes/libfs.sh +++ b/src/datastore_mad/remotes/libfs.sh @@ -503,3 +503,22 @@ function get_destination_host { echo ${HOSTS_ARRAY[$ARRAY_INDEX]} } + +#-------------------------------------------------------------------------------- +# Rebase backing files of snapshots in current directory +# @param $1 name of the backing_file symlink used internally +#-------------------------------------------------------------------------------- +rebase_backing_files() { + local DST_FILE=$1 + + for SNAP_ID in $(find * -maxdepth 0 -type f -print); do + INFO=$(qemu-img info --output=json $SNAP_ID) + + if [[ $INFO =~ "backing-filename" ]]; then + BACKING_FILE=${INFO/*backing-filename\": \"/} + BACKING_FILE=${BACKING_FILE/\"*/} + BACKING_FILE=$(basename ${BACKING_FILE}) + qemu-img rebase -f qcow2 -u -b "${DST_FILE}.snap/$BACKING_FILE" $SNAP_ID + fi + done +} diff --git a/src/tm_mad/qcow2/cpds.ssh b/src/tm_mad/qcow2/cpds.ssh index 5c37677b837..d0ed286d89c 100755 --- a/src/tm_mad/qcow2/cpds.ssh +++ b/src/tm_mad/qcow2/cpds.ssh @@ -57,15 +57,11 @@ while IFS= read -r -d '' element; do done < <(onevm show -x $VMID| $XPATH \ /VM/DEPLOY_ID \ /VM/LCM_STATE \ - /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/TARGET \ - /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SOURCE \ - /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/CLONE) + /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/TARGET) DEPLOY_ID="${XPATH_ELEMENTS[j++]}" LCM_STATE="${XPATH_ELEMENTS[j++]}" DISK_TARGET="${XPATH_ELEMENTS[j++]}" -DISK_SRC="${XPATH_ELEMENTS[j++]}" -CLONE="${XPATH_ELEMENTS[j++]}" #------------------------------------------------------------------------------- # Set dst path and dir @@ -82,7 +78,6 @@ DST_DS_PATH="$(dirname $(dirname $DST_ARG_PATH))" DST_PATH="${SRC_DS_PATH}${DST_ARG_PATH##$DST_DS_PATH}" if [ "$SNAP_ID" != "-1" ]; then - [ "$CLONE" != "YES" ] && SRC_PATH="$DISK_SRC" SRC_PATH="$SRC_PATH.snap/$SNAP_ID" fi diff --git a/src/tm_mad/qcow2/ln.ssh b/src/tm_mad/qcow2/ln.ssh index 0cf962cf1d2..745e500ea8b 100755 --- a/src/tm_mad/qcow2/ln.ssh +++ b/src/tm_mad/qcow2/ln.ssh @@ -26,7 +26,6 @@ SRC=$1 DST=$2 - VMID=$3 DSID=$4 @@ -36,25 +35,23 @@ else TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh fi -. $TMCOMMON - DRIVER_PATH=$(dirname $0) +LIBFS=${DRIVER_PATH}/../../datastore/libfs.sh + +. $TMCOMMON #------------------------------------------------------------------------------- # Set dst path and dir #------------------------------------------------------------------------------- -DST_PATH=`arg_path $DST` DST_HOST=`arg_host $DST` +DST_PATH=`arg_path $DST` +DST_SNAP_DIR=${DST_PATH}.snap +DST_FILE=`basename $DST_PATH` DST_DIR=`dirname $DST_PATH` -SRC_ARG_PATH=`arg_path $SRC` - -DST_DS_PATH="$(dirname $(dirname $(dirname $DST_PATH)))" -SRC_DS_PATH="$(dirname $(dirname $SRC_ARG_PATH))" - -SRC_PATH="${DST_DS_PATH}${SRC_ARG_PATH##$SRC_DS_PATH}" -SNAP_DIR="${SRC_PATH}.snap" -SNAP_NAME="$(basename $SNAP_DIR)" +SRC_HOST=`arg_host $SRC` +SRC_PATH=`arg_path $SRC` +SRC_SNAP_DIR=${SRC_PATH}.snap #------------------------------------------------------------------------------- # Create DST path @@ -63,42 +60,38 @@ SNAP_NAME="$(basename $SNAP_DIR)" ssh_make_path $DST_HOST $DST_DIR 'ssh' #------------------------------------------------------------------------------- -# Link (ln) SRC into DST +# Copy SRC into DST #------------------------------------------------------------------------------- -log "Linking $SRC_PATH in $DST" +log "Copying $SRC_PATH in $DST" -type="$(file -b --mime-type $SRC_PATH)" - -if [ "$type" == "application/x-iso9660-image" ]; then - CMD="ln -sf ${SRC_PATH} ${DST_PATH}" -else - CMD=$(cat <&2 +MV_CMD=$(cat <&2 + exit 1 +fi + +qemu-img create -f qcow2 -o backing_fmt=qcow2 -b "\${PREVIOUS_SNAP}" "${SNAP_PATH}" +ln -sf $SNAP_PATH_SHORT $SYSTEM_DS_DISK_PATH +EOT +) + +ssh_exec_and_log "${SRC_HOST}" "${SNAP_CMD}" \ + "Error creating snapshot ${SNAP_PATH}" + diff --git a/src/tm_mad/qcow2/snap_create_live.ssh b/src/tm_mad/qcow2/snap_create_live.ssh new file mode 100755 index 00000000000..95209ae387a --- /dev/null +++ b/src/tm_mad/qcow2/snap_create_live.ssh @@ -0,0 +1,159 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_create host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VMID=$3 +DSID=$4 + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh + DATASTORES=/var/lib/one/datastores +else + TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh + DATASTORES=$ONE_LOCATION/var/datastores +fi + +DRIVER_PATH=$(dirname $0) + +source $TMCOMMON +source ${DRIVER_PATH}/../../etc/vmm/kvm/kvmrc + +SRC_PATH=$(arg_path $SRC) +SRC_HOST=$(arg_host $SRC) + +#------------------------------------------------------------------------------- +# Get Image information +#------------------------------------------------------------------------------- + +DISK_ID=$(basename ${SRC} | cut -d. -f2) + +XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin" + +unset i j XPATH_ELEMENTS + +while IFS= read -r -d '' element; do + XPATH_ELEMENTS[i++]="$element" +done < <(onevm show -x $VMID| $XPATH \ + /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/TARGET \ + /VM/DEPLOY_ID \ + '%m%/VM/TEMPLATE/DISK/TARGET') + +TARGET="${XPATH_ELEMENTS[j++]}" +DEPLOY_ID="${XPATH_ELEMENTS[j++]}" +ALL_DISKS="${XPATH_ELEMENTS[j++]}" + +SYSTEM_DS_PATH=$(dirname ${SRC_PATH}) + +SYSTEM_DS_DISK_PATH="${SYSTEM_DS_PATH}/disk.${DISK_ID}" + +DISK_PATH="${SYSTEM_DS_DISK_PATH}" +DISK_PATH_SHORT="$(basename ${SYSTEM_DS_DISK_PATH})" + +NEXT_SNAP_ID=$(($SNAP_ID+1)) + +SNAP_DIR="${DISK_PATH}.snap" +SNAP_DIR_SHORT="${DISK_PATH_SHORT}.snap" + +SNAP_PATH="${SNAP_DIR}/${NEXT_SNAP_ID}" +SNAP_PATH_SHORT="${SNAP_DIR_SHORT}/${NEXT_SNAP_ID}" + +# 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. + +# +# 1 +# snap 1 +# +# +# +# +# +# +# +# + +DOC=" + + ${DISK_ID}-${SNAP_ID} + snap ${DISK_ID}-${SNAP_ID} + " + +for disk in $ALL_DISKS; do + if [ "$disk" = "$TARGET" ]; then + DOC="$DOC + + + " + else + DOC="$DOC + " + fi +done + +DOC="$DOC + +" + +CMD=$(cat < \$FILENAME + +if virsh -c $LIBVIRT_URI domfsfreeze $DEPLOY_ID ; then + trap "virsh -c $LIBVIRT_URI domfsthaw $DEPLOY_ID" EXIT TERM INT HUP +elif virsh -c $LIBVIRT_URI suspend $DEPLOY_ID; then + trap "virsh -c $LIBVIRT_URI resume $DEPLOY_ID" EXIT TERM INT HUP +else + echo "Could not domfsfreeze or suspend domain" >&2 + exit 1 +fi + +# older qemu-img requires relative backing file paths +# to be resolvable from the current directory +cd "${SNAP_DIR}" + +if [ -e "${SNAP_PATH}" ]; then + echo "Snapshot file ${SNAP_PATH} already exists." >&2 + exit 1 +fi + +$QEMU_IMG create -o backing_fmt=qcow2 -b "\${PREVIOUS_SNAP}" \ + -f qcow2 ${QCOW2_OPTIONS} "${SNAP_PATH}" + +virsh -c $LIBVIRT_URI snapshot-create $DEPLOY_ID --disk-only --atomic --no-metadata \ + --reuse-external --xmlfile \$FILENAME + +rm \${FILENAME} + +ln -sf $SNAP_PATH_SHORT $SYSTEM_DS_DISK_PATH +EOT +) + +ssh_exec_and_log "${SRC_HOST}" "${CMD}" \ + "Error creating snapshot ${SNAP_PATH}" diff --git a/src/tm_mad/qcow2/snap_delete.ssh b/src/tm_mad/qcow2/snap_delete.ssh new file mode 100755 index 00000000000..4a4f2b61580 --- /dev/null +++ b/src/tm_mad/qcow2/snap_delete.ssh @@ -0,0 +1,51 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_delete host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VMID=$3 +DSID=$4 + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh + DATASTORES=/var/lib/one/datastores +else + TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh + DATASTORES=$ONE_LOCATION/var/datastores +fi + +DRIVER_PATH=$(dirname $0) + +. $TMCOMMON + +SRC_PATH=$(arg_path $SRC) +SRC_HOST=$(arg_host $SRC) + +DISK_ID=$(basename ${SRC} | cut -d. -f2) +SYSTEM_DS_PATH=$(dirname ${SRC_PATH}) + +DISK_PATH="${SYSTEM_DS_PATH}/disk.${DISK_ID}" + +SNAP_DIR="${DISK_PATH}.snap" +SNAP_PATH="${SNAP_DIR}/${SNAP_ID}" + +ssh_exec_and_log "${SRC_HOST}" "rm ${SNAP_PATH}" \ + "Error deleting snapshot ${SNAP_PATH}" + diff --git a/src/tm_mad/qcow2/snap_revert.ssh b/src/tm_mad/qcow2/snap_revert.ssh new file mode 100755 index 00000000000..e300e1be345 --- /dev/null +++ b/src/tm_mad/qcow2/snap_revert.ssh @@ -0,0 +1,67 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_create host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VMID=$3 +DSID=$4 + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh + DATASTORES=/var/lib/one/datastores +else + TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh + DATASTORES=$ONE_LOCATION/var/datastores +fi + +DRIVER_PATH=$(dirname $0) + +. $TMCOMMON + +SRC_PATH=$(arg_path $SRC) +SRC_HOST=$(arg_host $SRC) + +#------------------------------------------------------------------------------- +# Get Image information +#------------------------------------------------------------------------------- + +DISK_ID=$(basename ${SRC} | cut -d. -f2) + + +SYSTEM_DS_PATH=$(dirname ${SRC_PATH}) + +DISK_PATH="${SYSTEM_DS_PATH}/disk.${DISK_ID}" + +SNAP_DIR="${DISK_PATH}.snap" +SNAP_DIR_SHORT=$(basename "$SNAP_DIR") + +SNAP_PATH="${SNAP_DIR}/${SNAP_ID}" +SNAP_PATH_SHORT="${SNAP_DIR_SHORT}/${SNAP_ID}" + +SNAP_CMD=$(cat <