From 3fea3738cadd1a4eee8721aefa9ae74841e08553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20B=C3=BCttner?= Date: Thu, 22 May 2025 09:55:57 +0200 Subject: [PATCH] netapp_ontap_status: Respect suppression and acknowledgements Netapp allows to suppress and acknowledge alerts in its GUI. This change modifies netapp_ontap_status to consider all alerts that are either acknowledged or suppressed on the Netapp side as OK. If alerts are present, but all are suppressed, these will be listed in the details. --- .../netapp/agent_based/netapp_ontap_status.py | 30 +++++++++++++++-- cmk/plugins/netapp/models.py | 4 +++ .../agent_based/test_netapp_ontap_status.py | 33 +++++++++++++++++-- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/cmk/plugins/netapp/agent_based/netapp_ontap_status.py b/cmk/plugins/netapp/agent_based/netapp_ontap_status.py index a1dabcef775..b367e21bcae 100644 --- a/cmk/plugins/netapp/agent_based/netapp_ontap_status.py +++ b/cmk/plugins/netapp/agent_based/netapp_ontap_status.py @@ -29,6 +29,15 @@ # } +def format_alert(alert): + s = alert["name"] + if alert.get("acknowledge"): + s += f", acknowledged by {alert['acknowledger']}" + if alert.get("suppress"): + s += f", suppressed by {alert['suppressor']}" + return s + + def parse_netapp_api_status(string_table: StringTable) -> Section: return [ alert for line in string_table for alert in [models.AlertModel.model_validate_json(line[0])] @@ -51,9 +60,26 @@ def check_netapp_ontap_status(section: Section) -> CheckResult: """ if not section: - yield Result(state=State.OK, summary="Status: OK") + yield Result(state=State.OK, summary="No alerts present") else: - yield Result(state=State.CRIT, summary="Status: Alerts present") + alerts = [dict(alert) for alert in section] + unhandled_alerts = [ + alert for alert in alerts if not (alert.get("acknowledge") or alert.get("suppress")) + ] + handled_alerts = [ + alert for alert in alerts if alert.get("acknowledge") or alert.get("suppress") + ] + details = "\n".join(format_alert(alert) for alert in unhandled_alerts + handled_alerts) + if unhandled_alerts: + yield Result( + state=State.CRIT, summary="Unhandled alerts present, see details", details=details + ) + else: + yield Result( + state=State.OK, + summary="Alerts present, but all acknowledged or suppressed, see details", + details=details, + ) check_plugin_netapp_ontap_status = CheckPlugin( diff --git a/cmk/plugins/netapp/models.py b/cmk/plugins/netapp/models.py index 5b1a3995667..b356048420e 100644 --- a/cmk/plugins/netapp/models.py +++ b/cmk/plugins/netapp/models.py @@ -545,6 +545,10 @@ class AlertModel(BaseModel): """ name: str + acknowledge: bool + acknowledger: str = "" + suppress: bool + suppressor: str = "" class SvmTrafficCountersModel(BaseModel): diff --git a/tests/unit/cmk/plugins/netapp/agent_based/test_netapp_ontap_status.py b/tests/unit/cmk/plugins/netapp/agent_based/test_netapp_ontap_status.py index ba7066ecf40..b5a0fefe7e9 100644 --- a/tests/unit/cmk/plugins/netapp/agent_based/test_netapp_ontap_status.py +++ b/tests/unit/cmk/plugins/netapp/agent_based/test_netapp_ontap_status.py @@ -21,15 +21,42 @@ class AlertModelFactory(ModelFactory): "alerts_models, expected_result", [ pytest.param( - [AlertModelFactory.build(name="alert1"), AlertModelFactory.build(name="alert2")], - [Result(state=State.CRIT, summary="Status: Alerts present")], + [ + AlertModelFactory.build(name="alert1", acknowledge=False, suppress=False), + AlertModelFactory.build(name="alert2", acknowledge=False, suppress=False), + ], + [ + Result( + state=State.CRIT, + summary="Unhandled alerts present, see details", + details="alert1\nalert2", + ) + ], id="alerts present", ), pytest.param( [], - [Result(state=State.OK, summary="Status: OK")], + [Result(state=State.OK, summary="No alerts present")], id="no alerts present", ), + pytest.param( + [ + AlertModelFactory.build( + name="alert1", acknowledge=True, acknowledger="hhirsch", suppress=False + ), + AlertModelFactory.build( + name="alert2", acknowledge=False, suppress=True, suppressor="hhirsch" + ), + ], + [ + Result( + state=State.OK, + summary="Alerts present, but all acknowledged or suppressed, see details", + details="alert1, acknowledged by hhirsch\nalert2, suppressed by hhirsch", + ) + ], + id="alerts suppressed", + ), ], ) def test_check_netapp_ontap_status(