#!/bin/bash

function cpu_check() {
    local check_ip=$1
    local req_cpus=$REQ_CPUS
    local cpus=$(ssh root@$check_ip "lscpu | awk '/^CPU\(s):/{print \$2}'")
    if [[ -n ${req_cpus} && -n ${cpus} ]]; then
        if [[ $(awk 'BEGIN{print('"$cpus"'<'"$req_cpus"')?0:1}') -eq 0 ]]; then
            log_error "[$check_ip] 运行环境：$RUNENV, CPU 核心数要求：$req_cpus core, 实际CPU核心数：$cpus core, 不符合运行要求"
            exit 10
        else
            log_info "[$check_ip] 运行环境：$RUNENV, CPU 核心数要求：$req_cpus core, 实际CPU核心数：$cpus core"
        fi
    else
        log_error "[$check_ip]: 获取宿主机cpu核心数失败"
    fi
}

function mem_check() {
    local check_ip=$1
    local mem_total=$(ssh root@$check_ip "cat /proc/meminfo | awk '/MemTotal:/{print \$2\$3}'")
    local mem_gb=$(unit_convert $mem_total)
    local req_mem=${REQ_MEM:0:-1}
    if [[ -n ${req_mem} && -n ${mem_gb} ]]; then
        if [[ $(awk 'BEGIN{print('"$mem_gb"'<'"$req_mem"')?0:1}') -eq 0 && $(awk 'BEGIN{print('"$mem_gb"'-'"$req_mem"'<=-1)?0:1}') -eq 0 ]]; then
            log_error "[$check_ip] 运行环境：$RUNENV, 内存大小要求：${req_mem}gb, 实际内存大小：${mem_gb}gb, 不符合运行要求"
            exit 11
        else
            log_info "[$check_ip] 运行环境：$RUNENV, 内存大小要求：${req_mem}gb, 实际内存大小：${mem_gb}gb"
        fi
    else
        log_error "[$check_ip]: 获取宿主机内存失败"
    fi
}

function disk_iops_test() {
    local check_ip=$1
    local disk=$2
    local iops=$(ssh root@$check_ip "fio -filename=${disk}/fio.txt -direct=1 -iodepth 6 -thread -rw=write -ioengine=psync -bs=4k -size=5G -numjobs=8 -runtime=30 -group_reporting -name=mytest | grep IOPS | awk -F'IOPS=|,' '{print \$2}' && rm -f ${disk}/fio.txt")
    local iops=$(iops_unit_convert $iops)
    local req_mid_disk_iops=${REQ_MID_DISK_IOPS:0:-1}
    if [[ -n ${req_mid_disk_iops} && -n ${iops} ]]; then
        if [[ $(awk 'BEGIN{print('"$iops"'<'"$req_mid_disk_iops"')?0:1}') -eq 0 ]]; then
            log_error "[$check_ip] 运行环境：$RUNENV, 磁盘iops最低要求：${req_mid_disk_iops}k, 实际测试磁盘iops：${iops}k, 不符合运行要求"
            exit 12
        else
            log_info "[$check_ip] 运行环境：$RUNENV, 磁盘iops最低要求：${req_mid_disk_iops}k, 实际测试磁盘iops：${iops}k"
        fi
    else
        log_error "[$check_ip]: 测试主机磁盘 $disk iops 失败"
    fi
}

function iops_unit_convert() {
    typeset -l size
    size=$1
    to_k=$(echo $size | awk '{
            if($1 ~ /k$/){
                sub(/k$/,"");
                print $1
            } else {
                print $1/1000
            }
        }')
    echo $to_k
}

function disk_partation_size_check() {
    local check_ip=$1
    local check_partation=$2
    local req_size=$3
    local mounted=
    local mounted_avail=


    for (( ; ; )); do
        mounted=$(mounted_match $check_ip $check_partation)
        if [ $? -ne 0 ]; then
            check_partation=${check_partation%/*}
            if [ "$check_partation"x == "x" ]; then
                check_partation="/"
            fi
            continue
        fi
        break
    done
    log_info "检测到目录 $2, 使用的挂载分区为: $mounted"

    mounted="${mounted//\//\\\\\\/}"
    mounted_avail=$(ssh root@$check_ip "df -h | awk '\$NF ~ /^'"$mounted"'$/{print \$(NF-2)}'")
    mounted_avail=$(unit_convert $mounted_avail)
    req_size=${req_size:0:-1}
    mounted_avail=${mounted_avail:0:-1}
    if [[ -n ${req_size} && -n ${mounted_avail} ]]; then
        if [[ $(awk 'BEGIN{print('"$mounted_avail"'<'"$req_size"')?0:1}') -eq 0 ]]; then
            log_error "[$check_ip] 运行环境：$RUNENV, 查看目录空间：$check_partation, 磁盘空间要求：${req_size}g, 实际可用空间：${mounted_avail}g, 不符合运行要求"
            exit 13
        else
            log_info "[$check_ip] 运行环境：$RUNENV, 查看目录空间：$check_partation, 磁盘空间要求：${req_size}g, 实际可用空间：${mounted_avail}g"
        fi
    else
        log_error "[$check_ip]: 获取主机磁盘空间失败"
    fi

}

function mounted_match() {
    local check_ip=$1
    local check_dir=
    local match_dir=

    if [ "${2}"x != "/x" ]; then
        check_dir=$(echo $2 | sed 's/\/$//')
    else
        check_dir="/"
    fi
    check_dir="${check_dir//\//\\\\\\/}"
    match_dir=$(ssh root@$check_ip "df -h | awk '\$NF ~ /^\//{print \$NF}' | awk '\$1 ~ /^'"$check_dir"'$/'")
    if [ -z $match_dir ]; then
        return 1
    fi
    echo $match_dir
    return 0
}

function unit_convert() {
    typeset -l size
    size=$1
    to_gb=$(echo $size | awk '{
            if ($1 ~ /pb$/ || $1 ~ /p$/){
                print $1 * 1024 * 1024
            } else if ($1 ~ /tb$/ || $1 ~ /t$/){
                print $1 * 1024
            } else if ($1 ~ /gb$/ || $1 ~ /g$/){
                print $1
            } else if ($1 ~ /mb$/ || $1 ~ /m$/){
                print $1/1024
            } else if ($1 ~ /kb$/ || $1 ~ /k$/){
                print $1/1024/1024
            } else if ($1 ~ /b$/){
                print $1/1024/1024/1024
            }
        }')
    echo $to_gb
}

function hardware_perfcheck() {
    ## 设置内存和磁盘的单位注意是g(或G)，不是gb(GB)，不要转换为m之类的，这地方没做校验
    if [ "${RUNENV}"x == "test"x ]; then
        REQ_CPUS=8
        REQ_MEM=16g
        REQ_MID_DISK_IOPS=1k
    elif [ "${RUNENV}"x == "prod"x ]; then
        REQ_CPUS=16
        REQ_MEM=32g
        REQ_MID_DISK_IOPS=6k
    fi
    REQ_SYS_ROOT=25g
    REQ_DOCKER_ROOT=80g

    if [ "${TYPE}" == "cluster" ]; then
        for ip in $WorkNode01 $WorkNode02 $WorkNode03; do
            log_info "${ip}: start hardware perf check..."
            cpu_check $ip
            mem_check $ip
            log_info "${ip}: 检测宿主机根目录：/ 存储空间大小..."
            disk_partation_size_check $ip "/" $REQ_SYS_ROOT
            log_info "${ip}: 检测docker root目录：$DOCKER_DATA_ROOT存储空间大小..."
            disk_partation_size_check $ip $DOCKER_DATA_ROOT $REQ_DOCKER_ROOT
            disk_iops_test $ip $BASE_DIR
        done
        
    elif [ "${TYPE}" == "allinone" ]; then
        ip="${ONE_IP}"
        log_info "${ip}: start hardware perf check..."
        cpu_check $ip
        mem_check $ip
        log_info "${ip}: 检测宿主机根目录：/ 存储空间大小..."
        disk_partation_size_check $ip "/" $REQ_SYS_ROOT
        log_info "${ip}: 检测docker root目录：$DOCKER_DATA_ROOT存储空间大小..."
        disk_partation_size_check $ip $DOCKER_DATA_ROOT $REQ_DOCKER_ROOT
        disk_iops_test $ip $BASE_DIR
        
    fi
    

    #middleware_data_path_create
    log_info "测试中间件存储路径：$BASE_DIR 的iops"
    if [[ $BASE_DIR =~ ^/dev || $BASE_DIR =~ ^/boot ]];then
        log_error "不能设置中间件存储路径BASE_DIR在 /dev或/boot下"
        exit
    fi

    log_info "测试NAS是否满足安装权限"
    [ -d "$BASE_DIR" ] && touch $BASE_DIR/nas_perm.test
    if [ $? -ne 0 ];then
        log_error "不能在$BASE_DIR创建测试文件，请确认是否挂载nas或目录是否存在"
        exit
    fi
    chown 999.999 ${BASE_DIR}/nas_perm.test
    if [ $(ls -nd ${BASE_DIR}/nas_perm.test | awk '$3==999&&$4==999{print "ok"}')x == "okx"  ];then
        log_info "nas 存储权限测试成功，满足中间件安装需求"
        rm -f $BASE_DIR/nas_perm.test
    else
        log_error "nas 存储权限测试失败，无法进行文件权限更改，不满足中间件安装"
        rm -f $BASE_DIR/nas_perm.test
        exit
    fi
}

