From 50dd2a631eb3fa5d766e854d992f989d8404fb49 Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 16 Mar 2026 22:19:58 +0000 Subject: [PATCH] Filter dead temp sensors from SES health and recompute overall status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Xyratex HB-1235 enclosures have non-functional temperature sensor slots that report Unrecoverable/Unknown at 0°C. The SES header rolls these into UNRECOV=1, causing a false CRITICAL flag. Now we skip dead sensors (0°C + non-OK status) and derive overall_status from the actual parsed elements instead of the raw header counts. --- services/enclosure.py | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/services/enclosure.py b/services/enclosure.py index b142200..5864d99 100644 --- a/services/enclosure.py +++ b/services/enclosure.py @@ -183,21 +183,6 @@ def _parse_ses_page02(text: str) -> dict: "voltages": [], } - # Parse header line for overall status: - # INVOP=0, INFO=0, NON-CRIT=0, CRIT=1, UNRECOV=0 - header_match = re.search( - r"INVOP=\d+,\s*INFO=\d+,\s*NON-CRIT=(\d+),\s*CRIT=(\d+),\s*UNRECOV=(\d+)", - text, - ) - if header_match: - non_crit = int(header_match.group(1)) - crit = int(header_match.group(2)) - unrecov = int(header_match.group(3)) - if crit > 0 or unrecov > 0: - result["overall_status"] = "CRITICAL" - elif non_crit > 0: - result["overall_status"] = "WARNING" - # Split into element type sections. # Each section starts with "Element type: " sections = re.split(r"(?=\s*Element type:)", text) @@ -250,6 +235,12 @@ def _parse_ses_page02(text: str) -> dict: elif "temperature" in element_type: temp_match = re.search(r"Temperature=\s*([\d.]+)\s*C", elem_text) temp = float(temp_match.group(1)) if temp_match else None + # Skip dead/disconnected sensors: 0°C with a non-OK status + # is a non-functional sensor slot, not an actual reading. + if (temp is None or temp == 0) and status.lower() in ( + "unrecoverable", "unknown", "not available", + ): + continue result["temps"].append({ "index": idx, "status": status, @@ -267,4 +258,21 @@ def _parse_ses_page02(text: str) -> dict: "voltage": voltage, }) + # Derive overall_status from the actual parsed elements rather than + # the raw SES header, which counts dead/disconnected sensors as + # UNRECOV and inflates severity. + all_statuses = ( + [e["status"] for e in result["psus"]] + + [e["status"] for e in result["fans"]] + + [e["status"] for e in result["temps"]] + + [e["status"] for e in result["voltages"]] + ) + status_lower = [s.lower() for s in all_statuses] + if any(s in ("unrecoverable", "critical") for s in status_lower): + result["overall_status"] = "CRITICAL" + elif any(s in ("noncritical", "non-critical", "warning") for s in status_lower): + result["overall_status"] = "WARNING" + elif any(s not in ("ok", "unknown") for s in status_lower): + result["overall_status"] = "WARNING" + return result