checkmk-plugins/check_mk-cisco_ip_sla/local/share/check_mk/checks/cisco_ip_sla

238 lines
7.3 KiB
Python

#!/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.
factory_settings["cisco_ip_sla_default_levels"] = {
"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),
}
def parse_cisco_ip_sla(info):
precisions = {line[0]: "ms" if line[-1] == "1" else "us" for line in info[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 = [
( # 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 = {}
for content, entries in zip(contents, info):
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, {}
@get_parsed_item_data
def check_cisco_ip_sla(_item, params, data):
for description, value, unit, type_ in data:
if not value and "packets" not in unit:
continue
state = 0
if unit:
infotext = "%s: %s %s" % (description, value, unit)
else:
infotext = "%s: %s" % (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 += " (warn/crit at %s/%s)" % (warn, crit)
if 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"] = {
"parse_function": parse_cisco_ip_sla,
"inventory_function": inventory_cisco_ip_sla,
"check_function": check_cisco_ip_sla,
"service_description": "Cisco IP SLA %s",
"group": "cisco_ip_sla",
"default_levels_variable": "cisco_ip_sla_default_levels",
"has_perfdata": True,
"snmp_scan_function": lambda oid: "cisco" in oid(".1.3.6.1.2.1.1.1.0").lower()
and "ios" in oid(".1.3.6.1.2.1.1.1.0").lower()
and oid(".1.3.6.1.4.1.9.9.42.1.2.2.1.37.*"),
"snmp_info": [
(
".1.3.6.1.4.1.9.9.42.1.2.2.1",
[
OID_END,
BINARY(2), # rttMonEchoAdminTargetAddress
BINARY(6), # rttMonEchoAdminSourceAddress
# only needed to determine the unit (ms/us)
37, # rttMonEchoAdminPrecision
],
),
(
".1.3.6.1.4.1.9.9.42.1.2.1.1",
[
OID_END,
2, # rttMonCtrlAdminOwner
3, # rttMonCtrlAdminTag
4, # rttMonCtrlAdminRttType
5, # rttMonCtrlAdminThreshold
],
),
(
".1.3.6.1.4.1.9.9.42.1.2.9.1",
[
OID_END,
10, # rttMonCtrlOperState
2, # rttMonCtrlOperDiagText
5, # rttMonCtrlOperConnectionLostOccurred
6, # rttMonCtrlOperTimeoutOccurred
7, # rttMonCtrlOperOverThresholdOccurred
],
),
(
".1.3.6.1.4.1.9.9.42.1.2.10.1",
[
OID_END,
1, # rttMonLatestRttOperCompletionTime
2, # rttMonLatestRttOperSense
],
),
(
".1.3.6.1.4.1.9.9.42.1.5.2.1",
[
OID_END,
26, # rttMonLatestJitterOperPacketLossSD
27, # rttMonLatestJitterOperPacketLossDS
]
)
],
}