#!/bin/bash
set +x

LOG_FILE="/var/log/inspect.log"
source /opt/node_type_recognize.sh
source /opt/node_devicename.sh
G_MML_FILE_PATH="/opt/huawei/snas/script/inspect_mml"
source "${G_MML_FILE_PATH}/CommonFunc.sh"
source ${G_MML_FILE_PATH}/CheckItems
CurInspectNum="113"
CurInspectFun="$(GetInspectType $CurInspectNum)"
RESULTFILE="${G_TMP_INSPECT_PATH}tmpResult${CurInspectFun}"


source "/opt/inspect/inspect_map.sh"
DISK_STATUS_MML=${G_MML_FILE_PATH}/ShowDiskOnposition
#mml命令"cm localdiskinfo show"命令固定将结果生成到/tmp/tmpfilelocaldiskinfo文件里
TMP_RESULT_FILE="/tmp/tmpfilelocaldiskinfo"
#使用寿命部分临时文件
TMP_FILE_disklist="/tmp/tmp_disklist"
TMP_FILE_saslist="/tmp/tmp_saslist"
TMP_FILE_nvmelist="/tmp/tmp_nvmelist"
TMP_FILE_RESULT="/tmp/tmp_lifetime"
TMP_FILE_diskinfo="/tmp/tmp_diskinfo"

LOCAL_BACK_IP=""

>"${RESULTFILE}"

function LOG
{
    time=$(date)
    echo "[${time}][$$][$CurInspectFun]$*" >> $LOG_FILE
}

function set_ifs
{
    IFS_OLD=$IFS
    IFS=$'\n'
}

function restore_ifs
{
    IFS=$IFS_OLD
}

# 执行MML返回码不为0或获取tmpfilelocaldiskinfo失败均视为MML失败，把结果写入结果并退出进程
function deal_mml_failure()
{
    echo "[ERR]INFO: Failed to execute command(MmlBatch 4016 'cm localdiskinfo show')." >> "${RESULTFILE}" 2>&1
    echo "${CurInspectFun}_Pass ${CHECK_FAILED}" >> "${RESULTFILE}" 2>&1
    LOG "[$LINENO]Failed to execute command(MmlBatch 4016 'cm localdiskinfo show')."
    exit 0;
}


# 执行MML命令
function get_cm_diskinfo()
{
    LOCAL_BACK_IP=$(GetLocalIp)
    if [ "${LOCAL_BACK_IP}X" == "X" ];then
        echo "[ERR]INFO: Can't get backend IP." >> "${RESULTFILE}" 2>&1
        echo "${CurInspectFun}_Pass ${CHECK_FAILED}" >> "${RESULTFILE}" 2>&1
        LOG "[$LINENO]$(hostname) Can't get backend IP."
        exit 0;
    fi

    # isTmpResultFileOk 表示MML的结果文件是否存在，0表示ok
    local isTmpResultFileOk=1
    # 可能出现MML执行返回码为0，但是结果文件未获取到的情况，所以尝试3次
    for j in $(seq 1 3)
    do
        LOG "[$LINENO]the ($j)th attempt to get disk info."
        ${DISK_STATUS_MML} "${LOCAL_BACK_IP}" >/dev/null 2>&1
        if [ $? -ne 0 ]; then
           # 如果是MML返回码不为0，则退出不尝试重新执行MML
           deal_mml_failure
        fi

        for i in $(seq 1 15)
        do
            if [ -f "${TMP_RESULT_FILE}" ];then
                isTmpResultFileOk=0
                break
            else
                LOG "[$LINENO]times($i) no file."
            fi
            sleep 10
        done

        if [ $isTmpResultFileOk -eq 0 ]; then
            break
        fi
    done

    # 如果3次都还没有成功获得MML的结果文件，则也视为MML失败
    if [ $isTmpResultFileOk -ne 0 ]; then
        deal_mml_failure
    fi
    LOG "[$LINENO]get disk info successfully."

    return 0
}


function CheckSSD()
{

    local devicetype=""
    local diskAccSlotNum=""
    local AllDiskFile=${TMP_RESULT_FILE}"Disk_SSD"
    local isPass=0
    local AllSSD=1
    local isSlotOk=1
    local SSDExistFlag=0
    local SSDNotExistFlag=0

    get_cm_diskinfo
    dos2unix ${TMP_RESULT_FILE} >/dev/null 2>&1

    cat ${TMP_RESULT_FILE} |grep "Disk_ID"|sed 's/^ *//g'|sed "/^$/d" > ${AllDiskFile}  2>&1

    set_ifs
    GetSSDLifetime
    NotSSDinfo=`cat $AllDiskFile | grep -v "Disk_type: 3" | grep -v "Disk_type: 16" | grep -v "Disk_type: 17" | grep -v "Disk_type: -1"`
    locationlist=`cat $AllDiskFile | egrep "Disk_type: 3|Disk_type: 16|Disk_type: 17" | awk '{print $8}'`
    oneNidinfo=`cat $AllDiskFile | egrep "Disk_type: 3|Disk_type: 16|Disk_type: 17" `
    # AllDiskFile 是此脚本产生的临时文件，需要删除
    [ -f "${AllDiskFile}" ] && rm "${AllDiskFile}"

    devicetype=$(cat /opt/huawei/deploy/etc/deploy.ini | grep devicetype |awk -F= '{print $2}')
    diskAccSlotNum=$(cat /opt/huawei/snas/etc/cm.ini | grep diskAccSlotNum | awk -F= '{print $2}')

    type=$(MapNodeType  $devicetype)
    #判断是否是全闪存
    if [ "$type" == "S25A Node" ] || [ "$type" == "S25B Node" ] || [ "$type" == "S25X Node" ] || [ "$type" == "S12A Node" ] ; then
        AllSSD=0
    fi

    #全闪存环境必须全为SSD盘，其他场景如果存在SSD盘，则cm.ini中配置的位置至少有一个是SSD盘
    if [ "$AllSSD" == "0" ]; then
        if [ "X${NotSSDinfo}" != "X" ];then
            for line in $NotSSDinfo; do
                notSSDlocation=`echo $line|awk '{print $8}'`
                echo "[ERR]INFO: location $notSSDlocation not SSD." >>${RESULTFILE} 2>&1
            done
            isPass=1
        fi
    else
        if [ "$oneNidinfo" == "" ]; then
            echo "location:No SSD information.||healthStatus:--||runningStatus:--||bandwidth:--||Temperature(degrees):--||model:--||version:--||manu:--||SN:--||size(bytes):--||runTime(days):--||DiskNeedUpg:--||letter:--||PowerOnTime(hours):--||lifeexpend:--" >> "${RESULTFILE}" 2>&1
            echo "${CurInspectFun}_Pass ${isPass}" >> "${RESULTFILE}" 2>&1
            return
        fi

        isSlotOk=1
        # 先把diskAccSlotNum中引号去掉，再以逗号分隔转化为数组
        diskAccSlotNum="${diskAccSlotNum//\"/}"
        OLD_IFS="$IFS"
        IFS=","
        diskAccSlotNumArr=($diskAccSlotNum)
        IFS="$OLD_IFS"

        restore_ifs
        for disknum in "${diskAccSlotNumArr[@]}"; do
            echo ${locationlist} | egrep -w "0$disknum|$disknum" >/dev/null 2>&1
            if [ $? -eq 0 ]; then
                isSlotOk=0
                break
            fi
        done
        set_ifs

        if [ "$isSlotOk" -ne 0 ];then
            echo "[ERR]INFO: location $diskAccSlotNum at least one SSD is required." >>${RESULTFILE} 2>&1
            isPass=1
        fi
    fi

    #判断ssd盘的状态
    for line in $oneNidinfo; do
        LOG "[$FUNCNAME]line($line)"

        ID=`echo $line |awk '{print $2}'`

        parentID=`echo $line |awk '{print $5}'`
        #根据parentID获得IP
        parentIP=`get_node_backnet_ip $parentID`

        location=`echo $line|awk '{print $8}'`

        healthStatus=`echo $line |awk '{print $11}'|sed 's/^ *//g'|sed "/^$/d"`
        runningStatus=`echo $line |awk '{print $14}'|sed 's/^ *//g'|sed "/^$/d"`

        healthStatus=`MapHealthStatus $healthStatus`
        runningStatus=`MapRunningStatus $runningStatus`

        bandwidth=`echo $line |awk '{print $20}'`
        Temperature=`echo $line |awk '{print $26}'`

        model=`echo $line |awk -F: '{print $11}'|sed 's/|| Version//'`

        version=`echo $line |awk -F: '{print $12}'|sed 's/|| Manufacture//'`
        manu=`echo $line |awk -F: '{print $13}'|sed 's/|| SN//'`
        SN=`echo $line |awk -F: '{print $14}'|sed 's/|| Size//'`
        size=`echo $line |awk -F: '{print $15}'|sed 's/|| RunTime//'`
        runTime=`echo $line |awk -F: '{print $16}'|sed 's/|| DiskNeedUpg//'`
        DiskNeedUpg=`echo $line|awk -F: '{print $17}'|sed 's/|| DiskUpgStrategy//'`

        #使用寿命
        sn=$(echo $SN | sed 's/ //g')
        lifeline=$(cat $TMP_FILE_RESULT | grep $sn)
        LOG "[$FUNCNAME]line($lifeline)"
        letter=$(echo $lifeline | awk '{print $2}')
        PowerOnTime=$(echo $lifeline | awk '{print $3}')
        lifeexpend=$(echo $lifeline | awk '{print $4}')
	if [ "X$PowerOnTime" != "X" ];then
            expectexpend=$(echo "" | awk -v x=$PowerOnTime '{print int(x/24/365*20)}')
		
	else
	    expectexpend="-1"
	fi

        if [ "$runningStatus" != "NOT_EXIST" ];then
            SSDExistFlag=1
            echo "location:${location}||healthStatus:${healthStatus}||runningStatus:${runningStatus}||bandwidth:${bandwidth}||Temperature(degrees):${Temperature}||model:${model}||version:${version}||manu:${manu}||SN:${SN}||size(bytes):${size}||runTime(days):${runTime}||DiskNeedUpg:${DiskNeedUpg}||letter:${letter}||PowerOnTime(hours):${PowerOnTime}||lifeexpend:${lifeexpend}" >>${RESULTFILE} 2>&1
            #计算 PowerOnTime(年)/5年 *100 > lifeexpend 则巡检通过 简化为*20
            
            if [ "$runningStatus" != "ONLINE" ] || [ "$healthStatus" != "NORMAL" ] || [ ${Temperature} -gt 55 ] || [ ${expectexpend} -lt ${lifeexpend} ];then
                LOG "[$FUNCNAME]:Error, $Result"
                isPass=1
                echo "[ERR]INFO: location $location runningStatus(${runningStatus}) is not ONLINE or healthStatus(${healthStatus}) is not NORMAL or Temperature(${Temperature}) is greate than 55 or Expectexpend(${expectexpend}) is less than Lifeexpend(${lifeexpend})." >>${RESULTFILE} 2>&1
            fi
        else
            SSDNotExistFlag=1
            continue
        fi
    done
    [ -f "${TMP_FILE_RESULT}" ] && rm "${TMP_FILE_RESULT}"
    if [ $SSDExistFlag -eq 0 ] && [ $SSDNotExistFlag -eq 1 ];then
       echo "location:No SSD information.||healthStatus:--||runningStatus:--||bandwidth:--||Temperature(degrees):--||model:--||version:--||manu:--||SN:--||size(bytes):--||runTime(days):--||DiskNeedUpg:--||letter:--||PowerOnTime(hours):--||lifeexpend:--" >> ${RESULTFILE} 2>&1
    fi
    restore_ifs
    echo "${CurInspectFun}_Pass ${isPass}" >>${RESULTFILE} 2>&1

}


#新增ssd盘使用寿命部分
function get_disklist()
{
    /usr/local/bin/MmlBatch 4016 "cm showdiskname" >$TMP_FILE_disklist 2>&1
    dos2unix -f $TMP_FILE_disklist >/dev/null 2>&1
    LOG "[$FUNCNAME][$LINENO] MmlBatch 4016 'cm showdiskname'"
    if [ ! -s $TMP_FILE_disklist ];then
        echo "[ERR]INFO:Failed to execute command(MmlBatch 4016 'cm showdiskname')."    >>${RESULTFILE} 
        LOG "[$LINENO] exec command failed(/usr/local/bin/MmlBatch 4016 cm showdiskname)"   
    fi
}

function use_disktool()
{
    #先用disktool看，没结果就换smartctl，哪个有结果用哪个，disktool内部也会调用smartctl
    id=$1
    disktool -f a $id >$TMP_FILE_diskinfo 2>&1
    #华为自研sas的关键字
    usedtime=$(cat $TMP_FILE_diskinfo | grep "Power on time" | awk '{print $4}')
    if [ "X${usedtime}" == "X" ];then
        usedtime=$(cat $TMP_FILE_diskinfo | grep "Power_On_Hours" | awk '{print $10}')
    fi
    lifeexpend=$(cat $TMP_FILE_diskinfo | grep "Disk Life Expend" | awk '{print $4}')
    if [ "X${lifeexpend}" == "X" ];then
        #不是华为自研，已知闪迪可以用这个看
        lifeexpend=$(cat $TMP_FILE_diskinfo | grep "Percentage used endurance" | awk '{print $7}' | sed 's/%//g')
    fi
    smartctl -l devstat $id >$TMP_FILE_diskinfo 2>&1
    if [ "X${lifeexpend}" == "X" ];then
        #smartctl方法 和-a参数结果略有不同
        lifeexpend=$(cat $TMP_FILE_diskinfo | grep "Percentage Used Endurance Indicator" | awk '{print $4}')
    fi
    sn=$(disktool -f i $id | grep "Serial Number" | awk '{print $3}')
    echo "$sn $id $usedtime $lifeexpend" >> $TMP_FILE_RESULT 2>&1
    [ -f "${TMP_FILE_diskinfo}" ] && rm "${TMP_FILE_diskinfo}"
    
}




function get_sas_info()
{
    poollist=$(cat $TMP_FILE_saslist)
    #先用disktool方法，smartctl方法合并在disktool方法里面
    for i in $poollist;
    do
        use_disktool "$i"
    done
    [ -f "${TMP_FILE_saslist}" ] && rm "${TMP_FILE_saslist}"

}

function use_smartlog()
{
    id=$1
    nvme smart-log $id >$TMP_FILE_diskinfo 2>&1
    usedtime=$(cat $TMP_FILE_diskinfo | grep power_on_hours | awk '{print $3}' | sed 's/,//g')
    lifeexpend=$(cat $TMP_FILE_diskinfo |grep percentage_used | awk '{print $3}' | sed 's/%//g')
    sn=$(disktool -f i $id | grep "Serial Number" | awk '{print $3}')
    echo "$sn $id $usedtime $lifeexpend" >> $TMP_FILE_RESULT 2>&1 
    [ -f "${TMP_FILE_diskinfo}" ] && rm "${TMP_FILE_diskinfo}"
}

function get_nvme_info()
{
    poollist=$(cat $TMP_FILE_nvmelist)
    #NVME盘直接用nvme smart-log
    for i in $poollist;
    do
        use_smartlog "$i"
    done
    [ -f "${TMP_FILE_nvmelist}" ] && rm "${TMP_FILE_nvmelist}"
}


#通过盘符获取ssd盘的已用时间、磨损度、剩余寿命、sn号
#在CheckSSD中，用sn做索引，将新增部分添加到原有输出格式中
function GetSSDLifetime()
{
    get_disklist

    cat $TMP_FILE_disklist | grep -e "Disk_Type:3" -e "Disk_Type:17" | awk '{print $3}' > $TMP_FILE_saslist
    cat $TMP_FILE_disklist | grep "Disk_Type:16" | awk '{print $3}' > $TMP_FILE_nvmelist
    [ -f "${TMP_FILE_disklist}" ] && rm "${TMP_FILE_disklist}"   

    dos2unix -f $TMP_FILE_saslist >/dev/null 2>&1
    dos2unix -f $TMP_FILE_nvmelist >/dev/null 2>&1
    #已知本节点SAS和NVME两种ssd的id，接下来获取sn和lifetime
    #SAS盘华为用disktool，外部用smartctl，不好判断所以都试一下
    #SATA_SSD和SAS_SSD一同判断
    #NVME的盘已知华为的可以用nvme smart-log，外部的还不确定
    get_sas_info 
    get_nvme_info
}

CheckSSD
exit 0


