diff --git a/CHANGELOG b/CHANGELOG index 7305a0001589628c0eaa0e2e3e2f98b31d00c907..4599d9ce2b2d817c613b06a06356e294193c7727 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,3 +17,5 @@ 2022-04-01: added RADIO MAC address 2022-05-31: removed "Software" from snmp detect function 2022-10-23: fixed warning in upgrade "non-empty params vanished" for vpn_entry +2023-02-21: added cluster function (backport from check_mk) THX to roger[dot]ellenberger[at]wagner[dot]ch + diff --git a/agent_based/cisco_wlc.py b/agent_based/cisco_wlc.py index f36ff2f5211eeea4786c5dc4bb5b4df5294c4686..87133bb05d4baf3faf2530967d4c628a584b7316 100644 --- a/agent_based/cisco_wlc.py +++ b/agent_based/cisco_wlc.py @@ -26,10 +26,12 @@ # 2022-04-01: added RADIO MAC address # 2022-05-31: removed "Software" from snmp detect function # 2022-10-23: fixed warning on upgrade "non-empty params vanished" for inv_ap_info +# 2023-02-21: added cluster function (backport from check_mk) THX to roger[dot]ellenberger[at]wagner[dot]ch +# from time import time from dataclasses import dataclass -from typing import Optional, List, Dict +from typing import Optional, List, Dict, Mapping, Any, Union from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( DiscoveryResult, CheckResult, @@ -120,6 +122,8 @@ class InvApInfo: cdp_neigh_platform: Optional[str] = None +Section = Dict[str, Ap] + _operationasl_state = { 1: 'associated', 2: 'disassociating', @@ -152,7 +156,6 @@ _cdp_speed = { '5': 'auto', } - _interface_displayhints = { 'ethernet': 'eth', 'fastethernet': 'Fa', @@ -168,6 +171,12 @@ _interface_displayhints = { 'management': 'Ma', } +_map_states = { + "1": (State.OK, "online"), + "2": (State.CRIT, "critical"), + "3": (State.WARN, "warning"), +} + def _get_short_if_name(ifname: str) -> str: """ @@ -293,7 +302,6 @@ def parse_cisco_wlc(string_table: List[StringTable]) -> Optional[Dict[str, Ap]]: lwap_info=_get_lwapap_info(ap_oid_end, lwapap), ) }) - return parsed @@ -304,7 +312,7 @@ def parse_cisco_wlc(string_table: List[StringTable]) -> Optional[Dict[str, Ap]]: ########################################################################### -def discovery_cisco_wlc(section: Dict[str, Ap]) -> DiscoveryResult: +def discovery_cisco_wlc(section: Section) -> DiscoveryResult: for ap_name in section.keys(): ap = section.get(ap_name) @@ -334,7 +342,7 @@ def discovery_cisco_wlc(section: Dict[str, Ap]) -> DiscoveryResult: ########################################################################### -def check_cisco_wlc(item, params, section: Dict[str, Ap]) -> CheckResult: +def check_cisco_wlc(item, params, section: Section) -> CheckResult: ap_missing_state = params.get('state_ap_missing', 1) if params.get('inv_ap_info'): inv_ap_info = InvApInfo( @@ -571,6 +579,48 @@ def check_cisco_wlc(item, params, section: Dict[str, Ap]) -> CheckResult: else: yield Result(state=State.WARN, summary='AP data from discovery missing.') +########################################################################### +# +# Cluster function +# +########################################################################### + + +def _node_not_found(item: str, params: Mapping[str, Any]) -> Result: + infotext = "Accesspoint not found" + for ap_name, ap_state in params.get("ap_name", []): + if item.startswith(ap_name): + return Result(state=ap_state, summary=infotext) + return Result(state=State.CRIT, summary=infotext) + + +def _ap_info(node: Optional[str], wlc_status: Union[str, Ap]) -> Result: + wlc_status = str(wlc_status.ap_info.ap_operationstatus) if isinstance(wlc_status, Ap) else wlc_status + status, state_readable = _map_states.get(wlc_status, (State.UNKNOWN, f"unknown[{wlc_status}]")) + return Result(state=status, + summary="Accesspoint: %s%s" % (state_readable, (" (connected to %s)" % node) if node else ""), + ) + + +def cluster_check_cisco_wlc( + item: str, + params: Mapping[str, Any], + section: Mapping[str, Optional[Section]], +) -> CheckResult: + + for node, node_section in section.items(): + if node_section is not None and item in node_section: + yield _ap_info(node, node_section[item]) + yield from check_cisco_wlc(item, params, node_section) + return + yield _node_not_found(item, params) + +########################################################################### +# +# Register SNMP section +# +########################################################################### + register.snmp_section( name='cisco_wlc', @@ -635,6 +685,13 @@ register.snmp_section( contains('.1.3.6.1.2.1.1.1.0', 'C9800'), # sysDescr -> IOS-XE )) +########################################################################### +# +# Register Check Plugin +# +########################################################################### + + register.check_plugin( name='cisco_wlc', service_name='AP %s', @@ -656,4 +713,5 @@ register.check_plugin( # 'inv_ap_info': {}, }, check_ruleset_name='cisco_wlc', + cluster_check_function=cluster_check_cisco_wlc, ) diff --git a/cisco_wlc.mkp b/cisco_wlc.mkp index c52c8c134ed37078a3f4ba5e450b8f1543d2009d..45dd8e4c2cf646e68e9b0486f7db3808d26c9a72 100644 Binary files a/cisco_wlc.mkp and b/cisco_wlc.mkp differ diff --git a/packages/cisco_wlc b/packages/cisco_wlc index ca244c5cb5165ad3b7c7e480f5f5ad375f2c2b68..e2cb239f0cef5e82dc5a94d37e4dcc2bc3f049d8 100644 --- a/packages/cisco_wlc +++ b/packages/cisco_wlc @@ -12,9 +12,8 @@ 'web': ['plugins/wato/cisco_wlc.py', 'plugins/metrics/cisco_wlc.py']}, 'name': 'cisco_wlc', - 'num_files': 3, 'title': 'monitor Cisco WLC APs', - 'version': '20221023.v0.6b', + 'version': '20230221.v0.7', 'version.min_required': '2.0.0', - 'version.packaged': '2021.09.20', + 'version.packaged': '2.1.0p21', 'version.usable_until': None} \ No newline at end of file diff --git a/web/plugins/wato/cisco_wlc.py b/web/plugins/wato/cisco_wlc.py index 6a10e240dc84d3bec2e2758145d7a48424547d63..c0ed795298af71121a7914314fc5ed1ec6021678 100644 --- a/web/plugins/wato/cisco_wlc.py +++ b/web/plugins/wato/cisco_wlc.py @@ -109,6 +109,7 @@ def _parameter_valuespec_cisco_wlc(): help=_('The configured value must match a AP item as reported by the monitored ' 'device. For example: "AP1.4"'), allow_empty=False, + size=40, ), TextUnicode( title=_('AP Alias'), @@ -116,8 +117,10 @@ def _parameter_valuespec_cisco_wlc(): 'the text configured in the "AP item name" field. The alias will ' 'be shown in the check info'), allow_empty=False, + size=40, ), - ] + ], + orientation='horizontal', ), title=_('AP alias'), add_label=_('Add name'))),