From cffe6a2bd7265281268f73c617eb083dd26c23d4 Mon Sep 17 00:00:00 2001 From: "David K." <142583+neffs@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:18:33 +0200 Subject: [PATCH 1/3] genua_extend check Support for GENUA-EXTEND-MIB --- genua/agent_based/genua_extend.py | 172 ++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 genua/agent_based/genua_extend.py diff --git a/genua/agent_based/genua_extend.py b/genua/agent_based/genua_extend.py new file mode 100644 index 0000000..9eaee08 --- /dev/null +++ b/genua/agent_based/genua_extend.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 + +"""checkmk plugin for GENUA-EXTEND-MIB""" + +from cmk.agent_based.v2 import ( + SimpleSNMPSection, + SNMPTree, + StringTable, + State, + CheckPlugin, + DiscoveryResult, + CheckResult, + Service, + Result, + check_levels, + all_of, + exists, +) + +from cmk.plugins.lib.genua import DETECT_GENUA + +import re + +Section = dict[str, dict[str, str]] + + +def parse_genua_extend(string_table: StringTable) -> Section: + parsed = {} + for line in string_table: + extendName, extendDescription, extendStatus, extendPerformancedata = line + extendPerformancedata = { + name: val + for name, val in [ + a.split("=") for a in extendPerformancedata.split(" ") if "=" in a + ] + } + sub_parsed = { + "extendName": extendName, + "extendDescription": extendDescription, + "extendStatus": int(extendStatus), + "extendPerformancedata": extendPerformancedata, + } + parsed[extendName] = sub_parsed + return parsed + + +snmp_section_genua_extend = SimpleSNMPSection( + name="genua_extend", + detect=all_of( + DETECT_GENUA, + exists(".1.3.6.1.4.1.3717.66.1.1.*"), # genuaExtend + ), + fetch=SNMPTree( + base=".1.3.6.1.4.1.3717.66.1.1", # GENUA-EXTEND-MIB::extendTable + oids=[ + "1", # extendName + "2", # extendDescription + "3", # extendStatus + "4", # extendPerformancedata + ], + ), + parse_function=parse_genua_extend, +) + + +def discover_genua_extend(section: Section) -> DiscoveryResult: + for check in section.keys(): + yield Service( + item=check, + ) + + +# Helpers + + +def float_ignore_uom(value: str) -> float: + """16MB -> 16.0""" + while value: + try: + return float(value) + except ValueError: + value = value[:-1] + return 0.0 + + +def uom_from_value(value: str) -> str: + """16.2MB -> MB""" + m = re.match(r"[0-9.]* ?(.*)", value) + return m.group(1) if m else None + + +def render_value_func(uom): + """Render function with supplied UOM""" + + def render_value(value): + int_value = int(value) + if value == int_value: + value = int_value + return f"{value} {uom}" + + return render_value + + +def parse_thresholds(t): + """Parse simple Nagios-style thresholds + '10', '10:' or '10:20' are supported, but not @, ~""" + if ":" in t: + upper, _, lower = t.partition(":") + upper = float_or_none(upper) + lower = float_or_none(lower) + return lower, upper + return float_or_none(t), None + + +def float_or_none(string): + try: + f = float(string) + return f + except ValueError: + return None + + +def check_genua_extend(item: str, params: dict, section: Section) -> CheckResult: + pe = section.get(item, {}) + statuscode = pe.get("extendStatus", 99) + code2state = {0: State.OK, 1: State.WARN, 2: State.CRIT, 3: State.UNKNOWN} + + if statuscode in range(0, 4): + yield Result( + state=code2state[statuscode], + summary=pe.get("extendDescription", "No Description"), + ) + else: + desc = pe.get("extendDescription", "No SNMP data") + yield Result(state=State.UNKNOWN, summary=desc) + extendPerformancedata = pe.get("extendPerformancedata", {}) + for name, value in extendPerformancedata.items(): + split_v = value.split(";") + while len(split_v) <= 5: + split_v.append("") + value, warn, crit, min_bound, max_bound = split_v[0:5] + check_params = {} + + min_bound = float_or_none(min_bound) + max_bound = float_or_none(max_bound) + crit_upper, crit_lower = parse_thresholds(crit) + warn_upper, warn_lower = parse_thresholds(warn) + + if min_bound or max_bound: + check_params["boundaries"] = (min_bound, max_bound) + if warn_upper and crit_upper: + check_params["levels_upper"] = ("fixed", (crit_upper, warn_upper)) + if warn_lower and crit_lower: + check_params["levels_lower"] = ("fixed", (crit_lower, warn_lower)) + uom = uom_from_value(value) + value = float_ignore_uom(value) + if uom: + check_params["render_func"] = render_value_func(uom) + + yield from check_levels( + value, metric_name=name, label=name, notice_only=True, **check_params + ) + + +check_plugin_genua_extend = CheckPlugin( + name="genua_extend", + service_name="Extend %s", + sections=["genua_extend"], + discovery_function=discover_genua_extend, + check_function=check_genua_extend, + check_ruleset_name="genua_extend", +) From 8d031aacb0c8f7cefa05a84256ed70bb6fa77f1d Mon Sep 17 00:00:00 2001 From: "David K." <142583+neffs@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:22:46 +0200 Subject: [PATCH 2/3] manpage for genua_extend --- genua/checkman/genua_extend | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 genua/checkman/genua_extend diff --git a/genua/checkman/genua_extend b/genua/checkman/genua_extend new file mode 100644 index 0000000..24ed7c7 --- /dev/null +++ b/genua/checkman/genua_extend @@ -0,0 +1,15 @@ +title: genua: Extend +agents: snmp +catalog: hw/network/genua +license: GPLv2 +distribution: check_mk +description: + This check shows custom check data created by customer specific scripts on + genua appliances. The format is described in GENUA-EXTEND-MIB. + + The check supports the OID table under ".1.3.6.1.4.1.3717.66.1.1" + +discovery: + A service is created if + - the device is recognized as a genua device + - the OID table under ".1.3.6.1.4.1.3717.66.1.1.*" exists From e19e95c81550e6bfd3f3a875832bd0bd6c516924 Mon Sep 17 00:00:00 2001 From: "David K." <142583+neffs@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:23:26 +0200 Subject: [PATCH 3/3] Fix default parameters --- genua/agent_based/genua_extend.py | 1 + 1 file changed, 1 insertion(+) diff --git a/genua/agent_based/genua_extend.py b/genua/agent_based/genua_extend.py index 9eaee08..908364a 100644 --- a/genua/agent_based/genua_extend.py +++ b/genua/agent_based/genua_extend.py @@ -169,4 +169,5 @@ def check_genua_extend(item: str, params: dict, section: Section) -> CheckResult discovery_function=discover_genua_extend, check_function=check_genua_extend, check_ruleset_name="genua_extend", + check_default_parameters={}, )