#!/bin/bash

# -------------------------------------------------------------------------- #
# Copyright 2002-2018, 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.                                             #
#--------------------------------------------------------------------------- #

# MV <hostA:system_ds/disk.i|hostB:system_ds/disk.i> vmid dsid
#    <hostA:system_ds/|hostB:system_ds/>
#   - hostX is the target host to deploy the VM
#   - system_ds is the path for the system datastore in the host
#   - vmid is the id of the VM
#   - dsid is the target datastore (0 is the system datastore)

SRC=$1
DST=$2

VMID=$3
DSID=$4

#--------------------------------------------------------------------------------

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

DRIVER_PATH=$(dirname $0)

. $TMCOMMON

#--------------------------------------------------------------------------------

SRC=`fix_dir_slashes $SRC`
DST=`fix_dir_slashes $DST`

SRC_PATH=`arg_path $SRC`
DST_PATH=`arg_path $DST`

SRC_HOST=`arg_host $SRC`
DST_HOST=`arg_host $DST`

DST_DIR=`dirname $DST_PATH`

SRC_DS_DIR=`dirname  $SRC_PATH`
SRC_VM_DIR=`basename $SRC_PATH`

SRC_DS_SYS_ID=$(echo $SRC_DS_DIR | $AWK -F '/' '{print $(NF-1)}')
DST_DS_SYS_ID=$(echo $DST_DIR | $AWK -F '/' '{print $(NF-1)}')

# Activate the disk in the target host
if [ `is_disk $DST_PATH` -eq 1 ]; then
    #---------------------------------------------------------------------------
    # Get Image information
    #---------------------------------------------------------------------------

    DISK_ID=${SRC_VM_DIR##*.}

    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]/TYPE )

    TYPE="${XPATH_ELEMENTS[j++]}"

    ####

    if [ "${TYPE}" != "BLOCK" ]; then
        exit 0
    fi

    LV_NAME="lv-one-${VMID}-${DISK_ID}"
    SRC_VG_NAME="vg-one-${SRC_DS_SYS_ID}"
    SRC_DEV="/dev/${SRC_VG_NAME}/${LV_NAME}"
    DST_VG_NAME="vg-one-${DST_DS_SYS_ID}"
    DST_DEV="/dev/${DST_VG_NAME}/${LV_NAME}"

    # copy volume between datastores
    if [ "${SRC_PATH}" != "${DST_PATH}" ]; then
        # create new volume
        CREATE_CMD=$(cat <<EOF
            set -e -o pipefail
            ${SUDO} ${SYNC}
            ${SUDO} ${LVSCAN}
            SIZE=\$(${SUDO} ${LVS} --noheadings --units B -o lv_size "${SRC_DEV}" | tr -d '[:blank:]')
            ${SUDO} ${LVCREATE} --wipesignatures n -L"\${SIZE}" -n "${LV_NAME}" "${DST_VG_NAME}"
EOF
)

        LOCK="tm-fs_lvm-${DST_DS_SYS_ID}.lock"
        exclusive "${LOCK}" 120 ssh_exec_and_log "${SRC_HOST}" "${CREATE_CMD}" \
                "Error creating LV named ${LV_NAME}"

        # copy volume data
        ssh_exec_and_log "$SRC_HOST" \
            "${DD} if=${SRC_DEV} of=${DST_DEV} bs=64k" \
            "Error copying ${SRC} to ${DST}"

        # delete old volume and update device symlinks
        DELETE_CMD=$(cat <<EOF
            set -e -o pipefail
            ${SUDO} ${LVREMOVE} -f ${SRC_DEV}
            ${SUDO} ${SYNC}

            rm -f "${SRC_PATH}"
            ln -s "${DST_DEV}" "${SRC_PATH}"
EOF
)

        LOCK="tm-fs_lvm-${SRC_DS_SYS_ID}.lock"
        exclusive "${LOCK}" 120 ssh_exec_and_log "${SRC_HOST}" "${DELETE_CMD}" \
            "Error deleting old LV ${SRC_DEV}"
    fi

    # activate
    CMD=$(cat <<EOF
        set -ex -o pipefail
        ${SUDO} ${SYNC}
        ${SUDO} ${LVSCAN}
        ${SUDO} ${LVCHANGE} -ay "${DST_DEV}"

        hostname -f >"${DST_DIR}/.host" || :
EOF
)
    ssh_exec_and_log "$DST_HOST" "$CMD" \
        "Error activating disk $DST_PATH"

    exit 0
fi

# Return if the target path is the same as the source path. No need to move
# anything. This is *not* a system ds migration.
if [ "$SRC_PATH" == "$DST_PATH" ]; then
    exit 0
fi

ssh_exec_and_log "$DST_HOST" "mv $SRC_PATH $DST_PATH" \
    "Error moving VM files to another System DS: $SRC_PATH to $DST_PATH in $DST_HOST"
