#!/bin/bash

LIB_DIR="$( realpath "$(dirname "$(realpath "$0")")/../../eehyp-tools" )"
if [[ -e "$LIB_DIR/common" ]]; then
    # shellcheck source=/dev/null
    source "$LIB_DIR/common"
else
    echo "Failed to load eehyp-tools common lib"
    exit 1
fi

function usage () {
    ERROR="$1"
    EXIT_CODE=0
    if [[ -n "$ERROR" ]]; then
        echo "$ERROR"
        echo
        EXIT_CODE=3
    fi
    cat << EOF
Usage : $0 [-d] [-h] [options]
    -r hyp_reserved_mem     Specify hypervisor reserved memory (in Mio, default: ${HYP_RESERVED_MEMORY}Mio)
    -w warning_mem_ratio    Warning threshold ratio of allocated memory (default: ${CLUSTER_WARNING_ALLOCATED_MEMORY_PERC}%)
    -c critical_mem_ratio   Critical threshold ratio of allocated memory (default: ${CLUSTER_CRITICAL_ALLOCATED_MEMORY_PERC}%)
    -W warning_cpu_ratio    Warning threshold ratio of allocated vCPU (default: ${WARNING_CPU_THRESHOLD}%)
    -C critical_cpu_ratio   Critical threshold ratio of allocated vCPU (default: ${CRITICAL_CPU_THRESHOLD}%)
    -d                      Debug mode
    -h                      Show this message
EOF
    exit $EXIT_CODE
}

DEBUG=0
while getopts "hr:w:c:d" OPTION; do
    case $OPTION in
        r)
            HYP_RESERVED_MEMORY=$OPTARG
        ;;
        w)
            WARNING_CPU_THRESHOLD=$OPTARG
        ;;
        c)
            CRITICAL_CPU_THRESHOLD=$OPTARG
        ;;
        d)
            # shellcheck disable=SC2034
            DEBUG=1
        ;;
        h)
            usage
        ;;
        \?)
            usage "Invalid option $OPTION"
    esac
done

TOTAL_CLUSTER_VM=0
TOTAL_CLUSTER_ALLOCATED_VCPU=0
TOTAL_CLUSTER_ALLOCATED_MEMORY=0

TOTAL_CLUSTER_MEMORY=0
TOTAL_CLUSTER_ALLOCABLE_MEMORY=0
TOTAL_CLUSTER_VCPU=0

HYP_MAX_ALLOCABLE_MEMORY=0
HYP_MAX_CPU=0

for hyp in $HYPS; do
    # Retrieve hyp VM allocated resources
    debug "Retrieve $hyp VMs allocated resources"
    HYP_VM=0
    HYP_ALLOCATED_CPU=0
    HYP_ALLOCATED_MEMORY=0
    set_newline_ifs
    for line in $( ssh "$hyp" pgrep -f '\(qemu-system\|/usr/bin/kvm\)' -a ); do
        # shellcheck disable=SC2001
        NAME=$( sed 's/^.* -name \([^ ]*\) .*$/\1/' <<< "$line" | sed 's/guest=\([^,]*\),.*/\1/' )
        (( HYP_VM+=1 ))

        # Retrieve allocated memories
        # shellcheck disable=SC2001
        ALLOCATED_MEMORY=$( sed 's/^.* -m \([0-9]*\) .*$/\1/' <<< "$line" )
        (( HYP_ALLOCATED_MEMORY+=ALLOCATED_MEMORY ))

        # Retrieve allocated CPU
        # shellcheck disable=SC2001
        VCPU=$( sed 's/^.* -smp \([0-9]*\),.*$/\1/' <<< "$line" )
        (( HYP_ALLOCATED_CPU+=VCPU ))
        debug "VM $NAME => Mem=$ALLOCATED_MEMORY / vCPU=$VCPU"
    done
    restore_ifs

    debug "Total $hyp VM : ${HYP_VM}"
    debug "Total $hyp allocated memory : ${HYP_ALLOCATED_MEMORY}Mo"
    debug "Total $hyp allocated vCPU : ${HYP_ALLOCATED_CPU}"

    (( TOTAL_CLUSTER_VM+=HYP_VM ))
    (( TOTAL_CLUSTER_ALLOCATED_MEMORY+=HYP_ALLOCATED_MEMORY ))
    (( TOTAL_CLUSTER_ALLOCATED_VCPU+=HYP_ALLOCATED_CPU ))

    # Retrieve Hyp resources
    debug "Retrieve $hyp resources"
    HYP_MEMORY=$( ssh "$hyp" 'cat /proc/meminfo'|grep '^MemTotal:'|awk '{print $2}' )
    (( HYP_MEMORY=HYP_MEMORY/1024 ))
    debug "Total $hyp memory: ${HYP_MEMORY}Mo"

    (( HYP_ALLOCABLE_MEMORY=HYP_MEMORY-HYP_RESERVED_MEMORY ))
    debug "Total $hyp allocable memory: ${HYP_ALLOCABLE_MEMORY}Mo"

    (( TOTAL_CLUSTER_MEMORY+=HYP_MEMORY ))
    (( TOTAL_CLUSTER_ALLOCABLE_MEMORY+=HYP_ALLOCABLE_MEMORY ))

    HYP_CPU=$( ssh "$hyp" 'cat /proc/cpuinfo'|grep -c ^processor )
    debug "Total $hyp CPU thread: $HYP_CPU"

    (( TOTAL_CLUSTER_VCPU+=HYP_CPU ))

    # Check hyp resource against cluster hyp max
    if [[ $HYP_ALLOCABLE_MEMORY -gt $HYP_MAX_ALLOCABLE_MEMORY ]]; then
        HYP_MAX_ALLOCABLE_MEMORY=$HYP_ALLOCABLE_MEMORY
    fi

    if [[ $HYP_CPU -gt $HYP_MAX_CPU ]]; then
        HYP_MAX_CPU=$HYP_CPU
    fi
done

debug "Total cluster VMs: $TOTAL_CLUSTER_VM"
debug "Total cluster allocated memory: ${TOTAL_CLUSTER_ALLOCATED_MEMORY}Mo"
debug "Total cluster allocated vCPU: ${TOTAL_CLUSTER_ALLOCATED_VCPU}"

(( CLUSTER_ALLOCABLE_MEMORY=TOTAL_CLUSTER_ALLOCABLE_MEMORY-HYP_MAX_ALLOCABLE_MEMORY ))
(( CLUSTER_ALLOCABLE_CPU=TOTAL_CLUSTER_VCPU-HYP_MAX_CPU ))

debug "Total cluster allocable memory: ${CLUSTER_ALLOCABLE_MEMORY}Mo"
debug "Total cluster allocable CPU: ${CLUSTER_ALLOCABLE_CPU}"

(( CLUSTER_ALLOCATED_MEMORY_PERC=TOTAL_CLUSTER_ALLOCATED_MEMORY*100/CLUSTER_ALLOCABLE_MEMORY ))
debug "Cluster allocated memory ratio: $CLUSTER_ALLOCATED_MEMORY_PERC%"

(( CLUSTER_ALLOCATED_CPU_PERC=TOTAL_CLUSTER_ALLOCATED_VCPU*100/CLUSTER_ALLOCABLE_CPU ))
debug "Cluster allocated CPU ratio: $CLUSTER_ALLOCATED_CPU_PERC%"

EXIT_CODE=0
EXIT_STATUS=OK
if [[ $CLUSTER_ALLOCATED_MEMORY_PERC -ge $CLUSTER_CRITICAL_ALLOCATED_MEMORY_PERC ]]; then
    EXIT_CODE=2
    EXIT_STATUS=CRITICAL
elif [[ $CLUSTER_ALLOCATED_MEMORY_PERC -ge $CLUSTER_WARNING_ALLOCATED_MEMORY_PERC ]]; then
    EXIT_CODE=1
    EXIT_STATUS=WARNING
fi

(( CLUSTER_WARNING_ALLOCATED_CPU_THRESHOLD=CLUSTER_ALLOCABLE_CPU*WARNING_CPU_THRESHOLD ))
(( CLUSTER_CRITICAL_ALLOCATED_CPU_THRESHOLD=CLUSTER_ALLOCABLE_CPU*CRITICAL_CPU_THRESHOLD ))
debug "Cluster critical/warning allocated CPU thresholds:" \
    "$CLUSTER_WARNING_ALLOCATED_CPU_THRESHOLD / $CLUSTER_CRITICAL_ALLOCATED_CPU_THRESHOLD"

if [[ $TOTAL_CLUSTER_ALLOCATED_VCPU -ge $CLUSTER_CRITICAL_ALLOCATED_CPU_THRESHOLD ]]; then
    EXIT_CODE=2
    EXIT_STATUS=CRITICAL
elif [[ $EXIT_CODE -le 1 ]] && \
    [[ $TOTAL_CLUSTER_ALLOCATED_VCPU -ge $CLUSTER_WARNING_ALLOCATED_CPU_THRESHOLD ]]; then
    EXIT_CODE=1
    EXIT_STATUS=WARNING
fi

add_perfdata \
    allocated_memory \
    ${TOTAL_CLUSTER_ALLOCATED_MEMORY}Mo \
    $CLUSTER_ALLOCABLE_MEMORY $TOTAL_CLUSTER_MEMORY \
    0 $TOTAL_CLUSTER_MEMORY

add_perfdata \
    allocated_vcpu \
    ${TOTAL_CLUSTER_ALLOCATED_VCPU} \
    $CLUSTER_WARNING_ALLOCATED_CPU_THRESHOLD $CLUSTER_CRITICAL_ALLOCATED_CPU_THRESHOLD \
    0 $TOTAL_CLUSTER_VCPU

echo "$EXIT_STATUS - $CLUSTER_ALLOCATED_MEMORY_PERC% allocated memory" \
    "($TOTAL_CLUSTER_ALLOCATED_MEMORY/${CLUSTER_ALLOCABLE_MEMORY}Mo allocable," \
    "${TOTAL_CLUSTER_ALLOCABLE_MEMORY}Mo total), ${TOTAL_CLUSTER_ALLOCATED_VCPU} allocated vCPU" \
    "(${CLUSTER_WARNING_ALLOCATED_CPU_THRESHOLD} warning /" \
    "${CLUSTER_CRITICAL_ALLOCATED_CPU_THRESHOLD} critical) | $(format_perfdata)"

exit $EXIT_CODE
