#!/usr/bin/env python3

import re
import sys
import os

MDSTAT_PATH = "/proc/mdstat"

def parse_mdstat():
    if not os.path.exists(MDSTAT_PATH):
        return [], "CRITICAL - /proc/mdstat not found", 2

    arrays = {}
    current_array = None

    try:
        with open(MDSTAT_PATH, "r") as f:
            for line in f:
                # RAID device line (e.g., "md127 : active raid1 sda1[0] sdb1[1]")
                match = re.match(r'^(md\d+)\s*:\s*(.*)', line)
                if match:
                    current_array = match.group(1)
                    arrays[current_array] = {'status': match.group(2), 'lines': [line.strip()]}
                elif current_array:
                    arrays[current_array]['lines'].append(line.strip())
    except Exception as e:
        return [], f"CRITICAL - Error reading /proc/mdstat: {e}", 2

    return arrays, None, None

def analyze_arrays(arrays):
    total = len(arrays)
    degraded = []
    recovering = []
    resyncing = []

    for md, data in arrays.items():
        combined = " ".join(data['lines'])
        if re.search(r'\[.*_.*\]', combined):
            degraded.append(md)
        elif "recovery" in combined:
            recovering.append(md)
        elif "resync" in combined:
            resyncing.append(md)

    return total, degraded, recovering, resyncing

def main():
    arrays, error_msg, exit_code = parse_mdstat()

    if error_msg:
        print(error_msg)
        sys.exit(exit_code)

    total, degraded, recovering, resyncing = analyze_arrays(arrays)

    if recovering:
        print(f"WARNING - Checked {total} arrays, recovering: {', '.join(recovering)}")
        sys.exit(1)
    elif resyncing:
        print(f"WARNING - Checked {total} arrays, resync: {', '.join(resyncing)}")
        sys.exit(1)
    elif not degraded:
        print(f"OK - Checked {total} arrays. All arrays healthy.")
        sys.exit(0)
    else:
        print(f"CRITICAL - Checked {total} arrays, degraded: {', '.join(degraded)}")
        sys.exit(2)

if __name__ == "__main__":
    main()
