Update check_xfs.py
This commit is contained in:
94
check_xfs.py
94
check_xfs.py
@@ -10,6 +10,10 @@ ESC = {"reset": "\033[0m", "red": "\033[31m", "yellow": "\033[33m", "green": "\0
|
|||||||
def color_text(text, color):
|
def color_text(text, color):
|
||||||
return f"{ESC[color]}{text}{ESC['reset']}"
|
return f"{ESC[color]}{text}{ESC['reset']}"
|
||||||
|
|
||||||
|
def is_interactive():
|
||||||
|
"""Detect if running interactively (not Nagios)"""
|
||||||
|
return sys.stdout.isatty()
|
||||||
|
|
||||||
def run_cmd(cmd):
|
def run_cmd(cmd):
|
||||||
try:
|
try:
|
||||||
return subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.STDOUT).strip()
|
return subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.STDOUT).strip()
|
||||||
@@ -31,15 +35,17 @@ def is_xfs_mount(mount):
|
|||||||
return "xfs" in mounts_output.lower()
|
return "xfs" in mounts_output.lower()
|
||||||
|
|
||||||
def check_disk_usage(mount):
|
def check_disk_usage(mount):
|
||||||
output = run_cmd(f"df -h {mount}")
|
"""Use df -P for consistent POSIX output"""
|
||||||
|
output = run_cmd(f"df -P -h {mount}")
|
||||||
for line in output.splitlines():
|
for line in output.splitlines():
|
||||||
if mount in line:
|
parts = line.split()
|
||||||
parts = line.split()
|
if len(parts) >= 6 and mount in parts[5]: # Target is LAST column in -P
|
||||||
usage_str = parts[4] # e.g. '45%'
|
usage_str = parts[4]
|
||||||
usage_pct = int(usage_str.strip('%'))
|
if '%' in usage_str:
|
||||||
size = parts[1]
|
usage_pct = int(usage_str.strip('%'))
|
||||||
avail = parts[3]
|
size = parts[1]
|
||||||
return usage_pct, size, avail
|
avail = parts[3]
|
||||||
|
return usage_pct, size, avail
|
||||||
return None, None, None
|
return None, None, None
|
||||||
|
|
||||||
def check_xfs_repair(mount):
|
def check_xfs_repair(mount):
|
||||||
@@ -97,9 +103,9 @@ Examples:
|
|||||||
else:
|
else:
|
||||||
target_mounts = find_xfs_mounts()
|
target_mounts = find_xfs_mounts()
|
||||||
|
|
||||||
# Nagios: No mounts = UNKNOWN (3)
|
# Nagios: No mounts = UNKNOWN (3) - SINGLE LINE
|
||||||
if not target_mounts:
|
if not target_mounts:
|
||||||
print(color_text("UNKNOWN No XFS mount points found or specified|", "yellow"))
|
print("UNKNOWN No XFS mount points found or specified|")
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
||||||
warn_threshold = args.warn_threshold
|
warn_threshold = args.warn_threshold
|
||||||
@@ -107,68 +113,76 @@ Examples:
|
|||||||
global_status = 0
|
global_status = 0
|
||||||
all_perfdata = []
|
all_perfdata = []
|
||||||
|
|
||||||
# Human-readable output (colorful)
|
# ONLY show verbose colorful output in INTERACTIVE mode
|
||||||
print(color_text("Checking XFS filesystems:", "bold"))
|
if is_interactive():
|
||||||
print(f"Thresholds: WARN>{warn_threshold}%% CRIT>{crit_threshold}%%")
|
print(color_text("Checking XFS filesystems:", "bold"))
|
||||||
print("=" * 60)
|
print(f"Thresholds: WARN>{warn_threshold}% CRIT>{crit_threshold}%")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
for mount in target_mounts:
|
for mount in target_mounts:
|
||||||
print(f"\n{color_text(mount, 'cyan')}")
|
if is_interactive():
|
||||||
|
print(f"\n{color_text(mount, 'cyan')}")
|
||||||
|
|
||||||
# Validate it's actually XFS
|
# Validate it's actually XFS
|
||||||
if not is_xfs_mount(mount):
|
if not is_xfs_mount(mount):
|
||||||
print(color_text(" UNKNOWN: Mount point not found or not XFS", "red"))
|
if is_interactive():
|
||||||
|
print(color_text(" UNKNOWN: Mount point not found or not XFS", "red"))
|
||||||
global_status = max(global_status, 3)
|
global_status = max(global_status, 3)
|
||||||
all_perfdata.append(f"{mount}_status=3")
|
all_perfdata.append(f"{mount.replace('/', '_')}_status=3")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
usage_pct, size, avail = check_disk_usage(mount)
|
usage_pct, size, avail = check_disk_usage(mount)
|
||||||
if usage_pct is None:
|
if usage_pct is None:
|
||||||
print(color_text(" UNKNOWN: Unable to read disk usage", "red"))
|
if is_interactive():
|
||||||
|
print(color_text(" UNKNOWN: Unable to read disk usage", "red"))
|
||||||
global_status = max(global_status, 3)
|
global_status = max(global_status, 3)
|
||||||
all_perfdata.append(f"{mount}_status=3")
|
all_perfdata.append(f"{mount.replace('/', '_')}_status=3")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Usage status
|
||||||
usage_status = 0
|
usage_status = 0
|
||||||
if usage_pct > crit_threshold:
|
if usage_pct > crit_threshold:
|
||||||
usage_status = 2
|
usage_status = 2
|
||||||
elif usage_pct > warn_threshold:
|
elif usage_pct > warn_threshold:
|
||||||
usage_status = 1
|
usage_status = 1
|
||||||
|
|
||||||
usage_color = "green" if usage_status == 0 else "yellow" if usage_status == 1 else "red"
|
if is_interactive():
|
||||||
print(f" Usage: {color_text(f'{usage_pct}%', usage_color)} (Size: {size}, Available: {avail})")
|
usage_color = "green" if usage_status == 0 else "yellow" if usage_status == 1 else "red"
|
||||||
|
print(f" Usage: {color_text(f'{usage_pct}%', usage_color)} (Size: {size}, Available: {avail})")
|
||||||
|
|
||||||
|
# XFS repair check
|
||||||
repair_ok, repair_out = check_xfs_repair(mount)
|
repair_ok, repair_out = check_xfs_repair(mount)
|
||||||
if not repair_ok:
|
xfs_status = 2 if not repair_ok else 0
|
||||||
print(color_text(" CRITICAL: XFS filesystem issues detected", "red"))
|
|
||||||
print(f" {repair_out[:200]}...")
|
if is_interactive():
|
||||||
global_status = max(global_status, 2)
|
if not repair_ok:
|
||||||
xfs_status = 2
|
print(color_text(" CRITICAL: XFS filesystem issues detected", "red"))
|
||||||
else:
|
else:
|
||||||
print(color_text(" XFS filesystem OK (xfs_repair dry-run)", "green"))
|
print(color_text(" XFS filesystem OK (xfs_repair dry-run)", "green"))
|
||||||
xfs_status = 0
|
|
||||||
|
|
||||||
# Final status for this mount
|
# Final status for this mount
|
||||||
mount_status = max(usage_status, xfs_status)
|
mount_status = max(usage_status, xfs_status)
|
||||||
global_status = max(global_status, mount_status)
|
global_status = max(global_status, mount_status)
|
||||||
|
|
||||||
# Nagios perfdata: metric=value;warn;crit;min;max
|
# Nagios perfdata format
|
||||||
perf = f"used_pct={usage_pct};{warn_threshold};{crit_threshold};0;100 size={size} avail={avail} xfs_repair={xfs_status}"
|
mount_name = mount.replace('/', '_').replace(' ', '_')
|
||||||
|
perf = f"{mount_name}_used_pct={usage_pct};{warn_threshold};{crit_threshold};0;100 size={size} avail={avail} xfs_status={xfs_status}"
|
||||||
all_perfdata.append(perf)
|
all_perfdata.append(perf)
|
||||||
|
|
||||||
perfdata = " ".join(all_perfdata)
|
perfdata = "| " + " ".join(all_perfdata)
|
||||||
status_text = {0: "OK", 1: "WARNING", 2: "CRITICAL", 3: "UNKNOWN"}
|
status_text = {0: "OK", 1: "WARNING", 2: "CRITICAL", 3: "UNKNOWN"}
|
||||||
|
|
||||||
# Colorful human output
|
# ALWAYS: Clean Nagios output FIRST LINE (parseable)
|
||||||
status_color = "green" if global_status == 0 else "yellow" if global_status == 1 else "red"
|
print(f"{status_text[global_status]} XFS check: {len(target_mounts)} mount(s){perfdata}")
|
||||||
print("\n" + "=" * 60)
|
|
||||||
print(color_text(f"FINAL STATUS: {status_text[global_status]}", status_color))
|
|
||||||
print(f"| {perfdata}")
|
|
||||||
|
|
||||||
# NAGIOS: Clean single-line output (no colors, parseable)
|
# ONLY interactive: Additional colorful summary
|
||||||
print(f"\n{status_text[global_status]} XFS check complete| {perfdata}")
|
if is_interactive():
|
||||||
|
status_color = "green" if global_status == 0 else "yellow" if global_status == 1 else "red"
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print(color_text(f"FINAL STATUS: {status_text[global_status]}", status_color))
|
||||||
|
print(f"{perfdata}")
|
||||||
|
|
||||||
# Nagios standard exit codes
|
# Nagios standard exit codes: 0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN
|
||||||
sys.exit(global_status)
|
sys.exit(global_status)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user