#!/usr/bin/env bash

############################################################
# Name:        unzipCBB
# Description: 解压欧方包到升级目录
#
############################################################
# 非单点执行的升级，需在此处定义解压路径
[ -z "${UNZIPPATH}" ] && export UNZIPPATH=/opt/oss/NCEEngr/O2_path

# 企业定制了sudobin目录为/opt/sudobin，升级/回滚时，需要识别sudobin的路径
custom_sudobin_file=/opt/oss/manager/bin/engr_profile.sh
[ -f "${custom_sudobin_file}" ] && . "${custom_sudobin_file}"
# 如果脚本加载成功，SUPER_ROOT变量即为企业的sudobin路径
if [ -z "${SUPER_ROOT}" ];then
    sudobin=/usr/local/uniepsudobin/
else
    sudobin="${SUPER_ROOT}"
fi

unzip_os_mediation()
{
    CBBPakg="$(ls ${current_dir}/sudoconfig_*.tar.gz)"
    if [ ! -f "${CBBPakg}" ]; then
        echo "[$(date)] \"${CBBPakg}\" package is not exist." >> ${log} >&2
        exit 1
    fi

    CBBPath="${UNZIPPATH}/sudoconfig"
    [ -d "${CBBPath}" ] && rm -rf "${CBBPath}"
    mkdir -p "${CBBPath}"
    if [ $? -ne 0 ];then
        echo "[$(date)] mkdir \"${CBBPath}\" is failed." >> ${log} >&2
        exit 1
    fi
    echo "[$(date)] mkdir \"${CBBPath}\" is finished." >> ${log}

    tar xvfz "${CBBPakg}" -C "${CBBPath}" --no-same-owner >/dev/null 2>&1
    if [ $? -ne 0 ];then
        echo "[$(date)] unzip \"${CBBPakg}\" to \"${CBBPath}\" is failed." >> ${log} >&2
        exit 1
    fi
    local OSConfigPkg=
    if [ "${OS_TYPE}" = "suse" ]; then
        echo "[$(date)] current os type is SuSE"
        OSConfigPkg=$(ls ${current_dir}/osconfig-*.zip | grep -vi euler)
    elif [ "${OS_TYPE}" = "euler" ] || [ "${OS_TYPE}" = "kylin" ] || [ "${OS_TYPE}" = "centos" ]; then
        echo "[$(date)] current os type is ${OS_TYPE}."
        OSConfigPkg=$(ls ${current_dir}/osconfig-*.zip | grep -i euler)
    else
        echo "[$(date)] can not support OS type, only support euler, suse or kylin." >&2
        exit 1
    fi

    if [ ! -f "${OSConfigPkg}" ];then
        echo "[$(date)] \"${OSConfigPkg}\" package is not exist." >> ${log} >&2
        exit 1
    fi

    OSConfigPath="${UNZIPPATH}/osconfig"
    [ -d "${OSConfigPath}" ] && rm -rf ${OSConfigPath}
    mkdir -p "${OSConfigPath}"
    if [ $? -ne 0 ];then
        echo "[$(date)] mkdir \"${OSConfigPath}\" is failed." >> ${log} >&2
        exit 1
    fi
    echo "[$(date)] mkdir \"${OSConfigPath}\" is finished." >> ${log}

    unzip -d ${OSConfigPath} -o ${OSConfigPkg} >/dev/null 2>&1
    if [ $? -ne 0 ];then
        echo "[$(date)] unzip \"${OSConfigPkg}\" to \"${OSConfigPath}\" is failed." >> ${log} >&2
        exit 1
    fi
    # 复制扩展包
    cp ${current_dir}/custom-* ${OSConfigPath}/ >/dev/null 2>&1
    cp ${current_dir}/framework-* ${OSConfigPath}/ >/dev/null 2>&1
    cp ${current_dir}/default-* ${OSConfigPath}/ >/dev/null 2>&1
    chown -R ossadm:ossgroup "${CBBPath}"
    chown -R ossadm:ossgroup "${OSConfigPath}"
}

############################################################
# Name:        print_log
# Description: 打印日志
#
############################################################
function print_log() {
    local log_level=$1
    local log_info=$2

    echo "[$(date)] [${log_level}]: [${FUNCNAME[1]}] ${log_info}"
}


############################################################
# Name:        check_flag
# Description: 检查结果，执行升级或者回滚后，10分钟内持续检查标志文件
#
############################################################
function check_flag() {
    local ip=$1
    local path=$2
    local type=$3
    for try_count in $(seq 20);do
        res_ok=$(run_ssh_cmd "${ip}" "[ -f ${path}/${type}_succeed_flag ] && echo exec_ok")
        # 排除掉run_ssh_cmd自身打印出来的日志信息，只取ssh远程执行命令结果
        res_ok=$(echo "${res_ok}" | grep -v "run_ssh_cmd" 2>/dev/null)
        if [ "${res_ok}" = "exec_ok" ];then
            return 0
        fi
        res_nok=$(run_ssh_cmd "${ip}" "[ -f ${path}/${type}_fail_flag ] && echo exec_nok")
        # 排除掉run_ssh_cmd自身打印出来的日志信息，只取ssh远程执行命令结果
        res_nok=$(echo "${res_nok}" | grep -v "run_ssh_cmd" 2>/dev/null)
        if [ "${res_nok}" = "exec_nok" ];then
            return 1
        fi
        print_log "INFO" "check result of ${type} in ${ip} for ${try_count} times"
        sleep 30
    done
    print_log "ERROR" "${type} timeout, please check the process."
    return 1
}

############################################################
# Name:        run_ssh_cmd
# Description: 执行ssh连接，执行命令
#
############################################################
function run_ssh_cmd() {
    local node_ip="${1}"
    local cmd="${2}"
    local ssh_para="-o ConnectTimeout=30 -o stricthostkeychecking=no -o ConnectionAttempts=5 -o ServerAliveInterval=3 -o ServerAliveCountMax=20"
    local ssh_cmd="ssh ${ssh_para} ${node_ip} ${cmd} 2>>/dev/null"
    ssh ${ssh_para} "${node_ip}" "${cmd}" 2>>/dev/null
    if [ $? -ne 0 ];then
        print_log "ERROR" "failed to execute: ${ssh_cmd}, please check."
        return 1
    else
        print_log "INFO" "succeed to execute: ${ssh_cmd}."
        return 0
    fi
}


############################################################
#
# Description: 获取内部通信ip
#
############################################################
function get_node_list() {
    local all_node=$(
. ${custom_sudobin_file}
python <<PEOF
import json
import sys
node_file = r'/opt/oss/manager/etc/sysconf/nodelists.json'
manager_ips = []
try:
    with open(node_file, mode="r") as f:
        node_info = json.load(f)
    for node_id, one_node in node_info.get("nodeList", {}).items():
        manager_ips.extend([one_ip.get("IP") for one_ip in one_node.get("IPAddresses",{}) if "maintenance" in one_ip.get("usage")])
    print(" ".join(manager_ips))
    sys.exit(0)
except Exception as _:
    print("exception occur when read {}".format(node_file))
    sys.exit(1)
PEOF
)
    if [[ "${all_node}" =~ "exception" ]];then
        print_log "WARN" "query node info failed:${all_node}."
        return 1
    fi

    node_list=$(echo "${all_node}" | xargs -n1 | sort -u)
    print_log "INFO" "print node list:"
    for node in ${node_list[@]};do
        echo ${node}
    done
    return 0
}

############################################################
# Name:        clean_after_rollback
# Description: 删除平台osconfig的备份目录，避免同版本换包反复升级回滚，无法持续备份
############################################################
function clean_after_rollback() {
    print_log "INFO" "start to clean directory after rollback."
    local osconfig_bak_path="${current_dir}/../bak_${version}"
    [ -d "${osconfig_bak_path}" ] && rm -rf "${osconfig_bak_path}"
    print_log "INFO" "finish to clean directory:bak_${version} after rollback."
}
