#!/bin/bash

function usage {
    cat << EOF
usage: $0 options

    Check the disk space available for the configured directories

OPTIONS:
    -h              Show this message
    -f              Skip checking if spacewalk services are running
EOF
}

function parseArguments {
    while getopts "h?f" opt; do
        case "$opt" in
            h|\?)
                usage
                exit 0
                ;;
            f)
                SKIP_SERVICES_CHECK=1
                ;;
        esac
    done
}

function parseConfiguration {
    local conf="$1"

    if [ -z "${DISKCHECKDIRS}" ] && [ -f "$conf" ]; then
        DISKCHECKDIRS=$(grep '^[[:blank:]]*spacecheck_dirs' "$conf" | sed -e 's/.*=[[:blank:]]*//')
    fi
    if [ -z "${DISKCHECKALERT}" ] && [ -f "$conf" ]; then
        DISKCHECKALERT=$(grep '^[[:blank:]]*spacecheck_free_alert' "$conf" | sed -e 's/.*=[[:blank:]]*//')
    fi
    if [ -z "${DISKTHRESHOLD}" ] && [ -f "$conf" ]; then
        DISKTHRESHOLD=$(grep '^[[:blank:]]*spacecheck_free_critical' "$conf" | sed -e 's/.*=[[:blank:]]*//')
    fi

    [ -z "${DISKCHECKDIRS}" ] && DISKCHECKDIRS="/var/spacewalk /var/cache /srv"
    [ -z "${DISKCHECKALERT}" ] && DISKCHECKALERT=90
    [ -z "${DISKTHRESHOLD}" ]  && DISKTHRESHOLD=95

    # Strip surrounding quotes that may have been introduced via env or rhn.conf.
    DISKCHECKDIRS="${DISKCHECKDIRS%\"}"; DISKCHECKDIRS="${DISKCHECKDIRS#\"}"
    DISKCHECKDIRS="${DISKCHECKDIRS%\'}"; DISKCHECKDIRS="${DISKCHECKDIRS#\'}"

    # Split into a bash array for safe iteration.
    read -ra DISKCHECKDIRS_ARR <<< "$DISKCHECKDIRS"

    validatePercentage DISKCHECKALERT 90
    validatePercentage DISKTHRESHOLD 95
    validateFreeMB DISKTHRESHOLD_FREE_MB
    validateFreeMB DISKCHECKALERT_FREE_MB
}

# Reset the named variable to the default if it is not a percentage between 0 and 100,
# and report the misconfiguration.
function validatePercentage {
    local name="$1"
    local default="$2"
    local value="${!name}"

    if ! [[ "$value" =~ ^[0-9]{1,3}$ ]] || [ "$value" -gt 100 ]; then
        echo "DISKCHECK: invalid $name value '$value', using the default ${default}%"
        printf -v "$name" '%s' "$default"
        updateSeverity 1
    fi
}

# Unset the named variable if it is not a valid number of MB, so that the percentage
# threshold of the same level is used, and report the misconfiguration.
function validateFreeMB {
    local name="$1"
    local value="${!name}"

    if [ -n "$value" ] && ! [[ "$value" =~ ^[0-9]{1,15}$ ]]; then
        echo "DISKCHECK: invalid $name value '$value', using the percentage threshold"
        unset "$name"
        updateSeverity 1
    fi
}

function ensureSpacewalkRunning {
    if [ "$SKIP_SERVICES_CHECK" = "1" ]; then
        return
    fi
    systemctl status spacewalk.target > /dev/null 2>&1
    if [ $? != 0 ]; then
        echo  "DISKCHECK: spacewalk services are not running - skipping disk check."
        exit 0
    fi
}

function updateSeverity {
    if [ $1 -gt $CHECKSEVERITY ]; then
        CHECKSEVERITY=$1
    fi
}

# Main script

CHECKSEVERITY=0
SKIP_TARGET_CHECK=0

parseArguments "$@"
ensureSpacewalkRunning
parseConfiguration /etc/rhn/rhn.conf

for DIR in "${DISKCHECKDIRS_ARR[@]}"; do
    if [ ! -d "$DIR" ]; then
        echo "DISKCHECK: Directory $DIR does not exist"
        updateSeverity 1
        continue
    fi

    USEDSPACE=$(df -PH "$DIR" | tail -1 | awk '{print $5}' | sed -e 's/%//')
    AVAILMB=$(df -P -B1M "$DIR" | tail -1 | awk '{print $4}')

    # *_FREE_MB, when set, has priority over the percentage threshold of the same level.
    CRITICAL=0
    ALERT=0
    if [ -n "$DISKTHRESHOLD_FREE_MB" ]; then
        [ "$AVAILMB" -lt "$DISKTHRESHOLD_FREE_MB" ] && CRITICAL=1
    elif [ "$USEDSPACE" -gt "$DISKTHRESHOLD" ]; then
        CRITICAL=1
    fi
    if [ -n "$DISKCHECKALERT_FREE_MB" ]; then
        [ "$AVAILMB" -lt "$DISKCHECKALERT_FREE_MB" ] && ALERT=1
    elif [ "$USEDSPACE" -gt "$DISKCHECKALERT" ]; then
        ALERT=1
    fi

    if [ "$CRITICAL" -eq 1 ]; then
        echo "DISKCHECK: $DIR critical: ${USEDSPACE}% used, ${AVAILMB} MB available"
        updateSeverity 3
    elif [ "$ALERT" -eq 1 ]; then
        echo "DISKCHECK: $DIR alert: ${USEDSPACE}% used, ${AVAILMB} MB available"
        updateSeverity 2
    fi
done

exit $CHECKSEVERITY
