Collection of CheckMK checks (see https://checkmk.com/). All checks and plugins are provided as is. Absolutely no warranty. Send any comments to thl-cmk[at]outlook[dot]com

Skip to content
Snippets Groups Projects
Commit 5c658ad5 authored by thl-cmk's avatar thl-cmk :flag_na:
Browse files

update project

parent f9dcad47
No related branches found
No related tags found
No related merge requests found
......@@ -48,8 +48,13 @@
# 2021-11-14: merged check function with bgp_peer
# merged parse function with bgp_peer
# added basic support for VRFs (cbgpPeer3Entry)
# 2022.04.22: moved inventory plugin to inv_cisco_bgp_peer.py
# 2022-04-29: added info if device is admin prefix limit capable (device_admin_limit)
# 2022-04-30: code cleanup/streamlining
#
from typing import List, Dict, Optional
from typing import List, Dict, Optional, Tuple
from dataclasses import dataclass
from cmk.base.plugins.agent_based.agent_based_api.v1 import (
register,
......@@ -66,11 +71,7 @@ from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
)
from cmk.base.plugins.agent_based.utils.bgp_peer import (
bgp_peerstate,
bgp_errors,
bgp_render_ip_address,
bgp_get_peer,
ByteToHex,
bgp_get_ip_address_from_oid,
BgpPeer,
bgp_get_peer_entry,
)
......@@ -80,35 +81,38 @@ from cmk.base.plugins.agent_based.utils.bgp_peer import (
# cisco_bgp_peer (CISCO-BGP4-MIB:cbgpPeer2Entry)
#
###########################################################################
@dataclass
class CiscoPrefixes:
address_family: str
metric_count: List[Tuple[str, int]]
metric_rate: List[Tuple[str, int]]
accepted_prefixes: Optional[int]
prefix_admin_limit: Optional[int]
prefix_clear_threshold: Optional[int]
prefix_threshold: Optional[int]
def parse_cisco_bgp_peer(string_table: List[StringTable]) -> Dict[str, BgpPeer]:
cbgpPeer2Entry, cbgpPeer2AddrFamily = string_table
# create dictionary from cbgpPeer2Entry (peer ip address as index)
peer_table = {}
for entry in cbgpPeer2Entry:
entry[0] = bgp_get_peer(entry[0]) # replace OID_END with remote address
bgp_peer = bgp_get_peer_entry(entry)
if bgp_peer:
peer_table.update(bgp_peer)
prefixes_table = {}
# create dictionary from cbgpPeer2AddrFamily (with 'remoteip addrfamilyname' as index)
peer_prefixes = {}
# create dictionary by peer address and list of entries per address family
for entry in cbgpPeer2AddrFamily:
oid_end, addrfamilyname, acceptedprefixes, deniedprefixes, prefixadminlimit, prefixthreshold, \
prefixclearthreshold, advertisedprefixes, suppressedprefixes, withdrawnprefixes = entry
if not oid_end == '':
remoteaddr = bgp_get_peer(oid_end)
# merge peer info with prefixes
prefixes = peer_table[remoteaddr]
prefixes.prefix_admin_limit = int(prefixadminlimit) if prefixadminlimit.isdigit() else None
prefixes.accepted_prefixes = int(acceptedprefixes) if acceptedprefixes.isdigit() else None
prefixes.prefix_clear_threshold = int(prefixclearthreshold) if prefixclearthreshold.isdigit() else None
prefixes.prefix_threshold = int(prefixthreshold) if prefixthreshold.isdigit() else None
remote_addr = bgp_get_ip_address_from_oid(oid_end)
prefixes = CiscoPrefixes(
address_family=addrfamilyname,
metric_count=[],
metric_rate=[],
accepted_prefixes=int(acceptedprefixes) if acceptedprefixes.isdigit() else None,
prefix_admin_limit=int(prefixadminlimit) if prefixadminlimit.isdigit() else None,
prefix_clear_threshold=int(prefixthreshold) if prefixthreshold.isdigit() else None,
prefix_threshold=int(prefixthreshold) if prefixthreshold.isdigit() else None
)
for key, value in [
('advertisedprefixes', advertisedprefixes),
('deniedprefixes', deniedprefixes),
......@@ -120,20 +124,34 @@ def parse_cisco_bgp_peer(string_table: List[StringTable]) -> Dict[str, BgpPeer]:
except ValueError:
pass
prefixes_table.update({f'{remoteaddr} {addrfamilyname}': prefixes})
if peer_prefixes.get(remote_addr):
peer_prefixes[remote_addr].append(prefixes)
else:
peer_prefixes[remote_addr] = [prefixes]
# create dictionary from cbgpPeer2Entry (peer ip address as index)
peer_table: Dict[str, BgpPeer] = {}
for entry in cbgpPeer2Entry:
remote_address = bgp_get_ip_address_from_oid(entry[0])
entry[0] = remote_address # replace OID_END with remote address
bgp_peer = bgp_get_peer_entry(entry)
if bgp_peer:
prefixes = peer_prefixes.get(remote_address, [])
if prefixes:
for address_family in prefixes:
item = f'{remote_address} {address_family.address_family}'
peer_table[item] = bgp_peer[remote_address]
peer_table[item].accepted_prefixes = address_family.accepted_prefixes
peer_table[item].prefix_admin_limit = address_family.prefix_admin_limit
peer_table[item].prefix_clear_threshold = address_family.prefix_clear_threshold
peer_table[item].prefix_threshold = address_family.prefix_threshold
peer_table[item].device_admin_limit = True
peer_table[item].metric_rate += address_family.metric_count
peer_table[item].metric_rate += address_family.metric_rate
else:
peer_table.update(bgp_peer)
if prefixes_table:
for peer in peer_table.keys():
no_address_family = False
for address_family in prefixes_table.keys():
if address_family.startswith(peer):
no_address_family = True
break
if not no_address_family:
prefixes_table.update({peer:peer_table[peer]})
return prefixes_table
else:
return peer_table
return peer_table
register.snmp_section(
......@@ -188,7 +206,7 @@ register.snmp_section(
###########################################################################
# ToDo: add support for non ipv6, needs sample
# ToDo: add support for non IPv4, needs sample
def parse_cisco_bgp_peer_3(string_table: StringByteTable) -> Optional[Dict[str, BgpPeer]]:
peer_table = {}
for entry in string_table:
......@@ -257,121 +275,3 @@ register.snmp_section(
# '30', # cbgpPeer3LastErrorTxt
# '31', # cbgpPeer3PrevState
###########################################################################
#
# INVENTORY Plugin inv_cisco_bgp_peer (CISCO-BGP4-MIB::cbgpPeer2Entry)
#
###########################################################################
def parse_inv_cisco_bgp_peer(string_table: List[StringTable]):
peers, address_family, base = string_table
bgp_peers = []
# convert families from list to dict
# [
# ['1.4.77.235.182.229.1.1', 'IPv4 Unicast'],
# ['1.4.217.119.208.2.1.1', 'IPv4 Unicast'],
# ['1.4.217.119.208.34.1.1', 'IPv4 Unicast'],
# ['2.16.42.0.28.160.16.0.1.53.0.0.0.0.0.0.0.1.2.1', 'IPv6 Unicast'],
# ['2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.17.2.1', 'IPv6 Unicast']
# ]
#
# {
# '1.4.77.235.182.229.1.1': 'IPv4 Unicast',
# '1.4.217.119.208.2.1.1': 'IPv4 Unicast',
# '1.4.217.119.208.34.1.1': 'IPv4 Unicast',
# '2.16.42.0.28.160.16.0.1.53.0.0.0.0.0.0.0.1.2.1': 'IPv6 Unicast',
# '2.16.42.5.87.192.0.0.255.255.0.0.0.0.0.0.0.17.2.1': 'IPv6 Unicast'
# }
peer_families = dict(map(lambda x: (x[0], x[1]), address_family))
for entry in peers:
try:
oid_end, local_addr, local_as, local_id, remote_as, remote_id, last_error, last_errortxt, \
prev_state = entry
except ValueError:
return
if local_as == '0':
try:
local_as = base[0][0]
except (ValueError, IndexError):
local_as = 'N/A'
address_families = []
for key in peer_families:
if key.startswith(oid_end):
address_families.append(peer_families[key])
peer = {
'remote_addr': bgp_get_peer(oid_end),
'remote_id': remote_id,
'version': '4',
'local_addr': bgp_render_ip_address(local_addr),
'remote_as': remote_as,
'local_as': local_as,
'local_id': local_id,
'status_columns': {
'last_error_code': ByteToHex(last_error),
'last_error': bgp_errors(last_error),
'prev_state': bgp_peerstate(prev_state),
},
}
if local_as.isdigit():
if local_as == remote_as:
peer['bgp_type'] = 'iBGP'
else:
peer['bgp_type'] = 'eBGP'
else:
peer['bgp_type'] = 'N/A'
if address_families:
peer['address_family'] = ','.join(address_families)
bgp_peers.append(peer)
return bgp_peers
register.snmp_section(
name='inv_cisco_bgp_peer',
parse_function=parse_inv_cisco_bgp_peer,
parsed_section_name='inv_bgp_peer',
supersedes=['inv_bgp_peer'],
fetch=[
SNMPTree(
base='.1.3.6.1.4.1.9.9.187.1.2.5.1', # CISCO-BGP4-MIB::cbgpPeer2Entry
oids=[
OIDEnd(),
'6', # cbgpPeer2LocalAddr
'8', # cbgpPeer2LocalAs -> empty
'9', # cbgpPeer2LocalIdentifier
'11', # cbgpPeer2RemoteAs
'12', # cbgpPeer2RemoteIdentifier
'17', # cbgpPeer2LastError
'28', # cbgpPeer2LastErrorTxt
'29', # cbgpPeer2PrevState
]
),
SNMPTree(
base='.1.3.6.1.4.1.9.9.187.1.2', # cbgpPeer
oids=[
OIDEnd(), #
'7.1.3', # cbgpPeer2AddrFamilyName
]
),
SNMPTree(
base='.1.3.6.1.2.1.15', # BGP-4-MIB
oids=[
'2', # bgpLocalAs
]
)
],
detect=all_of(
contains('.1.3.6.1.2.1.1.1.0', 'Cisco'),
exists('.1.3.6.1.4.1.9.9.187.1.2.5.1.3.*')
),
)
#!/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 : 2020-04-22
#
# inventory of Cisco BGP Peers (IPv4 and IPv6)
#
# 2022-04-22: moved here from cisco_bgp_peer
# 2022-04-30: code cleanup/streamlining
#
from typing import List
from cmk.base.plugins.agent_based.agent_based_api.v1 import (
register,
SNMPTree,
exists,
contains,
all_of,
OIDEnd,
OIDBytes,
)
from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
StringByteTable
)
from cmk.base.plugins.agent_based.utils.bgp_peer import (
InvBgpPeer,
bgp_error_as_string,
bgp_render_ip_address,
bgp_get_ip_address_from_oid,
bgp_error_code_as_hex,
get_bgp_type,
)
def parse_inv_cisco_bgp_peer(string_table: List[StringByteTable]):
peers, address_family, base = string_table
try:
base_local_as = base[0][0]
except (ValueError, IndexError):
base_local_as = 'N/A'
bgp_peers = []
peer_families = dict(address_family)
for entry in peers:
try:
oid_end, state, local_addr, local_as, local_id, remote_as, remote_id, last_error, \
fsm_established_time, last_errortxt = entry
except ValueError:
return
if len(local_addr) == 4:
local_addr_type = '1' # IPv4
elif len(local_addr) == 16:
local_addr_type = '2' # IPv6
else:
local_addr_type = '0'
if local_as == '0':
local_as = base_local_as
address_families = []
for key in peer_families:
if key.startswith(oid_end):
address_families.append(peer_families[key])
bgp_peer: InvBgpPeer = {
'remote_addr': bgp_get_ip_address_from_oid(oid_end),
'remote_id': remote_id,
'version': '4',
'local_addr': bgp_render_ip_address(local_addr_type, local_addr),
'remote_as': remote_as,
'local_as': local_as,
'local_id': local_id,
'bgp_type': get_bgp_type(local_as, remote_as),
'fsm_established_time': int(fsm_established_time),
'peer_state': 1 if state == '6' else 2, # adjust to match if_oper_status for inventory painter
'last_error_code': bgp_error_code_as_hex(last_error),
'last_error': bgp_error_as_string(last_error),
'status_columns': {},
'address_family': ','.join(address_families)
}
bgp_peers.append(bgp_peer)
return bgp_peers
register.snmp_section(
name='inv_cisco_bgp_peer',
parse_function=parse_inv_cisco_bgp_peer,
parsed_section_name='inv_bgp_peer',
supersedes=['inv_bgp_peer'],
fetch=[
SNMPTree(
base='.1.3.6.1.4.1.9.9.187.1.2.5.1', # CISCO-BGP4-MIB::cbgpPeer2Entry
oids=[
OIDEnd(),
'3', # cbgpPeer2State
OIDBytes('6'), # cbgpPeer2LocalAddr
'8', # cbgpPeer2LocalAs -> empty
'9', # cbgpPeer2LocalIdentifier
'11', # cbgpPeer2RemoteAs
'12', # cbgpPeer2RemoteIdentifier
OIDBytes('17'), # cbgpPeer2LastError
'19', # cbgpPeer2FsmEstablishedTime
'28', # cbgpPeer2LastErrorTxt
]
),
SNMPTree(
base='.1.3.6.1.4.1.9.9.187.1.2', # cbgpPeer
oids=[
OIDEnd(), #
'7.1.3', # cbgpPeer2AddrFamilyName
]
),
SNMPTree(
base='.1.3.6.1.2.1.15', # BGP-4-MIB
oids=[
'2', # bgpLocalAs
]
)
],
detect=all_of(
contains('.1.3.6.1.2.1.1.1.0', 'Cisco'),
exists('.1.3.6.1.4.1.9.9.187.1.2.5.1.3.*')
),
)
No preview for this file type
......@@ -21,12 +21,12 @@
'v0.5: merged with bgp_peer '
'(https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/bgp_peer)\n',
'download_url': 'https://thl-cmk.hopto.org',
'files': {'agent_based': ['cisco_bgp_peer.py'],
'files': {'agent_based': ['cisco_bgp_peer.py', 'inv_cisco_bgp_peer.py'],
'checkman': ['cisco_bgp_peer']},
'name': 'cisco_bgp_peer',
'num_files': 2,
'num_files': 3,
'title': 'Cisco BGP Peer',
'version': '20211114.v.0.5',
'version': '20220422.v.0.6',
'version.min_required': '2.0.0',
'version.packaged': '2021.09.20',
'version.usable_until': None}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment