#!/usr/bin/env bash

current_dir=$(dirname $0)
log=${current_dir}/execute_upgrade.log
type=$1
version=$2
package=$3
package_name=$(echo "${package}" | awk -F"/" '{print $NF}')
package_path=/opt/oss/NCEEngr/tmp
if [[ "${type}" =~ "single" ]];then
    upgrade_path="${4}/NCEEngr/O2_path/upgrade_config_${version}"
    # 定义解压osconfig和sudoconfig的路径
    export UNZIPPATH="${4}/NCEEngr/O2_path"
else
    upgrade_path=/opt/oss/NCEEngr/O2_path/upgrade_config_${version}
fi
flag_path=${upgrade_path}/upgrade_rollback_flag

. "${current_dir}/upgrade_rollback_func.sh"
node_list=""

function scp_package() {
    local file="$1"
    local ip="$2"
    for try_count in $(seq 3);do
        scp -o StrictHostKeyChecking=no "${file}" [${ip}]:"${package_path}" &>> /dev/null
        local res=$?
        if [ ${res} -ne 0 ];then
            sleep 5
            continue
        fi
        break
    done
    [ "${res}" -ne 0 ] && print_log "ERROR" "scp ${file} to ${ip} failed" && return 1
    print_log "INFO" "success to scp ${file} to ${ip}" && return 0
}


function upgrade() {
    local file="$1"
    local ip="$2"
    # 创建升级目录
    run_ssh_cmd "${ip}" "mkdir -p ${upgrade_path} ${package_path};rm -rf ${upgrade_path}/*;chown -R ossadm:ossgroup ${upgrade_path}" || return 1
    # 传包
    scp_package "${file}" "${ip}" || return 1
    # 节点解包
    run_ssh_cmd "${ip}" "unzip -o ${package_path}/${package_name} -d ${upgrade_path} >/dev/null 2>&1;rm -f ${package_path}/${package_name}" || return 1
    # 修改属组
    run_ssh_cmd "${ip}" "chown -R ossadm:ossgroup ${upgrade_path}" || return 1
    # 节点升级
    run_ssh_cmd "${ip}" "bash ${upgrade_path}/upgrade.sh ${version} ${upgrade_path}"
    if [ $? -eq 0 ];then
        return 0
    else
        check_flag "${ip}" "${upgrade_path}" "upgrade"
        if [ $? -eq 0 ];then
            return 0
        else
            print_log "ERROR" "upgrade fail in ${ip}, please read log in: ${upgrade_path}" && return 1
        fi
    fi
}

function rollback() {
    local file="$1"
    local ip="$2"

    # 节点回滚
    local judge_res=$(run_ssh_cmd "${ip}" "[ -d ${upgrade_path} ] && [ -f ${upgrade_path}/rollback.sh ] && echo enable" 2>/dev/null)
    if [[ "${judge_res}" =~ "enable" ]];then
        # 传包
        scp_package "${file}" "${ip}"
        [ $? -ne 0 ] && return 1
        # 节点解包
        run_ssh_cmd "${ip}" "unzip -o ${package_path}/${package_name} -d ${upgrade_path} >/dev/null 2>&1;rm -f ${package_path}/${package_name}" || return 1
        # 修改属组
        run_ssh_cmd "${ip}" "chown -R ossadm:ossgroup ${upgrade_path}" || return 1
        # 节点回滚执行
        run_ssh_cmd "${ip}" "bash ${upgrade_path}/rollback.sh ${version} ${upgrade_path}"
        if [ $? -eq 0 ];then
            return 0
        else
            check_flag "${ip}" "${upgrade_path}" "rollback"
            if [ $? -eq 0 ];then
                return 0
            else
                print_log "ERROR" "rollback fail in ${ip}, please read log in: ${upgrade_path}" && return 1
            fi
        fi
    else
        print_log "INFO" "${ip} skip"
        return 0
    fi
    return 0
}

function excute_rollback() {
    # 判断omp节点是否存储好OSMediation包，没有则直接返回
    if [ ! -f "${upgrade_path}/../package/${package_name}" ];then
        print_log "WARN" "upgrade may not start, no need to rollback."
        return 0
    fi

    local package_file
    # 优先使用保存在omp节点的包，如果没有，使用原升级路径的包，
    if [ -f "${upgrade_path}/../package/${package_name}" ];then
        package_file="${upgrade_path}/../package/${package_name}"
    elif [ -f "${package}" ];then
        package_file="${package}"
    fi
    for node in ${node_list};do
        { rollback "${package_file}" "${node}"
        if [ $? -eq 0 ];then
            echo "rollback ${node}:success" >> ${flag_path}
        else
            echo "rollback ${node}:fail" >> ${flag_path}
        fi
         } &
    done

    # 等待子线程结束
    wait
    return 0
}


function excute_upgrade() {
    for node in ${node_list};do
        { upgrade "${package}" "${node}"
        if [ $? -eq 0 ];then
            echo "upgrade ${node}:success" >> ${flag_path}
        else
            echo "upgrade ${node}:fail" >> ${flag_path}
        fi
        } &
    done

    # 等待子线程结束
    wait
    return 0
}


function single_upgrade() {
    echo "start to upgrade config in single node."
    mkdir -p "${upgrade_path}"
    rm -rf "${upgrade_path}"/*
    chown -R ossadm:ossgroup "${upgrade_path}"
    if [ $? -ne 0 ];then
        print_log "ERROR" "failed to chown ${upgrade_path}"
        echo "fail to upgrade" > "${flag_path}"
        return 1
    fi
    unzip -o "${package}" -d "${upgrade_path}"
    chown -R ossadm:ossgroup ${upgrade_path}
    timeout 900 bash "${upgrade_path}"/upgrade.sh "${version}" "${upgrade_path}"
    local res=$?
    if [ "${res}" -ne 0 ];then
        print_log "ERROR" "failed to upgrade, return code: ${res}"
        echo "fail to upgrade" > "${flag_path}"
        return 1
    fi
    echo "sucess to upgrade" > "${flag_path}"
}


function single_rollback() {
    echo "start to rollback config in single node."
    [ ! -f ${upgrade_path}/rollback.sh ] && print_log "INFO" "skip to rollback" && return
    timeout 900 bash "${upgrade_path}"/rollback.sh "${version}" "${upgrade_path}"
    local res=$?
    if [ "${res}" -ne 0 ];then
        print_log "ERROR" "failed to rollback, return code: ${res}"
        echo "fail to rollback" > "${flag_path}"
        return 1
    fi
    echo "sucess to rollback" > "${flag_path}"
}


function deploy_omp() {
    print_log "INFO" "start to prepare in omp node"
    # 保存OSMediation包，用于回滚；因为升级完成后，升级包会被升级任务删除
    mkdir -p "${upgrade_path}/../package"
    cp -f "${package}" "${upgrade_path}/../package"
    chmod 640 "${upgrade_path}"/../package/*
    [ $? -ne 0 ] && print_log "ERROR" "failed to store package, please check." && exit 1
    print_log "INFO" "success to prepare in omp node"
}


############################################################
# Name:        main
# Description: 主函数，入口
#
############################################################
function main() {
    # 检测包是否存在
    if [[ "${type}" =~ "upgrade" ]];then
        [ ! -f "${package}" ] && print_log "ERROR" "can not find ${package}, please check." && return 1
    fi
    # 升级包部署到omp01节点
    if [[ "${type}" = "upgrade" ]];then
        deploy_omp
    fi

    # 删除标志文件
    [ -f "${flag_path}" ] && rm -f "${flag_path}"

    if [[ "${type}" =~ "single" ]];then
        # 单点升级
        [[ "${type}" =~ "upgrade" ]] && single_upgrade "${version}"
        [[ "${type}" =~ "rollback" ]] && single_rollback "${version}"
    else
        # NCE多点升级，获取节点列表
        for i in $(seq 3);do
            get_node_list
            if [ -z "${node_list}" ]; then
                print_log "WARN" "can not get node list, retry."
                sleep 20
                continue
            else
                break
            fi
        done
        [ -z "${node_list}" ] && print_log "ERROR" "can not get node list, please check." && return 1
        # 执行升级或者回滚
        [ "${type}" = "upgrade" ] && excute_upgrade "${version}"
        [ "${type}" = "rollback" ] && excute_rollback "${version}"
    fi

    grep "fail" "${flag_path}" >/dev/null
    if [ $? -eq 0 ];then
        return 1
    else
        return 0
    fi
}
print_log "INFO" "start to execute"

main
res=$?
if [ "${res}" -eq 0 ];then
    echo "success to ${type}."
    exit 0
else
    echo "failed to ${type}."
    exit 1
fi