#!/usr/bin/bash
ASCEND_SECLOG="/var/log/ascend_seclog"
logFile="${ASCEND_SECLOG}/ascend_install.log"
runLogFile="${ASCEND_SECLOG}/ascend_run_servers.log"
installInfo="/etc/ascend_install.info"
ASCEND_DRIVER_CFG_FILE="/etc/ascend_driver.conf"
KMSAGENT_CONFIG_ITEM="kmsagent"
username=HwHiAiUser
usergroup=HwHiAiUser
hotreset_status_file="/var/log/hotreset_status.log"
preinst_flag_first_file="/var/log/ascend_preinst_first_flag"

occupy_space=300

OPERATION_LOGDIR="${ASCEND_SECLOG}"
OPERATION_LOGPATH="${OPERATION_LOGDIR}/operation.log"
LOG_OPERATION_INSTALL="Install"
LOG_OPERATION_UPGRADE="Upgrade"
LOG_OPERATION_UNINSTALL="Uninstall"
LOG_LEVEL_SUGGESTION="SUGGESTION"
LOG_LEVEL_MINOR="MINOR"
LOG_LEVEL_UNKNOWN="UNKNOWN"
LOG_RESULT_FAILED="failed"
# the two are both for secure-install-path
first_time_install_drv_flag="NA"
old_drv_install_path="NA"
install_for_all="no"
native_pkcs_conf=""

# pkg arch
PKG_ARCH="UNKNOWN"

SHELL_DIR=$(cd "$(dirname "$0")" || exit; pwd)
COMMON_SHELL="$SHELL_DIR/common.sh"
if [ -e ${COMMON_SHELL} ]; then
    source "${COMMON_SHELL}"
fi

export input_install_for_all=n
export native_pkcs_conf

install_info_key_array=("Driver_Install_Type" "UserName" "UserGroup" "Driver_Install_Path_Param" "Firmware_Install_Path_Param" "Firmware_Install_Type"
                        "Driver_Install_For_All" "Driver_Install_Mode")

function setFileChmod() {
    local option="$1"
    local mod="$2"
    local file_path="$3"

    if [ ${input_install_for_all} == y ]; then
        local mod=${mod:0:-1}${mod: -2:1}
    fi

    chmod ${option} "${mod}" "${file_path}" >& /dev/null
    if [ $? -ne 0 ]; then
        echo "[ERROR]chmod ${mod} $file_path failed!"
        exit 1
    fi
}

function createFile() {
    local _file=$1
    if [ -e "${_file}" ]; then
        rm -f "${_file}"
    fi
    touch "${_file}"
    chown -h "$2" "${_file}"
    setFileChmod -f "$3" "${_file}"
    if [ $? -ne 0 ]; then
        return 1
    fi
    return 0
}

function getInstallParam() {
    local _key="$1"
    local _file="$2"
    local _param

    if [ ! -f "${_file}" ];then
        exit 1
    fi

    # deal with abnormal install-cfg file.
    # when install-cfg file is abnormal, command 'grep' can not be used but 'sed' does.
    local normal_args
    grep -r "${_key}" "${_file}" | grep -q '='
    if [ $? -ne 0 ]; then
        normal_args=$(sed -n '/=/p' ${_file})
        echo "${normal_args}" > ${_file}
    fi

    for key_param in "${install_info_key_array[@]}"; do
        if [ ${key_param} == ${_key} ]; then
            _param=`grep -r "${_key}=" "${_file}" | cut -d"=" -f2-`
            break;
        fi
    done
    echo "${_param}"
}

function crossVersion() {
    if [ -f /etc/HiAI_install.info ]; then
        . /etc/HiAI_install.info
        if [ -z $Install_Path_Param ]; then
            drvEcho "[ERROR]ERR_NO:0x0094;ERR_DES:Operation failed, An all-in-one RUN package is found, which needs to be uninstalled before proceeding."
        else
            drvEcho "[ERROR]ERR_NO:0x0094;ERR_DES:Operation failed, An all-in-one RUN package is found in $Install_Path_Param, which needs to be uninstalled before proceeding."
        fi
        exit
    fi
}

function log() {
   cur_date=`date +"%Y-%m-%d %T"`
   user_id=`id | awk '{printf $1}'`
    echo "[Driver] [$cur_date] [$user_id] "$1 >> $logFile
}

function drvEcho() {
    cur_date=`date +"%Y-%m-%d %T"`
    echo "[Driver] [$cur_date] $1"
}

function drvColorEcho() {
    cur_date=`date +"%Y-%m-%d %T"`
    echo -e  "[Driver] [$cur_date] $1"
}

function get_kmsagent_config() {
    if [ $kmsagent_is_enable = y ];then
        return 0
    fi

    if [ -f $ASCEND_DRIVER_CFG_FILE ];then
        local kms_config_txt=`grep -r "${KMSAGENT_CONFIG_ITEM}=" "${ASCEND_DRIVER_CFG_FILE}" | cut -d"=" -f2-`
        if [ "${kms_config_txt}X" = "enableX" ];then
            kmsagent_is_enable=y
        fi
    fi
}

function exitLog() {
    cur_date=`date +"%Y-%m-%d %T"`
    drvEcho "[INFO]End time: ${cur_date}"
    drvEcho "[INFO]End time: ${cur_date}" >> $logFile
    exit $1
}

function errorUsage() {
    if [ $# -eq 1 ]; then
        drvEcho "[ERROR]ERR_NO:0x0004;ERR_DES: Unrecognized parameters: ${1}. Try './xxx.run --help' for more information."
        exitLog 1
    elif [ $# -eq 2 ]; then
        log "$2"
        drvEcho "$2"
        exitLog "$1"
    else
        drvEcho "[ERROR]ERR_NO:0x0004;ERR_DES: Unrecognized parameters. Try './xxx.run --help' for more information."
        exit 1
    fi
}

# LogFile polling and backup
function rotateLog() {
    echo "${logFile} {
        su root root
        daily
        size=5M
        rotate 3
        missingok
        create 440 root root
    }" > /etc/logrotate.d/ascend-install
}

function startLog() {
    cur_date=`date +"%Y-%m-%d %T"`
    drvEcho "[INFO]Start time: $cur_date"
    drvEcho "[INFO]Start time: $cur_date" >> $logFile
}

# support absolute path and relative path
function getAbsolutePath(){

    local current_path="${PWD}" parent_dir=""
    flag1=$(echo "${Install_Path_Param:0:3}" |grep "\./")''$(echo "$Install_Path_Param" |grep "~/")''$(echo "$Install_Path_Param" |grep "/\.")
    flag2=$(echo "${Install_Path_Param:0:1}" |grep "/")

    if [ -z $flag1  ] && [  -z $flag2  ]; then
        errorUsage 1 "[ERROR]ERR_NO:0x0003;ERR_DES:install-path input error, install failed"
    fi
    if [ ! -z $flag1 ];then
        cd "$runPackagePath" >& /dev/null
        log "[INFO]enter runPackagePath:$runPackagePath"

        eval "cd ${Install_Path_Param}" >& /dev/null
        if [ $? -ne 0 ]; then
            # get parent directory
            parent_dir=`dirname "${Install_Path_Param}"`
            log "[INFO]parent_dir value is [${parent_dir}]"

            eval "cd ${parent_dir}" >& /dev/null
            if [ $? -eq 0 ]; then
                cd - >& /dev/null
                eval "mkdir ${Install_Path_Param}" >& /dev/null
                if [ $? -ne 0 ]; then
                    log "[ERROR][${parent_dir}] is invalid."
                    drvEcho "[ERROR]Relative path $Install_Path_Param doesn't exist, please input a valid path"
                    exitLog 1
                else
                    log "[INFO]create dir [${Install_Path_Param}] success."
                    setFileChmod -f 755 ${Install_Path_Param}
                    eval "cd ${Install_Path_Param}" >& /dev/null
                fi
            else
                log "[ERROR][${parent_dir}] is invalid."
                drvEcho "[ERROR]Relative path $Install_Path_Param doesn't exist, please input a valid path"
                exitLog 1
            fi
        fi

        log "[INFO]enter Install_Path_Param=$Install_Path_Param, pwd: $PWD "
        Install_Path_Param="${PWD}"
        cd "${current_path}" >& /dev/null

        log "[INFO]current path: $PWD"
    fi
    log "[INFO]Install_Path_Param=$Install_Path_Param"
}

# check if the installation path is valid
function isValidPath() {
    makeDefaultPath=n
    if [ "$input_install_path" = "" ]; then
        if [ -f $installInfo ]; then
            Driver_Install_Path_Param=$(getInstallParam "Driver_Install_Path_Param" "${installInfo}")
            if [ ! -z "$Driver_Install_Path_Param" ]; then
                Install_Path_Param="$Driver_Install_Path_Param"
            fi
        fi
    else
        Install_Path_Param="${input_install_path}"
    fi

    getAbsolutePath
    if [ ! -d "$Install_Path_Param" ]; then
        if [ "$Install_Path_Param" = "/usr/local/Ascend" ]; then
            mkdir -p "$Install_Path_Param"
            setFileChmod -f 755 "$Install_Path_Param"
            makeDefaultPath=y
        else
            parentPath=`dirname "$Install_Path_Param"`
            if [ ! -d "$parentPath" ];then
                errorUsage 1 "[ERROR]ERR_NO:0x0003;ERR_DES:install path $parentPath not exists,runpackage only support create one level of directory,need create $parentPath."
            fi
            su - "$username" -s /bin/bash -c "test -x $parentPath"
            if [ $? -ne 0 ]; then
                errorUsage 1 "[ERROR]ERR_NO:0x0003;ERR_DES:The $username do not have the permission to access $parentPath, please reset the directory to a right permission."
            fi
            mkdir -p "$Install_Path_Param"
            setFileChmod -f 755 "$Install_Path_Param"
            makeDefaultPath=y
        fi
    fi

    su - "$username" -s /bin/bash -c "test -x $Install_Path_Param"
    if [ $? -ne 0 ]; then
        if [ $makeDefaultPath = y ]; then
            rm -rf "$Install_Path_Param"
        fi
        errorUsage 1 "[ERROR]ERR_NO:0x0003;ERR_DES:The $username do not have the permission to access $Install_Path_Param, please reset the directory to a right permission."
    fi
    # format the installation path after checking its validity
    which realpath >/dev/null 2>&1 && Install_Path_Param=`realpath $Install_Path_Param 2>/dev/null`
}

# check env tool before installation
function checkEnvTool() {
    checkToolFile="${SHELL_DIR}/check_tools.conf"
    [ -e "${checkToolFile}" ] || return

    local strLeakTool=""
    local retCheckEnvTool="y"

    while read toolFileLine || [[ -n ${toolFileLine} ]]
    do
        # Some object only need to install one of toolFileLine
        toolA=`echo ${toolFileLine} | cut -d \, -f 1`
        toolB=`echo ${toolFileLine} | cut -d \, -f 2`
        which ${toolA} > /dev/null 2>&1 || which ${toolB} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            strLeakTool="${strLeakTool}${toolFileLine},"
            retCheckEnvTool="n"
            continue;
        fi
    done < ${checkToolFile}

    if [ "${retCheckEnvTool}"x = "n"x ]; then
        errorUsage 1 "[ERROR]The list of missing tools: ${strLeakTool}"
    fi

    return 0
}

function checkEnvFile() {
    # check /etc/pam.d/su Indicates whether to forcibly enter the password when su user
    if [ -e /etc/pam.d/su ]; then
        grep "auth" /etc/pam.d/su | grep "sufficient" |grep "pam_rootok.so" | grep -v "#" >/dev/null 2>&1
        if [ $? -ne 0 ];then
            drvEcho "[WARNING]The Root use cmd(su user) must enter the user passwd forcibly(set by /etc/pam.d/su)"
            log "[WARNING]The Root user cmd(su user) must enter the user passwd forcibly(set by /etc/pam.d/su)"
        fi
    fi
    return 0
}

function checkItems() {
    # set status of PCIe driver for first installation
    # drv_pcie_host: Physical machine
    # drv_vpcie: Compute-slicing virtual-machine
    PCIE_INSMOD_STATUS_BEFORE_INSTALL="n"
    lsmod | grep -E "drv_pcie_host|drv_vpcie" >& /dev/null && PCIE_INSMOD_STATUS_BEFORE_INSTALL="y"
    log "[INFO]PCIE_INSMOD_STATUS_BEFORE_INSTALL=${PCIE_INSMOD_STATUS_BEFORE_INSTALL}"

    checkEnvTool
    checkEnvFile
}

# check if there are multiple run processes in execution
function checkProcess(){
    name=`ps -ef | awk '$2=='$$'{print $10}'|rev|cut -d "/" -f1|rev`
    checkname=`echo "$name" | awk -F "-" '{print $1"-"$2}'`
    shellname=`echo $0 |rev |cut -d "/" -f1 |rev`
    process=`ps -ef | grep -v "grep" | grep -w "$shellname" |grep -w "${checkname}-.*.run" 2>/dev/null`
    pid=`echo "$process" | awk -F ' ' '{print $2}'`
    ret=`echo "$process" | awk -F ' ' '{print $3}' | grep -v "$pid" | wc -l`
    if [ $ret -gt 1 ]; then
        log "[INFO]$name;$shellname;$ret;$process"
        errorUsage 1 "[ERROR]ERR_NO:0x0094;ERR_DES:There is already a process being executed,please do not execute multiple tasks at the same time"
    fi
}

# check the disk space of the installation directory before installation or upgrade，driver need 300M，firmware need 32M.
function checkFreeSpace(){
    freeSpace=`df -BM "$Install_Path_Param" |awk '/[0-9]%/{print $(NF-2)}'`
    freeSpace=${freeSpace:: -1}
    log "[INFO]freeSpace:${freeSpace} freeSpace_test ${freeSpace_test} occupy_space:$occupy_space"
    if [ ${freeSpace} -le $occupy_space ];then
        errorUsage 1 "[ERROR]free space only ${freeSpace}, cannot install driver package (greater than ${occupy_space}M), please make sure enough space under the installation path"
    fi
}

# check if the user exists
function checkUser(){
    ret=`cat /etc/passwd | cut -f1 -d':' | grep -w "$1" -c`
    if [ $ret -le 0 ]; then
        return 1
    else
        return 0
    fi
}

function isExistsGroup(){
    local ret=`cat /etc/group | cut -f1 -d':' | grep -w "$1" -c`
    if [ $ret -le 0 ]; then
        return 1
    else
        return 0
    fi
}

# check the association between users and user groups
function checkGroup(){
    result=$(groups "$2" | grep ":")
    if [ "${result}X" != "X" ]; then
        group_user_related=`groups "$2"|awk -F":" '{print $2}'|grep -w "$1"`
    else
        group_user_related=`groups "$2"|grep -w "$1"`
    fi
    if [ "${group_user_related}x" != "x" ];then
        return 0
    else
        return 1
    fi
}

# check installation conditions
function checkUserAndGroup() {
    checkUser "${username}"
    if [ $? -ne 0 ];then
        errorUsage 1 "[ERROR]ERR_NO:0x0091;ERR_DES:${username} not exists! Please add ${username}"
    fi
    isExistsGroup "${usergroup}"
    if [ $? -ne 0 ];then
        errorUsage 1 "[ERROR]ERR_NO:0x0091;ERR_DES:${usergroup} group not exists! Please add ${usergroup} group"
    fi

    checkGroup "${usergroup}" "${username}"
    if [ $? -ne 0 ];then
        errorUsage 1 "[ERROR]ERR_NO:0x0096;ERR_DES:${usergroup} not right! Please check the relatianship of ${username} and ${usergroup}"
    fi
    drvEcho "[INFO]set username and usergroup, ${username}:${usergroup}"

}

function getUserInfo() {
    if [ -f ${installInfo} ]; then
        UserName=$(getInstallParam "UserName" "${installInfo}")
        UserGroup=$(getInstallParam "UserGroup" "${installInfo}")
        Driver_Install_For_All=$(getInstallParam "Driver_Install_For_All" "${installInfo}")
        if [ ${input_install_username} = y ] || [ ${input_install_usergroup} = y ]; then
            if [ "x${UserName}" = "x" ]; then
                sub_file=`echo $Install_Path_Param |awk -F"/" '{print $NF}'`
                username_cur=`ls -l "${Install_Path_Param}/../" |grep -w "${sub_file}" |awk '{print $3}'`
                if [ "x${username}" != "x${username_cur}" ]; then
                    echo "username: ${username} not equel to username_cur: ${username_cur}"
                    errorUsage 1 "[ERROR]ERR_NO:0x0095;ERR_DES:The user and group are not same with last installation,do not support overwriting installation"
                fi
            else
                if [ "x${username}" != "x${UserName}" ]; then
                    echo "username: ${username} not equel to UserName: ${UserName}"
                    errorUsage 1 "[ERROR]ERR_NO:0x0095;ERR_DES:The user and group are not same with last installation,do not support overwriting installation"
                else
                    username="${UserName}"
                fi
            fi

            if [ "x${UserGroup}" = "x" ]; then
                sub_file=`echo $Install_Path_Param |awk -F"/" '{print $NF}'`
                usergroup_cur=`ls -l "${Install_Path_Param}/../" |grep -w "${sub_file}" |awk '{print $4}'`
                if [ "x${usergroup}" != "x${usergroup_cur}" ]; then
                    echo "username: ${usergroup} not equel to usergroup_cur: ${usergroup_cur}"
                    errorUsage 1 "[ERROR]ERR_NO:0x0095;ERR_DES:The user and group are not same with last installation,do not support overwriting installation"
                fi
            else
                if [ "x${usergroup}" != "x${UserGroup}" ]; then
                    echo "username: ${usergroup} not equel to UserGroup: ${UserGroup}"
                    errorUsage 1 "[ERROR]ERR_NO:0x0095;ERR_DES:The user and group are not same with last installation,do not support overwriting installation"
                else
                    usergroup="${UserGroup}"
                fi
            fi
        fi
        if [ ${input_install_username} = n ] || [ ${input_install_usergroup} = n ]; then
            if [ "x${UserName}" != "x" ]; then
                if [ "${UserName}" = "root" ] && [ $upgrade != y ]; then
                    errorUsage 1 "[ERROR]ERR_NO:0x0091;ERR_DES:username not permission for root, check /etc/ascend_install.info"
                else
                    username="${UserName}"
                    if [ "x$Driver_Install_For_All" = "xyes" ] && [ $upgrade = y ]; then
                        install_for_all="$Driver_Install_For_All"
                        input_install_for_all=y
                    fi
                fi
            fi
            if [ "x${UserGroup}" != "x" ]; then
                if [ "${UserGroup}" = "root" ] && [ $upgrade != y ]; then
                    errorUsage 1 "[ERROR]ERR_NO:0x0091;ERR_DES:usergroup not permission for root, check /etc/ascend_install.info"
                else
                    usergroup="${UserGroup}"
                    if [ "x$Driver_Install_For_All" = "xyes" ] && [ $upgrade = y ]; then
                        install_for_all="$Driver_Install_For_All"
                        input_install_for_all=y
                    fi
                fi
            fi
        fi
    fi
}

# check if root permission
function isRoot() {
    if [ $(id -u) -ne 0 ]; then
        drvEcho "[ERROR]ERR_NO:0x0093;ERR_DES:do not have root permission, operation failed, please use root permission!"
        exit 1
    fi
}

# get the version number under the installation path (version2)
getVersionInstalled() {
    version2="none"
    if [ -f "$1"/driver/version.info ]; then
        version2=`cat "$1"/driver/version.info | awk -F '=' '$1=="Version" {print $2}'`
    fi
    echo $version2
}
# get the version number in the run package (version1)
getVersionInRunFile() {
    version1="none"
    if [ -f ./version.info ]; then
        version1=`cat version.info | awk -F '=' '$1=="Version" {print $2}'`
    fi
    echo $version1
}

function logBaseVersion() {
    if [ -f ${installInfo} ];then
        Driver_Install_Path_Param=$(getInstallParam "Driver_Install_Path_Param" "${installInfo}")
        if [ ! -z "$Driver_Install_Path_Param" ]; then
            installed_version=$(getVersionInstalled "$Driver_Install_Path_Param")
            if [ ! "${installed_version}"x = ""x ]; then
                drvEcho "[INFO]base version is ${installed_version}."
                log "[INFO]base version is ${installed_version}."
                return 0
            fi
        fi
    fi
    log "[INFO]base version was destroyed or not exist."
}

# determine whether the command returns a failure, and report an error if it fails.
# $1:Operation type, $2:ret code,   $3:(Optional)print messages
function error() {
    local operation="$1"
    local retcode="$2"
    local msg="$3"
    if [ ${retcode} -ne 0 ]; then
        logOperation "${operation}" "${start_time}" "${runfilename}" "${LOG_RESULT_FAILED}" "${installType}" "${all_parma}"
    fi

    if [ $# -eq 3 ]; then
        if [ ${retcode} -ne 0 ]; then
            drvEcho "[ERROR]${msg}"
            log "[ERROR]${msg}"
            exitLog 1
        fi
    elif [ $# -eq 2 ]; then
        if [ ${retcode} -ne 0 ]; then
            exitLog 1
        fi
    fi
}

# update /etc/ascend_install.info
function updateInstallInfo() {
    local installMode_before=""

    if [ -d "$installInfo" ]; then
        rm -rf "$installInfo"
    fi

    if [ -f "$installInfo" ]; then
        UserName=$(getInstallParam "UserName" "${installInfo}")
        UserGroup=$(getInstallParam "UserGroup" "${installInfo}")
        Driver_Install_Type=$(getInstallParam "Driver_Install_Type" "${installInfo}")
        Driver_Install_Path_Param=$(getInstallParam "Driver_Install_Path_Param" "${installInfo}")
        Driver_Install_For_All=$(getInstallParam "Driver_Install_For_All" "${installInfo}")
        if [ -z "$UserName" ]; then
            updateInstallParam "UserName" "$username" "$installInfo"
        fi
        if [ -z "$UserGroup" ]; then
            updateInstallParam "UserGroup" "$usergroup" "$installInfo"
        fi
    else
        createFile "$installInfo" "root":"root" 644
        updateInstallParam "UserName" "$username" "$installInfo"
        updateInstallParam "UserGroup" "$usergroup" "$installInfo"
    fi
    updateInstallParam "Driver_Install_Type" "$installType" "$installInfo"
    updateInstallParam "Driver_Install_Path_Param" "$Install_Path_Param" "$installInfo"
    updateInstallParam "Driver_Install_For_All" "$install_for_all" "$installInfo"
    if [ "${upgrade}" = "y" ]; then
        installMode_before="$(getInstallParam "Driver_Install_Mode" "${installInfo}")"
        if [ -z "${installMode_before}" ]; then
            updateInstallParam "Driver_Install_Mode" "${installMode}" "${installInfo}"
        else
            updateInstallParam "Driver_Install_Mode" "${installMode_before}" "${installInfo}"
        fi
    else
        updateInstallParam "Driver_Install_Mode" "${installMode}" "${installInfo}"
    fi
    setFileChmod -f 644 $installInfo
}

function backupKmsData(){
    # Backup kmsagent data to backup_data.
    if [ -f "./driver/script/kmsagent_backup_conf.sh" ]; then
        ./driver/script/kmsagent_backup_conf.sh $KMSAGENT_WORK_DIR $username $usergroup >>$logFile 2>&1
    fi
}

function parent_dirs_permision_check(){
    current_dir="$1" parent_dir="" short_install_dir=""
    local owner="" mod_num=""

    parent_dir=$(dirname "${current_dir}")
    short_install_dir=$(basename "${current_dir}")
    log "[INFO]parent_dir value is [${parent_dir}] and children_dir value is [${short_install_dir}]"

    if [ "${current_dir}"x = "/"x ]; then
        log "[INFO]parent_dirs_permision_check success"
        return 0
    else
        owner=$(stat -c %U "${parent_dir}"/"${short_install_dir}")
        if [ "${owner}" != "root" ]; then
            log "[WARNING][${short_install_dir}] permision isn't right, it should belong to root."
            return 1
        fi
        log "[INFO][${short_install_dir}] belongs to root."

        mod_num=$(stat -c %a "${parent_dir}"/"${short_install_dir}")
        mod_num=${mod_num: -3}
        if [ ${mod_num} -lt 755 ] && [ ${input_install_for_all} == n ]; then
            log "[WARNING][${short_install_dir}] permission is too small, it is recommended that the permission be 755 for the root user."
            return 2
        elif [ ${mod_num} -eq 755 ] && [ ${input_install_for_all} == n ]; then
            log "[INFO][${short_install_dir}] permission is ok."
        else
            if [ ${input_install_for_all} == n ]; then
                log "[WARNING][${short_install_dir}] permission is too high, it is recommended that the permission be 755 for the root user."
            fi
        fi
        if [ ${mod_num} -lt 750 ] && [ ${input_install_for_all} == y ]; then
             log "[WARNING][${parent_dir}/${short_install_dir}] permission is too small."
             return 2
        fi

        parent_dirs_permision_check "${parent_dir}"
    fi
}

function install_path_should_belong_to_root() {
    local ret=0

    # install drv first time
    if [ ${first_time_install_drv_flag} = "Y" ]; then
        # default dir doesn't exist or exists, but permission not correct
        if [ "${Install_Path_Param}" = "/usr/local/Ascend" ]; then
            mkdir -p "${Install_Path_Param}"
            setFileChmod -f 755 "${Install_Path_Param}"
            chown -fh root:root "${Install_Path_Param}" >& /dev/null
        fi

        parent_dirs_permision_check "${Install_Path_Param}" && ret=$? || ret=$?
        if [ ${ret} -eq 1 ]; then
            log "[ERROR][${short_install_dir}] permision not right, it should belong to root."
            drvColorEcho  "[ERROR]\033[31mThe given directory, including its parents, should belong to root, details in : $logFile \033[0m"
            return 1
        elif [ ${ret} -eq 2 ]; then
            log "[ERROR][${short_install_dir}] permission is too small."
            drvColorEcho  "[ERROR]\033[31mThe given directory, or its parents, permission is too small, details in : $logFile \033[0m"
            return 1
        fi
    fi

    return 0
}

# check whether any script size is zero or not.
function check_local_file_size() {
    local filelist="${Driver_Install_Path_Param}"/driver/script/filelist.csv
    local install_type=""

    [ -e "${filelist}" ] && [ $(stat -c %s "${filelist}") -ne 0 ] || { log "[INFO]filelist.csv doesn't exist or its size is zero." && return 1; }

    # check whether any file size is zero, if yes, it will return 1 directly.
    cd "${Driver_Install_Path_Param}" >& /dev/null
    # the full install-type and the run install-type contain the same scripts.
    [ "${Driver_Install_Type}" = "full" ] && install_type="run" || install_type="${Driver_Install_Type}"
    if stat -c %s $(grep "\.sh" "${filelist}" | grep -w "${install_type}" | awk -F [,] '{print $4}') | grep -wq "0"; then
        log "[INFO]there is a local script with zero size."
        cd - >& /dev/null
        return 1
    fi
    cd - >& /dev/null

    log "[INFO]check_local_file_size success."
    return 0
}

function exitInstallInfo() {
    drvColorEcho "[ERROR]\033[31mThe davinci nodes are occupied by some processes, please stop processes and install or uninstall again, details in : $logFile \033[0m"
    log "[ERROR]The davinci nodes are occupied by some processes, please stop processes and install or uninstall again."
    logOperation "${operation}" "${start_time}" "${runfilename}" "${LOG_RESULT_FAILED}" "${installType}" "${all_parma}"
    exitLog 1
}

function uninstallRun() {
    if [ -f "$Driver_Install_Path_Param"/driver/script/${ASCEND_DRIVER_SETUP_SCRIPT} ]; then
        "$Driver_Install_Path_Param"/driver/script/${ASCEND_DRIVER_SETUP_SCRIPT} $KMSAGENT_CONFIG_ITEM stop >> $runLogFile
    fi

    operation="${LOG_OPERATION_UNINSTALL}"
    Driver_Install_Type=$(getInstallParam "Driver_Install_Type" "${installInfo}")
    Driver_Install_Path_Param=$(getInstallParam "Driver_Install_Path_Param" "${installInfo}")
    if [ -f "$Driver_Install_Path_Param"/driver/script/specific_func.inc ]; then
        source "$Driver_Install_Path_Param"/driver/script/specific_func.inc
    fi
    if [ -f "$Driver_Install_Path_Param"/driver/script/common.sh ]; then
        source "$Driver_Install_Path_Param"/driver/script/common.sh
    fi
    [ -f /etc/pss.cfg ] && native_pkcs_conf=$(cat /etc/pss.cfg)
    # set hot reset flag
    local phyflag=""
    if [ "$force" = n ]; then
        if [ -f "$Driver_Install_Path_Param"/driver/tools/upgrade-tool ]; then
            systemd-detect-virt -v | grep "kvm" >> /dev/null 2>&1
            phyflag=$?
            timeout 20s "$Driver_Install_Path_Param"/driver/tools/upgrade-tool --device_index -1 --boot_status 2>> /dev/null | grep -v fail | grep "boot status" | grep -v "boot status:0" >> /dev/null 2>&1
            if [ $? -eq 0 ]; then
                if [ "$phyflag"x = "0"x ]; then
                    log "[INFO]VM scene, continue to uninstall the old software package."
                else
                    if checkUserDocker && setHotResetFlag ; then
                        log "[INFO]Check docker process and set hot reset flag is over, continue to uninstall the old software package."
                    else
                        exitInstallInfo
                    fi
                fi
            else
                log "[WARNING]The chip can not set the hot reset flag."
            fi
        fi
    fi
    # remove version.info
    if [ -f "$Driver_Install_Path_Param"/driver/version.info ];then
       chattr -i "$Driver_Install_Path_Param"/driver/version.info > /dev/null 2>&1
       rm -rf "$Driver_Install_Path_Param"/driver/version.info
       log "[INFO]rm -rf version.info success"
    fi
    # This is for compatibility with earlier versions.
    if [ -f "$Driver_Install_Path_Param"/host_sys_stop.sh ]; then
        "$Driver_Install_Path_Param"/host_sys_stop.sh
    fi
    if [ -f "$Driver_Install_Path_Param"/host_servers_remove.sh ]; then
        bash "$Driver_Install_Path_Param"/host_servers_remove.sh
    else
        ./host_servers_remove.sh
    fi

    # if new-install-path is the same as the old one, the original directory will not be deleted.
    export NEW_Driver_Install_Path="${Install_Path_Param}"
    uninstall_result=n
    if check_local_file_size; then
        if [ -f "$Driver_Install_Path_Param"/driver/script/run_driver_uninstall.sh ]; then
            "$Driver_Install_Path_Param"/driver/script/run_driver_uninstall.sh --uninstall "$Driver_Install_Path_Param" $force && uninstall_result=y
        fi
    fi
    if [ $uninstall_result = n ]; then
        ./driver/script/run_driver_uninstall.sh --uninstall "$Driver_Install_Path_Param" $force
        if [ $? -eq 0 ]; then
            uninstall_result=y
        else
            log "[WARNING]uninstall driver failed"
        fi
    fi

    if [ $uninstall_result = n ]; then
        drvEcho "[ERROR]ERR_NO:0x0090;ERR_DES:uninstall driver failed, details in : ${ASCEND_SECLOG}/ascend_install.log"
        logOperation "${operation}" "${start_time}" "${runfilename}" "${LOG_RESULT_FAILED}" "${installType}" "${all_parma}"
        log "[ERROR]ERR_NO:0x0090;ERR_DES:uninstall driver failed"
        exitLog 1
    fi

    if [ $uninstall_result = y ]; then
        log "[INFO]uninstall driver success"
    fi
    unset "Driver_Install_Path_Param"

}
function changeLogMode() {
    if [ ! -f $logFile ]; then
        touch $logFile
    fi
    setFileChmod -f 640 $logFile
}

function logOperation() {
    local operation="$1"
    local start_time="$2"
    local runfilename="$3"
    local result="$4"
    local install_type="$5"
    local cmdlist="$6"
    local level

    if [ "${operation}" = "${LOG_OPERATION_INSTALL}" ]; then
        level="${LOG_LEVEL_SUGGESTION}"
    elif [ "${operation}" = "${LOG_OPERATION_UPGRADE}" ]; then
        level="${LOG_LEVEL_MINOR}"
    elif [ "${operation}" = "${LOG_OPERATION_UPGRADE}" ]; then
        level="${LOG_LEVEL_MAJOR}"
    else
        level="${LOG_LEVEL_UNKNOWN}"
    fi

    if [ ! -d "${OPERATION_LOGDIR}" ]; then
        mkdir -p ${OPERATION_LOGDIR}
        setFileChmod -f 750 ${OPERATION_LOGDIR}
    fi

    if [ ! -f "${OPERATION_LOGPATH}" ]; then
        touch ${OPERATION_LOGPATH}
        setFileChmod -f 640 ${OPERATION_LOGPATH}
    fi

    if [ $upgrade = y ]; then
        echo "${operation} ${level} root ${start_time} 127.0.0.1 ${runfilename} ${result}"\
            "cmdlist=${cmdlist}." >> ${OPERATION_LOGPATH}
    else
        echo "${operation} ${level} root ${start_time} 127.0.0.1 ${runfilename} ${result}"\
            "install_type=${install_type}; cmdlist=${cmdlist}." >> ${OPERATION_LOGPATH}
    fi
}

function uniqueMode() {
    if [ ! -z $installType ]; then
        errorUsage 1 "[ERROR]ERR_NO:0x0004;ERR_DES:only support one type: full/run/docker/devel, operation failed!"
    fi
}

function updateInstallParam() {
    local _key="$1"
    local _val="$2"
    local _file="$3"

    if [ ! -f "${_file}" ]; then
        exit 1
    fi

    for key_param in "${install_info_key_array[@]}"; do
        if [ ${key_param} == ${_key} ]; then
            sed -i "/${_key}=/d" "${_file}"
            echo "${_key}=${_val}" >> "${_file}"
            break
        fi
    done
}

# mixed package handling
check_package_mix() {
    local driver_install_path_param package_name ret
    if [ -f ${installInfo} ]; then
        driver_install_path_param=$(getInstallParam "Driver_Install_Path_Param" "${installInfo}")
        package_name=$(getVersionInstalled "$driver_install_path_param")
        if [ -n "$driver_install_path_param" ]; then
            drvEcho "[INFO]This environment has installed run package $package_name, and it will now be uninstalled."
            bash "$driver_install_path_param"/driver/script/uninstall.sh
            ret=$?
            if [ ${ret} -ne 0 ]; then
                drvEcho "[WARNING]Driver uninstall failed, details in ${logFile}."
                return
            fi
        fi
    fi
}

user=`cat /etc/passwd | grep -w ^"HwHiAiUser"`
if [ "${user}" == "" ];then
    groupadd HwHiAiUser
    useradd -g HwHiAiUser -d /home/HwHiAiUser -m HwHiAiUser -s /bin/bash
    mkdir -p -m 0755 /usr/local/Ascend/
    touch /usr/local/Ascend/creatuserHwHiAiUser
fi

crossVersion

if [ ! -d "${ASCEND_SECLOG}" ]; then
    mkdir -p ${ASCEND_SECLOG}
    setFileChmod -f 755 /var/log
    setFileChmod -f 750 ${ASCEND_SECLOG}
fi

if [ -f "${installInfo}" ]; then
    setFileChmod -f 644 "${installInfo}"
    UserName=$(getInstallParam "UserName" "${installInfo}")
    UserGroup=$(getInstallParam "UserGroup" "${installInfo}")
    if [ ! -z "$UserName" ]; then
        username="$UserName"
    fi
    if [ ! -z "$UserGroup" ]; then
        usergroup="$UserGroup"
    fi
fi


runfilename="${1##*/}"
full_install=y
upgrade=n
input_install_username=n
input_install_usergroup=n
Install_Path_Param="/usr/local/Ascend"
operation="Install"
installType=""
installMode="normal"
kmsagent_is_enable=n
runPackagePath=""
driver_install_status=0
check=n
quiet=n
force=n
start_time=$(date +"%Y-%m-%d %T")
all_parma="$@"
if [ -z "$all_parma" ]; then
    errorUsage
fi

package_type=$1
if [ $1 -eq 2 ]; then
    full_install=n
    upgrade=y
    operation="Upgrade"
    package_type=$1
else
    name=$(rpm -qa | grep "Ascend.*driver" | sed 's/Ascend\(.*\)driver.*/\1/')
    if [[ $name =~ ^[0-9]{3} ]]; then
        full_install=n
        upgrade=y
        operation="Upgrade"
        package_type=2
    fi
fi

startLog
drvEcho "[INFO]LogFile: ${ASCEND_SECLOG}/ascend_install.log"
drvEcho "[INFO]OperationLogFile: ${ASCEND_SECLOG}/operation.log"
log "[INFO]UserCommand: $runfilename $all_parma"

isRoot
changeLogMode

checkProcess
logBaseVersion

if [ $upgrade = y ] || [ $full_install = y ]; then
    drvColorEcho  "[WARNING]\033[33mDo not power off or restart the system during the installation/upgrade\033[0m"
fi

get_kmsagent_config

if [ $input_install_username = y ] || [ $input_install_usergroup = y ]; then
    if [ -z $username ]; then
        errorUsage 1 "[ERROR]ERR_NO:0x0091;ERR_DES:input_install_username is empty"
    elif [ $username = "root" ] && [ ${input_install_for_all} = n ]; then
        errorUsage 1 "[ERROR]ERR_NO:0x0091;ERR_DES:username not permission for root"
    fi

    if [ -z $usergroup ]; then
        errorUsage 1 "[ERROR]ERR_NO:0x0091;ERR_DES:input_install_group is empty"
    elif [ $usergroup = "root" ] && [ ${input_install_for_all} = n ]; then
        errorUsage 1 "[ERROR]ERR_NO:0x0091;ERR_DES:usergroup not permission for root"
    fi
fi

trap "logOperation \"${operation}\" \"${start_time}\" \"${runfilename}\" \"${LOG_RESULT_FAILED}\" \"${installType}\" \"${all_parma}\";exit 1" \
INT QUIT TERM HUP
if [ $upgrade = y ]; then
    uniqueMode
    if [ -f ${installInfo} ];then
        Driver_Install_Type=$(getInstallParam "Driver_Install_Type" "${installInfo}")
        if [ -z "$Driver_Install_Type" ]; then
            installType="full"
        else
            installType="$Driver_Install_Type"
        fi
    else
        installType="full"
    fi
fi

getUserInfo
rotateLog
checkUserAndGroup
isValidPath
checkFreeSpace

# Prevent empty directories from occupying the disk space.
if [ -d /usr/local/bin/npu-smi ]; then
    rm -rf /usr/local/bin/npu-smi
fi
if [ -d /usr/local/sbin/npu-smi ]; then
    rm -rf /usr/local/sbin/npu-smi
fi

if [ -f ${installInfo} ]; then
    Driver_Install_Path_Param=$(getInstallParam "Driver_Install_Path_Param" "${installInfo}")
    # first installation scenario
    if [ -z "$Driver_Install_Path_Param" ]; then
        if [ $full_install = y ] || [ $upgrade = y ]; then
            first_time_install_drv_flag="Y"
            install_path_should_belong_to_root
            if [ $? -ne 0 ]; then
                exitLog 1
            fi
            operation="${LOG_OPERATION_INSTALL}"
        fi
    else
        first_time_install_drv_flag="N"
        if [ $full_install = y ]; then
            Driver_Install_Path=`cat /etc/ascend_install.info | grep ^"Driver_Install_Path_Param" | awk -F "=" '{print $2}'`
            Npusmi_Install_Path=`cat ${Driver_Install_Path}/driver/script/filelist.csv | grep npu-smi | awk -F ',' '{print $4}'`
            for i in ${Npusmi_Install_Path}
            do
                rm -rf "${i}"
            done
            sleep 3
            check_package_mix
            first_time_install_drv_flag="Y"
            install_path_should_belong_to_root
            if [ $? -ne 0 ]; then
              exitLog 1
            fi
            operation="${LOG_OPERATION_INSTALL}"
        # upgrade scenario 
        elif [ $upgrade = y ]; then
            install_path_should_belong_to_root
            if [ $? -ne 0 ]; then
                exitLog 1
            fi
            if [ -f ./driver/script/ver_check.sh ]; then
                ./driver/script/ver_check.sh $check $quiet || exitLog 1
            fi
            backupKmsData
            uninstallRun
            isValidPath
            #installRun "Upgrade"
            operation="${LOG_OPERATION_UPGRADE}"
        fi
    fi
else
    if [ $full_install = y ] || [ $upgrade = y ]; then
        first_time_install_drv_flag="Y"
        install_path_should_belong_to_root || exitLog 1
        operation="${LOG_OPERATION_INSTALL}"
    fi
fi

if [ $full_install = y ] || [ $upgrade = y ]; then
    checkItems
fi

installType="full"
install_path_should_belong_to_root
updateInstallInfo

[ -e "${hotreset_status_file}" ] && echo "Flag_Install_not_Uninstall" >> ${hotreset_status_file}
echo "PCIE_INSMOD_STATUS_BEFORE_INSTALL=$PCIE_INSMOD_STATUS_BEFORE_INSTALL" > $preinst_flag_first_file
echo "first_time_install_drv_flag=$first_time_install_drv_flag" >> $preinst_flag_first_file