#!/bin/bash

week=$(date +%U)
snapshot_name=$(date +%Y%m%d)
backup_record_file="/tmp/backup_record.log"
retry_times=5
backup_location_prefix="/data/esbackup"
#backup_location_prefix="/esdata"
#backup_location_prefix="/esbackup"
esurl="http://192.168.251.252:39205"
indices="_all"

function unit_convert() {
    typeset -l size
    size=$1
    to_gb=$(echo $size | awk '{
            if ($1 ~ /pb$/ || $1 ~ /p$/){
                print $1 * 1024 * 1024
            } else if ($1 ~ /tb$/ || $1 ~ /t$/){
                print $1 * 1024
            } else if ($1 ~ /gb$/ || $1 ~ /g$/){
                print $1
            } else if ($1 ~ /mb$/ || $1 ~ /m$/){
                print $1/1024
            } else if ($1 ~ /kb$/ || $1 ~ /k$/){
                print $1/1024/1024
            } else if ($1 ~ /b$/){
                print $1/1024/1024/1024
            }
        }')
    echo $to_gb
}

function es_total_storage_used(){
    size=$(curl -s ${esurl}/_stats/store?pretty | awk -F "[:| ]" '
        {
            if($0 ~ /_all/){
                all_k=1;
                next;
            }
            if ( all_k==1 && $0 ~ /total/){
                total_k=1;
                next;
            }
            if ( all_k == 1 && total_k==1 && $0 ~ /store/){
                store_k=1;
                next;
            }
            if ( all_k == 1 && total_k==1 && store_k==1){
                gsub(" ","");
                print $2/2*1.1;
                exit;
            }
        }
    ')
    echo $(unit_convert "$size"b)
}

function disk_partation_size_check() {
    local check_partation=$1
    local req_size=$2
    local mounted=
    local mounted_avail=
    typeset -l mounted_avail

    mounted=$(df -h $1 | awk 'NR!=1{print $NF}')
    echo -e "$(date +%FT%T) 检测到目录 $1, 使用的挂载分区为: $mounted" >> $backup_record_file

    mounted_avail=$(df -h $1 | awk 'NR!=1{print $4}')
    mounted_avail=$(unit_convert $mounted_avail)
    req_size=${req_size:0:-1}
    mounted_avail=${mounted_avail:0:-1}
    if [[ -n ${req_size} && -n ${mounted_avail} ]]; then
        if [[ $(awk 'BEGIN{print('"$mounted_avail"'<'"$req_size"')?0:1}') -eq 0 ]]; then
            echo -e "$(date +%FT%T) 备份目录：$check_partation, 磁盘空间要求：${req_size}g, 实际可用空间：${mounted_avail}g, 不能进行备份" >> $backup_record_file
            exit 13
        else
            echo -e "$(date +%FT%T) 备份目录：$check_partation, 磁盘空间要求：${req_size}g, 实际可用空间：${mounted_avail}g" >> $backup_record_file
            return 12
        fi
    else
        echo -e "$(date +%FT%T) 获取磁盘空间失败" >> $backup_record_file
        exit 14
    fi
}

function create_snapshot_warehouse() {
    if [ $(curl -sL -w "%{http_code}\n" -o /dev/null --location --request GET "${esurl}/_snapshot/macrowing-$week") != 200 ]; then
        local status=$(curl -sL -w "%{http_code}\n" -o /dev/null -XPOST "${esurl}/_snapshot/macrowing-$week" -H 'Content-Type: application/json' -d '
            {
                "type": "fs",
                "settings": {
                    "location": "'/esbackup/macrowing-$week'",
                    "compress": true
                }
            }
        ')
        if [ "$status"x != "200"x ];then
            echo -e "$(date +%FT%T) snapshot warehose create http_response_code is ${status}, sleep 3s, retry..." >> $backup_record_file
            sleep 3
            retry_times=$(($retry_times-1))
            if [ $retry_times -ge 0 ];then
                create_snapshot_warehouse
            fi
            retry_times=5
            return 10
        fi
    fi
}

function remove_old_backup() {
    last_week=$(date -d '-1 day' "+%U")
    if [ "$week" -ne "$last_week" ];then
        last_week_warehouse=macrowing-$last_week
        
        snapshot_by_warehouse=$(curl -s "${esurl}/_snapshot/${last_week_warehouse}/_all?pretty" | awk 'BEGIN{FS=":"} $0 ~ /"snapshot"/{gsub("\"|,| ",""); print $2}' | xargs)
        if [ ! -z "${snapshot_by_warehouse}" ];then
            for _snapshot in ${snapshot_by_warehouse[@]}; do 
                curl -s -XDELETE "${esurl}/_snapshot/${last_week_warehouse}/${_snapshot}" &> /dev/null
            done
        fi

        # remove old warehouse directory
        _old_warehouse_location=$(curl -s "${esurl}/_snapshot/${last_week_warehouse}?pretty" | awk -F ":" '/"location"/{gsub("\"","");print $2}' |xargs)
        if [ -d "${backup_location_prefix}/${_old_warehouse_location}" -a ! -z "${_old_warehouse_location}" ]; then
            echo -e "$(date +%FT%T) remove history warehouse directory: ${backup_location_prefix}/${_old_warehouse_location}" >> $backup_record_file
            rm -fr ${backup_location_prefix}/${_old_warehouse_location}
        fi
        # delete warehouse
        curl -s -XDELETE "${esurl}/_snapshot/${last_week_warehouse}" &> /dev/null
        echo -e "$(date +%FT%T) call es restful DELETE warehouse ${_old_warehouse_location}" >> $backup_record_file
    fi
}

function create_snapshot() {
    echo ${indices}"============================"
    local status=$(curl -sL -w "%{http_code}\n" -o /dev/null -XPOST "${esurl}/_snapshot/macrowing-$week/$snapshot_name" -H 'Content-Type: application/json' -d '
        {
            "indices": "'${indices}'",
            "ignore_unavailable": true
        }
    ')

    if [ "$status"x != "200"x ];then
        echo -e "$(date +%FT%T) snapshot create http_response_code is ${status}, sleep 3s, retry..." >> $backup_record_file
        sleep 3
        retry_times=$(($retry_times-1))
        if [ $retry_times -ge 0 ];then
            create_snapshot
        fi
        retry_times=5
        return 11
    fi
}

function main() {
    disk_partation_size_check "$backup_location_prefix" $(es_total_storage_used)
    if [  $? -eq 12 ];then
        create_snapshot_warehouse
        if [  $? -eq 10 ];then
            echo -e "$(date +%FT%T) elasticsearch create warehouse fail: macrowing-$week " >> $backup_record_file
            remove_old_backup 
            exit 10
        fi
        create_snapshot
        if [  $? -eq 11 ];then
            echo -e "$(date +%FT%T) elasticsearch create snapshot fail: macrowing-$week/${snapshot_name} " >> $backup_record_file
            remove_old_backup 
            exit 11
        fi
        while true ;do 
            if [ "$(curl -s "${esurl}/_snapshot/macrowing-$week/${snapshot_name}?pretty" | awk -F ":" '$0 ~ /"state"/ {gsub("\"|,| ","");print $2}')"x == "SUCCESS"x ]; then
                echo -e "$(date +%FT%T) elasticsearch index backup success: macrowing-$week/${snapshot_name} " >> $backup_record_file
                break
            fi 
            sleep 10
        done
        remove_old_backup 
    else
        echo -e "$(date +%FT%T) disk_partation_size_check error " >> $backup_record_file
        exit 15
    fi
}

main
