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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user