#!/bin/bash

#rbt

# cpds host:remote_system_ds/disk.i fe:SOURCE snapid vmid dsid
#   - fe is the front-end hostname
#   - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
#   - host is the target host to deploy the VM
#   - remote_system_ds is the path for the system datastore in the host
#   - snapid is the snapshot id. "-1" for none

SRC=$1
DST=$2
SNAP_ID=$3
VM_ID=$4
DS_ID=$5

if [ -z "${ONE_LOCATION}" ]; then
    TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
else
    TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
fi

DRIVER_PATH=$(dirname $0)

. $TMCOMMON
. ${DRIVER_PATH}/../../etc/vmm/kvm/kvmrc

#-------------------------------------------------------------------------------
# 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 $VM_ID| $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/HISTORY_RECORDS/HISTORY[last\(\)]/VM_MAD \
                    '%m%/VM/TEMPLATE/DISK/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++]}"
VM_MAD="${XPATH_ELEMENTS[j++]}"
ALL_DISKS="${XPATH_ELEMENTS[j++]}"

if [ "${LCM_STATE}" = '26' -a "${VM_MAD}" != "kvm" ]; then
    error_message "cpds: Live operation not supported on ${VM_MAD}"
    exit 1
fi

#-------------------------------------------------------------------------------
# Set dst path and dir
#-------------------------------------------------------------------------------
SRC_PATH=`arg_path $SRC`
SRC_HOST=`arg_host $SRC`

DST_PATH=`arg_path $DST`
DST_HOST=`arg_host $DST`


DISK_ID=$(echo $SRC_PATH|$AWK -F. '{print $NF}')
DS_SYS_ID=$(echo $SRC_PATH|$AWK -F/ '{print $(NF-2)}')

LV_NAME="lv-one-vm-$VM_ID-$DISK_ID"
VG_NAME="vg-one-$DS_SYS_ID"

VG_IMAGE_NAME="vg-one-${DS_ID}"
LV_IMAGE_NAME=`basename $DST`

SNAP_ID="temp"
VG_NAME="vg-one-${DS_SYS_ID}"
ORIG_LV_NAME="lv-one-vm-${VM_ID}-${DISK_ID}"
NEW_LV_NAME="${ORIG_LV_NAME}-snap${SNAP_ID}"


# sync the constant value with dm_mad/mkfs, see SAVE_AS_SIZE=100
MKFS_SIZE=1024

#HOTPLUG_SAVEAS state (save_as for running VM)
if [ "${LCM_STATE}" = '26' ]; then
    CPDS_CMD=$(cat <<EOT
    set -ex -o pipefail
    ORIG_DEV=\$(readlink $SRC_PATH)
    SNAP_DEV="/dev/${VG_NAME}/${NEW_LV_NAME}"

    DOC="
    <domainsnapshot>
    <name>${DISK_ID}-${SNAP_ID}</name>
    <description>snap ${DISK_ID}-${SNAP_ID}</description>
    <disks>"

    for disk in $ALL_DISKS; do
        if [ "\$disk" = "$DISK_TARGET" ]; then
            DOC="\$DOC
        <disk name='\$disk' type='block' snapshot='external'>
        <source dev='\$SNAP_DEV'/>
        </disk>"
        else
            DOC="\$DOC
        <disk name='\$disk' snapshot='no'/>"
        fi
    done

    DOC="\$DOC
    </disks>
    </domainsnapshot>"

    # Temporary xml file
    FILENAME="/tmp/snapshot-$VMID-$DISK_ID-$SNAP_ID"
    echo "\$DOC" > \$FILENAME

    if virsh -c $LIBVIRT_URI domfsfreeze $DEPLOY_ID ; then
        domain_state="FREEZE"
    elif virsh -c $LIBVIRT_URI suspend $DEPLOY_ID; then
        domain_state="SUSPEND"
    else
        error_message "Could not domfsfreeze or suspend domain"
        exit 1
    fi

    FILE_SIZE=\$(qemu-img measure -U --output=json -O qcow2 \$ORIG_DEV | jq '."required"')
    FILE_SIZEMB=\$(( \$FILE_SIZE / 1024 / 1024))
    SIZE8=\$(bc<<<"scale=1;\$FILE_SIZEMB*1.08"   | awk '{ print int(\$1) }')

    $SUDO $LVCREATE --wipesignatures n -L 100M -n $NEW_LV_NAME ${VG_NAME}
    $SUDO $QEMU_IMG create -f qcow2 "/dev/$VG_NAME/$NEW_LV_NAME" \$FILE_SIZEMB

    function post_actions()
    {
        virsh -c $LIBVIRT_URI blockcommit --active --pivot "one-"$VM_ID $DISK_TARGET
        $SUDO $LVREMOVE -f /dev/$VG_NAME/$NEW_LV_NAME
    }

    virsh -c $LIBVIRT_URI snapshot-create $DEPLOY_ID --disk-only --atomic --no-metadata \
        --reuse-external --xmlfile \$FILENAME

    if [ $? -eq 0 ]; then
        trap post_actions EXIT TERM INT HUP
    fi

    if [ \$domain_state == "FREEZE" ]; then
        virsh -c $LIBVIRT_URI domfsthaw $DEPLOY_ID
    else
        virsh -c $LIBVIRT_URI resume $DEPLOY_ID
    fi

    rm \${FILENAME}

    $SUDO $LVCHANGE -ay $DST
    # LV itself created before in dm_mad/mkfs
    if [ \$SIZE8 -gt $MKFS_SIZE ]; then
        $SUDO $LVEXTEND -L\${SIZE8}M $DST
    fi


    $SUDO $QEMU_IMG convert -O qcow2 \$ORIG_DEV $DST

    $SUDO $LVCHANGE -an $DST

EOT
)
else

    CPDS_CMD=$(cat <<EOT
    set -ex -o pipefail
    DEV=\$(readlink $SRC_PATH)

    $SUDO $SYNC
    $SUDO $LVSCAN

    $SUDO lvchange -ay $DST
    $SUDO lvchange -ay \$DEV

    FILE_SIZE=\$(qemu-img measure -U --output=json -O qcow2 \$DEV | jq '."required"')
    FILE_SIZEMB=\$(( \$FILE_SIZE / 1024 / 1024))
    SIZE8=\$(bc<<<"scale=1;\$FILE_SIZEMB*1.08"   | awk '{ print int(\$1) }')

    # LV itself created before in dm_mad/mkfs
    if [ \$SIZE8 -gt $MKFS_SIZE ]; then
        $SUDO $LVEXTEND -L\${SIZE8}M $DST
    fi
    $SUDO $QEMU_IMG convert -U -O qcow2 \${DEV} $DST
    $SUDO lvchange -an $DST
    $SUDO lvchange -an \$DEV
EOT
)

fi

log "Copying $SRC_PATH to datastore as $DST_PATH"
ssh_exec_and_log $SRC_HOST "$CPDS_CMD" "Could not move image $DST_PATH"

exit 0
