#!/usr/bin/bash
# MDADM SNMP extension for LibreNMS
# Version
extendVer='2'
# Initial portion of json
mdadmSNMPOutput='{ "data": ['

# Outputs a list of devices
list_devices() {
    for device in "${1}/slaves/"*; do
        if [ "${2,,}" == 'count' ]; then
            ((devCount++))
        elif [ "${2,,}" != 'missing' ] || [ ! -e "${device}" ]; then
            printf '%b\t    "%s"' "${multiDisk}" "$(basename "${device}")"
            multiDisk=',\n'
        fi
    done
    [ "${devCount}" ] && echo "${devCount}"
}

# Outputs either 0, 100, or the value of the file referenced
maybe_get() {
    if [ -f "${1}" ] && [[ $(cat "${1}") =~ " / " ]]; then
        echo $((100 * $(cat "${1}")))
    elif [ -f "${1}" ] && [ "$(cat "${1}")" != 'none' ]; then
        cat "${1}"
    else
        echo 0
    fi
}

main() {
    if ! which 'jq' > /dev/null 2>&1; then
        errorCode=1
        # The underscore here is a hack since we have to strip spaces without jq
        errorString='jq_missing!'
    elif stat "/dev/md"[[:digit:]]* > /dev/null 2>&1; then
        for mdadmArray in "/dev/md"[[:digit:]]*; do
            # Ignore partitions
            [[ "${mdadmArray}" =~ '/dev/md'[[:digit:]]+'p' ]] && continue

            mdadmName="$(basename "$(realpath "${mdadmArray}")")"

			# Ignore inactive arrays
			[[ $(grep "^${mdadmName}" /proc/mdstat) =~ 'inactive' ]] && continue

            mdadmSysDev="/sys/block/${mdadmName}"

            degraded=$(maybe_get "${mdadmSysDev}/md/degraded")
            syncSpeed=$(($(maybe_get "${mdadmSysDev}/md/sync_speed") * 1024))

            syncCompleted=$(maybe_get "${mdadmSysDev}/md/sync_completed")
            if [ $syncCompleted -eq 0 ] && [ $degraded -eq 0 ] && [ $syncSpeed -eq 0 ]; then
                syncCompleted="100"
            fi

            read -r -d '' mdadmOutput <<MDADMJSON

    ${multiArray}{
        "name": "${mdadmName}",
        "level": "$(maybe_get "${mdadmSysDev}/md/level")",
        "size": $((($(maybe_get "${mdadmSysDev}/size") * 1024) / 2)),
        "disc_count": $(maybe_get "${mdadmSysDev}/md/raid_disks"),
        "hotspare_count": $((($(list_devices "${mdadmSysDev}" count "${mdadmSysDev}") - $(maybe_get "${mdadmSysDev}/md/raid_disks")))),
        "device_list": [
$(list_devices "${mdadmSysDev}")
        ],
        "missing_devices_list": [
$(list_devices "${mdadmSysDev}" missing)
        ],
        "state": "$(maybe_get "${mdadmSysDev}/md/array_state")",
        "action": "$(maybe_get "${mdadmSysDev}/md/sync_action")",
        "degraded": $degraded,
        "sync_speed": $syncSpeed,
        "sync_completed": $syncCompleted
    }
MDADMJSON
            # Add a comma only after the first item
            multiArray=','
            mdadmSNMPOutput+="${mdadmOutput}"
        done
    else
        errorCode=2
        errorString='mdadm array not found!'
    fi

    read -r -d '' metadataOutput <<METADATA
],
    "error": ${errorCode:-0},
    "errorString": "${errorString}",
    "version": "${extendVer}"
}
METADATA

    # If JQ is missing we need to echo this manually and strip whitespace
    # SC2001 is not applicable because we already use parameter expansion search/replace
    # shellcheck disable=SC2001
    jq -c '.' <<< "${mdadmSNMPOutput}${metadataOutput}" 2> /dev/null || sed 's/\s//g' <<< "${mdadmSNMPOutput//$'\n'/}${metadataOutput//$'\n'/}"
}

main "${@}"
