#!/bin/bash

G_INSPECT_MMLPATH="/opt/huawei/snas/script/inspect_mml"
source $G_INSPECT_MMLPATH/CheckItems
CurInspectNum="171"
CurInspectFun="$(GetInspectType $CurInspectNum)"
RESULTFILE="/tmp/tmpResult${CurInspectFun}"
>${RESULTFILE}

isPass=0
LOGFILE="/var/log/inspect.log"
PERCENTAGE_LIMIT=18
SMARTINFO="smart infos"

CODE_WHITELIST="
02312YXY
02313EDD
02313EDF
02313KKD
02314BAR
02314CLB
02314BAS
02314CLG
02313EDG
02313EDH
02313TQT
02313KKH
02314CLD
02314BAT
02314CLH
02314BAU
02314DJK
02550078
02550079
02313FBD
02313FBE
02313KKS
02550168
02314BAC
02314CKU
02550522
02550552
02313KKT
02313XJU
02314BAJ
02314CKV
02550164
02550553
02550523
02313NUU
02314BAK
02314CKW
02550064
02313EDT
02313EDU
02550166
02313KJW
02313NUW
02313XJW
02550554
02550524
02314BAL
02314CKX
02314BAQ
02314CKY
02314BAM
02314CLJ
02314DJP
02550065
02313EDV
02313EDW
02313KJV
02314BAN
02314CLA
02314BAP
02314CLK
02550323
02550555
02550525
02550324
02550556
02550526
02550062
02550156
02550557
02550527
02550063
02550157
02550558
02550528
02550066
02550559
02550529
02312UBN
02312UCF
02312UCG
02312UCH
02312UCL
02312UCW
02312UCX
02312XDV
02312XDW
02312UED
02312UEE
02312UEH
02312UEJ
"

function LOG()
{
    echo [${time}][$$][$CurInspectFun]$@ >> ${LOGFILE}
}

##############################################################
## ȡsmartvendor smart
##############################################################
function getSmart()
{
    #  1: Ӳͣsas|nvme  2: sn 3̷
    #  smartvendor smart
    # ֵ 0:ȡsmartɹ; 1:ִʧ;
    local diskType=$1
    local sn=$2
    local device=$3
    SMARTINFO="${SMARTINFO} sn(${sn})"

    if [[ "$diskType" == "sas" ]];then
        smartctlLifeTemp=$(timeout -k 3 30 smartctl -a ${device})
        if [ $? -ne 0 ];then
            return 1
        fi
        smartctlTimeTemp=$(timeout -k 3 30 smartctl -l background ${device})
        if [ $? -ne 0 ];then
            return 1
        fi
        local sasVendorSmart=$(timeout -k 3 30 hioadm info -d ${device:5} -e)
        SMARTINFO="${SMARTINFO} ${smartctlLifeTemp}"
        SMARTINFO="${SMARTINFO} ${smartctlTimeTemp}"
        SMARTINFO="${SMARTINFO} vendor smart ${sasVendorSmart}"
    else
        nvmeSmartTemp=$(timeout -k 3 30 hioadm info -d ${device} -s)
        if [ $? -ne 0 ];then
            return 1
        fi
        local nvmeVendorSmart=$(timeout -k 3 30 hioadm info -d ${device} -e)
        SMARTINFO="${SMARTINFO} ${nvmeSmartTemp}"
        SMARTINFO="${SMARTINFO} vendor smart ${nvmeVendorSmart}"
    fi
    return 0
}

##############################################################
## ʣʱ
##############################################################
function calcTimeRemaining()
{
    #  1: Ӳ 
    #  ȫֱ ʣ
    # ֵ 2ȡϵʱʧ; 3:ϵʱ0ʹٷֱСڵ1; 4:ʣʱ>=0; 5:ʣʱ<0
    local diskType=$1
    local pohVal=""
    local percentagUsed=""

    if [[ "$diskType" == "sas" ]];then
        pohVal=$(awk -F ':' '/power on time/{printf("%s", $2)}' <<< "${smartctlTimeTemp}" | awk -F" " '{print $2}' | sed -e 's/[ ]//g' | sed -e 's/,//g' | grep -v '[A-Z|a-z]')
        percentagUsed=$(awk -F ':' '/(Percentage|Media) used endurance indicator/{printf("%s", $2)}' <<< "${smartctlLifeTemp}" | sed -e 's/[ ]//g' | sed -e 's/[%]*$//g' | grep -v '[A-Z|a-z]')
    else
        pohVal=$(awk -F ':' '/power on hours/{printf("%s", $2)}' <<< "${nvmeSmartTemp}" | sed -e 's/[ ]//g' | sed -e 's/,//g'  | sed -e 's/[a-z|A-Z]//g' | grep -v '[A-Z|a-z]')
        percentagUsed=$(awk -F ':' '/percentage used/{printf("%s", $2)}' <<< "${nvmeSmartTemp}" | sed -e 's/[ ]//g' | sed -e 's/[%]*$//g' | grep -v '[A-Z|a-z]')
    fi

    if [ -z "${pohVal}" ] || [ -z "${percentagUsed}" ]; then  # ȡϵʱʧ
        return 2
    fi
    
    if [ ${pohVal} -eq 0 ] || [ ${percentagUsed} -le 1 ];then  # ϵʱ0ʹٷֱСڵ1
        return 3
    fi

    local timeRemainingDay=$(((${pohVal}*${PERCENTAGE_LIMIT}/${percentagUsed}-${pohVal})/24))
    timeRemaining="${timeRemainingDay}d"
    if [ ${timeRemainingDay} -ge 0 ];then # ʣʱ>=0
        return 4
    fi
    # ʣʱ<0
    return 5
}

##############################################################
## sasǷ
##############################################################
function checkSASDisk()
{
    if [ -z "${sasDevice}" ];then
        return
    fi

    local smartctlIsOkSAS=1
    while read line
    do
        sasDiskInfo=$(timeout -k 3 10 disktool -f i ${line})
        if [ $? -ne 0 ];then
            LOG "[${LINENO}] excute disktool -f i ${line} err."
            return
        fi
        
        smartctlLifeTemp=NA
        smartctlTimeTemp=NA
        timeRemaining=NA
        errCode=NA
        local sn=$(awk -F ':' '/Serial Number/{printf("%s", $2)}' <<< "$sasDiskInfo" | sed -e 's/[ ]//g')
        local fw=$(awk -F ':' '/Firmware Version/{printf("%s", $2)}' <<< "$sasDiskInfo"  | sed -e 's/[ ]//g' | grep '^[0-9]\{4\}')
        local mn=$(awk -F ':' '/Device Model/{printf("%s", $2)}' <<< "$sasDiskInfo"  | sed -e 's/[ ]//g')
        if [ ${smartctlIsOkSAS} -eq 1 ];then
            getSmart "sas" "${sn}" "${line}"
            if [ $? -eq 1 ];then
                smartctlIsOkSAS=0
                errCode=1
            fi
        fi

        isV6Disk=$(echo ${sasDiskInfo} | grep -E "HSSD-D7|HWE6" | wc -l)
        if [ ${isV6Disk} -eq 0 ];then
            LOG "[${LINENO}]Disk sn:${sn} fw:${fw} mn:${mn}, is not ES3000/HSSD V6 disk, no need check." ${FUNCNAME} ${SCRIPT_NAME}
            continue
        fi

        local code0231="${sn:2:8}"
        if [ ${#code0231} -ne 8 ] || [ ${#fw} -ne 4 ];then
            LOG "[${LINENO}]Disk sn:${sn} fw:${fw} mn:${mn}, the disk info is not as expected."
            continue
        fi

        if [ ${fw} -lt 5014 ] || [ ${fw} -gt 8316 ];then # fw汾50148316
            LOG "[${LINENO}]Disk sn:${sn} fw:${fw} mn:${mn}, fw version is no risk, no need check."
            continue
        fi

        local isRisk0231=$(echo ${CODE_WHITELIST} | grep ${code0231} | wc -l)
        if [ ${isRisk0231} -eq 0 ];then
            LOG "[${LINENO}]Disk sn:${sn} mn:${mn}, not exist risk , no need check."
            continue
        fi

        isPass=1
        if [ ${smartctlIsOkSAS} -eq 1 ];then
            calcTimeRemaining "sas"
            errCode=$?
            retProcess=". Not passed. If the firmware version of a disk in the device is too early, the number of bad sectors may increase and the fault rate may increase if the disk runs for a long time. Contact research and development engineers"
            if [ ${errCode} -eq 2 ];then
                smartctlIsOkSAS=0
            elif [ ${errCode} -eq 3 ] || [ ${errCode} -eq 4 ];then
                retProcess=". Not passed. If the firmware version of a disk in the device is too early, the number of bad sectors may increase and the fault rate may increase if the disk runs for a long time. Upgrade the firmware version to 8320 or later as soon as possible. At least one spare part must be prepared during the upgrade"
            fi
        fi
        echo "[ERR]INFO:Disk sn(${sn}) fw(${fw}) mn(${mn}) time remaining(${timeRemaining}) code(${errCode})${retProcess}." >> ${RESULTFILE} 2>&1
        LOG "[${LINENO}]Disk sn:${sn} fw:${fw} mn:${mn} time remaining:${timeRemaining} code:${errCode}${retProcess}."
    done <<< "$sasDevice"
    return
}

##############################################################
## nvmeǷ
##############################################################
function checkNVMeDisk()
{
    if [ -z "${nvmeDevice}" ];then
        return
    fi

    local nvmeDevices=$(echo $nvmeDevice | sed -e 's/|/\n/g')
    local hioadmInfoOkNVMe=1
    while read line
    do
        nvmeDiskInfo=$(timeout -k 3 20 hioadm info -d ${line})
        if [ $? -ne 0 ];then
            LOG "[$LINENO] excute hioadm info -d ${line} err."
            return
        fi

        nvmeSmartTemp=NA
        timeRemaining=NA
        errCode=NA
        local sn=$(awk -F ':' '/serial number/{printf("%s", $2)}' <<< "${nvmeDiskInfo}" | sed -e 's/[ ]//g')
        local fw=$(awk -F ':' '/firmware version/{printf("%s", $2)}' <<< "${nvmeDiskInfo}"  | sed -e 's/[ ]//g' | grep '^[0-9]\{4\}')
        local mn=$(awk -F ':' '/model number/{printf("%s", $2)}' <<< "${nvmeDiskInfo}"  | sed -e 's/[ ]//g')
        if [ ${hioadmInfoOkNVMe} -eq 1 ];then
            getSmart "nvme" "${sn}" "${line}"
            if [ $? -eq 1 ];then
                hioadmInfoOkNVMe=0
                errCode=1
            fi
        fi

        isV6Disk=$(echo ${nvmeDiskInfo} | grep -E "HSSD-D7|HWE6" | wc -l)
        if [ ${isV6Disk} -eq 0 ];then
            LOG "[${LINENO}]Disk sn:${sn} fw:${fw} mn:${mn}, is not ES3000/HSSD V6 disk, no need check." ${FUNCNAME} ${SCRIPT_NAME}
            continue
        fi

        local code0231="${sn:2:8}"
        if [ ${#code0231} -ne 8 ] || [ ${#fw} -ne 4 ];then
            LOG "[${LINENO}]Disk sn:${sn} fw:${fw} mn:${mn}, the disk info is not as expected."
            continue
        fi

        if [ ${fw} -lt 5014 ] || [ ${fw} -gt 8316 ];then # fw汾50148316
            LOG "[${LINENO}]Disk sn:${sn} fw:${fw} mn:${mn}, fw version is no risk, no need check."
            continue
        fi

        local isRisk0231=$(echo ${CODE_WHITELIST} | grep ${code0231} | wc -l)
        if [ ${isRisk0231} -eq 0 ];then
            LOG "[${LINENO}]Disk sn:${sn} mn:${mn}, not exist risk , no need check."
            continue
        fi

        isPass=1
        if [ ${hioadmInfoOkNVMe} -eq 1 ];then
            calcTimeRemaining "nvme"
            errCode=$?
            retProcess=". Not passed. If the firmware version of a disk in the device is too early, the number of bad sectors may increase and the fault rate may increase if the disk runs for a long time. Contact research and development engineers"
            if [ ${errCode} -eq 2 ];then
                hioadmInfoOkNVMe=0
            elif [ ${errCode} -eq 3 ] || [ ${errCode} -eq 4 ];then
                retProcess=". Not passed. If the firmware version of a disk in the device is too early, the number of bad sectors may increase and the fault rate may increase if the disk runs for a long time. Upgrade the firmware version to 8320 or later as soon as possible. At least one spare part must be prepared during the upgrade"
            fi
        fi
        echo "[ERR]INFO:Disk sn(${sn}) fw(${fw}) mn(${mn}) time remaining(${timeRemaining}) code(${errCode})${retProcess}." >> ${RESULTFILE} 2>&1
        LOG "[${LINENO}]Disk sn:${sn} fw:${fw} mn:${mn} time remaining:${timeRemaining} code:${errCode}${retProcess}."
    done <<< "$nvmeDevices"
    return
}

function checkES3000V5DiskLifeRisk()
{

    LOG "[${LINENO}]ProductName=CheckES3000V5DiskLifeRisk"

    nvmeDevice=''
    for devId in {0..7}
    do
        local devMn=$(timeout 30 hioadm info -d nvme${devId} | grep "model number" | grep -E "HSSD-D[6-9]|HWE[5-9]")
        if [ ! -z "$devMn" ]; then
            if [ -z "$nvmeDevice" ]; then
                nvmeDevice="nvme${devId}"
            else
                nvmeDevice=${nvmeDevice}"|nvme${devId}"
            fi
        fi
    done

    sasDevice=$(lsscsi -g | grep -E "HSSD-D[6-9]|HWE[5-9]" | awk -F' ' '{print $6}' | sed -e 's/[ ]//g')
    if [ -z "${nvmeDevice}" ] && [ -z "${sasDevice}" ]; then
        echo "INFO:This node does not have a ES3000/HSSD disk. No need check." >> ${RESULTFILE} 2>&1
        LOG "[${LINENO}] This node does not have a ES3000/HSSD disk. No need check."
        return
    fi
    checkSASDisk
    checkNVMeDisk

    if [[ ${isPass} -eq 0 ]];then
        echo "INFO:This node has no risk." >> ${RESULTFILE} 2>&1
        LOG "[${LINENO}] This node has no risk."
    fi

    echo "INFO:$(echo ${SMARTINFO} | sed -e 's/[^0-9a-zA-Z()=,. ]/ /g')" >> ${RESULTFILE} 2>&1
    return
}

checkES3000V5DiskLifeRisk
echo "${CurInspectFun}_Pass ${isPass}" >> ${RESULTFILE} 2>&1
exit 0