diff --git a/cisco-ip-sla/cisco_ip_sla-1.0.1.mkp b/check_mk-cisco_ip_sla/2.2/cisco_ip_sla-1.0.1.mkp similarity index 100% rename from cisco-ip-sla/cisco_ip_sla-1.0.1.mkp rename to check_mk-cisco_ip_sla/2.2/cisco_ip_sla-1.0.1.mkp diff --git a/cisco-ip-sla/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py b/check_mk-cisco_ip_sla/2.2/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py similarity index 100% rename from cisco-ip-sla/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py rename to check_mk-cisco_ip_sla/2.2/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py diff --git a/cisco-ip-sla/2.2/cisco_ip_sla-1.0.1.mkp b/cisco-ip-sla/2.2/cisco_ip_sla-1.0.1.mkp new file mode 100644 index 0000000..5a71703 Binary files /dev/null and b/cisco-ip-sla/2.2/cisco_ip_sla-1.0.1.mkp differ diff --git a/cisco-ip-sla/2.2/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py b/cisco-ip-sla/2.2/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py new file mode 100644 index 0000000..2931e30 --- /dev/null +++ b/cisco-ip-sla/2.2/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +from cmk.gui.i18n import _ +from cmk.gui.plugins.wato.utils import ( + CheckParameterRulespecWithItem, + rulespec_registry, + RulespecGroupCheckParametersNetworking, +) +from cmk.gui.valuespec import Dictionary, DropdownChoice, Integer, TextInput, Tuple + + +def _item_spec_cisco_ip_sla(): + return TextInput( + title=_("RTT row index of the service"), + allow_empty=True, + ) + + +def _parameter_valuespec_cisco_ip_sla(): + return Dictionary( + elements=[ + ( + "rtt_type", + DropdownChoice( + title=_("RTT type"), + choices=[ + ("echo", _("echo")), + ("path echo", _("path echo")), + ("file IO", _("file IO")), + ("UDP echo", _("UDP echo")), + ("TCP connect", _("TCP connect")), + ("HTTP", _("HTTP")), + ("DNS", _("DNS")), + ("jitter", _("jitter")), + ("DLSw", _("DLSw")), + ("DHCP", _("DHCP")), + ("FTP", _("FTP")), + ("VoIP", _("VoIP")), + ("RTP", _("RTP")), + ("LSP group", _("LSP group")), + ("ICMP jitter", _("ICMP jitter")), + ("LSP ping", _("LSP ping")), + ("LSP trace", _("LSP trace")), + ("ethernet ping", _("ethernet ping")), + ("ethernet jitter", _("ethernet jitter")), + ("LSP ping pseudowire", _("LSP ping pseudowire")), + ], + default_value="echo", + ), + ), + ( + "threshold", + Integer( + title=_("Treshold"), + help=_( + "Depending on the precision the unit can be " + "either milliseconds or micoseconds." + ), + unit=_("ms/us"), + minvalue=1, + default_value=5000, + ), + ), + ( + "state", + DropdownChoice( + title=_("State"), + choices=[ + ("active", _("active")), + ("inactive", _("inactive")), + ("reset", _("reset")), + ("orderly stop", _("orderly stop")), + ("immediate stop", _("immediate stop")), + ("pending", _("pending")), + ("restart", _("restart")), + ], + default_value="active", + ), + ), + ( + "connection_lost_occured", + DropdownChoice( + title=_("Connection lost occured"), + choices=[ + ("yes", _("yes")), + ("no", _("no")), + ], + default_value="no", + ), + ), + ( + "timeout_occured", + DropdownChoice( + title=_("Timeout occured"), + choices=[ + ("yes", _("yes")), + ("no", _("no")), + ], + default_value="no", + ), + ), + ( + "completion_time_over_treshold_occured", + DropdownChoice( + title=_("Completion time over treshold occured"), + choices=[ + ("yes", _("yes")), + ("no", _("no")), + ], + default_value="no", + ), + ), + ( + "latest_rtt_completion_time", + Tuple( + title=_("Latest RTT completion time"), + help=_( + "Depending on the precision the unit can be " + "either milliseconds or micoseconds." + ), + elements=[ + Integer( + title=_("Warning at"), + unit=_("ms/us"), + minvalue=1, + default_value=100, + ), + Integer( + title=_("Critical at"), + unit=_("ms/us"), + minvalue=1, + default_value=200, + ), + ], + ), + ), + ( + "latest_rtt_state", + DropdownChoice( + title=_("Latest RTT state"), + choices=[ + ("ok", _("OK")), + ("disconnected", _("disconnected")), + ("over treshold", _("over treshold")), + ("timeout", _("timeout")), + ("other", _("other")), + ], + default_value="ok", + ), + ), + ( + "packets_lost_src->dest", + Tuple( + title=_("Packets lost src->dest"), + elements=[ + Integer( + title=_("Warning at"), + unit=_("packets"), + minvalue=1, + default_value=100, + ), + Integer( + title=_("Critical at"), + unit=_("packets"), + minvalue=1, + default_value=1000, + ), + ], + ), + ), + ( + "packets_lost_dest->src", + Tuple( + title=_("Packets lost dest->src"), + elements=[ + Integer( + title=_("Warning at"), + unit=_("packets"), + minvalue=1, + default_value=100, + ), + Integer( + title=_("Critical at"), + unit=_("packets"), + minvalue=1, + default_value=1000, + ), + ], + ), + ), + ], + ) + + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name="cisco_ip_sla", + group=RulespecGroupCheckParametersNetworking, + item_spec=_item_spec_cisco_ip_sla, + match_type="dict", + parameter_valuespec=_parameter_valuespec_cisco_ip_sla, + title=lambda: _("Cisco IP SLA"), + ) +) diff --git a/cisco-ip-sla/local/share/check_mk/checks/cisco_ip_sla b/cisco-ip-sla/2.2/local/share/check_mk/checks/cisco_ip_sla similarity index 99% rename from cisco-ip-sla/local/share/check_mk/checks/cisco_ip_sla rename to cisco-ip-sla/2.2/local/share/check_mk/checks/cisco_ip_sla index 66db9fa..15ace06 100644 --- a/cisco-ip-sla/local/share/check_mk/checks/cisco_ip_sla +++ b/cisco-ip-sla/2.2/local/share/check_mk/checks/cisco_ip_sla @@ -161,7 +161,7 @@ def check_cisco_ip_sla(_item, params, data): if state: infotext += " (warn/crit at %s/%s)" % (warn, crit) - if unit == "ms/us": + if unit == "ms" or unit == "us" or unit == "ms/us": factor = 1e3 if unit == "ms" else 1e6 perfdata = [ ("rtt", value / factor, warn / factor, crit / factor) diff --git a/cisco-ip-sla/2.3/cisco_ip_sla-0.1.0.mkp b/cisco-ip-sla/2.3/cisco_ip_sla-0.1.0.mkp new file mode 100755 index 0000000..de599a0 Binary files /dev/null and b/cisco-ip-sla/2.3/cisco_ip_sla-0.1.0.mkp differ diff --git a/cisco-ip-sla/2.3/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py b/cisco-ip-sla/2.3/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py new file mode 100644 index 0000000..919d003 --- /dev/null +++ b/cisco-ip-sla/2.3/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +from cmk.gui.i18n import _ +from cmk.gui.plugins.wato.utils import ( + CheckParameterRulespecWithItem, + rulespec_registry, + RulespecGroupCheckParametersNetworking, +) +from cmk.gui.valuespec import Dictionary, DropdownChoice, Integer, TextInput, Tuple + + +def _item_spec_cisco_ip_sla(): + return TextInput( + title=_("RTT row index of the service"), + allow_empty=True, + ) + + +def _parameter_valuespec_cisco_ip_sla(): + return Dictionary( + elements=[ + ( + "rtt_type", + DropdownChoice( + title=_("RTT type"), + choices=[ + ("echo", _("echo")), + ("path echo", _("path echo")), + ("file IO", _("file IO")), + ("UDP echo", _("UDP echo")), + ("TCP connect", _("TCP connect")), + ("HTTP", _("HTTP")), + ("DNS", _("DNS")), + ("jitter", _("jitter")), + ("DLSw", _("DLSw")), + ("DHCP", _("DHCP")), + ("FTP", _("FTP")), + ("VoIP", _("VoIP")), + ("RTP", _("RTP")), + ("LSP group", _("LSP group")), + ("ICMP jitter", _("ICMP jitter")), + ("LSP ping", _("LSP ping")), + ("LSP trace", _("LSP trace")), + ("ethernet ping", _("ethernet ping")), + ("ethernet jitter", _("ethernet jitter")), + ("LSP ping pseudowire", _("LSP ping pseudowire")), + ], + default_value="echo", + ), + ), + ( + "threshold", + Integer( + title=_("Treshold"), + help=_( + "Depending on the precision the unit can be " + "either milliseconds or micoseconds." + ), + unit=_("ms/us"), + minvalue=1, + default_value=5000, + ), + ), + ( + "state", + DropdownChoice( + title=_("State"), + choices=[ + ("active", _("active")), + ("inactive", _("inactive")), + ("reset", _("reset")), + ("orderly stop", _("orderly stop")), + ("immediate stop", _("immediate stop")), + ("pending", _("pending")), + ("restart", _("restart")), + ], + default_value="active", + ), + ), + ( + "connection_lost_occured", + DropdownChoice( + title=_("Connection lost occured"), + choices=[ + ("yes", _("yes")), + ("no", _("no")), + ], + default_value="no", + ), + ), + ( + "timeout_occured", + DropdownChoice( + title=_("Timeout occured"), + choices=[ + ("yes", _("yes")), + ("no", _("no")), + ], + default_value="no", + ), + ), + ( + "completion_time_over_treshold_occured", + DropdownChoice( + title=_("Completion time over treshold occured"), + choices=[ + ("yes", _("yes")), + ("no", _("no")), + ], + default_value="no", + ), + ), + ( + "latest_rtt_completion_time", + Tuple( + title=_("Latest RTT completion time"), + help=_( + "Depending on the precision the unit can be " + "either milliseconds or micoseconds." + ), + elements=[ + Integer( + title=_("Warning at"), + unit=_("ms/us"), + minvalue=1, + default_value=100, + ), + Integer( + title=_("Critical at"), + unit=_("ms/us"), + minvalue=1, + default_value=200, + ), + ], + ), + ), + ( + "latest_rtt_state", + DropdownChoice( + title=_("Latest RTT state"), + choices=[ + ("ok", _("OK")), + ("disconnected", _("disconnected")), + ("over treshold", _("over treshold")), + ("timeout", _("timeout")), + ("other", _("other")), + ], + default_value="ok", + ), + ), + ( + "packets_lost_src->dest", + Tuple( + title=_("Packets lost src->dest"), + elements=[ + Integer( + title=_("Warning at"), + unit=_("packets"), + minvalue=1, + default_value=100, + ), + Integer( + title=_("Critical at"), + unit=_("packets"), + minvalue=1, + default_value=1000, + ), + ], + ), + ), + ( + "packets_lost_dest->src", + Tuple( + title=_("Packets lost dest->src"), + elements=[ + Integer( + title=_("Warning at"), + unit=_("packets"), + minvalue=1, + default_value=100, + ), + Integer( + title=_("Critical at"), + unit=_("packets"), + minvalue=1, + default_value=1000, + ), + ], + ), + ), + ], + ) + + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name="cisco_ip_sla", + group=RulespecGroupCheckParametersNetworking, + item_spec=_item_spec_cisco_ip_sla, + match_type="dict", + parameter_valuespec=_parameter_valuespec_cisco_ip_sla, + title=lambda: _("Cisco IP SLA"), + ) +) diff --git a/cisco-ip-sla/2.3/local/share/check_mk/checks/cisco_ip_sla b/cisco-ip-sla/2.3/local/share/check_mk/checks/cisco_ip_sla new file mode 100644 index 0000000..2cf7942 --- /dev/null +++ b/cisco-ip-sla/2.3/local/share/check_mk/checks/cisco_ip_sla @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + + +from collections.abc import Callable, Sequence + +from cmk.base.check_api import LegacyCheckDefinition +from cmk.base.config import check_info + +from cmk.agent_based.v2 import all_of, contains, exists, OIDBytes, OIDEnd, SNMPTree + + +def parse_cisco_ip_sla(string_table): + precisions = {line[0]: "ms" if line[-1] == "1" else "us" for line in string_table[0]} + + rtt_types = { + "1": "echo", + "2": "path echo", + "3": "file IO", + "4": "script", + "5": "UDP echo", + "6": "TCP connect", + "7": "HTTP", + "8": "DNS", + "9": "jitter", + "10": "DLSw", + "11": "DHCP", + "12": "FTP", + "13": "VoIP", + "14": "RTP", + "15": "LSP group", + "16": "ICMP jitter", + "17": "LSP ping", + "18": "LSP trace", + "19": "ethernet ping", + "20": "ethernet jitter", + "21": "LSP ping pseudowire", + } + + states = { + "1": "reset", + "2": "orderly stop", + "3": "immediate stop", + "4": "pending", + "5": "inactive", + "6": "active", + "7": "restart", + } + + rtt_states = { + "0": "other", + "1": "ok", + "2": "disconnected", + "3": "over threshold", + "4": "timeout", + "5": "busy", + "6": "not connected", + "7": "dropped", + "8": "sequence error", + "9": "verify error", + "10": "application specific error", + } + + def to_ip_address(int_list): + if len(int_list) == 4: + return "%d.%d.%d.%d" % tuple(int_list) + elif len(int_list) == 6: + return "%d:%d:%d:%d:%d:%d" % tuple(int_list) + return "" + + # contains description, parse function, unit and type + contents: Sequence[tuple[tuple[str, Callable | None, str, str | None], ...]] = [ + ( # rttMonEchoAdminEntry + ("Target address", to_ip_address, "", None), + ("Source address", to_ip_address, "", None), + # rttMonEchoAdminPrecision is deliberatly dropped by zip below + ), + ( # rttMonCtrlAdminEntry + ("Owner", None, "", None), + ("Tag", None, "", None), + ("RTT type", lambda x: rtt_types.get(x, "unknown"), "", "option"), + ("Threshold", int, "ms", "option"), + ), + ( # rttMonCtrlOperEntry + ("State", lambda x: states.get(x, "unknown"), "", "option"), + ("Text", None, "", None), + ( + "Connection lost occured", + lambda x: "yes" if x == "1" else "no", + "", + "option", + ), + ("Timeout occured", lambda x: "yes" if x == "1" else "no", "", "option"), + ( + "Completion time over treshold occured", + lambda x: "yes" if x == "1" else "no", + "", + "option", + ), + ), + ( # rttMonLatestRttOperEntry + ("Latest RTT completion time", int, "ms/us", "level"), + ("Latest RTT state", lambda x: rtt_states.get(x, "unknown"), "", "option"), + ), + ( # rttMonJitterStatsEntry + ("Packets lost src->dest", int, "packets", "level"), + ("Packets lost dest->src", int, "packets", "level"), + ), + ] + + parsed: dict[str, list] = {} + for content, entries in zip(contents, string_table): + if not entries: + continue + + for entry in entries: + index, values = entry[0], entry[1:] + data = parsed.setdefault(index, []) + for (description, parser, unit, type_), value in zip(content, values): + if parser: + value = parser(value) + if unit == "ms/us": + unit = precisions[index] + data.append((description, value, unit, type_)) + + return parsed + + +def inventory_cisco_ip_sla(parsed): + for index in parsed: + yield index, {} + + +def check_cisco_ip_sla(item, params, parsed): + if not (data := parsed.get(item)): + return + for description, value, unit, type_ in data: + if not value and "packets" not in unit: + continue + + state = 0 + if unit: + infotext = f"{description}: {value} {unit}" + else: + infotext = f"{description}: {value}" + perfdata = [] + + param = params.get(description.lower().replace(" ", "_")) + + if type_ == "option": + if param and param != value: + state = 1 + infotext += " (expected %s)" % param + elif type_ == "level": + warn, crit = param # a default level hat to exist + if value >= crit: + state = 2 + elif value >= warn: + state = 1 + + if state: + infotext += f" (warn/crit at {warn}/{crit})" + + # last check ("ms/us") is probably a harmless bug, but keeping + if unit == "ms" or unit == "us" or unit == "ms/us": + factor = 1e3 if unit == "ms" else 1e6 + perfdata = [ + ("rtt", value / factor, warn / factor, crit / factor) + ] # fixed: true-division + elif unit == "packets": + perfdata = [ + ("lost", value, warn, crit) + ] + + yield state, infotext, perfdata + + +check_info["cisco_ip_sla"] = LegacyCheckDefinition( + detect=all_of( + contains(".1.3.6.1.2.1.1.1.0", "cisco"), + contains(".1.3.6.1.2.1.1.1.0", "ios"), + exists(".1.3.6.1.4.1.9.9.42.1.2.2.1.37.*"), + ), + fetch=[ + SNMPTree( + base=".1.3.6.1.4.1.9.9.42.1.2.2.1", + oids=[OIDEnd(), OIDBytes("2"), OIDBytes("6"), "37"], + ), + SNMPTree( + base=".1.3.6.1.4.1.9.9.42.1.2.1.1", + oids=[OIDEnd(), "2", "3", "4", "5"], + ), + SNMPTree( + base=".1.3.6.1.4.1.9.9.42.1.2.9.1", + oids=[OIDEnd(), "10", "2", "5", "6", "7"], + ), + SNMPTree( + base=".1.3.6.1.4.1.9.9.42.1.2.10.1", + oids=[OIDEnd(), "1", "2"], + ), + SNMPTree( + base=".1.3.6.1.4.1.9.9.42.1.5.2.1", + # rttMonLatestJitterOperPacketLossSD + # rttMonLatestJitterOperPacketLossDS + oids=[OIDEnd(), "26", "27"], + ), + ], + parse_function=parse_cisco_ip_sla, + service_name="Cisco IP SLA %s", + discovery_function=inventory_cisco_ip_sla, + check_function=check_cisco_ip_sla, + check_ruleset_name="cisco_ip_sla", + check_default_parameters={ + "state": "active", + "connection_lost_occured": "no", + "timeout_occured": "no", + "completion_time_over_treshold_occured": "no", + "latest_rtt_completion_time": (250, 500), + "latest_rtt_state": "ok", + "packets_lost_src->dest": (100, 1000), + "packets_lost_dest->src": (100, 1000), + }, +)