#!/bin/bash
set +x
LOG_FILE="/var/log/inspect.log"
OLD_VER="V100R001C01SPC100 V100R001C01SPC200 V100R001C01SPC210 V100R001C01SPC290 V100R001C20SPC100 V100R001C20SPC001 V100R001C20 V100R001C30 V100R001C30SPC100 V100R001C30SPC110 V100R001C30 V100R001C30SPC200 V300R005C00SPC100 V300R005C00SPC110 V300R005C00SPC160 V300R005C00SPC170 V300R005C00"
NEW_VER="Exclude ${OLD_VER}"
OLD_PATH="/opt/huawei/patch"
NEW_PATH="/var/huawei/patch"
G_MML_FILE_PATH="/opt/huawei/snas/script/inspect_mml"
source $G_MML_FILE_PATH/CheckItems
CurInspectNum="282"
CurInspectFun="$(GetInspectType $CurInspectNum)"
RESULTFILE="${G_TMP_INSPECT_PATH}tmpResult${CurInspectFun}"
>${RESULTFILE}

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

function getModuleViaPatchName()
{
    local patchName=$1
    echo "${patchName}" | awk -F'SPH[0-9]+|.patch' '{print $2}'
}

#特殊处理环境上原本没有的补丁模块，但是补丁包里面又包含补丁模块，则不需要处理，需要过滤掉
#返回值 0:表示需要处理   1:不需要处理 2:lsmod命令异常
function special_operate()
{
    local patchName=$1
    local moduleName=$(getModuleViaPatchName ${patchName})
    local ofed_ver="3.2"

    echo ${moduleName} | grep -q "ko2iblnd" >/dev/null 2>&1
    if [ $? -eq 0 ];then
        ofed_ver=$(ofed_info -s | grep -Po '(?<=-)[0-9.]+-' | tr -d '-')
        if [ "X$ofed_ver" == "X" ];then
            LOG "[$LINENO]no need to active ${patchName}!"
            return 1
        fi
        echo ${moduleName} | grep -q "$ofed_ver" >/dev/null 2>&1
        ret=$?
        if [ "$ofed_ver" == "3.2" ] && [ $ret -ne 0 ] ;then
            echo "${moduleName}"
            return 0
        elif [ $ret -eq 0 ];then
            echo "${moduleName%_$ofed_ver}"
            return 0
        fi
        LOG "[$LINENO]no need to active ${patchName}!"
        return 1
    fi

    lsmod | grep -w snas_base >/dev/null 2>&1
    if [ $? -ne 0 ];then
        LOG "[$LINENO]lsmod maybe abnormal!"
        return 2
    fi
    lsmod | grep -qw ${moduleName} >/dev/null 2>&1
    if [ $? -ne 0 ];then
        echo ${moduleName} | grep -q "cm_sysctrl_t3000" >/dev/null 2>&1
        if [ $? -eq 0 ];then
            #cm_sysctrl_t3000.ko不仅适用T3000还适用RH
            echo "${moduleName%_t3000}"
            return 0
        fi
        echo ${moduleName} | grep -q "pangea_sal" >/dev/null 2>&1
        if [ $? -eq 0 ];then
            #pangea_sal 名字转换
            echo "sal"
            return 0
        fi

        LOG "[$LINENO]no need to active ${patchName}!"
        return 1
    fi

    return 0
}

# Return 1, need filter this patch
function patchSdFilter()
{
    local patchName=$1
    local moduleName=$(getModuleViaPatchName ${patchName})
    if [ "${moduleName}" = "sd_t3000" -o "${moduleName}" = "sd" ]; then
        patchName=${patchName};
    else
        return 0
    fi
    if [ "${moduleName}" = "sd_t3000" ]; then
        LOG "[$LINENO]: Filter ${patchName} on RH."
        return 1
    fi
    return 0
}
function get_livepatch_moudle()
{
    local ppath=$(find $1 -name "$2" -exec dirname {} \;)
    local pname="$2"
    local tmpDir="${G_TMP_INSPECT_PATH}tmp_HotPatch$$"
    if [ ! -d "${tmpDir}" ]; then
        mkdir -p "${tmpDir}"
    else
        rm -rf "${tmpDir}/*"
    fi
    local tmpfile="${tmpDir}/tmp.tar.gz"
    cp ${ppath}/${pname} ${tmpDir}
    DATA_POS="`grep -a -n "^##\[\[DATA\]\]##" ${tmpDir}/${pname} | awk -F":" '{print $1}'`"
    DATA_POS=`expr $DATA_POS + 1`
    tail -n +${DATA_POS} "${tmpDir}/${pname}" >$tmpfile 2>/dev/null
    tar zxf $tmpfile -C ${tmpDir} > /dev/null 2>&1
    module=$(ls ${tmpDir} | grep ".tar.gz" | grep -v tmp.tar.gz |awk -F"." '{print $1}' | awk -F'SPH[0-9]+|.patch' '{print $2}')
    ls ${tmpDir} |grep "${module}.ko_flag" >/dev/null 2>&1 
    if [ $? -ne 0 ];then
        echo "NO"
    else
        echo "$module"
    fi
    rm -rf ${tmpDir}
}
#获取补丁列表存入临时文件中。调用者保证目录和临时文件有效
function get_patch_list()
{
    local tmppath="$1"
    local tmpfile="$2"
    local patchList=""
    local errFlag=0
    local iret=0
    local moduleName=""
    local nochecklist="$3"

    # 从7.0开始livepatch查询的补丁名字和补丁文件名字已经无明确对应关系了，只有模块名能对应上
    # 从补丁文件中获取模块名，模块可能有多个补丁，从livepatch -q结果中按顺序对应
    tmppath=$(find ${tmppath} -name "hotpatch.conf" -exec dirname {} \;)
    if [ -f ${tmppath}/hotpatch.conf ]; then
        patchList=$(cat ${tmppath}/hotpatch.conf | awk '{print $1}')
    fi
    >${tmpfile}
    for item in ${patchList}; do
        echo "${nochecklist}" | grep -qw ${item} 2>&1
        if [ $? -eq 0 ];then
            continue
        fi
        moduleName=$(patchSdFilter ${item})
        iret=$?
        if [ ${iret} -ne 0 ]; then
            continue
        fi
        if [ -n "${moduleName}" ]; then
            echo "${item} ${moduleName}" >>${tmpfile}
            continue
        fi

        moduleName=$(special_operate ${item})
        iret=$?
        if [ ${iret} -ne 0 ];then
            continue
        fi
        if [ -n "${moduleName}" ]; then
            echo "${item} ${moduleName}" >>${tmpfile}
            continue
        fi

        moduleName=$(getModuleViaPatchName ${item})
        if [ -n "${moduleName}" ]; then
            echo "${item} ${moduleName}" >>${tmpfile}
        fi
    done

    return ${errFlag}
}

#获取补丁列表存入临时文件中。调用者保证目录和临时文件有效
function get_patch_list_new()
{
    local tmppath="$1"
    local tmpfile="$2"
    local patchList=""
    local errFlag=0
    local iret=0
    local moduleName=""
    local nochecklist="$3"

    tmppath=$(find ${tmppath} -name "hotpatch.conf" -exec dirname {} \;)
    if [ -f ${tmppath}/hotpatch.conf ]; then
        patchList=$(cat ${tmppath}/hotpatch.conf | awk '{print $1}')
    fi
    >${tmpfile}
    for item in ${patchList}; do
        #按补丁文件名过滤不检查补丁.
        echo "${nochecklist}" | grep -qw ${item} 2>&1
        if [ $? -eq 0 ];then
            continue
        fi
        #进到此处,hotpatch_list存在且不为空,
        #如果item在hotpatch_list中没有patchName,不检查
        patchName=$(cat $tmppath/hotpatch_list | grep $item | awk '{print $1}')
        if [ "X${patchName}" == "X" ]; then
            continue
        fi

        moduleName=$(patchSdFilter ${item})
        iret=$?
        if [ ${iret} -ne 0 ]; then
            continue
        fi
        if [ "X${moduleName}" != "X" ]; then
            echo "${item} ${patchName}" >>${tmpfile}
            continue
        fi

        moduleName=$(special_operate ${item})
        iret=$?
        if [ ${iret} -ne 0 ];then
            continue
        fi
        if [ "X${moduleName}" != "X" ]; then
            echo "${item} ${patchName}" >>${tmpfile}
            continue
        fi

        echo "${item} ${patchName}" >>${tmpfile}

    done

    return ${errFlag}
}

function get_patch_path()
{
    local nr=0
    local patch_base="${NEW_PATH}"
    local work_path=""
    local found=0
    local dir=""
    local sub_dirs="cur tmp"
    local tmpver=""
    local ver=""
    local ret=0

    tmpver=$(grep ProductVersion /opt/huawei/deploy/package/version)
    ret=$?
    ver=$(echo "${tmpver}" | awk -F "=" '{print $2}')
    if [ ${ret} -ne 0 -o "$ver" == "" ];then
        LOG "[$LINENO]get version fail"
        echo "Get patch version failed" >>${RESULTFILE} 2>&1
        return 1
    fi
    echo ${OLD_VER} | grep -w ${ver} > /dev/null 2>&1
    if [ $? -eq 0 ];then
        patch_base="${OLD_PATH}"
    else
        patch_base="${NEW_PATH}"
    fi

    for dir in ${sub_dirs}
    do
        if [ -d ${patch_base}/${dir} ];then
            nr=$(find ${patch_base}/${dir} -type d -name "*SPH*" | wc -l 2>/dev/null )
            if [ ! -z ${nr} -a ${nr} -ne 0 ];then
                work_path=${patch_base}/${dir}
                found=1
                break
            fi
        fi
    done

    if [ ${found} -eq 1 ];then
        echo ${work_path}
        LOG "[$LINENO]Get work path of hot patch ok, ${work_path}"
        return 0
    fi
    LOG "[$LINENO]Get work path of hot patch fail, maybe there is no patch"
    return 0
}

function check_patch()
{
    local ret=0
    local hpath=$1
    local module=""
    local moduleList=""
    local patchCount=0
    local activeCount=0
    local livepatchInfo=""
    local tmppath=""
    local patchfile=""
    local PATCH_FILE_LIST="${G_TMP_INSPECT_PATH}tmp_HotPatchlist$$.txt"
    local nochecklist="OceanStor_9000_V5_7.1.1.SPH3nas_proto_vfs.patch OceanStor_9000_V5_7.1.1.SPH21nas_proto_vfs.patch"

    tmppath=$(find ${hpath} -name "hotpatch.conf" -exec dirname {} \;) 
    local hotpatch_list=$([ -f $tmppath/hotpatch_list ] && cat $tmppath/hotpatch_list 2>&1)
    if [ "X${hotpatch_list}" != "X" ];then
        get_patch_list_new "${hpath}" "${PATCH_FILE_LIST}" "${nochecklist}"
        if [ $? -eq 1 ];then
            LOG "[$LINENO]Get patch infomation failed.path:${hpath}"
            echo "Get patch infomation failed" >>${RESULTFILE} 2>&1
            return 1
        fi

        moduleList=$(cat "${PATCH_FILE_LIST}" | awk '{print $2}' | sort -u)
        for module in ${moduleList}; do
            livepatch -q${module} | grep "^Patch State" | grep -q "Active" >/dev/null 2>&1
            if [  $? -ne 0 ];then
                LOG "[$LINENO]Check hot patch of ${module} fail"
                patchfile=$(cat "${PATCH_FILE_LIST}" | grep "${module}" | awk '{print $1}')
                echo "${patchfile}: Hot patch active fail" >>${RESULTFILE} 2>&1
            fi
        done
    else
        get_patch_list "${hpath}" "${PATCH_FILE_LIST}" "${nochecklist}"
        if [ $? -eq 1 ];then
            LOG "[$LINENO]Get patch infomation failed.path:${hpath}"
            echo "Get patch infomation failed" >>${RESULTFILE} 2>&1
            return 1
        fi

        # 从7.0开始livepatch查询的补丁名字和补丁文件名字已经无明确对应关系了，只有模块名能对应上
        # 从补丁文件中获取模块名，模块可能有多个补丁，从livepatch -q结果中按顺序对应
        livepatchInfo=$(livepatch -q)
        moduleList=$(cat "${PATCH_FILE_LIST}" | awk '{print $2}' | sort -u)
        for module in ${moduleList}; do
            patchCount=$(cat "${PATCH_FILE_LIST}" | awk -v module=${module} '{if($2==module){print $0}}' | grep -wc "${module}")
            local patchName=$(cat "${PATCH_FILE_LIST}" | grep ${module} | awk '{print $1}')
            patch_module=$(get_livepatch_moudle "${hpath}" "${patchName}")
            if [ "X${patch_module}" = "XNO" ];then
                continue
            fi
            activeCount=$(echo "${livepatchInfo}" | sed -n '/Patch Name:[ VRCSPH0-9]\+'"${patch_module}"'$/{N;N;s/\n/ /g;p}' | grep -c "Patch State: Active")
            if [ ${patchCount} -gt ${activeCount} ]; then
                LOG "[$LINENO]Check hot patch of ${module} fail(${patch_module})"
                echo "${module}: Hot patch active fail(${patch_module})" >>${RESULTFILE} 2>&1
            fi
        done
        local deact_list="OceanStor_9000_V5_7.1.1.SPH3nas_proto_vfs.patch:V500R007C00SPH3vfs1"
        deact_list="${deact_list} OceanStor_9000_V5_7.1.1.SPH21nas_proto_vfs.patch:V500R007C00SPH21vfs1"
        #特殊处理OceanStor_9000_V5_7.1.1.SPH3nas_proto_vfs.patch补丁 V500R007C00SPH3vfs1
        for deact_patch in $deact_list;do
            local patchname=$(echo $deact_patch | awk -F':' '{print $2}')
            local patchfile=$(echo $deact_patch | awk -F':' '{print $1}')
            livepatch -q${patchname} | grep "^Patch State" | grep -q "Active" >/dev/null 2>&1
            if [  $? -eq 0 ];then
                echo "The ${patchfile} needs to be deactivated!" >>${RESULTFILE} 2>&1
            fi
        done

    fi

    if [ -f "${PATCH_FILE_LIST}" ];then
        rm -rf "${PATCH_FILE_LIST}"
    fi
    return 0
}

function get_sha256sum()
{
    local file_tmp=$1
    local shasum=""
    if [ "X$file_tmp" != "X" ] && [ -f $file_tmp ];then
        shasum=$(sha256sum $file_tmp 2>&1 | awk '{print $1}')
    fi
    echo $shasum
}

function check_snas_cm()
{
    #SPH103 SPH201
    local shasum_sph=""
    local shasum_cm=""
    local std_shasum="d3364f6420b7dfdcb950b93c7ddc0073c0a3693b7ccc5fb46c3213ca985c24fa"
    local snas_cm="/opt/huawei/snas/bin/snas_cm"
    local sph201="/var/huawei/patch/cur/sph/OceanStor_9000_V5_7.1.1.SPH201/7.1.1/coldpatch/snas_cm"

    if [ -f ${sph201} ];then
        shasum_sph="$(get_sha256sum $sph201)"
        shasum_cm="$(get_sha256sum $snas_cm)"
        echo "${shasum_sph} ${shasum_cm}" | grep -qw ${std_shasum} 2>&1
        if [ $? -eq 0 ];then
            echo "Use the upd_patch_for_7.1.1.SPH201.zip tool to rectify the fault!" >>${RESULTFILE} 2>&1
        fi
    fi
}

hppath=$(get_patch_path)
if [ -d "${hppath}" ];then
    check_patch ${hppath}
fi

arch_tmp=$(arch)
if [ $arch_tmp == "aarch64" ];then
    check_snas_cm
fi

