Filter dead temp sensors from SES health and recompute overall status

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.
This commit is contained in:
2026-03-16 22:19:58 +00:00
parent 3185acbb24
commit 50dd2a631e

View File

@@ -183,21 +183,6 @@ def _parse_ses_page02(text: str) -> dict:
"voltages": [], "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. # Split into element type sections.
# Each section starts with "Element type: <type>" # Each section starts with "Element type: <type>"
sections = re.split(r"(?=\s*Element type:)", text) sections = re.split(r"(?=\s*Element type:)", text)
@@ -250,6 +235,12 @@ def _parse_ses_page02(text: str) -> dict:
elif "temperature" in element_type: elif "temperature" in element_type:
temp_match = re.search(r"Temperature=\s*([\d.]+)\s*C", elem_text) temp_match = re.search(r"Temperature=\s*([\d.]+)\s*C", elem_text)
temp = float(temp_match.group(1)) if temp_match else None 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({ result["temps"].append({
"index": idx, "index": idx,
"status": status, "status": status,
@@ -267,4 +258,21 @@ def _parse_ses_page02(text: str) -> dict:
"voltage": voltage, "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 return result