#!/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.                                             #
#--------------------------------------------------------------------------- #

# 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

VM_ID=$3
DSID=$4

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

. $TMCOMMON

DRIVER_PATH=$(dirname $0)

source ${DRIVER_PATH}/../../datastore/libfs.sh
source ${DRIVER_PATH}/../../efs_utils

TS=`date +"%Y-%m-%d %H:%M:%S"`
echo "${TS} [TM:mv] - SRC ${SRC}" >>  /var/log/one/efs.log
echo "${TS} [TM:mv] - DST ${DST}" >>  /var/log/one/efs.log
echo "${TS} [TM:mv] - VM_ID ${VM_ID}" >>  /var/log/one/efs.log
echo "${TS} [TM:mv] - DSID ${DSID}" >>  /var/log/one/efs.log
#exit 0
#error_message "TM:MV stub"
#exit -1

#-------------------------------------------------------------------------------
# Return if moving a disk, we will move them when moving the whole system_ds
# directory for the VM
#-------------------------------------------------------------------------------
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`

SRC_DIR=`dirname $SRC_PATH`
DST_DIR=`dirname $DST_PATH`

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


if [ "$SRC" == "$DST" ]; then
    log "Not moving $SRC to $DST, they are the same path"
    exit 0
fi



# Directory should be deleted on SRC_SS
if [ `is_disk $DST_PATH` -eq 0 ]; then

    SRC_DS_ID=$(echo $SRC | sed s#//*#/#g | awk -F/ '{print $(NF-1)}')
    DST_DS_ID=$(echo $DST | sed s#//*#/#g | awk -F/ '{print $(NF-1)}')

    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/TEMPLATE/CONTEXT/AXC_VMTYPE)
    AXC_VMTYPE="${XPATH_ELEMENTS[j++]:-efs}"

    case "$AXC_VMTYPE" in
      aa|acr|anc|cf|efs|rb|sp|ve)
        ;;
      *)
        AXC_VMTYPE="efs"
        ;;
    esac

    unset i j XPATH_ELEMENTS

    while IFS= read -r -d '' element; do
            XPATH_ELEMENTS[i++]="$element"
    done < <(onedatastore show -x $SRC_DS_ID | $XPATH \
                        /DATASTORE/TEMPLATE/BRIDGE_LIST\
                        /DATASTORE/TEMPLATE/POOL_NAME)

    SRC_BRIDGE_LIST="${XPATH_ELEMENTS[j++]}"
    SRC_POOL_NAME="${XPATH_ELEMENTS[j++]}"

    #-----------
    # get_destination_host returns a host out of the BRIDGE_LIST
    # So we need to change BRIDGE_LIST global variable for source and destination
    BRIDGE_LIST=${SRC_BRIDGE_LIST}
    SRC_SS=`get_destination_host $SRC_DS_ID`

    unset i j XPATH_ELEMENTS

DELETE_CMD=$(cat <<EOF
        sudo zfs destroy ${SRC_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}
EOF
)
    if [ "$SRC_DS_ID" == "$DST_DS_ID" ]; then
        log "Source datastore $SRC_DS_ID the same as destination $DST_DS_ID. Nothing to do here"
        exit 0
    fi

    ssh_exec_and_log ${SRC_SS} "${DELETE_CMD}" \
        "Failed to delete vm dataset ${SRC_SS}:${SRC_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}"

    exit 0
fi

DISK_ID=$(echo $DST|awk -F. '{print $NF}')
# get destination datased id
DST_DS_ID=$(echo $DST | sed s#//*#/#g | awk -F/ '{print $(NF-2)}')
SRC_DS_ID=$(echo $SRC | sed s#//*#/#g | awk -F/ '{print $(NF-2)}')

if [ "$SRC_DS_ID" == "$DST_DS_ID" ]; then
    log "Source datastore $SRC_DS_ID the same as destination $DST_DS_ID. Nothing to do here"
    exit 0
fi


#if [ `lcm_state` -eq 60 ]; then
#    log "Not moving files from $SRC_HOST in FT mode"
#    exit 0
#fi

efs_log_var "SRC_DS_ID"
efs_log_var "DST_DS_ID"
#-------------------------------------------------------------------------------
# Get Image size information to resize it after clone if necessary
#-------------------------------------------------------------------------------

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/TEMPLATE/CONTEXT/AXC_VMTYPE \
                    /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/CLONE \
                    /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/ISCSI_BASE_IQN \
                    /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/ISCSI_LUN \
                    /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SOURCE )

AXC_VMTYPE="${XPATH_ELEMENTS[j++]:-efs}"
CLONE="${XPATH_ELEMENTS[j++]}"
SRC_ISCSI_BASE_IQN="${XPATH_ELEMENTS[j++]}"
SRC_ISCSI_LUN="${XPATH_ELEMENTS[j++]}"
SOURCE="${XPATH_ELEMENTS[j++]}"

case "$AXC_VMTYPE" in
  aa|acr|anc|cf|efs|rb|sp|ve)
    ;;
  *)
    AXC_VMTYPE="efs"
    ;;
esac

efs_log_var "AXC_VMTYPE"
efs_log_var "SOURCE"
#-------------------------------------------------------------------------------
# Get DST Datastore information
#-------------------------------------------------------------------------------

unset i j XPATH_ELEMENTS

while IFS= read -r -d '' element; do
        XPATH_ELEMENTS[i++]="$element"
done < <(onedatastore show -x $DST_DS_ID | $XPATH \
                    /DATASTORE/TEMPLATE/BRIDGE_LIST\
                    /DATASTORE/TEMPLATE/POOL_NAME\
                    /DATASTORE/TEMPLATE/ISCSI_HOST\
                    /DATASTORE/TEMPLATE/ISCSI_BASE_IQN\
                    /DATASTORE/TEMPLATE/ISCSI_LUN)

DST_BRIDGE_LIST="${XPATH_ELEMENTS[j++]}"
DST_POOL_NAME="${XPATH_ELEMENTS[j++]}"
DST_ISCSI_HOST="${XPATH_ELEMENTS[j++]}"
DST_ISCSI_BASE_IQN="${XPATH_ELEMENTS[j++]}"
DST_ISCSI_LUN="${XPATH_ELEMENTS[j++]}"

BRIDGE_LIST=${DST_BRIDGE_LIST}
#-------------------------------------------------------------------------------
# Get SRC Datastore information
#-------------------------------------------------------------------------------

unset i j XPATH_ELEMENTS

while IFS= read -r -d '' element; do
        XPATH_ELEMENTS[i++]="$element"
done < <(onedatastore show -x $SRC_DS_ID | $XPATH \
                    /DATASTORE/TEMPLATE/BRIDGE_LIST\
                    /DATASTORE/TEMPLATE/POOL_NAME)

SRC_BRIDGE_LIST="${XPATH_ELEMENTS[j++]}"
SRC_POOL_NAME="${XPATH_ELEMENTS[j++]}"

#-----------
# get_destination_host returns a host out of the BRIDGE_LIST
# So we need to change BRIDGE_LIST global variable for source and destination
DST_SS=`get_destination_host $DST_DS_ID`
BRIDGE_LIST=${SRC_BRIDGE_LIST}
SRC_SS=`get_destination_host $SRC_DS_ID`
BRIDGE_LIST=${DST_BRIDGE_LIST}


TS=$(date +"%Y-%m-%d_%H%M%S")
MIGRATE_SNAP="onemigrate_${TS}"
# check if destination doesn't exist
# copy source to dst
#
SNAPSHOT_CMD=$(cat <<EOF
    sudo zfs snapshot ${SRC_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}/${DISK_ID}@${MIGRATE_SNAP}
EOF
)

efs_log_var "SNAPSHOT_CMD"
efs_log_var "SRC_SS"
ssh_exec_and_log ${SRC_SS} "${SNAPSHOT_CMD}" \
    "Failed to create snapshot"

MIGRATE_CMD=$(cat <<EOF
    sudo zfs create -p ${DST_POOL_NAME}/one
    sudo zfs set canmount=noauto ${DST_POOL_NAME}/one
    # check if exists ${SRC_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}/${DISK_ID}
    sudo zfs create -p ${DST_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}
    sudo zfs set canmount=noauto ${DST_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}
    ssh $SRC_SS "sudo zfs send ${SRC_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}/${DISK_ID}@${MIGRATE_SNAP}" | sudo zfs recv ${DST_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}/${DISK_ID}
    sudo ctladd ${SOURCE}-${VM_ID}-${DISK_ID} ${DST_ISCSI_LUN} /dev/zvol/${DST_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}/${DISK_ID}
    sleep 5
    sudo service ctld reload
EOF
)

TFILE=$(mktemp /tmp/foo.XXXXXXXXX)
echo "${MIGRATE_CMD}" > ${TFILE}
scp ${TFILE} $DST_SS:${TFILE}
efs_log_var "TFILE"
ssh_exec_and_log ${DST_SS} "bash ${TFILE}" \
    "Failed to copy ${SRC_SS}:${SRC_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}/${DISK_ID}@${MIGRATE_SNAP} to ${DST_SS}:${DST_POOL_NAME}"


onedb change-body vm --id ${VM_ID} "/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/ISCSI_HOST" "${DST_ISCSI_HOST}"


# Remove disk on the source storage
DELETE_CMD=$(cat <<EOF
    set -e -o pipefail
    sudo ctldel ${SOURCE}-${VM_ID}-${DISK_ID} ${SRC_ISCSI_LUN}
    sleep 1
    sudo service ctld reload
    sleep 15
    TS=\$(date +%Y%m%d000000)
    sudo zfs rename -p ${SRC_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}/${DISK_ID} ${SRC_POOL_NAME}/one/to-del/\${TS}-${VM_ID}-system/${DISK_ID}
    sleep 5
EOF
)

ssh_exec_and_log ${SRC_SS} "${DELETE_CMD}" \
  "Failed to remove ${SRC_SS}:${SRC_POOL_NAME}/one/${AXC_VMTYPE}/system/${VM_ID}/${DISK_ID}"


#hup_collectd $DST_HOST
#hup_collectd $SRC_HOST

exit 0
