Update check_btrfs.py

This commit is contained in:
gru
2025-12-02 10:56:07 +01:00
parent d747dda3f5
commit e2c21d9afc

View File

@@ -10,6 +10,10 @@ ESC = {"reset": "\033[0m", "red": "\033[31m", "yellow": "\033[33m", "green": "\0
def color_text(text, color):
return f"{ESC[color]}{text}{ESC['reset']}"
def is_interactive():
"""Detect if running interactively (not Nagios)"""
return sys.stdout.isatty()
def run_cmd(cmd):
try:
return subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.STDOUT).strip()
@@ -84,9 +88,9 @@ Examples:
else:
target_mounts = find_btrfs_mounts()
# Nagios: No mounts = UNKNOWN (3)
# Nagios: No mounts = UNKNOWN (3) - SINGLE LINE
if not target_mounts:
print(color_text("UNKNOWN No BTRFS mount points found or specified|", "yellow"))
print("UNKNOWN No BTRFS mount points found or specified|")
sys.exit(3)
data_warn = args.data_threshold
@@ -98,30 +102,37 @@ Examples:
global_status = 0
all_perfdata = []
# Nagios: Human-readable output only (colorful)
print(color_text("Checking BTRFS filesystems:", "bold"))
print(f"Thresholds: Data(W>{data_warn}/C>{data_crit}) Meta(W>{meta_warn}/C>{meta_crit}) Scrub(>{max_scrub_err})")
print("=" * 80)
# ONLY show verbose colorful output in INTERACTIVE mode
if is_interactive():
print(color_text("Checking BTRFS filesystems:", "bold"))
print(f"Thresholds: Data(W>{data_warn}/C>{data_crit}) Meta(W>{meta_warn}/C>{meta_crit}) Scrub(>{max_scrub_err})")
print("=" * 80)
for mount in target_mounts:
print(f"\n{color_text(mount, 'cyan')}")
if is_interactive():
print(f"\n{color_text(mount, 'cyan')}")
# Validate mount point
if not is_btrfs_mount(mount):
print(color_text(f" UNKNOWN: Mount point not found or not BTRFS", "red"))
if is_interactive():
print(color_text(" UNKNOWN: Mount point not found or not BTRFS", "red"))
global_status = max(global_status, 3)
all_perfdata.append(f"{mount}_status=3")
mount_name = mount.replace('/', '_').replace(' ', '_')
all_perfdata.append(f"{mount_name}_status=3")
continue
# Test btrfs df
df_output = run_cmd(f"btrfs filesystem df {mount}")
if not df_output or "Data" not in df_output:
print(color_text(" UNKNOWN: btrfs filesystem df failed", "red"))
if is_interactive():
print(color_text(" UNKNOWN: btrfs filesystem df failed", "red"))
global_status = max(global_status, 3)
all_perfdata.append(f"{mount}_status=3")
mount_name = mount.replace('/', '_').replace(' ', '_')
all_perfdata.append(f"{mount_name}_status=3")
continue
print(color_text(" BTRFS filesystem accessible", "green"))
if is_interactive():
print(color_text(" BTRFS filesystem accessible", "green"))
# Parse usage percentages
data_match = re.search(r'Data.*?(\d+)%', df_output, re.IGNORECASE)
@@ -130,45 +141,48 @@ Examples:
data_pct = int(data_match.group(1)) if data_match else 0
meta_pct = int(meta_match.group(1)) if meta_match else 0
# Determine status colors
data_color = "green" if data_pct < data_warn else "yellow" if data_pct < data_crit else "red"
meta_color = "green" if meta_pct < meta_warn else "yellow" if meta_pct < meta_crit else "red"
# Determine status
data_status = 2 if data_pct >= data_crit else 1 if data_pct >= data_warn else 0
meta_status = 2 if meta_pct >= meta_crit else 1 if meta_pct >= meta_warn else 0
print(f" Data: {color_text(f'{data_pct}%', data_color)}")
print(f" Metadata: {color_text(f'{meta_pct}%', meta_color)}")
if is_interactive():
data_color = "green" if data_status == 0 else "yellow" if data_status == 1 else "red"
meta_color = "green" if meta_status == 0 else "yellow" if meta_status == 1 else "red"
print(f" Data: {color_text(f'{data_pct}%', data_color)}")
print(f" Metadata: {color_text(f'{meta_pct}%', meta_color)}")
# Scrub status
scrub = run_cmd(f"btrfs scrub status {mount}")
scrub_errors = len(re.findall(r'(\d+) errors?', scrub, re.IGNORECASE))
scrub_color = "green" if scrub_errors <= max_scrub_err else "red"
print(f" Scrub errors: {color_text(str(scrub_errors), scrub_color)}")
# Update global status per Nagios standard
data_status = 2 if data_pct >= data_crit else 1 if data_pct >= data_warn else 0
meta_status = 2 if meta_pct >= meta_crit else 1 if meta_pct >= meta_warn else 0
scrub_status = 2 if scrub_errors > max_scrub_err else 0
if is_interactive():
scrub_color = "green" if scrub_status == 0 else "red"
print(f" Scrub errors: {color_text(str(scrub_errors), scrub_color)}")
# Final status for this mount
mount_status = max(data_status, meta_status, scrub_status)
global_status = max(global_status, mount_status)
# Nagios perfdata format: metric=value;warn;crit;min;max
perf = f"data_pct={data_pct};{data_warn};{data_crit} meta_pct={meta_pct};{meta_warn};{meta_crit} scrub_err={scrub_errors};{max_scrub_err}"
# Nagios perfdata format
mount_name = mount.replace('/', '_').replace(' ', '_')
perf = f"{mount_name}_data_pct={data_pct};{data_warn};{data_crit} {mount_name}_meta_pct={meta_pct};{meta_warn};{meta_crit} {mount_name}_scrub_err={scrub_errors};{max_scrub_err}"
all_perfdata.append(perf)
# Nagios: Single line FINAL STATUS + perfdata
perfdata = " ".join(all_perfdata)
perfdata = "| " + " ".join(all_perfdata)
status_text = {0: "OK", 1: "WARNING", 2: "CRITICAL", 3: "UNKNOWN"}
# Colorful human output
status_color = "green" if global_status == 0 else "yellow" if global_status == 1 else "red"
print("\n" + "=" * 80)
print(color_text(f"FINAL STATUS: {status_text[global_status]}", status_color))
print(f"| {perfdata}")
# ALWAYS: Clean Nagios output FIRST LINE (parseable)
print(f"{status_text[global_status]} BTRFS check: {len(target_mounts)} mount(s){perfdata}")
# Nagios: Clean single-line output (no colors for parsing)
print(f"\n{status_text[global_status]} BTRFS check complete| {perfdata}")
# ONLY interactive: Additional colorful summary
if is_interactive():
status_color = "green" if global_status == 0 else "yellow" if global_status == 1 else "red"
print("\n" + "=" * 80)
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)
if __name__ == "__main__":