diff --git a/src/datastore_mad/remotes/fs/snap_flatten b/src/datastore_mad/remotes/fs/snap_flatten
index 262336989d..d7baa0e253 100755
--- a/src/datastore_mad/remotes/fs/snap_flatten
+++ b/src/datastore_mad/remotes/fs/snap_flatten
@@ -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}
diff --git a/src/tm_mad/qcow2/clone b/src/tm_mad/qcow2/clone
index bbce31ac90..6ba3bd8ed6 100755
--- a/src/tm_mad/qcow2/clone
+++ b/src/tm_mad/qcow2/clone
@@ -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
diff --git a/src/tm_mad/qcow2/snap_create b/src/tm_mad/qcow2/snap_create
index b5f0f595e9..f2bc71f5de 100755
--- a/src/tm_mad/qcow2/snap_create
+++ b/src/tm_mad/qcow2/snap_create
@@ -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.
+
+#
+# 1
+# snap 1
+#
+#
+#
+#
+#
+#
+#
+#
+
+
+DOC="
+
+ ${SNAP_ID}
+ snap ${SNAP_ID}
+ "
+
+for disk in $ALL_DISKS; do
+ if [ "$disk" = "$TARGET" ]; then
+ DOC="$DOC
+
+
+ "
+ else
+ DOC="$DOC
+ "
+ fi
+done
+
+DOC="$DOC
+
+"
+
CMD=$(cat < \$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
)
diff --git a/src/tm_mad/qcow2/snap_revert b/src/tm_mad/qcow2/snap_revert
index 8aa19a0ba0..3218e83134 100755
--- a/src/tm_mad/qcow2/snap_revert
+++ b/src/tm_mad/qcow2/snap_revert
@@ -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}"
diff --git a/src/tm_mad/shared/ln b/src/tm_mad/shared/ln
index d73a5f8f18..baf5a21d80 100755
--- a/src/tm_mad/shared/ln
+++ b/src/tm_mad/shared/ln
@@ -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 <