#!/bin/bash
# set -x

function wait_other() {
    local cmd=$1
    for i in {0..30};do
        ps -e|grep -q $cmd
        if [[ $? -ne 0 ]];then
            return 0
        fi
        sleep 1
    done
    error_quit "other '$cmd' still running"
}

function get_cache() {
    local cmd=$@
    local pname=$(basename $(echo "$1"|awk '{print $1}'))
    local cache_name="monitor_"`echo $*|tr ' ' '_'|tr '/' '_'|sed 's/[:,]//g'`
    local cache_file=/dev/shm/$cache_name
    local cache_time='0'
    local code=0

#    有几个内核进程nvme，ps -e 无法区分，ps -ef怕卡住
#    wait_other $pname

    if [[ -f $cache_file ]];then
        cache_time=`stat -c %Z $cache_file`
    fi
    if [[ $(($(date +%s) - $cache_time)) -gt 300 ]];then
        $cmd > $cache_file
        code=$?
    fi
    cat $cache_file

    return $code
}


function error_quit() {
    echo "$1" > /dev/null 2>&1
    exit 1
}

# detect vm
function detect_vm() {
    `cat /proc/cpuinfo | grep 'flags' | grep -q 'hypervisor'`
    if [ $? -eq 0 ]; then
        error_quit "Not Support VM"
    fi
}

function check_cmd_exist() {
    local cmd=$1
    type $cmd > /dev/null 2>&1 || {
        echo >&2 "require command [$cmd] but it's not installed. Aborting."
        exit 1
    }
}

function collect_nvme_info() {
    detect_vm

    check_if_nvme_ssd=`ls /dev/nvme[0-9*]n1 > /dev/null 2>&1`
    if [ $? -eq 0 ]; then
        nvme_ssd_collect $@
    else
        error_quit "No NVME SSD here"
    fi
}

CMD_NVME="get_cache /usr/sbin/nvme"

function join_string() {
    local arr=("${!2}")
    local result=$(printf "$1%s" "${arr[@]}")
    result=${result:1}
    echo -n $result
}

function get_value() {
    local ori_str="$1"
    local trim_cmd="awk"
    if [ $# -gt 1 ] && [ "$2" != " " ]; then
        trim_cmd="$trim_cmd -F$2"
    fi

    local result=$($trim_cmd '{
        gsub(/^[ \t]+/, "", $2);
        gsub(/[ \t]+$/, "", $2);
        print $2}' <<< "$ori_str")
    echo -n $result
}

function nvme_ssd_status() {
    local flag=$1
    local nvmes=$(get_nvmes)
    local status=()
    local PCIE="NVME"
    local i=0

    for nvme in ${nvmes[@]}; do
        local nvme_info=$($CMD_NVME smart-log $nvme)
        local nvmestatus
        case "$flag" in
            critical_warning)
                nvmestatus=$(get_value "$(grep "critical_warning" <<< "$nvme_info")" ":")
                ;;
            temperature)
                nvmestatus=$(grep "temperature" <<< "$nvme_info" | awk '{print $3}')
                ;;
            available_spare)
                nvmestatus=`echo $(get_value "$(grep -w "available_spare" <<< "$nvme_info")" ":") | awk -F"%" '{print $1}'`
                ;;
            percentage_used)
                nvmestatus=`echo $(get_value "$(grep "percentage_used" <<< "$nvme_info")" ":") | awk -F"%" '{print $1}'`
                ;;
            media_errors)
                nvmestatus=$(get_value "$(grep "media_errors" <<< "$nvme_info")" ":")
                ;;
            *)
                exit 1
                ;;
            esac
        if [ -z "$nvmestatus" ]; then
            continue
        fi
        status[i]='{"value": '$nvmestatus', "tags": "pcie_type='$PCIE',nvme_device='$nvme'"}'
        ((i++))
    done

    local laststatus=$(join_string "," status[@])
    echo -n "[$laststatus]"
}

function get_nvmes() {
    local result=$($CMD_NVME list|grep -v udisk|grep '\/dev'|awk '{print $1}')
    echo -n $result
}

function nvme_ssd_collect() {
    check_cmd_exist $CMD_NVME
    
    while getopts m: o; do
        case "$o" in
            m)
                local opt=$OPTARG
                nvme_ssd_status $opt
                ;;
            *)
                exit 1
                ;;
            esac
        done
}

collect_nvme_info $@
