#!/usr/bin/env bash

# 单独运行本脚本需要的外部变量
if [[ ! $SOURCE_LIB_CHECK ]] ;then
    INIT_TMP_DIR="/tmp/os_init"
    . $INIT_TMP_DIR/ucloud-basic-init/lib.sh
    BASEDIR="$INIT_TMP_DIR/ucloud-basic-init"
    ManufactureType=$(cat $INIT_TMP_DIR/cmdb.info|grep -E ^ManufactureType|awk -F ":" '{print $2}')
    Manufacture=$(cat $INIT_TMP_DIR/cmdb.info|grep -E ^Manufacture:|awk -F ":" '{print $2}')
fi

### Get Product Info with underline
Product=$(echo $ManufactureType|sed "s/^${Manufacture} //g")

check_disk_fw () {
    local action=$1
    local unknown raid_type temp_disk_info
    temp_disk_info=$(mktemp -p $BASEDIR -t disk_subete.XXXXXX.info)
    if ! /usr/bin/python $BASEDIR/utils/disk_subete.py -i > "$temp_disk_info" ;then
        PRINT_ERR "[ERROR] disk_subete.py 运行失败"
    fi

    unknown=$(jq -r '.[]|.pd|.[]|.info|select(.series=="unknown"  and .series!=null)|.manufacture +","+ .model' $temp_disk_info | uniq)
    if [[ -n $unknown ]];then
        PRINT_INFO "[INFO] Unknown HARDDISK $unknown Not Support"
    fi

    raid_type=$(jq -r '.[]|.type' $temp_disk_info)
    # HP_RAID Not Support AutoUpdate
    if [[ $action == update && $raid_type =~ 'hp' ]];then
        PRINT_INFO "[INFO] $raid_type Not Support AutoUpdate"
        return 0
    fi

    # 硬盘固件
    readarray -t series_fw <<< "$(jq -r '.[]|.pd|.[]|.info|select(.series!="unknown" and .series!=null)|.series+","+.firmware' $temp_disk_info | sort | uniq)"
    for line in "${series_fw[@]}"
    do
        [[ -z $line ]] && continue
        local series=${line%,*}
        local series_type=${series%.*}
        local series_str=${series#*.}
        local fw=${line#*,}
        local uconf_fw
        uconf_fw=`/usr/bin/python $BASEDIR/utils/GetApolloConf.py "HARDDISK" "HARDDISK/$series_type/$series_str" fw`
        if [[ -z $uconf_fw ]];then
            _check="FAIL"
            PRINT_ERR "[ERROR] HARDDISK $series FW Not Exist In UCONF, Please Check UCONF --> HARDDISK/$series_type/$series_str"
            continue
        fi
        if [[ ! "$uconf_fw" =~ "$fw" ]];then
            PRINT_INFO "[INFO] Disk $series Firmware Version: $fw Wait Update..."
            if [[ $action = 'update' ]];then
                local series_type=${series%.*}
                local series_str=${series#*.}
                # SSD ALL-IN-ONE, AIO = ALL-IN-ONE
                [[ $series_type == "SSD" ]] && local series_str="AIO"
                if run_fw_update "HARDDISK/${series_type}/${series_str}";then
                    PRINT_INFO "[INFO] Disk $series Firmware Version: $fw Updata Success."
                else
                    PRINT_ERR "[ERROR] Disk $series Firmware Version: $fw Update Fail."
                fi
            else
                _check="FAIL"
                PRINT_ERR "[ERROR] Disk $series Firmware Version: $fw Not Match Standard: $uconf_fw ;请尝试重新初始化，并通知硬件同学关注升级结果"
            fi
        else
            PRINT_INFO "[INFO] Disk $series Firmware Version: $fw check PASS"
        fi
        # NVME.Memblaze_D920 NVME.Memblaze_D926 升级OOB，屏蔽 Temperature Sensor 4:               159 Celsius
        if [[ $series =~ "NVME.Memblaze_D92" ]] ;then
            if [[ $action == 'update' ]];then
                which nvme &>/dev/null
                if [ $? -ne 0 ];then
                    yum install nvme-cli -y
                fi
                for DEV in `nvme list |egrep "\bP5920|\bP5926" |awk '{print $1}' |awk -F"/" '{print $3}' |sed 's/n1$//g'`;
                do
                    if_Memblaze_D92x_update=`smartctl -a /dev/$DEV | grep -w 'Temperature Sensor 4' | grep -c 159`
                    if [[ $? -ne 0 ]] ;then
                        run_fw_update "HARDDISK/${series/./\/}"
                        PRINT_INFO "[INFO] Disk $series Firmware Version: $fw update PASS"
                        break
                    fi
                done
            fi
        fi
    done

    # raid,HBA卡固件
    local ret=0
    readarray -t raid_fw <<< "$(jq -r '.[]|select(.type!="nvme")|select(.type!="shannon")|.type+","+.info.model+","+.info.firmware' $temp_disk_info | uniq)"
    for line in "${raid_fw[@]}";
    do
        [[ -z $line ]] && continue
        local raid_type model fw uconf_fw
        raid_type=$(echo $line|awk -F',' '{print $1}')
        model=$(echo $line|awk -F',' '{print $2}')
        fw=$(echo $line|awk -F',' '{print $3}')
        # LSI model名称不规律,但都包含连续4位数字 和两位数字两位字母xx 如 38xx :-)
        if [[ $raid_type =~ 'lsi' ]];then
            model=$(echo $model |sed -n -r 's/.*([0-9]{4}|[0-9]{2}xx).*/\1/p')
        fi

        uconf_fw=`/usr/bin/python $BASEDIR/utils/GetApolloConf.py "RAID" "${Manufacture}.${model}" fw`
        if [[ -z $uconf_fw ]];then
            _check="FAIL"
            PRINT_ERR "[ERROR] RAID FW --> RAID ${Manufacture}.${model} <-- Not Exist In UCONF, Please Check UCONF"
            continue
        fi
        if [[ ! "$uconf_fw" =~ "$fw" ]];then
            if [[ $action = 'update' ]];then
                # LSI 固件包区分型号
                if [[ $raid_type =~ 'lsi' ]];then
                    run_fw_update "RAID/LSI/SAS${model}"
                    ret=$((ret+$?))
                # 增加PMC的选项
                elif [[ $raid_type =~ 'pmc' ]] ;then
                    run_fw_update "RAID/PMC/${model}"
                    ret=$((ret+$?))
                else
                    run_fw_update "RAID/HP/${model}"
                    ret=$((ret+$?))
                fi
            else
                _check="FAIL"
                PRINT_ERR "[ERROR] Card ${Manufacture}.${model} Firmware Version: $fw Not Match Standard: $uconf_fw"
            fi
        else
            PRINT_INFO "[INFO] Card ${Manufacture}.${model} Firmware Version: $fw check PASS"
        fi
    done
    return $ret
}

run_fw_update () {
    # 固件目录名称和文件名称不带空格，替换成下划线
    local path
    path=$(echo "$1"|tr ' ' '_')
    local arg=$2 # only for Mellanox
    # BIOS/BMC 升级脚本统一提供密码
    if [[ $path =~ .*BMC || $path =~ .*BIOS ]] ;then
        json1=$(curl -s -H "Content-Type:application/json" -X POST --data  '{"data":  ["'"$IPMI"'"],"type": "IPMI"}' http://udcm.ucloudadmin.com/api/ipmi/v1/getpwd/)
        arg=$(jq -r .[].IPMIPassword <<< "$json1")
        if [[ -z "$arg" ]];then
            arg="ucloud.cn"
        fi
    fi
    mkdir -p /tmp/fw_update/$path
    if ! wget -q http://softlib.service.ucloud.cn/usa/firmware/$path/fw_update.tgz -O /tmp/fw_update/$path/fw_update.tgz ;then
        PRINT_ERR "[ERROR] $1 Wget --> usa/firmware/$path/fw_update.tgz <-- failed 下载升级固件出错, Not Support AutoUpdate"
        return 1
    fi
    # [[ -s /tmp/fw_update/$path/fw_update.tgz ]] || { PRINT_ERR "[INFO] WGET download $path failed, 下载升级固件出错 请检查路径是否正确 /tmp/fw_update/$path/fw_update.tgz"; return 2 ; }
    (
    set -e
    tar xf /tmp/fw_update/$path/fw_update.tgz -C /tmp/fw_update/$path
    cd /tmp/fw_update/$path
    if bash -x update.sh $arg &> /tmp/fw_update/$path/update-"$(date +%Y%m%d_%H%M%S_%Z)".log ;then
        [[ $path =~ .*BMC ||  $path =~ .*BIOS ]] && arg=''
        PRINT_INFO "[INFO] Update $path $arg Success"
        return 0
    else
        [[ $path =~ .*BMC ||  $path =~ .*BIOS ]] && arg=''
        PRINT_ERR "[ERROR] Update /tmp/fw_update/$path/fw_update.tgz $arg Failed; Please Check /tmp/fw_update/$path/update-$(date +%Y%m%d_%H%M%S_%Z).log"
        return 3
    fi
    )
}

check_bios () {
    if [[ "$Manufacture" == "HP" ]];then
        local BIOS_VERSION BIOS_RELEASE_DATE
        BIOS_VERSION=`dmidecode -t 0 |grep "Version"|awk -F ": " '{print $2}'`
        BIOS_RELEASE_DATE=`dmidecode -t0|grep "Release Date"|awk -F ": " '{print $2}'`
        L_BIOS_VER="$BIOS_VERSION $BIOS_RELEASE_DATE"
    else
        L_BIOS_VER=`dmidecode -s bios-version|sed '/^#/d'`
    fi

    R_BIOS_VER=`/usr/bin/python $BASEDIR/utils/GetApolloConf.py "BIOS" "${Manufacture}.${Product}.BIOS" fw`
    [[ -z $R_BIOS_VER ]] && PRINT_ERR "[ERROR] BIOS FW --> BIOS ${Manufacture}.${Product}.BIOS <-- Not Exist In UCONF, Please Check UCONF"
    if [[ "$R_BIOS_VER" =~ "$L_BIOS_VER" ]];then
        PRINT_INFO "[INFO] BIOS Version: $L_BIOS_VER Match Standard: $R_BIOS_VER"
        return 0
    else
        _check="FAIL"
        PRINT_ERR "[ERROR] BIOS Version: $L_BIOS_VER Not Match Standard: $R_BIOS_VER"
        return 1
    fi
}

check_bmc () {
    case $Manufacture in
        "H3C"|"INSPUR"|"GIGABYTE"|"PUERSAI"|"STONEGROUP")
            local prefix suffix bmcSuffix
            prefix=`ipmitool mc info | grep "Firmware Revision"|awk '{print $NF}'`
            suffix=`ipmitool mc info | grep -A 1 "Aux Firmware Rev Info"| tail -n 1 |awk '{print $1}'`
            bmcSuffix=`printf %d ${suffix}`
            L_BMC_VER="${prefix}.${bmcSuffix}"
            ;;
        *)
            L_BMC_VER=`ipmitool mc info |grep "Firmware Revision"|awk -F ": " '{print $2}'`
            ;;
    esac
    R_BMC_VER=`/usr/bin/python $BASEDIR/utils/GetApolloConf.py "BMC" "${Manufacture}.${Product}.BMC" fw`
    [[ ! -n $R_BMC_VER ]] && PRINT_ERR "[ERROR] BMC FW --> BMC ${Manufacture}.${Product}.BMC <-- Not Exist In UCONF, Please Check UCONF"
    if [[ "$R_BMC_VER" =~ "$L_BMC_VER" ]];then
        PRINT_INFO "[INFO] BMC Version: $L_BMC_VER Match Standard: $R_BMC_VER"
        return 0
    else
        _check="FAIL"
        PRINT_ERR "[ERROR] BMC Version: $L_BMC_VER Not Match Standard: Apollo --> firmware ${Manufacture}.${Product}.BMC : $R_BMC_VER"
        return 1
    fi
}

check_aio () {
    # For HP BMC/BMC/RAID Update
    echo "nothing" > /dev/null
    return 1
}

update_bios_bmc_raid () {
    local item need_update check_action
    item=$1
    need_update=`/usr/bin/python $BASEDIR/utils/GetApolloConf.py "fwupdate" "${Manufacture}.${Product}" fw`
    if [[ ! "${need_update}" =~ "$item" ]];then
        PRINT_INFO "[INFO] Not Support Update $item, Please Check UCONF/fwupdate"
        return 0
    fi

    case $item in
        BIOS)
            check_bios
            check_action=$?
            [[ $check_action == 1 ]] && bios_fw="reboot"
            ;;
        BMC)
            check_bmc
            check_action=$?
            ;;
        AIO)
            check_aio
            check_action=$?
            ;;
        *)
            PRINT_INFO "[INFO] Only Support Update BIOS/BMC"
            return 0
            ;;
    esac

    if [[ $check_action -eq 0 ]];then
        PRINT_INFO "[INFO] $item Firmware No Need Update"
        return 0
    fi
    if [[ $item == "BIOS" ]] && [[ $Manufacture == "SUGON" && $Product == "I620-G20" ]] && [[ ! "003 006" =~ $L_BIOS_VER ]];then
        PRINT_ERR "[ERROR] BIOS Version: NOT SUGON I620-G20 003 & 006"
        PRINT_ERR "[ERROR] BIOS Version: SUGON I620-G20 $item , Please contact hardware principal for a manual upgrade"
        return 0
    fi

    run_fw_update "SERVER/${Manufacture}/${Product}/${item}"
    run_status=$?
    if [[ $run_status == 0 && $item == "BIOS" ]];then
        PRINT_ERR "[ERROR] BIOS 升级成功 请等待重启完成后重新初始化$bios_fw ..."
        trap bios_fw_reboot EXIT
        return 1
    fi
    return $run_status
}

bios_fw_reboot(){
    UPLOAD_LOG BIOS
    shutdown -r 1 BIOS升级完成一分钟后重启
}

_install() {
    local ret=0
    # update RAID/BIOS/BMC
    if [[ "$Manufacture" == "HP" ]];then
        update_bios_bmc_raid "AIO" # AIO = ALL-IN-ONE
        ret=$((ret+$?))
    else
        # update RAID and Disk
        check_disk_fw update
        ret=$((ret+$?))

        # update BMC
        update_bios_bmc_raid "BMC"
        ret=$((ret+$?))

        # update BIOS
        update_bios_bmc_raid "BIOS"
        ret=$((ret+$?))

    fi
    return $ret
}

_check() {
    _check="PASS"

    ### Check BIOS Version
    check_bios

    ### Check BMC Version
    check_bmc

    # check RAID and Disk
    check_disk_fw

}
