#!/bin/bash
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
# Description: common script for dataturbo
# Create: 2022/10/12

SCRIPTNAME=$(basename $0)
CUR_DIR=$(cd "$(dirname "$0")"; pwd)

COMPONENT="dataturbo"
DATATURBO_PACKAGE_TYPE="release"
DATATURBO_LOG_DIR=/var/log/dataturbo
INFRA_DR_IDR=/var/log/dr
SCRIPT_LOG_DIR=${DATATURBO_LOG_DIR}/${COMPONENT}_script
SCRIPT_LOG="${SCRIPT_LOG_DIR}/$COMPONENT.action.log"
SYSINFO_LOG_DIR=${DATATURBO_LOG_DIR}/sysinfo

DEFAULT_USER=dataturbo
DEFAULT_GROUP=dataturbo

user_name=${DEFAULT_USER}
group_name=${DEFAULT_GROUP}

DATATURBO_PATH=/opt/oceanstor/dataturbo
DPC_PROCESS=${DATATURBO_PATH}/bin/dpc
CONF_PATH=/opt/oceanstor/dataturbo/conf
DPC_PROCESS_LOG_DIR=${DATATURBO_LOG_DIR}/dpc
PERMISSION_FTDS_LOG_DIR=750
PERMISSION_LOG_DIR=700
PERMISSION_LOG_FILE=600
PERMISSION_LOG_bak=400

DATATURBO_PID_FILE=/run/dataturbo.pid

WHITELIST_DIR="/opt/oceanstor/dataturbo/conf"
CONFIG_PATH=/opt/oceanstor/dataturbo/conf
CONFIG_BAK_PATH=/opt/oceanstor/dataturbo/conf_bak
LOGCBB_DPC_PATH=/OSM/logcbb/bak/dpc_0
FTDS_LOG_DIR=/var/log/dataturbo/ftds
MONITOR_SCRIPT_RUN_PATH=/usr/bin/dataturbo_sysinfo_monitor.sh
XNET_MONITOR_SCRIPT_RUN_PATH=/usr/bin/dataturbo_xnet_sysinfo_monitor.sh
FC_SG_RESCAN_SCRIPT_RUN_PATH=/usr/bin/dataturbo_rescan
ALARM_CONFIT_PATH=${CONFIG_PATH}/"dpc_alarm.xml"
readonly SHIM_CONF="${DATATURBO_PATH}/conf/shim_config.xml"

DPC_USER_CONF=${CONF_PATH}/dpc_user_config.xml
CGROUP_LIMIT=( 
"8,30" 
"12,50"
"20,95"
)

rpmsave_file_tag="rpmsave"
usr_config=""
new_config=""

WHITELIST_CONTENT=( 
"CentOS7,3.10.0,x86_64" 
"SLES12SP4,4.12.14,x86_64"
"SLES12SP5,4.12.14,x86_64"
"OL7,4.14.35,x86_64"
"Ubuntu20.04,5.*.*,x86_64"
"Kylin Linux Advanced ServerV10,4.19.90,aarch64"
)

function log_info()
{
    if [ -L ${SCRIPT_LOG} ]; then
        return;
    fi
    local func_name=${FUNCNAME[1]}
    if [ "$2" != "" ]; then
        func_name="$2"
    fi
    echo "[`date "+%Y-%m-%d %T"`:$$][INFO][${COMPONENT}][${0##*/}][${func_name}]:" "$1" >> ${SCRIPT_LOG} 
}

function log_error()
{
    if [ -L ${SCRIPT_LOG} ]; then
        return;
    fi
    local func_name=${FUNCNAME[1]}
    if [ "$2" != "" ]; then
        func_name="$2"
    fi
    echo "[`date "+%Y-%m-%d %T"`:$$][ERR][${COMPONENT}][${0##*/}][${func_name}]:" "$1" >> ${SCRIPT_LOG}
}

function log_warn()
{
    if [ -L ${SCRIPT_LOG} ]; then
        return;
    fi
    local func_name=${FUNCNAME[1]}
    if [ "$2" != "" ]; then
        func_name="$2"
    fi
    echo "[`date "+%Y-%m-%d %T"`:$$][WARN][${COMPONENT}][${0##*/}][${func_name}]:" "$1" >> ${SCRIPT_LOG}
}

function log_info_print()
{
    echo -e "$1"
    log_info "$1" "${FUNCNAME[1]}"
}

function log_error_print()
{
    echo -e -n "\033[31m[ERROR]\033[0m"; echo -e "$1"
    log_error "$1" "${FUNCNAME[1]}"
}

function log_warn_print()
{
    echo -e -n "\033[31m[WARN]\033[0m"; echo -e "$1"
    log_warn "$1" "${FUNCNAME[1]}"
}

function logInit()
{
    mkdir -p ${DATATURBO_LOG_DIR}/${COMPONENT}_script > /dev/null 2>&1
    if [ ! -e ${SCRIPT_LOG} ]; then
        touch ${SCRIPT_LOG}
    fi
    # 基础设施日志初始化默认会创建/var/log/dr目录，避免降权后创建失败
    mkdir -p ${INFRA_DR_IDR} > /dev/null 2>&1
    mkdir -p ${SYSINFO_LOG_DIR} > /dev/null 2>&1
    mkdir -p ${SYSINFO_LOG_DIR}/run > /dev/null 2>&1
    mkdir -p ${SYSINFO_LOG_DIR}/bak > /dev/null 2>&1
    if [ ! -e ${SYSINFO_LOG_DIR}/run/sys_info.log ]; then
        touch ${SYSINFO_LOG_DIR}/run/sys_info.log
    fi
    return 0;
}

function print_error()
{
    echo -e -n "\033[31m[ERROR]\033[0m[$(date +%Y%m%d%H%M%S)]"; echo "$1"
}

function print_warn()
{
    echo -e -n "\033[31m[WARNING]\033[0m[$(date +%Y%m%d%H%M%S)]"; echo "$1"
}

function print_debug()
{
    echo -e -n "\033[0;32;32m[DEBUG]\033[0m ";echo "$1"
}

function script_log_size_control()
{
    SCRIPT_LOG_FILE_MAX_SIZE=3072
    SCRIPT_LOG_DIR_MAX_SIZE=61440
    # 脚本日志单文件超过3M转储
    local script_run_log_size=$(du -k ${SCRIPT_LOG} | cut -f 1)
    if [[ ${script_run_log_size} -ge ${SCRIPT_LOG_FILE_MAX_SIZE} ]]; then
        mv ${SCRIPT_LOG} ${SCRIPT_LOG_DIR}/$COMPONENT.action-$(date "+%Y-%m-%d_%H-%M-%S.log")
        touch ${SCRIPT_LOG}
        chmod ${PERMISSION_LOG_FILE} ${SCRIPT_LOG}
        chown -h ${user_name}:${group_name} ${SCRIPT_LOG}
    fi

    # 脚本日志总大小超过60M进行删减
    local script_log_size=$(du -k ${SCRIPT_LOG_DIR} | cut -f 1)
    if [[ ${script_log_size} -gt ${SCRIPT_LOG_DIR_MAX_SIZE} ]]; then
        local delete_size=$((${script_log_size} - ${SCRIPT_LOG_DIR_MAX_SIZE}))
        local total_cnt=$(ls ${SCRIPT_LOG_DIR} | wc -l)
        for ((i=1; i<=${total_cnt}; i++))
        do
            delete_log_list=$(ls -rt ${SCRIPT_LOG_DIR}/* | head -$i)
            local tmp_size=$(du -skc ${delete_log_list[*]} 2>/dev/null |tail -1 | cut -f 1)
            if [[ ${tmp_size} -ge ${delete_size} ]]; then
                rm -rf ${delete_log_list[*]}
                break
            fi
        done
    fi
}

function get_dpc_pid()
{
    local retry_sleep_time=0.5
    local dpc_pid=""
    # When get dpc pid by ps cmd failed, it will be retried 3 times
    for i in {1..3}
    do
        dpc_pid=$(ps -ef | grep "$DPC_PROCESS" | grep -v grep | awk '{print $2}')
        if [ "${dpc_pid}" != "" ]; then
            break
        fi
        sleep ${retry_sleep_time}
    done

    if [ "${dpc_pid}" == "" ]; then
        log_error "get dpc pid failed."
    fi

    echo "${dpc_pid}"
}

# Call this function when config files have changed in upgrade package
function copy_old_config_to_new()
{
    # temporary method (fix me later): Overwrite the new configuration with the old one. 
    cat $usr_config > $new_config
    if [ $? -ne 0 ]; then
        log_warn "Recover $usr_config faild"
        return 1;
    fi
    log_info "Recover ${usr_config} to ${new_config} success."
    return 0
}

function recover_config_file()
{
    # When config files have changed in upgrade package, the local config file will be saved as a file with rpmsave suffix by rpm.
    list=$(find ${CONFIG_PATH}/ -name *.$rpmsave_file_tag)
    if [ ! -n "$list" ]; then
        log_warn "Can't find any config file saved by rpm"
        return 0;
    fi
    for file in $list; do
        usr_config=$file
        new_config=${file%.*}
        copy_old_config_to_new
        if [ $? -ne 0 ]; then
            return 1;
        fi
    done
    return 0
}

function create_dpc_process_log_path()
{
    if [ ! -d "${DPC_PROCESS_LOG_DIR}/run" ]; then
        mkdir -p ${DPC_PROCESS_LOG_DIR}/run
    fi
    if [ ! -d "${DPC_PROCESS_LOG_DIR}/bak" ]; then
        mkdir -p ${DPC_PROCESS_LOG_DIR}/bak
    fi
}

function prepare_logcbb_bak_dpc0()
{
    if [ ! -d ${LOGCBB_DPC_PATH} ]; then
        mkdir -p ${LOGCBB_DPC_PATH}
    fi
    chown -h ${user_name}:${group_name} ${LOGCBB_DPC_PATH} >/dev/null 2>&1
    logcbb_dpc_file=$(ls ${LOGCBB_DPC_PATH})
    for file in ${logcbb_dpc_file}; do
        chown -h ${user_name}:${group_name} ${LOGCBB_DPC_PATH}/${file}
    done

    if [ ! -d "/OSM/script" ]; then
        mkdir -p /OSM/script
    fi
    cp -af ${DATATURBO_PATH}/script/logcbb_file_ops.sh /OSM/script/
    chown -h ${user_name}:${group_name} /OSM/script/logcbb_file_ops.sh
}

function ftds_dir_permission_manage()
{
    local user=$1
    local group=$2
 
    if [ ! -d ${FTDS_LOG_DIR} ]; then
        return
    fi
 
    # change ftds log path owner
    chown -h ${user}:${group} ${FTDS_LOG_DIR}
    for ftds_dir in $(find ${FTDS_LOG_DIR} -type d); do
        chown -h ${user}:${group} ${ftds_dir}
    done
 
    for ftds_file in $(find ${FTDS_LOG_DIR} -type f); do
        chown -h ${user}:${group} ${ftds_file}
    done
 
    # chmod ftds log dir
    sudo -u ${user} -S chmod ${PERMISSION_FTDS_LOG_DIR} ${FTDS_LOG_DIR} >/dev/null 2>&1
    sudo -u ${user} -S chmod ${PERMISSION_FTDS_LOG_DIR} $(find ${FTDS_LOG_DIR} -type d) >/dev/null 2>&1
    sudo -u ${user} -S chmod ${PERMISSION_LOG_FILE} $(find ${FTDS_LOG_DIR} -type f) >/dev/null 2>&1
}

function log_dir_permission_manage()
{
    local user=$1
    local group=$2
    # change dataturbo log path owner
    chown -h ${user}:${group} ${DATATURBO_LOG_DIR}
    chown -h ${user}:${group} ${INFRA_DR_IDR}

    # change dpc log owner
    chown -h ${user}:${group} ${DPC_PROCESS_LOG_DIR}
    chown -h ${user}:${group} ${DPC_PROCESS_LOG_DIR}/run
    chown -h ${user}:${group} ${DPC_PROCESS_LOG_DIR}/bak
    chown -h ${user}:${group} ${SYSINFO_LOG_DIR}
    chown -h ${user}:${group} ${SYSINFO_LOG_DIR}/run
    chown -h ${user}:${group} ${SYSINFO_LOG_DIR}/bak
    log_path=$(ls ${DPC_PROCESS_LOG_DIR}/run)
    for file in ${log_path}; do
        chown -h ${user}:${group} ${DPC_PROCESS_LOG_DIR}/run/${file}
    done

    log_path=$(ls ${DPC_PROCESS_LOG_DIR}/bak)
    for file in ${log_path}; do
        chown -h ${user}:${group} ${DPC_PROCESS_LOG_DIR}/bak/${file}
    done

    log_path=$(ls ${SYSINFO_LOG_DIR}/run)
    for file in ${log_path}; do
        chown -h ${user}:${group} ${SYSINFO_LOG_DIR}/run/${file}
    done

    log_path=$(ls ${SYSINFO_LOG_DIR}/bak)
    for file in ${log_path}; do
        chown -h ${user}:${group} ${SYSINFO_LOG_DIR}/bak/${file}
    done

    # change dataturbo script log owner
    chown -h ${user}:${group} ${DATATURBO_LOG_DIR}/${COMPONENT}_script
    chown -h ${user}:${group} ${SCRIPT_LOG}

    # change CLI log owner
    mkdir -p ${DATATURBO_LOG_DIR}/cli_log
    chown -h ${user}:${group} ${DATATURBO_LOG_DIR}/cli_log >/dev/null 2>&1
    chown -h ${user}:${group} ${DATATURBO_LOG_DIR}/cli_log/oper.log >/dev/null 2>&1
    chown -h ${user}:${group} ${DATATURBO_LOG_DIR}/cli_log/cli.log >/dev/null 2>&1

    # chmod log file
    sudo -u ${user} -S chmod ${PERMISSION_LOG_DIR} ${DATATURBO_LOG_DIR}
    sudo -u ${user} -S chmod ${PERMISSION_LOG_DIR} ${INFRA_DR_IDR}
    sudo -u ${user} -S chmod ${PERMISSION_LOG_DIR} ${DATATURBO_LOG_DIR}/${COMPONENT}_script
    sudo -u ${user} -S chmod -R ${PERMISSION_LOG_DIR} ${DATATURBO_LOG_DIR}/dpc
    sudo -u ${user} -S chmod -R ${PERMISSION_LOG_DIR} ${DATATURBO_LOG_DIR}/cli_log >/dev/null 2>&1
    sudo -u ${user} -S chmod -R ${PERMISSION_LOG_FILE} ${DATATURBO_LOG_DIR}/cli_log/* >/dev/null 2>&1
    sudo -u ${user} -S chmod ${PERMISSION_LOG_bak} ${DATATURBO_LOG_DIR}/dpc/bak/* >/dev/null 2>&1
    sudo -u ${user} -S chmod ${PERMISSION_LOG_FILE} ${DPC_PROCESS_LOG_DIR}/run/dsware_dpc_0.log >/dev/null 2>&1
    sudo -u ${user} -S chmod ${PERMISSION_LOG_FILE} ${SCRIPT_LOG} >/dev/null 2>&1
    sudo -u ${user} -S chmod -R ${PERMISSION_LOG_DIR} ${SYSINFO_LOG_DIR}
    sudo -u ${user} -S chmod ${PERMISSION_LOG_FILE} ${SYSINFO_LOG_DIR}/run/* >/dev/null 2>&1
    sudo -u ${user} -S chmod ${PERMISSION_LOG_bak} ${SYSINFO_LOG_DIR}/bak/* >/dev/null 2>&1
}

function change_owner_of_sysinfo_monitor()
{
    rm -f ${MONITOR_SCRIPT_RUN_PATH}
    rm -f ${XNET_MONITOR_SCRIPT_RUN_PATH}
    cp -p ${DATATURBO_PATH}/script/dataturbo_sysinfo_monitor.sh /usr/bin
    cp -p ${DATATURBO_PATH}/script/dataturbo_xnet_sysinfo_monitor.sh /usr/bin
    chgrp -h "${group_name}" ${MONITOR_SCRIPT_RUN_PATH}
    chgrp -h "${group_name}" ${XNET_MONITOR_SCRIPT_RUN_PATH}
}

function change_owner_of_fc_sg_rescan()
{
    rm -f ${FC_SG_RESCAN_SCRIPT_RUN_PATH}
    cp -p ${DATATURBO_PATH}/script/dataturbo_rescan /usr/bin
    chgrp -h "${group_name}" ${FC_SG_RESCAN_SCRIPT_RUN_PATH}
}

function set_sudoers_with_drop_cache()
{
    sed -i '/'${user_name}' ALL=(root) NOPASSWD: \/opt\/oceanstor\/dataturbo\/script\/drop_caches.sh/d' /etc/sudoers
    echo ${user_name}' ALL=(root) NOPASSWD: /opt/oceanstor/dataturbo/script/drop_caches.sh' >> /etc/sudoers
}

function change_owner_of_dataturbo()
{
    group_name=$(cat ${DATATURBO_PATH}/bin/dpc_username_config.ini | grep "usergroup" | cut  -f2  -d "=")
    user_name=$(cat ${DATATURBO_PATH}/bin/dpc_username_config.ini | grep "username" | cut  -f2  -d "=")
    log_info "Get Dataturbo user_name=${user_name}, group_name=${group_name}."

    chown -h ${user_name}:${group_name} ${DATATURBO_PATH}/conf
    conf_path=$(ls ${DATATURBO_PATH}/conf/)
    for file in ${conf_path}; do
        chown -h ${user_name}:${group_name} ${DATATURBO_PATH}/conf/${file}
    done

    chown -h ${user_name}:${group_name} ${DATATURBO_PATH}/conf/config/node_config.xml
    
    sudo -u ${user_name} -S echo ${user_name} >> ${DATATURBO_PATH}/conf/whitelist
    # Copy dataturbo binaries to /usr/bin, set permissions to 550, and add affiliate groups
    rm -f /usr/bin/dataturbo
    cp ${INSTALL_BASE_DIR}/bin/dataturbo /usr/bin
    chmod 550 /usr/bin/dataturbo
    chgrp -h "${group_name}" /usr/bin/dataturbo
}

function start_to_whitelist() {
  filename="whitelist"
  cd ${WHITELIST_DIR}
  cat>$filename<<EOF
root
EOF
  chmod 600 $filename
}

function add_dev_shm_acl()
{
    username=$(cat ${DATATURBO_PATH}/bin/dpc_username_config.ini |grep username | sed -e "s/username=\([0-9A-Za-z]*\)/\1/g" | tr -d '\r')
    setfacl -m ${username}:rwx /dev/shm
    if [ $? -ne 0 ]; then
        log_warn "setfacl ${username} acl faild"
        return 1
    fi
    return 0
}

function handle_dev_shm_acl()
{
    local mod=$(stat -c '%a' /dev/shm)
    if [ ${mod:0-1} -eq 7 ] || [ ${mod:0-1} -eq 3 ]; then
        return 0
    fi

    local os_name=$(cat /etc/os-release |grep ^NAME | awk -F "=" '{print $2}' | sed 's/\"//g')
    if [ "${os_name}" == "Ubuntu" ]; then
        log_warn_print "Non root users have no permission to create files in the/dev/shm directory"
        log_warn_print "Try to execute 'chmod o+xw /dev/shm' or add the acl permission of dataturbo user for/dev/shm."
        return 0
    fi

    add_dev_shm_acl
    return $?
}

function dataturbo_permission_manage()
{
    start_to_whitelist

    handle_dev_shm_acl

    change_owner_of_dataturbo

    change_owner_of_sysinfo_monitor

    change_owner_of_fc_sg_rescan

    set_sudoers_with_drop_cache

    create_dpc_process_log_path

    ftds_dir_permission_manage ${user_name} ${group_name}

    log_dir_permission_manage ${user_name} ${group_name}

    prepare_logcbb_bak_dpc0
}

# If the log files belong to the default user(dataturbo), change the log files to the root user before uninstallation
function change_dataturbo_file_to_root()
{
    group_name=$(cat ${DATATURBO_PATH}/bin/dpc_username_config.ini | grep "usergroup" | cut  -f2  -d "=")
    user_name=$(cat ${DATATURBO_PATH}/bin/dpc_username_config.ini | grep "username" | cut  -f2  -d "=")

    if [ "${user_name}" != "${DEFAULT_USER}" ] || [ "${group_name}" != "${DEFAULT_GROUP}" ]; then
        return 0
    fi

    ftds_dir_permission_manage "root" "root"
    log_dir_permission_manage "root" "root"

    chown -h root:root ${LOGCBB_DPC_PATH} >/dev/null 2>&1
    logcbb_dpc_file=$(ls ${LOGCBB_DPC_PATH})
    for file in ${logcbb_dpc_file}; do
        chown -h root:root ${LOGCBB_DPC_PATH}/${file}
    done
}

function create_coredump_path()
{
    if [ "${DATATURBO_PACKAGE_TYPE}" == "debug" ]; then
        mkdir -p /var/crash/coredump
    fi
}

function get_os_type_online()
{
    local os_type=""
    if [ -f "/etc/oracle-release" ]; then
        if [ $(cat /etc/oracle-release | grep -c "Oracle Linux Server release 7") -ne 0 ]; then
            uVersion=$(cat /etc/oracle-release | awk -F "." '{print $2}')
	        if [ "${uVersion}" = "" ];then
                os_type="OL7U0"
            else
                os_type="OL7U${uVersion}"
            fi
        else
            log_error "This OS is not supported."
            exit 1
        fi
    elif [ -f "/etc/redhat-release" ]; then
        if [ $(cat /etc/redhat-release | grep -c -E "(Red Hat Enterprise Linux Server release 7|CentOS release 7|CentOS Linux release 7)") -ne 0 ]; then
            uVersion=$(cat /etc/redhat-release | awk -F "." '{print $2}' | awk -F " " '{print $1}')
            if [ "${uVersion}" = "" ]; then
                os_type="CentOS7U0"
            else
                os_type="CentOS7U${uVersion}"
            fi
        else
            log_error "This OS is not supported."
            exit 1
        fi
    elif [ -f "/etc/SuSE-release" ]; then
        local vernum=$(cat /etc/SuSE-release | sed -n 's/^[[:blank:]]*VERSION[[:blank:]]*=[[:blank:]]*\([0-9][0-9]*\)[[:blank:]]*$/\1/p')
        local versp=$(cat /etc/SuSE-release | sed -n 's/^[[:blank:]]*PATCHLEVEL[[:blank:]]*=[[:blank:]]*\([0-9][0-9]*\)[[:blank:]]*$/\1/p')
        local version="SLES${vernum}SP${versp}"
        if [ $(echo "${version}" | grep -c -E "SLES12SP4|SLES12SP5") -ne 0 ]; then
            os_type="${version}"
        else
            log_error "This OS is not supported. ${version}."
            exit 1
        fi
    elif [ -f "/etc/os-release" ]; then
        local name=$(cat /etc/os-release |grep ^NAME | awk -F "=" '{print $2}' | sed 's/\"//g')
        local version_id=$(cat /etc/os-release |grep ^VERSION_ID | awk -F "=" '{print $2}' | sed 's/\"//g')
        local version="${name}${version_id}"
        if [ $(echo "${version}" | grep -c -E "(Ubuntu20.04|Kylin Linux Advanced ServerV10)") -ne 0 ]; then
            os_type="${version}"
        else
            log_error "This OS is not supported. ${version}."
            exit 1
        fi
    fi

    echo "${os_type}"
}

# 检查dpc进程状态
function check_dpc_status()
{
    local retry_sleep_time=0.5
    local dpc_proc="/opt/oceanstor/dataturbo/bin/dpc"
    # When check dpc status by ps cmd failed, it will be retried 3 times
    for i in {1..3}
    do
        ps -ef | grep ${dpc_proc} | grep -v grep 1>/dev/null
        if [ $? -eq 0 ];then  # dpc is running
            return 1
        fi
        sleep ${retry_sleep_time}
    done
    return 0
}

# 检查dataturbo服务状态.
function check_srv_status()
{
    # Declare and assign separately to avoid masking return values.
    local status_in_system
    local loaded
    local active

    status_in_system=$(systemctl status dataturbo.service 2>/dev/null)
    loaded=$(echo "${status_in_system}"| grep -c "Loaded: loaded")
    active=$(echo "${status_in_system}"| grep -c "Active: active")
    if [ "$loaded" -eq "0" ] || [ "$active" -eq "0" ]; then
        return 0
    else
        log_warn_print "dataturbo.service status is active"
        return 1
    fi
}

function check_kernel_version()
{

    local os_type=""
    local cur_os_type="$(get_os_type_online)"
    local kernel_version=""
    
    for str in "${WHITELIST_CONTENT[@]}"
    do
        os_type=$(echo "${str}" | awk -F "," '{print $1}')
        kernel_version=$(echo "${str}" | awk -F "," '{print $2}')
        arch_type=$(echo "${str}" | awk -F "," '{print $3}')
        if [ $(echo "${cur_os_type}" | grep -c "${os_type}") -eq 1 ] && \
           [ $(uname -r | grep -c "${kernel_version}") -eq 1 ] && \
           [ "${arch_type}" == "$(uname -p)" ]; then
            return 0
        fi
    done

    return 1
}

# 磁盘空间检查函数
function do_check_free_space()
{
    local space_str=$(df -k "$1" | sed -n '$p')
    if [ "$space_str" = "" ]; then
        print_error "Check free space failed"
        return 1
    fi

    local free_space=$(df -k "$1" | sed -n '$p' | awk '{print $(NF-2)}')
    if [ -z "$free_space" ] || [ "$free_space" -lt "$2" ]; then
        print_error "[$1] File Directory need more disk free space, need[$(expr $2 / 1024)M], The current disk space is [$(expr ${free_space} / 1024)M]"
        return 1
    fi
}

# 内存空间检查 5G 5*1024*1024 -->5242880
function do_check_mem_space()
{
    local spaceStr=""
    if [ -z "$1" ]; then
        print_error "param error[$1]"
        return 1
    fi

    spaceStr=$(cat /proc/meminfo |awk '/MemAvailable/{print $2}')
    if [ "${spaceStr}" = "" ]; then
        print_error "get memory free space failed"
        return 1
    fi
    # 当前内存值小于阀值
    if [ "${spaceStr}" -lt "$1" ]; then
        let freeSpaceMB=$(expr "$1" / 1024)
        print_error "more memory free space need["${freeSpaceMB}"MB],The current memory size is [$(expr "${spaceStr}" / 1024)MB]"
        return 1
    fi
}

function check_logcbb_dpc_file_link()
{
    if [ -L ${LOGCBB_DPC_PATH} ]; then
        print_warn "${LOGCBB_DPC_PATH} is a link file"
        return 1
    fi

    logcbb_dpc_file=$(ls ${LOGCBB_DPC_PATH})
    for file in ${logcbb_dpc_file}; do
        if [ -L ${LOGCBB_DPC_PATH}/${file} ]; then
            print_warn "${LOGCBB_DPC_PATH}/${file} is a link file"
            return 1
        fi
    done
}

function check_log_file_link()
{
    if [ -L ${DATATURBO_LOG_DIR} ]; then
        print_warn "${DATATURBO_LOG_DIR} is a link file"
        return 1
    fi

    log_path=$(ls ${DATATURBO_LOG_DIR})
    for file in ${log_path}; do
        if [ -L ${DATATURBO_LOG_DIR}/${file} ]; then
            print_warn "${DATATURBO_LOG_DIR}/${file} is a link file"
            return 1
        fi
    done

    if [ -L ${DATATURBO_LOG_DIR}/dataturbo_script/dataturbo.action.log ]; then
        print_warn "${DATATURBO_LOG_DIR}/dataturbo_script/dataturbo.action.log is a link file"
        return 1
    fi

    if [ -L ${DATATURBO_LOG_DIR}/dpc/run ]; then
        print_warn "${DATATURBO_LOG_DIR}/dpc/run is a link file"
        return 1
    fi

    if [ -L ${DATATURBO_LOG_DIR}/dpc/run/dsware_dpc_0.log ]; then
        print_warn "${DATATURBO_LOG_DIR}/dpc/run/dsware_dpc_0.log is a link file"
        return 1
    fi

    if [ -L ${DATATURBO_LOG_DIR}/dpc/bak ]; then
        print_warn "${DATATURBO_LOG_DIR}/dpc/bak is a link file"
        return 1
    fi

    log_path=$(ls ${DATATURBO_LOG_DIR}/dpc/bak)
    for file in ${log_path}; do
        if [ -L  ${DATATURBO_LOG_DIR}/dpc/bak/${file} ]; then
            print_warn "${DATATURBO_LOG_DIR}/dpc/bak/${file} is a link file"
            return 1
        fi
    done

    log_path=$(ls ${DATATURBO_LOG_DIR}/cli_log)
    for file in ${log_path}; do
        if [ -L  ${DATATURBO_LOG_DIR}/cli_log/${file} ]; then
            print_warn "${DATATURBO_LOG_DIR}/cli_log/${file} is a link file"
            return 1
        fi
    done

    return 0
}

function check_ftds_log_link()
{
    local link_file_num=0
 
    if [ -L ${FTDS_LOG_DIR} ]; then
        print_warn "${FTDS_LOG_DIR} is a link file"
        return 1
    fi
 
    link_file_num=$(find ${FTDS_LOG_DIR} -type l | wc -l)
    if [ ${link_file_num} -ne 0 ]; then
        print_warn "${FTDS_LOG_DIR} has ${link_file_num} link file, you can input [ find ${FTDS_LOG_DIR} -type l ] to show it."
        return 1
    fi
 
    return 0
}

function check_conf_file_link()
{
    if [ -L ${DATATURBO_PATH}/conf ]; then
        print_warn "${DATATURBO_PATH}/conf is a link file"
        return 1
    fi

    filelist=$(ls ${DATATURBO_PATH}/conf)
    for file in ${filelist}; do
        if [ -L ${DATATURBO_PATH}/conf/${file} ]; then
            print_warn "${DATATURBO_PATH}/conf/${file} is a link file"
        return 1
    fi
    done

    filelist=$(ls ${DATATURBO_PATH}/conf/config)
    for file in ${filelist}; do
        if [ -L ${DATATURBO_PATH}/conf/config/${file} ]; then
            print_warn "${DATATURBO_PATH}/conf/config/${file} is a link file"
        return 1
    fi
    done

    return 0
}

# 检查文件是否存在软连接
function check_file_link()
{
    if [ -d ${FTDS_LOG_DIR} ]; then
        check_ftds_log_link
        if [ $? -ne 0 ]; then
            return 1
        fi
    fi

    if [ -d ${DATATURBO_LOG_DIR} ]; then
        check_log_file_link
        if [ $? -ne 0 ]; then
            return 1
        fi
    fi

    if [ -d ${DATATURBO_PATH}/conf ]; then
        check_conf_file_link
        if [ $? -ne 0 ]; then
            return 1
        fi
    fi

    if [ -d ${LOGCBB_DPC_PATH} ]; then
        check_logcbb_dpc_file_link
        if [ $? -ne 0 ]; then
            return 1
        fi
    fi

    return 0
}

function check_cpu_constant_tsc()
{
    cpu_tsc=$(cat /proc/cpuinfo | grep -o constant_tsc)
    if [ "${cpu_tsc}" ]; then
        return 0
    fi

    return 1
}

# 安装和升级前公共检查。
function install_check()
{
    check_kernel_version
    if [ $? -ne 0 ]; then
        print_error "This OS with kernel version{$(uname -r)} is not supported."
        return 1
    fi

    if [ ! -d /opt ]; then
        mkdir /opt
    fi
    # 磁盘空间检查函数 500M
    do_check_free_space /opt 512000
    if [ $? = "1" ]; then
        print_error "check free space failed."
        return 1
    fi

    # 内存空间检查 2G 2*1024*1024 -->2097152
    do_check_mem_space 2097152
    if [ $? = "1" ]; then
        print_error "check mem space failed."
        return 1
    fi

    if [ $(uname -p | grep -c "aarch64") -eq 0 ]; then
        check_cpu_constant_tsc
    fi

    if [ $? -ne 0 ]; then
        print_error "The cpu not support constant tsc."
        return 1
    fi

    check_file_link
    if [ $? = "1" ]; then
        print_error "dataturbo log or config file has been changed to link file."
        return 1
    fi
}

function script_tp_inject()
{
    TP_INJECT_FILE=${DATATURBO_PATH}/dataturbo_script_tp_inject
    if [ "${DATATURBO_PACKAGE_TYPE}" == "release" ] || [ ! -f ${TP_INJECT_FILE} ]; then
        return 0
    fi
    scriptName=$(cat ${TP_INJECT_FILE} | grep "script_name" | cut  -f2  -d "=")
    injectFlag=$(cat ${TP_INJECT_FILE} | grep "inject_flag" | cut  -f2  -d "=")
    sleepTime=$(cat ${TP_INJECT_FILE} | grep "sleep_time" | cut  -f2  -d "=")
    returnValue=$(cat ${TP_INJECT_FILE} | grep "return_value" | cut  -f2  -d "=")
    
    callTpScript=${1##*/} # the script name of calling script_tp_inject
    if [ "${scriptName}" != "${callTpScript}" ]; then
        return 0
    fi

    if [ "$2" != "" ] && [ "${injectFlag}" != "$2" ]; then
        return 0
    fi

    if [ ${sleepTime} -gt 0 ]; then
        sleep ${sleepTime}
    fi

    return ${returnValue}
}

function set_cpu_limit()
{
    if [ ! -f "${DPC_USER_CONF}" ]; then
        print_error "${DPC_USER_CONF} is not exsit, please reinstall."
        exit 1
    fi

    sed -i "s/<DpcCgroupLimitCPU min=\"1\" max=\"95\">[0-9]*<\/DpcCgroupLimitCPU>/<DpcCgroupLimitCPU min=\"1\" max=\"95\">$1<\/DpcCgroupLimitCPU>/g" "${DPC_USER_CONF}" >/dev/null 2>&1
}

function set_mem_limit()
{
    if [ ! -f "${DPC_USER_CONF}" ]; then
        print_error "${DPC_USER_CONF} is not exsit, please reinstall."
        exit 1
    fi

    sed -i "s/<DpcCgroupLimitMemory min=\"4\" max=\"20\">[0-9]*<\/DpcCgroupLimitMemory>/<DpcCgroupLimitMemory min=\"4\" max=\"20\">$1<\/DpcCgroupLimitMemory>/g" "${DPC_USER_CONF}" >/dev/null 2>&1
}

function set_cgroup_limit_conf()
{
    local str=${CGROUP_LIMIT[$1-1]}
    local memory=$(echo "${str}" | awk -F "," '{print $1}')
    local cpu=$(echo "${str}" | awk -F "," '{print $2}')

    set_cpu_limit ${cpu}
    set_mem_limit ${memory}
    log_info "set cpu[${cpu}%] and memory[${memory}GB] limit OK."
}

function check_and_set_cgroup_limit_conf()
{
    local dpc_level_val=$(cat ${SHIM_CONF} | grep DpcLevelVal)
    dpc_level_val=${dpc_level_val#*>}
    dpc_level_val=${dpc_level_val%%<*}

    log_info "current level val ${dpc_level_val}."
    if [ "${dpc_level_val}" != "1" ] && [ "${dpc_level_val}" != "2" ] && [ "${dpc_level_val}" != "3" ];then
        return
    fi

    set_cgroup_limit_conf ${dpc_level_val}
}

function check_is_uuid()
{
    local uuid=$1
    if [[ $uuid =~ ^\{?[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}\}?$ ]]; then
        return 0
    else
        return 1
    fi
}

function check_is_valid_uuid()
{
    local uuid=$1
    local substring='0000'
    if [[ $uuid == *${substring}* ]]; then
        return 1
    else
        return 0
    fi
}