#!/bin/bash

#rbt:BREST-2025
export_backup(){
# Решает проблему "Не выполняется резервная копия ВМ с диском на Ceph в пуле отличном от one или id отличным от libvirt"
script=`cat << _EOF_
import json
import subprocess

output = subprocess.run('onedatastore list -l ID --no-header --filter TM=ceph', shell=True, stdout=subprocess.PIPE, encoding='utf-8')
pool_and_name = {}

for line in output.stdout.split('\n')[:-1]:
    ds_show = subprocess.run(f'onedatastore show --json {line}', shell=True, stdout=subprocess.PIPE, encoding='utf-8')
    try:
        datastore_template = json.loads(ds_show.stdout)['DATASTORE']['TEMPLATE']
        pool_and_name[datastore_template['POOL_NAME']] = datastore_template['CEPH_USER']
    except KeyError:
        break

for pool, name in pool_and_name.items():
    if "$BackupRealFileName".startswith(f'{pool}/one'):
        subprocess.run(f'rbd export $BackupRealFileName $work_dir/$imageNameInBackup -p {pool} --id {name}', shell=True)
        exit(0)

subprocess.run(f'cp $BackupRealFileName $work_dir/$imageNameInBackup', shell=True)
_EOF_`
echo "$script" | python3 > /dev/null 2>&1
}

# work dir for create backup
tmp_dump_path=/var/tmp/one-dump

POSITIONAL=()
while [[ $# -gt 0 ]]; do
key="$1"
    case $key in
        -d|--datastoreid)
            FILE_DS="$2"
            shift # past argument
            shift # past value
            ;;
        -n|--name)
            NAME_BACKUP="$2"
            shift # past argument
            shift # past value
            ;;
        *)
            VMID=$1
            shift # past argument
        ;;
    esac
done

if [ -z $VMID ]; then
    echo "Not set VMID"
    exit 1
fi

#rbt: BREST-2046
if [ -z "$FILE_DS" ]; then
    FILE_DS=$(/usr/bin/onedatastore list --csv --csv-del "|" | sed '1d' | awk -F"|" '{if($7 == "fil"){want=$1;}}END{print want}')
fi

CHECK_FILE_DS=$(/usr/bin/onedatastore list --csv --csv-del "|"  | sed '1d' | awk -F"|" '{if($1 == '$FILE_DS' && $7 == "fil"){want=$1;}}END{print want}')
if [ "$CHECK_FILE_DS" != "$FILE_DS" ]; then
    echo "Datastore $FILE_DS not FILE type"
    exit 1
fi

function clean {
    rm -rf $work_dir
}

/usr/bin/onevm show $VMID > /dev/null 2>&1
if [ $? -eq "0" ]; then
    VMNamePrefix="$(/usr/bin/onevm show $VMID --name)"
    VMNamePrefix=${VMNamePrefix// /}
    VMDiskIDs=$(/usr/bin/onevm show $VMID --disklist | awk 'NR>1 { print $1; }')

    # timeout checking
    CheckImageTime=10
    BackupLOCK=1

    LCM_STATE=`/usr/bin/onevm show $VMID | grep ^LCM_STATE | cut -d ":" -f 2 | awk '{print $1}'`
    STATE=`/usr/bin/onevm show $VMID | grep ^STATE | cut -d ":" -f 2 | awk '{print $1}'`
    case $STATE  in
        ACTIVE )
            if [[ $LCM_STATE  == RUNNING ]]; then
                BackupLOCK=0
            else
                echo "LCM_STATE $LCM_STATE not for backup"
                exit 1
            fi
            ;;
        SUSPENDED )
            BackupLOCK=0
            ;;
        POWEROFF )
            BackupLOCK=0
            ;;
        * )
            echo "STATE $STATE not for backup"
            exit 1
            ;;
    esac
else
    echo "Error, check VM $VMID is exist"
    exit 1
fi

if [[ $BackupLOCK == 0 ]]; then
    mkdir -p $tmp_dump_path
    work_dir=$tmp_dump_path/${VMID}_$(($(date +%s%N)/1000000))
    mkdir $work_dir
    if [ $? -eq "0" ]; then
        # save template to file
        /usr/bin/onevm show $VMID --export > $work_dir/vm.template
        bootlist=$(/usr/bin/onevm show $VMID --bootlist)
        fullsize_disks=0
        for h in ${VMDiskIDs[@]}; do
            Status=`/usr/bin/onevm show $VMID | sed -n -e '/VM DISKS/,/VIRTUAL MACHINE HISTORY/ p' | grep -i -E 'OS|file|bloc|rbd'| grep -v -i -E 'rbd_c'| awk '{print $1}'| grep ^$h`
            if [[ $Status == $h ]]; then
                #ext=$(/usr/bin/onevm show $VMID --disklist | sed '1d' | awk '{if($1 == '$h'){want=$4;}}END{print want}')
                imageNameInBackup="disk${h}"
                BackupImageName="${imageNameInBackup}_${VMID}_`date +%Y%m%d-%H%M`"
                img_name=$(/usr/bin/onevm show $VMID --disklistcsv | sed '1d' | awk -F "," '{if($1 == '$h'){want=$5;}}END{print want}')
                img_target=$(/usr/bin/onevm show $VMID --disklistcsv | sed '1d' | awk -F "," '{if($1 == '$h'){want=$3;}}END{print want}')
                /usr/bin/oneimage show "${img_name}" --export > $work_dir/$imageNameInBackup.tmpl
                A=$(/usr/bin/oneimage show "${img_name}" --xml)
                TMP=${A#*<PERSISTENT>}
                B=${TMP%</PERSISTENT>*}
                if [ $B == "1" ]; then
                    PERSISTENT="yes"
                else
                    PERSISTENT="no"
                fi
                echo "PERSISTENT=$PERSISTENT" >> $work_dir/$imageNameInBackup.tmpl
                echo $img_target > $work_dir/$imageNameInBackup.target
                if [ $? -eq "0" ]; then
                    /usr/bin/onevm disk-saveas $VMID $h $BackupImageName > /dev/null 2>&1
                    if [ $? -eq "0" ]; then
                        # wait saving...
                        until [[ $(/usr/bin/oneimage show $BackupImageName | grep STATE | awk '{ print $3 }') == "rdy" ]]; do
                            sleep $CheckImageTime
                        done
                        BackupRealFileName=`/usr/bin/oneimage show $BackupImageName | grep SOURCE | awk '{ print $3 }'`
                        # brest-lvm - tm/cpds creates LV in image datastore and deactivate it
                        # before using it here - activate it
                        ONEVM_XML=$(/usr/bin/onevm show $VMID -x)
                        tm_mad=$(/usr/bin/xmlstarlet sel -t -v '/VM/TEMPLATE/TM_MAD_SYSTEM' <<< "$ONEVM_XML")
                        if [ $tm_mad == "brest_lvm" ]; then
                            sudo /usr/sbin/lvchange -ay $BackupRealFileName
                        fi
                        #rbt:BREST-2025
                        export_backup
                        if [ $? -eq "0" ]; then
                            /usr/bin/oneimage delete $BackupImageName
                            f_size=$(stat -c%s "$work_dir/$imageNameInBackup")
                            fullsize_disks=$(($fullsize_disks + $f_size))
                        else
                            /usr/bin/oneimage delete $BackupImageName > /dev/null 2>&1
                            clean
                            echo "Error copy $BackupImageName"
                            exit 1
                        fi
                    else
                        clean
                        echo "Error create $BackupImageName"
                        exit 1
                    fi
                else
                    clean
                    echo "Error get image $img_name template"
                    exit 1
                fi
            fi
            Status_cdrom=`/usr/bin/onevm show $VMID | sed -n -e '/VM DISKS/,/VM NICS/ p' | grep -i -E 'cdrom' | awk '{print $1}'| grep ^$h`
            # if cdrom, delete his from boot
            if [[ $Status_cdrom == $h ]]; then
                cdNameInBackup="disk${h}"
                bootlist=$(echo "${bootlist}" | sed "s/$cdNameInBackup//")
                bootlist=$(echo "${bootlist}" | sed "s/,,/,/")
                first_l=${bootlist:0:1}
                if [[ "$first_l" == "," ]]; then
                        bootlist=${bootlist#?}
                fi

                last_l=${bootlist: -1}
                if [[ "$last_l" == "," ]]; then
                        bootlist=${bootlist%?}
                fi
            fi
        done
        echo "${bootlist}" > $work_dir/boot
        cd $work_dir
        backup_arch=${VMNamePrefix}_`date +%Y%m%d-%H%M`
        tar -czf $backup_arch.tar.gz *
        cd $tmp_dump_path

        #rbt: BREST-2160
        BACKUP_NAME_IN_DS=$(oneimage list --list name --no-header | grep "^${NAME_BACKUP}$")

        if [[ -z "$NAME_BACKUP" || -n "$BACKUP_NAME_IN_DS" ]]; then
            NAME_BACKUP=$backup_arch
            NAME_BACKUP="$VMID-$NAME_BACKUP" # to avoid name collision
        fi
        fsize=$(stat -c%s "$work_dir/$backup_arch.tar.gz")
        fsize_mb=$(( $fsize/1024/1024 ))
        # --size $fsize_mb
        back_id=$(/usr/bin/oneimage create --path $work_dir/$backup_arch.tar.gz -d $FILE_DS --disk_type FILE --name "${NAME_BACKUP}" --type BACKUP --onevmid $VMID | awk '{print $2}')
        if [ $? -eq "0" ]; then
            # wait saving...
            until [[ $(/usr/bin/oneimage show "${NAME_BACKUP}" | grep STATE | awk '{ print $3 }') == "rdy" ]]; do
                sleep $CheckImageTime
            done
            cd $work_dir
            echo "BACKUP_FULLSIZE=$fullsize_disks" > ./fullsize.tmpl
            /usr/bin/oneimage update $back_id -a ./fullsize.tmpl
            rm ./fullsize.tmpl
            cd $tmp_dump_path
        else
            clean
            echo "Error upload backup to OpenNebula"
            exit 1
        fi
    else
        clean
        echo "Error create $work_dir"
        exit 1
    fi
fi
clean
