#!/bin/bash

# -------------------------------------------------------------------------- #
# Copyright 2002-2025, 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=$(cat)

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

#--------------------------------------------------------------------------------
# Remove target path to prevent overwrite errors
ssh_exec_and_log "$DST_HOST" "rm -rf '$DST_PATH' && mkdir -p '$DST_PATH'" \
    "Error preparing destination folder."

# Obtain original system directory (srcpath) for system DS migrations
DRIVER_PATH=$(dirname $0)
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/HISTORY_RECORDS/HISTORY[last\(\)-1]/DS_ID)

ORIG_DS_ID="${XPATH_ELEMENTS[j++]}"
#--------------------------------------------------------------------------------

if [ "$ORIG_DS_ID" != "$DSID" ]; then
    SRC_PATH="$(realpath -m "${DST_PATH}/../../${ORIG_DS_ID}/${VMID}")"

    PRE_CMD=$(cat <<EOF
        set -e -o pipefail
        $SYNC
        $SUDO $LVSCAN

        # Get LVM disks devices
        for disk in \$(ls ${SRC_PATH}/disk.*); do
            if [ -L "\$disk" ]; then
                DEVICE=\$(readlink "\$disk")

                if [[ "\$DEVICE" =~ ^/dev/vg-one.* ]]; then
                    # TODO, improve number of ssh connections
                    DEVICES="\$DEVICES \$DEVICE"
                fi
            fi
        done

        if [ -n "\$DEVICES" ]; then
            NEW_VG_NAME=vg-one-$DSID

            # Create destination LVs
            $SSH -n "$DST_HOST" "
                $SYNC
                $SUDO $LVSCAN
                for dev in \$DEVICES; do
                    FDS_RAW=\\\$($SUDO $LVS --noheadings -o lv_name,vg_name,lv_size,pool_lv \\\$dev)
                    FDS=(\\\$FDS_RAW)
                    NAME=\"\\\${FDS[0]}\"
                    OLD_VG_NAME=\"\\\${FDS[1]}\"
                    SIZE=\"\\\${FDS[2]}\"
                    POOL_NAME=\"\\\${FDS[3]}\"
                    # If the device has a pool, assume thin mode
                    if [ -n \"\\\$POOL_NAME\" ]; then
                        # Create pool if it does not exist yet
                        if [ -z \"\\\$($SUDO $LVS --noheading \$NEW_VG_NAME/\\\$POOL_NAME)\" ]; then
                            POOL_SIZE=\\\$($SUDO $LVS --noheadings -o lv_size \\\${OLD_VG_NAME}/\\\${POOL_NAME})
                            $SUDO $LVCREATE -ky -Zy -an -L \\\${POOL_SIZE} --type thin-pool --thinpool \\\$POOL_NAME \$NEW_VG_NAME
                        fi
                        $SUDO $LVCREATE -ky -K -ay --thin \$NEW_VG_NAME/\\\$POOL_NAME -V \\\${SIZE} -n \\\$NAME
                    else
                        $SUDO $LVCREATE -ay --wipesignatures n -L \\\${SIZE} -n \\\$NAME \$NEW_VG_NAME
                    fi
                done
                $SYNC
            "
        fi

        $SYNC

        $TAR -C $SRC_PATH -cSf - . | $SSH "$DST_HOST" "$TAR -xSf - -C $DST_PATH"
EOF
)
else
    PRE_CMD=$(cat <<EOF
        set -e -o pipefail
        $SYNC
        $SUDO $LVSCAN

        # Get LVM disks devices
        for disk in \$(ls ${DST_PATH}/disk.*); do
            if [ -L "\$disk" ]; then
                DEVICE=\$(readlink "\$disk")

                if [[ "\$DEVICE" =~ ^/dev/vg-one.* ]]; then
                    # TODO, improve number of ssh connections
                    DEVICES="\$DEVICES \$DEVICE"
                fi
            fi
        done

        if [ -n "\$DEVICES" ]; then
            # Activate LVs in the destination hosts
            $SSH -n "$DST_HOST" "$SUDO $LVCHANGE -ay -K \$DEVICES"
        fi

        $TAR -C $DST_PATH -cSf - . | $SSH "$DST_HOST" "$TAR -xSf - -C $DST_PATH"
EOF
)
fi

ssh_forward ssh_exec_and_log "$SRC_HOST" "$PRE_CMD" "Error running fs_lvm premigrate"

migrate_other "$@"
