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

###############################################################################
# This script is used to copy a VM image (SRC) to the image repository as DST
# Several SRC types are supported
###############################################################################

# -------- Set up the environment to source common tools & conf ------------

if [ -z "${ONE_LOCATION}" ]; then
    LIB_LOCATION=/usr/lib/one
else
    LIB_LOCATION=$ONE_LOCATION/lib
fi

. $LIB_LOCATION/sh/scripts_common.sh

DRIVER_PATH=$(dirname $0)
source ${DRIVER_PATH}/../libfs.sh

# -------- Get cp and datastore arguments from OpenNebula core ------------

DRV_ACTION=$1
ID=$2

export DRV_ACTION

UTILS_PATH="${DRIVER_PATH}/.."

XPATH="$UTILS_PATH/xpath.rb -b $DRV_ACTION"

unset i XPATH_ELEMENTS

while IFS= read -r -d '' element; do
    XPATH_ELEMENTS[i++]="$element"
done < <($XPATH     /DS_DRIVER_ACTION_DATA/DATASTORE/BASE_PATH \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/RESTRICTED_DIRS \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/SAFE_DIRS \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BRIDGE_LIST \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/STAGING_DIR \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TYPE \
                    /DS_DRIVER_ACTION_DATA/IMAGE/PATH \
                    /DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/MD5 \
                    /DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/SHA1 \
                    /DS_DRIVER_ACTION_DATA/IMAGE/DATASTORE_ID \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/NO_DECOMPRESS \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LIMIT_TRANSFER_BW \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/CONVERT \
                    /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/DRIVER \
                    /DS_DRIVER_ACTION_DATA/IMAGE/TYPE)

unset i

BASE_PATH="${XPATH_ELEMENTS[i++]}"
RESTRICTED_DIRS="${XPATH_ELEMENTS[i++]}"
SAFE_DIRS="${XPATH_ELEMENTS[i++]}"
BRIDGE_LIST="${XPATH_ELEMENTS[i++]}"
STAGING_DIR="${XPATH_ELEMENTS[i++]:-/var/tmp}"
TYPE="${XPATH_ELEMENTS[i++]}"
SRC="${XPATH_ELEMENTS[i++]}"
MD5="${XPATH_ELEMENTS[i++]}"
SHA1="${XPATH_ELEMENTS[i++]}"
DS_ID="${XPATH_ELEMENTS[i++]}"
NO_DECOMPRESS="${XPATH_ELEMENTS[i++]}"
LIMIT_TRANSFER_BW="${XPATH_ELEMENTS[i++]}"
CONVERT="${XPATH_ELEMENTS[i++]:-yes}"
DRIVER="${XPATH_ELEMENTS[i++]}"
IMAGE_TYPE="${XPATH_ELEMENTS[i++]}"



LV_NAME="lv-one-image-${ID}"
VG_NAME="vg-one-${DS_ID}"
DEV="/dev/${VG_NAME}/${LV_NAME}"

# Disable conversion for CD-ROM and 'files' datastores
CONVERT=$(echo "${CONVERT}" | $TR '[:upper:]' '[:lower:]')
if [ "$IMAGE_TYPE" = "1" ] || [ "$TYPE" = "2" ]; then
    CONVERT=no
fi

IMAGE_HASH=`generate_image_hash`
TMP_DST="$STAGING_DIR/$IMAGE_HASH"
DOWNLOADER_ARGS=`set_downloader_args "$MD5" "$SHA1" "$NO_DECOMPRESS" "$LIMIT_TRANSFER_BW" "$SRC" -`
COPY_COMMAND="$UTILS_PATH/downloader.sh $DOWNLOADER_ARGS"

case $SRC in
http://*|https://*)
    log "Downloading $SRC to the image repository"

    DUMP="$COPY_COMMAND"
    ;;

*)
    if [ `check_restricted $SRC` -eq 1 ]; then
        log_error "Not allowed to copy images from $RESTRICTED_DIRS"
        error_message "Not allowed to copy image file $SRC"
        exit -1
    fi

    log "Copying local image $SRC to the image repository"

    DUMP="$COPY_COMMAND"
    ;;
esac

# rbt: BREST-1495
$(exec_and_log "eval $DUMP | $DD of=$TMP_DST bs=64k" \
             "Error dumping $SRC to $DST_HOST:$TMP_DST")

RC=$?

if [ "x$RC" != "x0" ]; then
    FORMAT_SRC=`$QEMU_IMG info $SRC | grep "^file format:" | awk '{print \$3}' || :`
    $($LN -s -f $SRC $TMP_DST >/dev/null 2>&1)
    if [ ! -r $TMP_DST ] || [ "x$FORMAT_SRC" != 'xqcow2' ]; then
        $RM -f $TMP_DST
        exit $RC
    fi
fi

SIZE=`fs_size "${TMP_DST}" "${NO_DECOMPRESS}" "${LIMIT_TRANSFER_BW}"`

if [ -n "$BRIDGE_LIST" ]; then
    DST_HOST=`get_destination_host $ID`

    exec_and_log "$SSH $DST_HOST $SUDO $LVCREATE -L${SIZE}M -n $LV_NAME $VG_NAME -y" "Error create $LV_NAME"

    FORMAT=`$QEMU_IMG info $TMP_DST | grep "^file format:" | awk '{print \$3}' || :`

    if [ "x$CONVERT" = 'xyes' ] && [ "x$FORMAT" != 'xraw' ]; then
        exec_and_log "$QEMU_IMG convert -O raw ${TMP_DST} ${TMP_DST}.raw" "Error create ${TMP_DST}.raw"
        multiline_exec_and_log "set -e -o pipefail; $DD if=${TMP_DST}.raw bs=1M | $SSH $DST_HOST $DD of=${DEV} bs=1M" "Error copy $TMP_DST in ${DEV}"
        $RM -f ${TMP_DST}.raw
    else
        multiline_exec_and_log "set -e -o pipefail; $DD if=${TMP_DST} bs=1M | $SSH $DST_HOST $DD of=${DEV} bs=1M" "Error copy $TMP_DST in ${DEV}"
    fi
    $RM -f $TMP_DST
else
    $SUDO $LVCREATE -L${SIZE}M -n $LV_NAME $VG_NAME -y >/dev/null 2>&1

    FORMAT=`$QEMU_IMG info $TMP_DST | grep "^file format:" | awk '{print \$3}' || :`
    if [ "x$CONVERT" = 'xyes' ] && [ "x$FORMAT" != 'xraw' ]; then
	exec_and_log "$QEMU_IMG convert -O raw ${TMP_DST} $DEV" "Error create ${DEV}"
    else
	exec_and_log "$DD if=${TMP_DST} of=${DEV} bs=64k" "Error create ${DEV}"
    fi
$RM -f $TMP_DST
fi
echo "$DEV raw"
