From bb424f90fe9716da18fac2598c698723445990d3 Mon Sep 17 00:00:00 2001 From: Marsell Kukuljevic Date: Mon, 3 Jul 2023 15:14:25 +0200 Subject: [PATCH] Add three Cisco plugins (GDOI, SLA, BGP) used for BCCD-13. --- .../Cisco_BGP_Peer3-1.1.mkp | Bin 0 -> 9497 bytes check_mk-cisco_bgp_peer/README.md | 1 + .../plugins/agent_based/cisco_bgp_peer.py | 665 ++++++++++++++++++ .../web/plugins/metrics/cisco_bgp_peer.py | 178 +++++ .../web/plugins/wato/cisco_bgp_peer.py | 126 ++++ check_mk-cisco_gdoi/README.md | 1 + check_mk-cisco_gdoi/cisco_gdoi-1.1.0.mkp | Bin 0 -> 1534 bytes .../base/plugins/agent_based/cisco_gdoi.py | 98 +++ check_mk-cisco_ip_sla/README.md | 1 + check_mk-cisco_ip_sla/cisco_ip_sla-1.0.1.mkp | Bin 0 -> 3724 bytes .../wato/check_parameters/cisco_ip_sla.py | 208 ++++++ .../local/share/check_mk/checks/cisco_ip_sla | 237 +++++++ 12 files changed, 1515 insertions(+) create mode 100755 check_mk-cisco_bgp_peer/Cisco_BGP_Peer3-1.1.mkp create mode 100644 check_mk-cisco_bgp_peer/README.md create mode 100644 check_mk-cisco_bgp_peer/local/lib/check_mk/base/plugins/agent_based/cisco_bgp_peer.py create mode 100644 check_mk-cisco_bgp_peer/local/share/check_mk/web/plugins/metrics/cisco_bgp_peer.py create mode 100644 check_mk-cisco_bgp_peer/local/share/check_mk/web/plugins/wato/cisco_bgp_peer.py create mode 100644 check_mk-cisco_gdoi/README.md create mode 100755 check_mk-cisco_gdoi/cisco_gdoi-1.1.0.mkp create mode 100644 check_mk-cisco_gdoi/local/lib/check_mk/base/plugins/agent_based/cisco_gdoi.py create mode 100644 check_mk-cisco_ip_sla/README.md create mode 100644 check_mk-cisco_ip_sla/cisco_ip_sla-1.0.1.mkp create mode 100644 check_mk-cisco_ip_sla/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py create mode 100644 check_mk-cisco_ip_sla/local/share/check_mk/checks/cisco_ip_sla diff --git a/check_mk-cisco_bgp_peer/Cisco_BGP_Peer3-1.1.mkp b/check_mk-cisco_bgp_peer/Cisco_BGP_Peer3-1.1.mkp new file mode 100755 index 0000000000000000000000000000000000000000..9408abb44849e82e32c92f7d37e4e1e1d92f56aa GIT binary patch literal 9497 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 KJ`Mr^3GqJ}KgNLo literal 0 HcmV?d00001 diff --git a/check_mk-cisco_bgp_peer/README.md b/check_mk-cisco_bgp_peer/README.md new file mode 100644 index 0000000..49a4da9 --- /dev/null +++ b/check_mk-cisco_bgp_peer/README.md @@ -0,0 +1 @@ +This is a modification of a GPL plugin to additionally support CISCO-BGP4-MIB::CbgpPeer3Entry diff --git a/check_mk-cisco_bgp_peer/local/lib/check_mk/base/plugins/agent_based/cisco_bgp_peer.py b/check_mk-cisco_bgp_peer/local/lib/check_mk/base/plugins/agent_based/cisco_bgp_peer.py new file mode 100644 index 0000000..28e984e --- /dev/null +++ b/check_mk-cisco_bgp_peer/local/lib/check_mk/base/plugins/agent_based/cisco_bgp_peer.py @@ -0,0 +1,665 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2017-12-26 +# +# Monitor status of Cisco BGP Peer (IPv4 and IPv6) +# +# 2018-05-24: changed counters to 1/s +# 2018-05-25: a lot of code cleanup +# packet name changed from cisco_bgp to cisco_bgp_peer +# added support of more then one address family per peer +# (changed item from remoteip to remoteip+familyname, rewrite of parer, inventory and check function) +# 2018-05-27: changed scan function from '.1.3.6.1.4.1.9.9.187.1.2.7.1.3.* to sysdecr contains cisco +# 2018-05-28: changed wato, added peer alias, state if not found, infotext values +# 2018-05-29: fixed longoutpout (removed not configured) +# 2018-11-02: modified scanfunction (from "find 'cisco' =-1" to "'cisco' in OID" +# 2019-18-02: added fix for empty values ("" instead of "0") sugested by Laurent Barbier (lbarbier[at]arkane-studios[dot]com) +# 2020-02-24: added workaround for missing cbgpPeer2AddrFamily (example L2VPN EVPN peers, Fix for jonale82[at]gmail[dot]com) +# 2020-03-02: changed handling of perfdata, add only data the are really there (not None, instead of setting them to 0) +# 2020-06-04: code cleanup --> changed isdigit test to try/except loop, changed peer.get test to try/except loop +# 2020-09-10: fixed typo in metrics file. FMS --> FSM (thanks martin[dot]pechstein[at]posteo[dot]de) +# 2021-03-27: rewrite for CMK2.0 +# 2021-03-28: added warning for missing admin prefix limit/warn threshold +# 2023-01-15: modified by Spearhead Systems to support CISCO-BGP4-MIB::CbgpPeer3Entry + +# +# snmpwalk sample +# +# CISCO-BGP4-MIB::cbgpPeer2AddrFamilyEntry +# +# OMD[mysite]:~$ snmpwalk -ObentU -v2c -c simulant 1.3.6.1.4.1.9.9.187.1.2.7 +# .1.3.6.1.4.1.9.9.187.1.2.7.1.3.1.4.62.214.127.57.1.1 = STRING: "IPv4 Unicast" +# .1.3.6.1.4.1.9.9.187.1.2.7.1.3.1.4.217.119.208.1.1.1 = STRING: "IPv4 Unicast" +# .1.3.6.1.4.1.9.9.187.1.2.7.1.3.1.4.217.119.208.33.1.1 = STRING: "IPv4 Unicast" +# .1.3.6.1.4.1.9.9.187.1.2.7.1.3.2.16.32.1.20.56.7.0.0.39.0.0.0.0.0.0.0.1.2.1 = STRING: "IPv6 Unicast" +# .1.3.6.1.4.1.9.9.187.1.2.7.1.3.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = STRING: "IPv6 Unicast" +# +# CISCO-BGP4-MIB::CbgpPeer2Entry (IPv4) +# +# OMD[mysite]:~$ snmpwalk -ObentU -v2c -c simulant 1.3.6.1.4.1.9.9.187.1.2.5.1| grep 62.214.127.57 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.3.1.4.62.214.127.57 = INTEGER: 6 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.4.1.4.62.214.127.57 = INTEGER: 2 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.5.1.4.62.214.127.57 = INTEGER: 4 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.6.1.4.62.214.127.57 = Hex-STRING: 3E D6 7F 3A +# .1.3.6.1.4.1.9.9.187.1.2.5.1.7.1.4.62.214.127.57 = Gauge32: 29418 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.8.1.4.62.214.127.57 = Gauge32: 0 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.9.1.4.62.214.127.57 = IpAddress: 217.119.208.2 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.10.1.4.62.214.127.57 = Gauge32: 179 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.11.1.4.62.214.127.57 = Gauge32: 8881 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.12.1.4.62.214.127.57 = IpAddress: 62.214.127.57 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.13.1.4.62.214.127.57 = Counter32: 18 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.14.1.4.62.214.127.57 = Counter32: 2 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.15.1.4.62.214.127.57 = Counter32: 205 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.16.1.4.62.214.127.57 = Counter32: 195 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.17.1.4.62.214.127.57 = Hex-STRING: 00 00 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.18.1.4.62.214.127.57 = Counter32: 1 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.19.1.4.62.214.127.57 = Gauge32: 10446 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.20.1.4.62.214.127.57 = INTEGER: 60 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.21.1.4.62.214.127.57 = INTEGER: 180 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.22.1.4.62.214.127.57 = INTEGER: 60 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.23.1.4.62.214.127.57 = INTEGER: 180 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.24.1.4.62.214.127.57 = INTEGER: 60 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.25.1.4.62.214.127.57 = INTEGER: 30 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.26.1.4.62.214.127.57 = INTEGER: 30 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.27.1.4.62.214.127.57 = Gauge32: 5824 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.28.1.4.62.214.127.57 = "" +# .1.3.6.1.4.1.9.9.187.1.2.5.1.29.1.4.62.214.127.57 = INTEGER: 5 +# +# +# CISCO-BGP4-MIB::CbgpPeer2Entry (IPv6) +# +# OMD[mysite]:~$ snmpwalk -ObentU -v2c -c simulant 1.3.6.1.4.1.9.9.187.1.2.5.1| grep 16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.3.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 6 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.4.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 2 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.5.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 4 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.6.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Hex-STRING: 2A 05 57 C0 00 00 FF FF 00 00 00 00 00 00 00 11 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.7.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Gauge32: 179 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.8.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Gauge32: 0 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.9.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = IpAddress: 217.119.208.2 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.10.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Gauge32: 35062 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.11.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Gauge32: 31259 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.12.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = IpAddress: 217.119.208.1 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.13.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Counter32: 5 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.14.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Counter32: 6 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.15.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Counter32: 157 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.16.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Counter32: 161 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.17.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Hex-STRING: 06 04 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.18.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Counter32: 2 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.19.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Gauge32: 8430 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.20.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 60 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.21.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 180 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.22.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 60 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.23.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 180 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.24.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 60 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.25.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 0 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.26.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 0 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.27.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = Gauge32: 1494 +# .1.3.6.1.4.1.9.9.187.1.2.5.1.28.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = STRING: "Administrative Reset" +# .1.3.6.1.4.1.9.9.187.1.2.5.1.29.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 = INTEGER: 5 +# +# +# CISCO-BGP4-MIB::cbgpPeer2AddrFamilyPrefixEntry (IPv4) +# +# OMD[mysite]:~$ snmpwalk -ObentU -v2c -c simulant 1.3.6.1.4.1.9.9.187.1.2.8.1| grep 16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.1.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Counter32: 2 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.2.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 0 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.3.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 100000 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.4.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 85 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.5.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 80 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.6.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 10 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.7.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 0 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.8.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 0 +# +# +# CISCO-BGP4-MIB::cbgpPeer2AddrFamilyPrefixEntry (IPv6) +# +# OMD[mysite]:~$ snmpwalk -ObentU -v2c -c simulant 1.3.6.1.4.1.9.9.187.1.2.8.1| grep 16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.1.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Counter32: 2 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.2.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 0 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.3.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 100000 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.4.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 85 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.5.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 80 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.6.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 10 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.7.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 0 +# .1.3.6.1.4.1.9.9.187.1.2.8.1.8.2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.16.2.1 = Gauge32: 0 +# +# +# sample info +# +# [ +# [ +# ['1.4.77.235.182.229', '6', '2', 'M\xeb\xb6\xe6', '0', '217.119.208.1', '21413', '77.235.182.229', '1', '3', '48', +# '53', '\x04\x00', '8', '2581', '2581', 'hold time expired', '5'], +# ['1.4.217.119.208.2', '6', '2', '\xd9w\xd0\x01', '0', '217.119.208.1', '31259', '217.119.208.2', '11', '23', '168', +# '170', '\x06\x04', '3', '8380', '5774', 'Administrative Reset', '5'], +# ['1.4.217.119.208.34', '6', '2', '\xd9w\xd0!', '0', '217.119.208.1', '31259', '217.119.208.2', '11', '23', '168', +# '170', '\x06\x04', '3', '8377', '5774', 'Administrative Reset', '5'], +# ['2.16.42.0.28.160.16.0.1.53.0.0.0.0.0.0.0.1', '6', '2', '*\x00\x1c\xa0\x10\x00\x015\x00\x00\x00\x00\x00\x00\x00\x02', +# '0', '217.119.208.1', '21413', '77.235.182.229', '0', '4', '108', '121', '\x06\x04', '6', '6295', '0', +# 'Administrative Reset', '5'], +# ['2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.17', '6', '2', '*\x05W\xc0\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x10', +# '0', '217.119.208.1', '31259', '217.119.208.2', '6', '5', '160', '157', '\x06\x04', '2', '8380', '1409', +# 'Administrative Reset', '5'] +# ], +# [ +# ['1.4.77.235.182.229.1.1', 'IPv4 Unicast', '1', '0', '', '', '', '6', '0', '0'], +# ['1.4.217.119.208.2.1.1', 'IPv4 Unicast', '4', '0', '', '', '', '17', '0', '10'], +# ['1.4.217.119.208.34.1.1', 'IPv4 Unicast', '4', '0', '', '', '', '17', '0', '10'], +# ['2.16.42.0.28.160.16.0.1.53.0.0.0.0.0.0.0.1.2.1', 'IPv6 Unicast', '0', '0', '100000', '85', '80', '6', '0', '0'], +# ['2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.17.2.1', 'IPv6 Unicast', '2', '0', '100000', '85', '80', '8', '0', '0'] +# ] +# ] +# +# +# + +from dataclasses import dataclass +import re, time +from typing import Mapping, Dict, List, Tuple, NamedTuple + +from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( + DiscoveryResult, + CheckResult, + StringTable, +) + +from cmk.base.plugins.agent_based.agent_based_api.v1 import ( + register, + Service, + Result, + check_levels, + State, + SNMPTree, + contains, + OIDEnd, + get_rate, + get_value_store, + Metric, + render, +) + +@dataclass +class Section: + peer_prefixes: dict + peer_table: dict + + +########################################################################### +# +# DATA Parser function +# +########################################################################### + + +def parse_cisco_bgp_peer(string_table: List[StringTable]) -> Section: + def bgp_render_ipv4_address(bytestring): + return ".".join(["%s" % ord(m) for m in bytestring]) + + def bgp_shorten_ipv6_adress(address): + address = address.split(':') + span = 2 + address = [''.join(address[i:i + span]) for i in range(0, len(address), span)] + for m in range(0, len(address)): + address[m] = re.sub(r'^0{1,3}', r'', address[m]) + address = ':'.join(address) + zeros = ':0:0:0:0:0:0:' + while not zeros == '': + if zeros in address: + address = re.sub(r'%s' % zeros, r'::', address) + zeros = '' + else: + zeros = zeros[:-2] + return address + + def bgp_render_ipv6_address(bytestring): + address = ":".join(["%02s" % hex(ord(m))[2:] for m in bytestring]).replace(' ', '0').upper() + address = bgp_shorten_ipv6_adress(address) + + return address + + def bgp_render_ip_address(bytestring): + if len(bytestring) == 4: + return bgp_render_ipv4_address(bytestring) + elif len(bytestring) == 16: + return bgp_render_ipv6_address(bytestring) + else: + return '' + + def cisco_bgp_get_peer(OID_END): + # returns peer address string from OID_END + # u'1.4.217.119.208.34.1.1' --> 217.119.208.34 + # u'2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.17.2.1' --> 42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.17 + peer_ip = '' + OID_END = OID_END.split('.') + if int(len(OID_END)) == 7: # length of ip address + peer_ip = '.'.join(OID_END[3:7]) # ipv4 address + elif int(OID_END[1]) == 16: # ipv6 address + peer_ip = ':'.join('%02s' % hex(int(m))[2:] for m in OID_END[2:18]).replace(' ', '0').upper() + peer_ip = bgp_shorten_ipv6_adress(peer_ip) + + return peer_ip + + def cisco_bgp_errors(bytestring): + lasterrorhex = ''.join(["%02X " % ord(x) for x in bytestring]).strip() + byte1, byte2 = lasterrorhex.split() + + names = {} + names[0] = {0: 'NO ERROR'} + names[1] = {0: 'Message', + 2: 'Connection Not Synchronized', + 3: 'Bad Message Length', + 4: 'Bad Message Type', + } + names[2] = {0: 'OPEN', + 1: 'Unsupported Version Number', + 2: 'Bad Peer AS', + 3: 'Bad BGP Identifier', + 4: 'Unsupported Optional Parameter', + 5: 'Authentication Failure', + 6: 'Unacceptable Hold', + } + names[3] = {0: 'UPDATE', + 1: 'Malformed Attribute List', + 2: 'Unrecognized Well-known Attribute', + 3: 'Missing Well-known Attribute', + 4: 'Attribute Flags Error', + 5: 'Attribute Length Error', + 6: 'Invalid ORIGIN Attribute', + 7: 'AS Routing Loop', + 8: 'Invalid NEXT_HOP Attribute', + 9: 'Optional Attribute Error', + 10: 'Invalid Network Field', + 11: 'Malformed AS_PATH', + } + names[4] = {0: 'Hold Timer Expired', } + + names[5] = {0: 'Finite State Machine Error', } + + names[6] = {0: 'Administratively Shutdown', + 1: 'Max Prefix Reached', + 2: 'Peer Unconfigured', + 3: 'Administratively Reset', + 4: 'Connection Rejected', + 5: 'Other Configuration Change', + } + + return names[int(byte1, 16)].get(int(byte2, 16)) + + # bgp not active + if not string_table == [[], [], []]: + + cbgpPeer2Entry, cbgpPeer3Entry, cbgpPeer2AddrFamily = string_table + cbgpPeerEntry = cbgpPeer2Entry + cbgpPeer3Entry + + peer_prefixes = {} + # create dictionary from cbgpPeer2AddrFamily ('remoteip addrfamilyname' as index) + if len(cbgpPeer2AddrFamily) > 0: + for entry in cbgpPeer2AddrFamily: + oid_end, addrfamilyname, acceptedprefixes, deniedprefixes, prefixadminlimit, prefixthreshold, \ + prefixclearthreshold, advertisedprefixes, suppressedprefixes, withdrawnprefixes = entry + + remoteaddr = cisco_bgp_get_peer(entry[0]) + peer = { + 'remoteaddr': remoteaddr, + 'addrfamilyname': addrfamilyname + } + + for key, value in [ + ('prefixadminlimit', prefixadminlimit), + ('prefixthreshold', prefixthreshold), + ('prefixclearthreshold', prefixclearthreshold), + ('acceptedprefixes', acceptedprefixes), + ('advertisedprefixes', advertisedprefixes), + ('deniedprefixes', deniedprefixes), + ('suppressedprefixes', suppressedprefixes), + ('withdrawnprefixes', withdrawnprefixes), + ]: + try: + peer[key] = int(value) + except ValueError: + pass + + peer_prefixes.update({'%s %s' % (remoteaddr, addrfamilyname): peer}) + + # workaround: get remote ip from cbgpPeerEntry if cbgpPeer2AddrFamilyName is missing :-( + elif len(cbgpPeerEntry) > 0: + for entry in cbgpPeerEntry: + remoteaddr = cisco_bgp_get_peer(entry[0]) + addrfamilyname = '' + + peer = {'remoteaddr': remoteaddr, } + + peer_prefixes.update({'%s %s' % (remoteaddr, addrfamilyname): peer}) + + # create dictionary from cbgpPeerEntry (peer ip address as index) + peer_table = {} + for entry in cbgpPeerEntry: + oid_end, state, adminstatus, localaddr, localas, localidentifier, remoteas, remoteidentifier, inupdates, \ + outupdates, intotalmessages, outtotalmessages, lasterror, fsmestablishedtransitions, fsmestablishedtime, \ + inupdateelapsedtime, lasterrortxt, prevstate = entry + + peer = {'remoteaddr': cisco_bgp_get_peer(oid_end), + 'localaddr': bgp_render_ip_address(localaddr), + 'localid': localidentifier, + 'remoteid': remoteidentifier, + 'lasterror': cisco_bgp_errors(lasterror), + 'lasterrortxt': lasterrortxt, + 'prevstate': int(prevstate), + } + + for key, value in [ + ('state', state), + ('adminstate', adminstatus), + ('localas', localas), + ('remoteas', remoteas), + ('inupdates', inupdates), + ('outupdates', outupdates), + ('intotalmessages', intotalmessages), + ('outtotalmessages', outtotalmessages), + ('fsmestablishedtransitions', fsmestablishedtransitions), + ('fsmestablishedtime', fsmestablishedtime), + ('inupdateelapsedtime', inupdateelapsedtime), + ]: + try: + peer[key] = int(value) + except ValueError: + pass + + peer_table.update({'%s' % cisco_bgp_get_peer(oid_end): peer}) + + return Section( + peer_prefixes=peer_prefixes, + peer_table=peer_table, + ) + + +########################################################################### +# +# INVENTORY function +# +########################################################################### + + +def discovery_cisco_bgp_peer(section: Section) -> DiscoveryResult: + for key in section.peer_prefixes.keys(): + yield Service(item=key) + + +########################################################################### +# +# CHECK function +# +########################################################################### + + +def check_cisco_bgp_peer(item, params, section) -> CheckResult: + def cisco_bgp_adminstate(state): + names = {1: 'stop', + 2: 'start', } + return names.get(state, 'unknown (%s)' % state) + + def cisco_bgp_peerstate(state): + names = {0: 'none', + 1: 'idle', + 2: 'connect', + 3: 'active', + 4: 'opensned', + 5: 'openconfirm', + 6: 'established'} + return names.get(state, 'unknown (%s)' % state) + + peer_prefixes = section.peer_prefixes + peer_table = section.peer_table + + prefixes = peer_prefixes.get(item, None) + + alias = '' + peer_not_found_state = 3 + + for bgp_connection, bgp_alias, not_found_state in params.get('peer_list', []): + if item == bgp_connection: + alias = bgp_alias + peer_not_found_state = not_found_state + + if prefixes: + longoutput = '' + + peer = peer_table.get(prefixes.get('remoteaddr')) + + if peer.get('localas') == 0: + peer.update({'localas': params.get('useaslocalas')}) + + if alias != '': + yield Result(state=State.OK, summary='Alias: %s' % alias) + + peerstate = peer.get('state') + adminstate = peer.get('adminstate') + establishedtime = peer.get('fsmestablishedtime') + + if peerstate == 1: # idle + yield Result(state=State.CRIT, summary='Peer state: %s' % cisco_bgp_peerstate(peerstate)) + elif peerstate == 6: # established + yield from check_levels( + value=establishedtime, + label='Uptime', + levels_lower=params['minuptime'], + render_func=render.timespan + ) + + else: # everything else + yield Result(state=State.WARN, summary='Peer state: %s' % cisco_bgp_peerstate(peerstate)) + + if not adminstate == 2: # not start + yield Result(state=State.WARN, summary='Admin state: %s' % cisco_bgp_adminstate(adminstate)) + + for key, value in [ + ('remoteid', 'Remote ID: %s'), + ('remoteas', 'Remote AS: %s'), + ('localaddr', 'Local address: %s'), + ('localid', 'Local ID: %s'), + ('localas', 'Local AS: %s'), + ]: + if key in params['infotext_values']: + try: + yield Result(state=State.OK, summary=value % peer[key]) + except KeyError: + pass + + bgptype = '' + if not peer.get('localas') == 0: + if peer.get('remoteas') == peer.get('localas'): + bgptype = ' (iBGP)' + else: + bgptype = ' (eBGP)' + + longoutput_data = [ + ['IP-address (remote/local)', peer.get('remoteaddr'), peer.get('localaddr')], + ['Router-ID (remote/local)', peer.get('remoteid'), peer.get('localid')], + ['Autonomus System (remote/local)', peer.get('remoteas'), str(peer.get('localas')) + bgptype], + ['State', cisco_bgp_peerstate(peerstate), ''], + ['Admin state', cisco_bgp_adminstate(adminstate), ''], + ['Last error', peer.get('lasterror'), ''], + ['Last error text', peer.get('lasterrortxt'), ''], + ['Previous state', cisco_bgp_peerstate(peer.get('prevstate')), ''], + ['Address family name', prefixes.get('addrfamilyname', 'unknown'), ''], + ['Prefix clear threshold (%)', '%.0d' % prefixes.get('prefixclearthreshold', 0), ''] + , + ] + + acceptedprefixes = prefixes.get('acceptedprefixes', None) + prefixadminlimit = prefixes.get('prefixadminlimit', None) + prefixthreshold = prefixes.get('prefixthreshold', None) + + if prefixadminlimit is not None and prefixthreshold is not None: + warnthreshold = prefixadminlimit / 100.0 * prefixthreshold # use float (100.0) to get xx.xx in division + longoutput_data.append(['Prefix admin limit (prefixes)', '%.0d' % prefixadminlimit, '']) + longoutput_data.append(['Prefix threshold (prefixes/%)', '%.0d' % warnthreshold, '%.0d' % prefixthreshold]) + else: + yield Result(state=State(params['noprefixlimit']), notice='No admin prefix limit/warn threshold configured on the device.') + warnthreshold = None + + if params.get('htmloutput', False): + # + # disable 'Escape HTML codes in plugin output' in wato --> global settings + # + table_bracket = '%s
' + line_bracket = '%s' + cell_bracket = '%s%s%s' + cell_seperator = '' + + longoutput = '\n' + table_bracket % (''.join( + [line_bracket % cell_seperator.join([cell_bracket % (entry[0], entry[1], entry[2])]) for entry in + longoutput_data])) + else: + longoutput += '\nfor nicer output' \ + '\ndisable \'Escape HTML codes in plugin output\' in wato -> global settings and enable HTML output in \'Parameters for this service\'' + for entry in longoutput_data: + if not entry[2] == '': + longoutput += '\n{}: {} / {}'.format(entry[0], entry[1], entry[2]) + else: + longoutput += '\n{}: {}'.format(entry[0], entry[1]) + + if prefixadminlimit is not None: + yield from check_levels( + value=acceptedprefixes, + metric_name='cisco_bgp_peer_acceptedprefixes', + levels_upper=(warnthreshold, prefixadminlimit), + label='Prefixes accepted', + render_func=lambda v: '%s' % str(v) + ) + + now_time = time.time() + value_store = get_value_store() + rate_item = item.replace(' ', '_').replace(':', '_') + + for key in [ + 'deniedprefixes', + 'advertisedprefixes', + 'withdrawnprefixes', + 'suppressedprefixes', + 'inupdates', + 'outupdates', + 'intotalmessages', + 'outtotalmessages', + ]: + try: + value = get_rate(value_store, 'cisco_bgp_peer.%s.%s' % (key, rate_item), now_time, prefixes[key], + raise_overflow=False) + yield Metric(name='cisco_bgp_peer_%s' % key, value=value, boundaries=(0, None)) + except KeyError: + pass + + for key in [ + 'fsmestablishedtransitions', + 'fsmestablishedtime', + 'inupdateelapsedtime' + ]: + try: + yield Metric(name='cisco_bgp_peer_%s' % key, value=peer[key], boundaries=(0, None)) + except KeyError: + pass + + yield Result(state=State.OK, notice=longoutput) + else: + if alias != '': + yield Result(state=State.OK, summary=', Alias: %s' % alias) + yield Result(state=State(peer_not_found_state), summary='Item not found in SNMP data') + + +########################################################################### +# +# CHECK info +# +########################################################################### + +register.snmp_section( + name='cisco_bgp_peer', + parse_function=parse_cisco_bgp_peer, + fetch=[ + SNMPTree( + base='.1.3.6.1.4.1.9.9.187.1.2.5.1', # CCISCO-BGP4-MIB::cbgpPeer2Entry + oids=[ + OIDEnd(), + '3', # cbgpPeer2State + '4', # cbgpPeer2AdminStatus + '6', # cbgpPeer2LocalAddr + '8', # cbgpPeer2LocalAs -> empty + '9', # cbgpPeer2LocalIdentifier + '11', # cbgpPeer2RemoteAs + '12', # cbgpPeer2RemoteIdentifier + '13', # cbgpPeer2InUpdates + '14', # cbgpPeer2OutUpdates + '15', # cbgpPeer2InTotalMessages + '16', # cbgpPeer2OutTotalMessages + '17', # cbgpPeer2LastError + '18', # cbgpPeer2FsmEstablishedTransitions + '19', # cbgpPeer2FsmEstablishedTime + '27', # cbgpPeer2InUpdateElapsedTime + '28', # cbgpPeer2LastErrorTxt + '29', # cbgpPeer2PrevState + ] + ), + SNMPTree( + base='.1.3.6.1.4.1.9.9.187.1.2.9.1', # CCISCO-BGP4-MIB::cbgpPeer3Entry + oids=[ + OIDEnd(), + '5', # cbgpPeer3State + '6', # cbgpPeer3AdminStatus + '8', # cbgpPeer3LocalAddr + '10', # cbgpPeer3LocalAs -> empty + '11', # cbgpPeer3LocalIdentifier + '13', # cbgpPeer3RemoteAs + '14', # cbgpPeer3RemoteIdentifier + '15', # cbgpPeer3InUpdates + '16', # cbgpPeer3OutUpdates + '17', # cbgpPeer3InTotalMessages + '18', # cbgpPeer3OutTotalMessages + '19', # cbgpPeer3LastError + '20', # cbgpPeer3FsmEstablishedTransitions + '21', # cbgpPeer3FsmEstablishedTime + '29', # cbgpPeer3InUpdateElapsedTime + '30', # cbgpPeer3LastErrorTxt + '31', # cbgpPeer3PrevState + ] + ), + SNMPTree( + base='.1.3.6.1.4.1.9.9.187.1.2', # cbgpPeer + oids=[ + OIDEnd(), # + # .7.1 --> cbgpPeer2AddrFamilyEntry + '7.1.3', # cbgpPeer2AddrFamilyName + # .8.1 --> cbgpPeer2AddrFamilyPrefixEntry + '8.1.1', # cbgpPeer2AcceptedPrefixes + '8.1.2', # cbgpPeer2DeniedPrefixes + '8.1.3', # cbgpPeer2PrefixAdminLimit + '8.1.4', # cbgpPeer2PrefixThreshold + '8.1.5', # cbgpPeer2PrefixClearThreshold + '8.1.6', # cbgpPeer2AdvertisedPrefixes + '8.1.7', # cbgpPeer2SuppressedPrefixes + '8.1.8', # cbgpPeer2WithdrawnPrefixes + ] + ) + ], + detect=contains('.1.3.6.1.2.1.1.1.0', 'Cisco'), +) + +register.check_plugin( + name='cisco_bgp_peer', + service_name='Cisco BGP peer %s', + discovery_function=discovery_cisco_bgp_peer, + check_function=check_cisco_bgp_peer, + check_default_parameters={ + 'minuptime': (7200, 3600), + 'useaslocalas': 0, + 'htmloutput': False, + 'noprefixlimit': 1, + 'infotext_values': [], + 'peer_list': [], + }, + check_ruleset_name='cisco_bgp_peer', +) diff --git a/check_mk-cisco_bgp_peer/local/share/check_mk/web/plugins/metrics/cisco_bgp_peer.py b/check_mk-cisco_bgp_peer/local/share/check_mk/web/plugins/metrics/cisco_bgp_peer.py new file mode 100644 index 0000000..5f44750 --- /dev/null +++ b/check_mk-cisco_bgp_peer/local/share/check_mk/web/plugins/metrics/cisco_bgp_peer.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2017-12-26 +# +# Cisco BGP Peer metrics plugin +# +# 2018-05-25: cleanup +# 2020-09-10: fixed typo FMS --> FSM (Thanks martin[dot]pechstein[at]posteo[dot]de) +# 2021-03-27: rewrite for CMK 2.0 +# +from cmk.gui.i18n import _ + +from cmk.gui.plugins.metrics import ( + metric_info, + graph_info, + perfometer_info +) + + +##################################################################################################################### +# +# define metrics for bgp peer perfdata +# +##################################################################################################################### + +metric_info['cisco_bgp_peer_acceptedprefixes'] = { + 'title': _('Prefixes accepted'), + 'help': _('number of accepted prefixes'), + 'unit': 'count', + 'color': '11/a', +} +metric_info['cisco_bgp_peer_deniedprefixes'] = { + 'title': _('Prefixes denied'), + 'unit': '1/s', + 'color': '21/a', +} +metric_info['cisco_bgp_peer_advertisedprefixes'] = { + 'title': _('Prefixes advertised'), + 'unit': '1/s', + 'color': '31/a', +} +metric_info['cisco_bgp_peer_withdrawnprefixes'] = { + 'title': _('Prefixes withdrawn'), + 'unit': '1/s', + 'color': '41/a', +} +metric_info['cisco_bgp_peer_suppressedprefixes'] = { + 'title': _('Prefixes suppressed'), + 'unit': '1/s', + 'color': '12/a', +} +metric_info['cisco_bgp_peer_inupdates'] = { + 'title': _('Updates received'), + 'unit': '1/s', + 'color': '22/a', +} +metric_info['cisco_bgp_peer_outupdates'] = { + 'title': _('Updates send'), + 'unit': '1/s', + 'color': '32/a', +} +metric_info['cisco_bgp_peer_intotalmessages'] = { + 'title': _('Total messages received'), + 'unit': '1/s', + 'color': '42/a', +} +metric_info['cisco_bgp_peer_outtotalmessages'] = { + 'title': _('Total messages send'), + 'unit': '1/s', + 'color': '13/a', +} +metric_info['cisco_bgp_peer_fsmestablishedtransitions'] = { + 'title': _('FSM transitions'), + 'unit': 'count', + 'color': '23/a', +} +metric_info['cisco_bgp_peer_fsmestablishedtime'] = { + 'title': _('FSM last change'), + 'unit': 's', + 'color': '26/a', +} +metric_info['cisco_bgp_peer_inupdateelapsedtime'] = { + 'title': _('Last update received'), + 'unit': 's', + 'color': '43/a', +} + + +###################################################################################################################### +# +# how to graph perdata for bgp peer +# +###################################################################################################################### + +graph_info['cisco_bgp_peer.prefixes_accepted']={ + 'title': _('Accepted Prefixes'), + 'metrics': [ + ('cisco_bgp_peer_acceptedprefixes', 'line'), + ], + 'scalars': [ + ('cisco_bgp_peer_acceptedprefixes:crit', _('crit')), + ('cisco_bgp_peer_acceptedprefixes:warn', _('warn')), + ], +} + +graph_info['cisco_bgp_peer.prefixes_per_second']={ + 'title': _('Prefixes/s'), + 'metrics': [ + ('cisco_bgp_peer_deniedprefixes', 'line'), + ('cisco_bgp_peer_advertisedprefixes', 'line'), + ('cisco_bgp_peer_withdrawnprefixes', 'line'), + ('cisco_bgp_peer_suppressedprefixes', 'line'), + ], +} + + +graph_info['cisco_bgp_peer.updates_in_out']={ + 'title': _('Updates'), + 'metrics': [ + ('cisco_bgp_peer_inupdates', 'area'), + ('cisco_bgp_peer_outupdates', '-area'), + ] +} + +graph_info['cisco_bgp_peer.messages_in_out']={ + 'title': _('Total messages'), + 'metrics': [ + ('cisco_bgp_peer_intotalmessages', 'area'), + ('cisco_bgp_peer_outtotalmessages', '-area'), + ] +} + +graph_info['cisco_bgp_peer.fms_transitions_from_to']={ + 'title': _('FSM transitions from/to established'), + 'metrics': [ + ('cisco_bgp_peer_fsmestablishedtransitions', 'line'), + ], +} + +graph_info['cisco_bgp_peer.fms_transitions_last_change']={ + 'title': _('FSM established last change'), + 'metrics': [ + ('cisco_bgp_peer_fsmestablishedtime', 'line'), + ] +} + +graph_info['cisco_bgp_peer.time_since_last_update']={ + 'title': _('Time since last update received'), + 'metrics': [ + ('cisco_bgp_peer_inupdateelapsedtime', 'line'), + ] +} + +###################################################################################################################### +# +# define perf-o-meter for bgp peer uptime + prefixes accepted/advertised +# +###################################################################################################################### + +perfometer_info.append(('stacked', [ + { + 'type': 'logarithmic', + 'metric': 'cisco_bgp_peer_fsmestablishedtime', + 'half_value': 2592000.0, # ome month + 'exponent': 2, + }, + { + 'type': 'logarithmic', + 'metric': 'cisco_bgp_peer_acceptedprefixes', + 'half_value': 500000.0, + 'exponent': 2, + } +])) diff --git a/check_mk-cisco_bgp_peer/local/share/check_mk/web/plugins/wato/cisco_bgp_peer.py b/check_mk-cisco_bgp_peer/local/share/check_mk/web/plugins/wato/cisco_bgp_peer.py new file mode 100644 index 0000000..615f7ec --- /dev/null +++ b/check_mk-cisco_bgp_peer/local/share/check_mk/web/plugins/wato/cisco_bgp_peer.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2017-12-25 +# +# Check_MK cisco_bgp_peers WATO plugin +# +# 2021-03-27: rewrite for CMK 2.0 +# + +from cmk.gui.i18n import _ +from cmk.gui.valuespec import ( + Dictionary, + Integer, + TextAscii, + ListOfStrings, + FixedValue, + ListChoice, + ListOf, + Tuple, + TextUnicode, + MonitoringState, +) + +from cmk.gui.plugins.wato import ( + CheckParameterRulespecWithItem, + rulespec_registry, + RulespecGroupCheckParametersNetworking, +) + +cisco_bgp_peer_infotext_values = [ + ('remoteid', 'Remote router ID'), + ('remoteas', 'Remote autonomous system'), + ('localaddr', 'Local peer IP address'), + ('localid', 'Local router ID'), + ('localas', 'Local autonomous system'), +] + + +def _parameter_valuespec_cisco_bgp_peer(): + return Dictionary(elements=[ + ('minuptime', + Tuple( + title=_('Minimum uptime for peer'), + help=_('Set the time in seconds, a peer must be up before the peer is considered sable.' + 'If the peer uptime less then X, the check outcome is set to warning.'), + elements=[ + Integer(title=_('Warning if below'), unit='seconds', default_value=7200, minvalue=0), + Integer(title=_('Critical if below'), unit='seconsa', default_value=3600, minvalue=0) + ], + ), + ), + ('useaslocalas', + Integer( + help=_('Use this AS number if the SNMP Value for CISCO-BGP4-MIB::cbgpPeer2LocalAs is \'0\'.'), + title=_('Use AS as local AS, if SNMP cbgpPeer2LocalAs is not valid.'), + default_value=0, + # allow_empty=False, + ), + ), + ('htmloutput', + FixedValue( + True, + help=_('render long output of check plugin (multiline) as HTML table. Needs \'Escape HTML codes in plugin output\' in wato --> global settings disabled'), + title=_('enable HTML Output for long output of check plugin (multiline)'), + totext=_('enable HTML Output for long output of check plugin (multiline)'), + default_value=False, + )), + ('noprefixlimit', + MonitoringState( + default_value=1, + title=_('State if no admin prefix limit/warn threshold configured.'), + help=_('The admin prefix limit and warn threshold needs to be configured on the device. ' + 'For example: neighbor 172.17.10.10 maximum-prefix 10000 80. The threshold is in percentage ' + 'of the prefix limit') + )), + ('infotext_values', + ListChoice( + title=_('Add values to check info'), + help=_('Select values to add to the check output.'), + choices=cisco_bgp_peer_infotext_values, + default_value=[], + )), + ('peer_list', + ListOf( + Tuple( + # title=('BGP Peers'), + elements=[ + TextUnicode( + title=_('BGP Peer item name (without "Cisco BGP peer")'), + help=_('The configured value must match a BGP item reported by the monitored ' + 'device. For example: "10.194.115.98 IPv4 Unicast"'), + allow_empty=False, + ), + TextUnicode( + title=_('BGP Peer Alias'), + help=_('You can configure an individual alias here for the BGP peer matching ' + 'the text configured in the "BGP Peer item name" field. The alias will ' + 'be shown in the infotext'), + ), + MonitoringState( + default_value=2, + title=_('State if not found'), + help=_('You can configure an individual state if the BGP peer matching the text ' + 'configured in the "BGP Peer item name" field is not found') + ), + ]), + add_label=_('Add BGP peer'), + movable=False, + title=_('BGP Peers'), + )), + ]) + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name='cisco_bgp_peer', + group=RulespecGroupCheckParametersNetworking, + item_spec=lambda: TextAscii(title=_('BGP peer specific configuration'), ), + match_type='dict', + parameter_valuespec=_parameter_valuespec_cisco_bgp_peer, + title=lambda: _('Cisco BGP peer'), + )) \ No newline at end of file diff --git a/check_mk-cisco_gdoi/README.md b/check_mk-cisco_gdoi/README.md new file mode 100644 index 0000000..2d24015 --- /dev/null +++ b/check_mk-cisco_gdoi/README.md @@ -0,0 +1 @@ +This plugin checks the registration status (and KEK key timeout) of GDOI Group Members with GDOI Key Servers. diff --git a/check_mk-cisco_gdoi/cisco_gdoi-1.1.0.mkp b/check_mk-cisco_gdoi/cisco_gdoi-1.1.0.mkp new file mode 100755 index 0000000000000000000000000000000000000000..474157fc82e8573b75736e58495f38f4e3592b6f GIT binary patch literal 1534 zcmVV>h;1HzJUryN zkYvd^?R;U30Q2coe*+G`N3+qmGoDVTrzhjdXr_4c`FzqLqs}uR7t-f2W#|8i`<|c6 zZOVHK(!0*6&$rYM$@N}H8jIebOL`#{0cV+HX`)C*mfj^%>W5y=qe{4D5f#t^l^dE! z@5UE2g!Zx*FcGBQCQO-=?R%>S#ZLT~s-bnCRw9{4pi(ePs`c(}c;Cvt*+O-%>6LGsn)@88wAY%o2~&KXS&kRlUh0M&<`QFum^0CO@g9=KYT0kogg$)b{%4T?&hH{k{>A*Co{kRk|8#zGiuwO6`ERL2v=+pw6VVzF zs|b13p;M_LtMWv3mU+_bZ)RG>X%d=w1cW4yBIwnrulWBk^_6B*#MIzNMND-!>y;vD zSzXskk*;9SxVIV=4BAVpRl%&)!^3~Y|BZz@DiNMP|0h%RyOsar(dlf2`Trbf1@@P$ z|8wo{@#%DCzGqb&OlQ+c>HqO$JOTfoOefFke?mI3&jpR5kMjPm|0~7OH^W@;;SEcM zG`S_&9_nav(mm=Pk;{}*qV5MgHYL};Npnf$mI-1?w9plH0o<*WnOF>mcXxM=4k;%{ zW6(JKa6JsuKnz(bj{l4!^*t0c@Paf+ybYDNSu%v*YqrTvVIPiX$CFqp(lPWO1HswK zI0BQpYo5j=^ras}z7SLp7H27!wa75!K7(VS?0m%nIUsM~eyfkkUXhw1cmJt z&sKX<2o<6<-NAJL41-xpA;c%S^&^N>9S1dAfhqQ*jRN{|wCcB*oW|f6Wv>gWq~?qd zI6`?wdNJ5uFR+v7OpgGBW7#T z+&AL7WVu|e76)Ux%}^-f$*wqMOu1&Sn+nzL7}xfdJI`Uc30$`Jl`jW{R-I>6uTC41 zXHYAu2mk@siJ{8JE!9B~D)++?_>8XEX}S{IVI88P~d?djSI2dAO{BZn(HY zCJMJ0>68o7Hox4`VE3fG>23%YKl$0#21--YQe{nHfEbXr-DQZF-d4!~-7fjXj|4S- zQGu(%!VH1%HDes5Uf7MWhwF4Mlv2%fpeou$I`-=*fsiP8Ka$bnAha6>yyrP>^_rbF z#mm++xVm~d?=HZ$JcfgB?^;)tjsekglZ)3EMAuV`d=KmBSCN^dvN2_C%10-9d3FB2 zG1Z5p9<5ebwj7bfnJ1cItllne>*b=wrpT1OcMofhA+4zlw(hbtuPoDcYjci>9(D$! zF3*2nEP_p}exJn`baz#z>Kg{SSlr%L6`%zyStiC?(DyN$4GDqn(1DGp*iZ$&&z z@+PUM;a;QU+&?r4JcoB9mEIGU_q!bg0)apv5C{YUfj}S-2m}IwKp+qZ1OkCTAP@)y k0)apv5C{YUfj}S-2m}IwKp+qZ1md&t7gzZ*h5%3i0LH}fCIA2c literal 0 HcmV?d00001 diff --git a/check_mk-cisco_gdoi/local/lib/check_mk/base/plugins/agent_based/cisco_gdoi.py b/check_mk-cisco_gdoi/local/lib/check_mk/base/plugins/agent_based/cisco_gdoi.py new file mode 100644 index 0000000..259c83b --- /dev/null +++ b/check_mk-cisco_gdoi/local/lib/check_mk/base/plugins/agent_based/cisco_gdoi.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# +# More information about this Cisco system: +# https://www.cisco.com/en/US/docs/ios-xml/ios/sec_conn_getvpn/configuration/15-2mt/sec-get-vpn.html +# + +from dataclasses import dataclass +from typing import Dict, List + +from cmk.base.plugins.agent_based.agent_based_api.v1 import ( + register, + Service, + Result, + State, + SNMPTree, + contains, + OIDEnd, +) + +@dataclass +class Section: + kek_info: dict + +def chars_to_ip_addr(chars): + return ".".join(map(lambda c: str(ord(c)), [*chars])) + +conversions = { + "1": "using", + "2": "new", + "3": "old", +} + +# SNMP parsing function +def parse_cisco_gdoi(string_table): + def parse(data): + lookup = {} + + for val in data: + ip = chars_to_ip_addr(val[0]) + remaining = int(val[1]) + state = conversions[val[2]] + + lookup.setdefault(ip, {}) + lookup[ip][state] = remaining + + return lookup + + if string_table == [[]]: + return + + return Section( + kek_info=parse(string_table[0]), + ) + +# Inventory function, returning inventory based upon SNMP parsed result above +def discovery_cisco_gdoi(section): + yield Service(item="Keyservers", parameters=section.kek_info) + +# Check function, returning ok/crit based upon SNMP parsed result above +def check_cisco_gdoi(item, params, section): + state = params + registered = False + + for ip, state in params.items(): + in_use = state.get("using") + + if in_use > 0: + registered = True + yield Result(state=State.OK, summary="Registered, using KEK from " + ip) + + if not registered: + yield Result(state=State.CRIT, summary="Unregistered") + +register.snmp_section( + name="cisco_gdoi", + parse_function=parse_cisco_gdoi, + fetch=[ + SNMPTree( + # ciscoGdoiMIB::cgmGdoiGmKekRemainingLifetime + base=".1.3.6.1.4.1.9.9.759.1.3.2.1", + oids=[ + "5", # cgmGdoiGmKekSrcIdValue + "20", # cgmGdoiGmKekRemainingLifetime + "21", # cgmGdoiGmKekStatus + ] + ), + ], + detect=contains(".1.3.6.1.2.1.1.1.0", "Cisco"), +) + +register.check_plugin( + name="cisco_gdoi", + service_name="Cisco GDOI %s", + discovery_function=discovery_cisco_gdoi, + check_function=check_cisco_gdoi, + check_default_parameters={}, + check_ruleset_name="cisco_gdoi", +) diff --git a/check_mk-cisco_ip_sla/README.md b/check_mk-cisco_ip_sla/README.md new file mode 100644 index 0000000..b13cc50 --- /dev/null +++ b/check_mk-cisco_ip_sla/README.md @@ -0,0 +1 @@ +This is a modification of a Tribe29 GPL plugin to support tracking packet loss as well. diff --git a/check_mk-cisco_ip_sla/cisco_ip_sla-1.0.1.mkp b/check_mk-cisco_ip_sla/cisco_ip_sla-1.0.1.mkp new file mode 100644 index 0000000000000000000000000000000000000000..5a71703c805adda2d0d66366841120e75e7ce834 GIT binary patch literal 3724 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 literal 0 HcmV?d00001 diff --git a/check_mk-cisco_ip_sla/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py b/check_mk-cisco_ip_sla/local/lib/python3/cmk/gui/plugins/wato/check_parameters/cisco_ip_sla.py new file mode 100644 index 0000000..2931e30 --- /dev/null +++ b/check_mk-cisco_ip_sla/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/check_mk-cisco_ip_sla/local/share/check_mk/checks/cisco_ip_sla b/check_mk-cisco_ip_sla/local/share/check_mk/checks/cisco_ip_sla new file mode 100644 index 0000000..b8c3d77 --- /dev/null +++ b/check_mk-cisco_ip_sla/local/share/check_mk/checks/cisco_ip_sla @@ -0,0 +1,237 @@ +#!/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 + ] + ) + ], +}