#!/bin/bash

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

# PREMIGRATE SOURCE DST remote_system_dir vmid dsid template
#  - SOURCE is the host where the VM is running
#  - DST is the host where the VM is to be migrated
#  - remote_system_dir is the path for the VM home in the system datastore
#  - vmid is the id of the VM
#  - dsid is the target datastore
#  - template is the template of the VM in XML and base64 encoded

SRC_HOST=$1
DST_HOST=$2

DST_PATH=$3

VMID=$4
DSID=$5

TEMPLATE_64=$6

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

CURRENT_DS_ID=$(onevm show -x $VMID | xmlstarlet sel -t -v "/VM/HISTORY_RECORDS/HISTORY[position() = (last()-1)]/DS_ID")
SRC_DIR=/var/lib/one/datastores/$CURRENT_DS_ID/$VMID

CMD_CREATE=$(cat <<EOF
    set -ex -o pipefail

    export PATH=$PATH:/sbin
    mkdir -p /var/lib/one/datastores/$DSID
    pdp-one "/var/lib/one/datastores/$DSID"
    mkdir -p $DST_PATH

    for disk in /var/lib/one/datastores/$CURRENT_DS_ID/$VMID/*; do
	export PATH=$PATH:/sbin
	pdp-one "$DST_PATH"

        if [ -L "\$disk" ]; then

            DISK_ID=\${disk##*.}
            DEVICE=\$(readlink "\$disk")
            LV_NAME="lv-one-vm-${VMID}-\${DISK_ID}"
            DST_VG_NAME="vg-one-${DSID}"
            DST_DEV="/dev/\${DST_VG_NAME}/\${LV_NAME}"
            DST_MAP="vg--one--${DSID}-lv--one--vm--${VMID}--\${DISK_ID}"
            DST_DEV_MAP="/dev/mapper/\${DST_MAP}"

            if [ -e "\${DST_DEV_MAP}" ]; then
                $SUDO $SYNC
                $SUDO $DMSETUP remove \${DST_MAP}
            fi

            $SUDO $SYNC
            set +e
            $SUDO $LVSCAN | grep "\${DST_DEV}"
            if [ "x\$?" != "x0" ]; then
                set -ex -o pipefail
                SIZE=\$($SUDO lvdisplay --units m -o lv_size --nosuffix --noheadings -C \${DEVICE} | sed -e 's/^[[:space:]]*//' | awk '{print (\$0-int(\$0)>0)?int(\$0)+1:int(\$0)}' 2>/dev/null)
                $SUDO $LVCREATE -L\${SIZE}M -n \$LV_NAME \$DST_VG_NAME -y
            fi

            set -ex -o pipefail
            $SUDO $LVCHANGE -ay \$DST_DEV
            if ! [ -L "$DST_PATH/disk.\${DISK_ID}" ]; then
                ln -s \$DST_DEV $DST_PATH/disk.\${DISK_ID}
            fi
        fi

    done
EOF
)

if [ "$SRC_HOST" == "$DST_HOST" ]; then
    if [ "$CURRENT_DS_ID" != "$DSID" ]; then

        ssh_exec_and_log $DST_HOST "$CMD_CREATE" "Error lvm_lvm premigrate first step"
    fi

    exit 0
fi

if [ "$SRC_HOST" != "$DST_HOST" ]; then

    #rbt: create dirs
    CMD_PRE=$(cat <<EOF
	set -ex -o pipefail

	#rbt: create dirs
	export PATH=$PATH:/sbin
	mkdir -p /var/lib/one/datastores/$DSID
	pdp-one "/var/lib/one/datastores/$DSID"
	mkdir -p $DST_PATH
	pdp-one "$DST_PATH"
EOF
)

    #rbt: copy VM $HOME
    CMD_SYNC=$(cat <<EOF
	set -ex -o pipefail

	cd $DST_PATH
	tar cfp - * | ssh $DST_HOST "(cd $DST_PATH; tar xfp - )"
EOF
)

    CMD=$(cat <<EOF
	set -ex -o pipefail

	$SUDO $SYNC
	$SUDO $LVSCAN

	for disk in \$(ls ${DST_PATH}/disk.*); do
    	    if [ -L "\$disk" ]; then
        	DEVICE=\$(readlink "\$disk")
                DISK_ID=\${disk##*.}
                DST_MAP="vg--one--${DSID}-lv--one--vm--${VMID}--\${DISK_ID}"
                DST_DEV_MAP="/dev/mapper/\${DST_MAP}"
                if [ -e "\${DST_DEV_MAP}" ]; then
                    $SUDO $DMSETUP remove \${DST_MAP}
                fi
        	$SUDO $LVCHANGE -ay \$DEVICE
    	    fi
	done
EOF
)

    #clean old LV
    CLEAN_CMD=$(cat <<EOF
        set -e -o pipefail
	for disk in \$(ls ${SRC_DIR}/disk.*); do
	    if [ -L "\$disk" ]; then
        	DISK_ID=\${disk##*.}
        	LV_NAME="lv-one-vm-${VMID}-\${DISK_ID}"
        	LV_NAME_DISK="lv-one-vm-${VMID}-*"
        	SRC_VG_NAME="vg-one-${CURRENT_DS_ID}"
        	SRC_DEV="/dev/\${SRC_VG_NAME}/\${LV_NAME}"
        	SRC_MAP="vg--one--${CURRENT_DS_ID}-lv--one--vm--${VMID}--\${DISK_ID}"
        	SRC_DEV_MAP="/dev/mapper/\${SRC_MAP}"
        	SRC_DEV_DISK="/dev/\${SRC_VG_NAME}/\${LV_NAME_DISK}"
        	if [ -e "\${SRC_DEV}" ]; then
            	    $SUDO $SYNC
            	    $SUDO $LVREMOVE -f \${SRC_DEV_DISK}
        	fi
	    fi
	    if [ -d "${SRC_DIR}" ]; then
		rm -rf ${SRC_DIR}
	    fi
	done
EOF
)

    ssh_exec_and_log $DST_HOST "$CMD_PRE" \
    "Error running lvm_lvm premigrate"



    if [ "$CURRENT_DS_ID" != "$DSID" ]; then

	deploy_id=one-$VMID

	MOVE_CMD=$(cat <<EOF
	    set -e -o pipefail

    	    OUT="\$(mktemp)"
    	    virsh -c qemu:///system domblklist "$deploy_id" --details | tail -n+3 > \$OUT
    	    while read disk; do
        	if [ -n "\$disk" ]; then
            	    tdisk=(\$disk)
            	    DISK_ID=\${disk##*.}
            	    NEW_DISK_PATH=/var/lib/one/datastores/$DSID/$VMID/disk.\${DISK_ID}

            	    if [ "\${tdisk[0]}" == "block" ]; then
            		virsh -c qemu:///system blockcopy --domain $deploy_id --path \${tdisk[3]} --dest \$NEW_DISK_PATH --blockdev  --wait --verbose --pivot
        	     else
                        cp \${tdisk[3]} \$NEW_DISK_PATH
                        virsh -c qemu:///system change-media --domain $deploy_id \${tdisk[2]} \$NEW_DISK_PATH --live
            	    fi
        	fi
    	    done < \$OUT
EOF
)


	ssh_exec_and_log $SRC_HOST "$CMD_CREATE" \
        "Error running lvm_lvm premigrate"

	ssh_exec_and_log $SRC_HOST "$MOVE_CMD" \
	"Error move disks between datastore  $deploy_id"

	ssh_exec_and_log  $SRC_HOST "$CLEAN_CMD" \
	"Error clean old logic volumes"

	ssh_exec_and_log $SRC_HOST "$CMD_SYNC" \
	"Error sync virtual machine home"

	ssh_exec_and_log $DST_HOST "$CMD" \
        "Error running lvm_lvm premigrate"

    else

	ssh_exec_and_log $SRC_HOST "$CMD_SYNC" \
	"Error sync virtual machine home"

	ssh_exec_and_log $DST_HOST "$CMD" \
        "Error running lvm_lvm premigrate"
    fi
fi

migrate_other "$@"
