290 lines
10 KiB
Plaintext
290 lines
10 KiB
Plaintext
|
|
#!/bin/bash
|
|||
|
|
#
|
|||
|
|
# CheckMK Local Check für GPFS Fileset Inodes
|
|||
|
|
# Datei: /usr/lib/check_mk_agent/local/gpfs_fileset_inodes
|
|||
|
|
# Ausführbar machen: chmod +x /usr/lib/check_mk_agent/local/gpfs_fileset_inodes
|
|||
|
|
#
|
|||
|
|
# Überwacht Inode-Verbrauch aller Filesets in allen GPFS Filesystemen
|
|||
|
|
#
|
|||
|
|
|
|||
|
|
# GPFS Management API Konfiguration
|
|||
|
|
USER="checkmk"
|
|||
|
|
PASSWORD="RUIMv7A9CnUaWtnxVMzn"
|
|||
|
|
HOST="spsctstrz.ad.ghnit.net"
|
|||
|
|
PORT="443"
|
|||
|
|
BASE_URL="https://${HOST}:${PORT}/scalemgmt/v2/filesystems"
|
|||
|
|
|
|||
|
|
# Schwellwerte in Prozent
|
|||
|
|
WARN_THRESHOLD=80
|
|||
|
|
CRIT_THRESHOLD=90
|
|||
|
|
|
|||
|
|
# Hostname für Service-Namen
|
|||
|
|
HOSTNAME=$(hostname)
|
|||
|
|
|
|||
|
|
# Funktion für API-Aufrufe
|
|||
|
|
gpfs_api_call() {
|
|||
|
|
local url="$1"
|
|||
|
|
curl -s -u "${USER}:${PASSWORD}" \
|
|||
|
|
-H "Accept: application/json" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-X GET "${url}" 2>/dev/null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Prozentsatz berechnen - ohne bc für bessere Kontrolle
|
|||
|
|
calculate_percentage() {
|
|||
|
|
local used=$1
|
|||
|
|
local max=$2
|
|||
|
|
if [ "$max" -gt 0 ]; then
|
|||
|
|
# Bash-Integer-Arithmetik: (used * 10000 / max) / 100 für 2 Dezimalstellen
|
|||
|
|
local result=$((used * 10000 / max))
|
|||
|
|
local integer_part=$((result / 100))
|
|||
|
|
local decimal_part=$((result % 100))
|
|||
|
|
printf "%d.%02d" "$integer_part" "$decimal_part"
|
|||
|
|
else
|
|||
|
|
echo "0.00"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# CheckMK Status-Code bestimmen - ohne bc
|
|||
|
|
get_status_code() {
|
|||
|
|
local percentage_str=$1
|
|||
|
|
# Prozentsatz in Integer umwandeln für Vergleich (z.B. "1.52" -> 152)
|
|||
|
|
local percentage_int=$(echo "$percentage_str" | sed 's/\.//' | sed 's/^0*//')
|
|||
|
|
[ -z "$percentage_int" ] && percentage_int=0
|
|||
|
|
|
|||
|
|
local warn_int=$((WARN_THRESHOLD * 100))
|
|||
|
|
local crit_int=$((CRIT_THRESHOLD * 100))
|
|||
|
|
|
|||
|
|
if [ "$percentage_int" -ge "$crit_int" ]; then
|
|||
|
|
echo "2"
|
|||
|
|
elif [ "$percentage_int" -ge "$warn_int" ]; then
|
|||
|
|
echo "1"
|
|||
|
|
else
|
|||
|
|
echo "0"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Status-Text bestimmen
|
|||
|
|
get_status_text() {
|
|||
|
|
local code=$1
|
|||
|
|
case $code in
|
|||
|
|
0) echo "OK" ;;
|
|||
|
|
1) echo "WARNING" ;;
|
|||
|
|
2) echo "CRITICAL" ;;
|
|||
|
|
*) echo "UNKNOWN" ;;
|
|||
|
|
esac
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Einzelnes Fileset prüfen
|
|||
|
|
check_fileset() {
|
|||
|
|
local filesystem=$1
|
|||
|
|
local fileset=$2
|
|||
|
|
|
|||
|
|
# Service-Name erstellen
|
|||
|
|
local service_name="GPFS FILESET INODES ${filesystem}_${fileset} ${HOSTNAME}"
|
|||
|
|
|
|||
|
|
# Fileset-Details von API abrufen
|
|||
|
|
local detail_response=$(gpfs_api_call "${BASE_URL}/${filesystem}/filesets/${fileset}")
|
|||
|
|
|
|||
|
|
if [ $? -ne 0 ] || [ -z "$detail_response" ]; then
|
|||
|
|
echo "2 \"$service_name\" - CRITICAL: API call failed for fileset $fileset in $filesystem"
|
|||
|
|
return
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# JSON parsen - verschiedene mögliche Pfade versuchen
|
|||
|
|
local used_inodes=$(echo "$detail_response" | jq -r '
|
|||
|
|
.filesets[0]?.usage?.usedInodes //
|
|||
|
|
.usage?.usedInodes //
|
|||
|
|
.filesets[0]?.usage?.inodeSpaceUsedInodes //
|
|||
|
|
.usage?.inodeSpaceUsedInodes //
|
|||
|
|
0' 2>/dev/null)
|
|||
|
|
|
|||
|
|
local allocated_inodes=$(echo "$detail_response" | jq -r '
|
|||
|
|
.filesets[0]?.usage?.allocatedInodes //
|
|||
|
|
.usage?.allocatedInodes //
|
|||
|
|
0' 2>/dev/null)
|
|||
|
|
|
|||
|
|
local max_inodes=$(echo "$detail_response" | jq -r '
|
|||
|
|
.filesets[0]?.config?.maxNumInodes //
|
|||
|
|
.config?.maxNumInodes //
|
|||
|
|
0' 2>/dev/null)
|
|||
|
|
|
|||
|
|
local free_inodes=$(echo "$detail_response" | jq -r '
|
|||
|
|
.filesets[0]?.usage?.inodeSpaceFreeInodes //
|
|||
|
|
.usage?.inodeSpaceFreeInodes //
|
|||
|
|
0' 2>/dev/null)
|
|||
|
|
|
|||
|
|
# Fallback: wenn max_inodes 0 oder null ist, allocated_inodes verwenden
|
|||
|
|
if [ "$max_inodes" = "0" ] || [ "$max_inodes" = "null" ]; then
|
|||
|
|
max_inodes="$allocated_inodes"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Validierung der Werte
|
|||
|
|
if ! [[ "$used_inodes" =~ ^[0-9]+$ ]] || ! [[ "$max_inodes" =~ ^[0-9]+$ ]]; then
|
|||
|
|
echo "3 \"$service_name\" - UNKNOWN: Invalid inode data (used: $used_inodes, max: $max_inodes)"
|
|||
|
|
return
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ "$max_inodes" -eq 0 ]; then
|
|||
|
|
echo "0 \"$service_name\" used_inodes=$used_inodes;;;0 OK: No inode limit set for fileset"
|
|||
|
|
return
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Prozentsatz und Status berechnen
|
|||
|
|
local percentage=$(calculate_percentage "$used_inodes" "$max_inodes")
|
|||
|
|
local status_code=$(get_status_code "$percentage")
|
|||
|
|
local status_text=$(get_status_text "$status_code")
|
|||
|
|
|
|||
|
|
# Freie Inodes berechnen
|
|||
|
|
local calculated_free=$((max_inodes - used_inodes))
|
|||
|
|
if [ "$free_inodes" = "0" ] || [ "$free_inodes" = "null" ]; then
|
|||
|
|
free_inodes=$calculated_free
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Schwellwerte für Performance-Daten berechnen
|
|||
|
|
local warn_absolute=$(echo "scale=0; $max_inodes * $WARN_THRESHOLD / 100" | bc -l)
|
|||
|
|
local crit_absolute=$(echo "scale=0; $max_inodes * $CRIT_THRESHOLD / 100" | bc -l)
|
|||
|
|
|
|||
|
|
# Zusätzliche Metriken aus JSON extrahieren
|
|||
|
|
local used_bytes=$(echo "$detail_response" | jq -r '
|
|||
|
|
.filesets[0]?.usage?.usedBytes //
|
|||
|
|
.usage?.usedBytes //
|
|||
|
|
0' 2>/dev/null)
|
|||
|
|
|
|||
|
|
local allocated_bytes=$(echo "$detail_response" | jq -r '
|
|||
|
|
.filesets[0]?.usage?.allocatedBytes //
|
|||
|
|
.usage?.allocatedBytes //
|
|||
|
|
0' 2>/dev/null)
|
|||
|
|
|
|||
|
|
local max_bytes=$(echo "$detail_response" | jq -r '
|
|||
|
|
.filesets[0]?.config?.maxBytes //
|
|||
|
|
.config?.maxBytes //
|
|||
|
|
0' 2>/dev/null)
|
|||
|
|
|
|||
|
|
local free_bytes=0
|
|||
|
|
if [ "$allocated_bytes" -gt 0 ] && [ "$used_bytes" -gt 0 ]; then
|
|||
|
|
free_bytes=$((allocated_bytes - used_bytes))
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Performance-Daten erstellen - CheckMK-konformes Format
|
|||
|
|
# Format: metric=value;warn;crit;min;max (getrennt durch Leerzeichen oder |)
|
|||
|
|
local perfdata="used_inodes=${used_inodes};${warn_absolute};${crit_absolute};0;${max_inodes}"
|
|||
|
|
perfdata="${perfdata}|free_inodes=${free_inodes};;;0;${max_inodes}"
|
|||
|
|
perfdata="${perfdata}|allocated_inodes=${allocated_inodes};;;0"
|
|||
|
|
perfdata="${perfdata}|max_inodes=${max_inodes};;;0"
|
|||
|
|
perfdata="${perfdata}|usage_percent=${percentage};${WARN_THRESHOLD};${CRIT_THRESHOLD};0;100"
|
|||
|
|
|
|||
|
|
# Bytes-Metriken hinzufügen (falls verfügbar)
|
|||
|
|
if [ "$used_bytes" != "0" ] && [ "$used_bytes" != "null" ]; then
|
|||
|
|
perfdata="${perfdata}|used_bytes=${used_bytes};;;0"
|
|||
|
|
fi
|
|||
|
|
if [ "$allocated_bytes" != "0" ] && [ "$allocated_bytes" != "null" ]; then
|
|||
|
|
perfdata="${perfdata}|allocated_bytes=${allocated_bytes};;;0"
|
|||
|
|
if [ "$free_bytes" -gt 0 ]; then
|
|||
|
|
perfdata="${perfdata}|free_bytes=${free_bytes};;;0"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
if [ "$max_bytes" != "0" ] && [ "$max_bytes" != "null" ]; then
|
|||
|
|
perfdata="${perfdata}|max_bytes=${max_bytes};;;0"
|
|||
|
|
# Bytes-Prozentsatz berechnen
|
|||
|
|
if [ "$max_bytes" -gt 0 ] && [ "$used_bytes" -gt 0 ]; then
|
|||
|
|
local bytes_percentage=$(calculate_percentage "$used_bytes" "$max_bytes")
|
|||
|
|
perfdata="${perfdata}|bytes_usage_percent=${bytes_percentage};;;0;100"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Details-Text erstellen - mehr Informationen
|
|||
|
|
local details="Inodes: ${used_inodes}/${max_inodes} (${percentage}%)"
|
|||
|
|
|
|||
|
|
if [ "$allocated_inodes" != "$max_inodes" ] && [ "$allocated_inodes" -gt 0 ]; then
|
|||
|
|
details="${details}, allocated: ${allocated_inodes}"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Bytes-Information hinzufügen falls verfügbar
|
|||
|
|
if [ "$used_bytes" != "0" ] && [ "$used_bytes" != "null" ]; then
|
|||
|
|
local used_mb=$((used_bytes / 1024 / 1024))
|
|||
|
|
details="${details}, Size: ${used_mb}MB"
|
|||
|
|
|
|||
|
|
if [ "$allocated_bytes" != "0" ] && [ "$allocated_bytes" != "null" ]; then
|
|||
|
|
local allocated_mb=$((allocated_bytes / 1024 / 1024))
|
|||
|
|
details="${details}/${allocated_mb}MB"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ "$max_bytes" != "0" ] && [ "$max_bytes" != "null" ] && [ "$max_bytes" -gt 0 ]; then
|
|||
|
|
local max_mb=$((max_bytes / 1024 / 1024))
|
|||
|
|
local bytes_percentage=$(calculate_percentage "$used_bytes" "$max_bytes")
|
|||
|
|
details="${details} (limit: ${max_mb}MB, ${bytes_percentage}%)"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# CheckMK Service ausgeben
|
|||
|
|
# Format: STATUS_CODE "SERVICENAME" PERFDATA MESSAGE
|
|||
|
|
echo "$status_code \"$service_name\" $perfdata $status_text: $details"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Alle Filesysteme abrufen
|
|||
|
|
get_filesystems() {
|
|||
|
|
local response=$(gpfs_api_call "$BASE_URL")
|
|||
|
|
if [ $? -ne 0 ] || [ -z "$response" ]; then
|
|||
|
|
echo "2 \"GPFS FILESET INODES GLOBAL $HOSTNAME\" - CRITICAL: Cannot connect to GPFS Management API"
|
|||
|
|
return 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
echo "$response" | jq -r '.filesystems[]?.name // empty' 2>/dev/null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Filesets eines Filesystems abrufen
|
|||
|
|
get_filesets() {
|
|||
|
|
local filesystem=$1
|
|||
|
|
local response=$(gpfs_api_call "${BASE_URL}/${filesystem}/filesets")
|
|||
|
|
|
|||
|
|
if [ $? -ne 0 ] || [ -z "$response" ]; then
|
|||
|
|
echo "2 \"GPFS FILESET INODES ${filesystem}_ERROR $HOSTNAME\" - CRITICAL: Cannot get filesets for filesystem $filesystem"
|
|||
|
|
return 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
echo "$response" | jq -r '.filesets[]?.filesetName // empty' 2>/dev/null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# HAUPTTEIL: Alle Filesysteme und Filesets durchgehen
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
# Prüfen ob jq verfügbar ist
|
|||
|
|
if ! command -v jq >/dev/null 2>&1; then
|
|||
|
|
echo "2 \"GPFS FILESET INODES GLOBAL $HOSTNAME\" - CRITICAL: jq command not found - required for JSON parsing"
|
|||
|
|
exit 0
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Prüfen ob bc verfügbar ist
|
|||
|
|
if ! command -v bc >/dev/null 2>&1; then
|
|||
|
|
echo "2 \"GPFS FILESET INODES GLOBAL $HOSTNAME\" - CRITICAL: bc command not found - required for calculations"
|
|||
|
|
exit 0
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Alle Filesysteme abrufen
|
|||
|
|
filesystems=$(get_filesystems)
|
|||
|
|
if [ $? -ne 0 ] || [ -z "$filesystems" ]; then
|
|||
|
|
exit 0
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Für jedes Filesystem alle Filesets prüfen
|
|||
|
|
for filesystem in $filesystems; do
|
|||
|
|
filesets=$(get_filesets "$filesystem")
|
|||
|
|
if [ $? -ne 0 ]; then
|
|||
|
|
continue
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ -z "$filesets" ]; then
|
|||
|
|
echo "1 \"GPFS FILESET INODES ${filesystem}_EMPTY $HOSTNAME\" - WARNING: No filesets found in filesystem $filesystem"
|
|||
|
|
continue
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Für jedes Fileset einen separaten Service erstellen
|
|||
|
|
for fileset in $filesets; do
|
|||
|
|
if [ -n "$fileset" ]; then
|
|||
|
|
check_fileset "$filesystem" "$fileset"
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
done
|