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

DRIVER_PATH=$(dirname $0)

DEPLOY_ID=$1
DST_PATH=$2
SRC_HOST=$3
VM_ID=$4

# There is data in stdin, read it
DRV_ACTION=$(cat)

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

source $(dirname $0)/../../scripts_common.sh

XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin"

unset i j XPATH_ELEMENTS

while IFS= read -r -d '' element; do
    XPATH_ELEMENTS[i++]="$element"
done < <(echo "$DRV_ACTION" | base64 -d | $XPATH \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TM_MAD \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LS_CONTROLLERS \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LS_CERTFILE \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LS_KEYFILE \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LS_CAFILE \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/RESOURCE_GROUP \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/NODE_LIST \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LAYER_LIST \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/PROVIDERS \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/REPLICAS_ON_SAME \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/REPLICAS_ON_DIFFERENT \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/AUTO_PLACE \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/REPLICA_COUNT \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/CHECKPOINT_AUTO_PLACE \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/CHECKPOINT_REPLICA_COUNT \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/DO_NOT_PLACE_WITH \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/DO_NOT_PLACE_WITH_REGEX \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/STORAGE_POOL \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/DISKLESS_POOL \
                    /VMM_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/ENCRYPTION)

TM_MAD="${XPATH_ELEMENTS[j++]}"
LS_CONTROLLERS="${XPATH_ELEMENTS[j++]}"
LS_CERTFILE="${XPATH_ELEMENTS[j++]}"
LS_KEYFILE="${XPATH_ELEMENTS[j++]}"
LS_CAFILE="${XPATH_ELEMENTS[j++]}"
RESOURCE_GROUP="${XPATH_ELEMENTS[j++]}"
NODE_LIST="${XPATH_ELEMENTS[j++]}"
LAYER_LIST="${XPATH_ELEMENTS[j++]}"
PROVIDERS="${XPATH_ELEMENTS[j++]}"
REPLICAS_ON_SAME="${XPATH_ELEMENTS[j++]}"
REPLICAS_ON_DIFFERENT="${XPATH_ELEMENTS[j++]}"
AUTO_PLACE="${XPATH_ELEMENTS[j++]}"
REPLICA_COUNT="${XPATH_ELEMENTS[j++]:-$AUTO_PLACE}"
CHECKPOINT_AUTO_PLACE="${XPATH_ELEMENTS[j++]}"
CHECKPOINT_REPLICA_COUNT="${XPATH_ELEMENTS[j++]:-$CHECKPOINT_AUTO_PLACE}"
DO_NOT_PLACE_WITH="${XPATH_ELEMENTS[j++]}"
DO_NOT_PLACE_WITH_REGEX="${XPATH_ELEMENTS[j++]}"
STORAGE_POOL="${XPATH_ELEMENTS[j++]}"
DISKLESS_POOL="${XPATH_ELEMENTS[j++]:-DfltDisklessStorPool}"
ENCRYPTION="${XPATH_ELEMENTS[j++]}"

if [ -n "$CHECKPOINT_AUTO_PLACE" ]; then
    AUTO_PLACE="$CHECKPOINT_AUTO_PLACE"
fi

DST_RES="one-vm-${VM_ID}-checkpoint"
DST_DEV="/dev/drbd/by-res/${DST_RES}/0"

#-------------------------------------------------------------------------------
# TM_MAD is not 'linstor_un'
#-------------------------------------------------------------------------------P

if [ "$TM_MAD" != "linstor_un" ]; then
    echo "$DRV_ACTION" | $SSH "$SRC_HOST" /var/tmp/one/vmm/kvm/save "$@"
    exit $?
fi

#-------------------------------------------------------------------------------
# TM_MAD is 'linstor_un'
#-------------------------------------------------------------------------------

source ${DRIVER_PATH}/../../etc/vmm/kvm/kvmrc
source ${DRIVER_PATH}/../../datastore/libfs.sh
source ${DRIVER_PATH}/../../etc/datastore/linstor_un/linstor_un.conf
source ${DRIVER_PATH}/../../datastore/linstor_un/linstor_utils.sh

linstor_load_keys

# Load cleanup trap
revert() {
    $SSH $SRC_HOST virsh --connect $LIBVIRT_URI resume $DEPLOY_ID
    linstor_cleanup_trap
}
trap revert EXIT

# Suspend VM
ssh_exec_and_log "$SRC_HOST" \
    "virsh --connect $LIBVIRT_URI suspend $DEPLOY_ID" \
    "Could not suspend $DEPLOY_ID on $SRC_HOST"

ORIGINAL_SIZE_K="$($SSH $SRC_HOST virsh --connect $LIBVIRT_URI dommemstat $DEPLOY_ID | \
    $AWK '$1 == "rss" {print $2}')"

if [ -z "$ORIGINAL_SIZE_K" ]; then
    error_message "Error getting checkpoint size"
    ssh_exec_and_log_no_error "$SRC_HOST" \
        "virsh --connect $LIBVIRT_URI resume $DEPLOY_ID" \
        "Could not resume $DEPLOY_ID on $SRC_HOST"
    exit -1
fi
if [ "$ORIGINAL_SIZE_K" -lt 4 ]; then
    ORIGINAL_SIZE_K="4"
fi

# Deploy new volume
linstor_exec_and_log \
    "resource-definition create $DST_RES $RD_CREATE_ARGS"
LINSTOR_CLEANUP_RD+=" $DST_RES"
linstor_exec_and_log \
    "volume-definition create $DST_RES ${ORIGINAL_SIZE_K}K $VOL_CREATE_ARGS"
if [ -n "$RESOURCE_GROUP" ]; then
    linstor_exec_and_log \
        "resource-definition auto-place $DST_RES $RD_AUTO_PLACE_ARGS"
else
    linstor_exec_and_log \
        "resource create $NODE_LIST $DST_RES $RES_CREATE_ARGS"
fi

# Attach diskless resource for DST_RES on SRC_HOST
if linstor_attach_diskless "$SRC_HOST" "$DST_RES" "$DISKLESS_POOL"; then
    LINSTOR_CLEANUP_RES+=" $SRC_HOST:$DST_RES"
fi

# saving vm state
ssh_exec_and_log "$SRC_HOST" \
    "virsh --connect $LIBVIRT_URI save $DEPLOY_ID $DST_DEV" \
    "could not save $DEPLOY_ID to $DST_PATH on $SRC_HOST"

trap linstor_cleanup_trap EXIT
LINSTOR_CLEANUP_RD=
exit 0
