diff --git a/README.md b/README.md index f2d0b5887621441683dc40580c9099a233536e3a..48a86791f8377a66b8dd4f7f4a24b3ce6b557473 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[PACKAGE]: ../../raw/master/mkp/cisco_bgp_peer-1.0.0-20230613.mkp "cisco_bgp_peer-1.0.0-20230613.mkp" +[PACKAGE]: ../../raw/master/mkp/cisco_bgp_peer-1.0.2-20241220.mkp "cisco_bgp_peer-1.0.2-20241220.mkp" # Cisco BGP Peer Monitors status of Cisco BGP peers (IPv4 and IPv6, with basic support for VRFs on NXOS) diff --git a/mkp/cisco_bgp_peer-1.0.2-20241220.mkp b/mkp/cisco_bgp_peer-1.0.2-20241220.mkp new file mode 100644 index 0000000000000000000000000000000000000000..2cc84073d786e387917b039e1f2b314f2cc45f04 Binary files /dev/null and b/mkp/cisco_bgp_peer-1.0.2-20241220.mkp differ diff --git a/source/agent_based/cisco_bgp_peer.py b/source/agent_based/cisco_bgp_peer.py index cbf12593d7383405af56575c297f5be11dd12558..a39204b1b212205ec1e7d40f81fe13f7fd60df2e 100644 --- a/source/agent_based/cisco_bgp_peer.py +++ b/source/agent_based/cisco_bgp_peer.py @@ -54,30 +54,30 @@ # 2022-05-09: added item to BgpPeer class, this is used in the discovery function # 2022-05-11: changed bgp_get_peer_entry to get proper parameters instead of Nontransparent list # added remote_as to BgpPeerItem -# +# 2024-07-19: added in peerv2 local/remote AS/ID/Address for BGP topology +# 2024-12-20: added local address/as/identifier in cisco_bgp_peer for bgp_topology +# 2024-12-23: added local address/as/identifier in cisco_bgp_peer_3 for bgp_topology +# fixed item in cisco_bgp_peer_3 -import copy -from typing import List, Dict, Optional, Tuple from dataclasses import dataclass +from typing import List, Dict, Optional, Tuple +import copy from cmk.base.plugins.agent_based.agent_based_api.v1 import ( - register, + OIDBytes, + OIDEnd, SNMPTree, - exists, - contains, all_of, - OIDEnd, - OIDBytes, -) -from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( - StringTable, - StringByteTable, + contains, + exists, + register, ) - +from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import StringByteTable from cmk.base.plugins.agent_based.utils.bgp_peer import ( - bgp_get_ip_address_from_oid, BgpPeer, + bgp_get_ip_address_from_oid, bgp_get_peer_entry, + bgp_render_ip_address, ) ########################################################################### @@ -98,31 +98,46 @@ class CiscoPrefixes: prefix_threshold: Optional[int] -def parse_cisco_bgp_peer(string_table: List[StringTable]) -> Dict[str, BgpPeer]: - cbgpPeer2Entry, cbgpPeer2AddrFamily = string_table +def parse_cisco_bgp_peer(string_table: List[StringByteTable]) -> Dict[str, BgpPeer]: + peer2_entry, peer2_addr_family, base_local_as = string_table + + try: + base_local_as = base_local_as[0][0] + except (ValueError, IndexError): + base_local_as = None 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 + for entry in peer2_addr_family: + ( + oid_end, + addr_family_name, + accepted_prefixes, + denied_prefixes, + prefix_admin_limit, + prefix_threshold, + prefix_clear_threshold, + advertised_prefixes, + suppressed_prefixes, + withdrawn_prefixes + ) = entry if not oid_end == '': remote_addr = bgp_get_ip_address_from_oid(oid_end) prefixes = CiscoPrefixes( - address_family=addrfamilyname, + address_family=addr_family_name, 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 + accepted_prefixes=int(accepted_prefixes) if accepted_prefixes.isdigit() else None, + prefix_admin_limit=int(prefix_admin_limit) if prefix_admin_limit.isdigit() else None, + prefix_clear_threshold=int(prefix_threshold) if prefix_threshold.isdigit() else None, + prefix_threshold=int(prefix_threshold) if prefix_threshold.isdigit() else None ) for key, value in [ - ('advertisedprefixes', advertisedprefixes), - ('deniedprefixes', deniedprefixes), - ('suppressedprefixes', suppressedprefixes), - ('withdrawnprefixes', withdrawnprefixes), + ('advertisedprefixes', advertised_prefixes), + ('deniedprefixes', denied_prefixes), + ('suppressedprefixes', suppressed_prefixes), + ('withdrawnprefixes', withdrawn_prefixes), ]: try: prefixes.metric_rate.append((key, int(value))) @@ -136,23 +151,49 @@ def parse_cisco_bgp_peer(string_table: List[StringTable]) -> Dict[str, BgpPeer]: # create dictionary from cbgpPeer2Entry (peer ip address as index) peer_table: Dict[str, BgpPeer] = {} - for entry in cbgpPeer2Entry: - remote_addr, peer_state, admin_state, remote_as, in_updates, out_updates, in_messages, out_messages, \ - fsm_established_transitions, fsm_established_time, in_update_elapsed_time = entry + for entry in peer2_entry: + ( + remote_addr, + peer_state, + admin_state, + local_addr, + local_as, + local_id, + remote_as, + remote_id, + in_updates, + out_updates, + in_messages, + out_messages, + fsm_established_transitions, + fsm_established_time, + in_update_elapsed_time + ) = entry + + 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' remote_addr = bgp_get_ip_address_from_oid(remote_addr) bgp_peer = bgp_get_peer_entry( - remote_addr=remote_addr, - peer_state=peer_state, admin_state=admin_state, - remote_as=remote_as, - in_updates=in_updates, - out_updates=out_updates, + fsm_established_time=fsm_established_time, + fsm_established_transitions=fsm_established_transitions, in_messages=in_messages, + in_update_elapsed_time=in_update_elapsed_time, + in_updates=in_updates, + local_addr=bgp_render_ip_address(local_addr_type, local_addr), + local_as=local_as if local_as != '0' else base_local_as, + local_id=local_id, out_messages=out_messages, - fsm_established_transitions=fsm_established_transitions, - fsm_established_time=fsm_established_time, - in_update_elapsed_time=in_update_elapsed_time + out_updates=out_updates, + peer_state=peer_state, + remote_addr=remote_addr, + remote_as=remote_as, + remote_id=remote_id, ) if bgp_peer: prefixes = peer_prefixes.get(remote_addr, []) @@ -187,7 +228,11 @@ register.snmp_section( OIDEnd(), '3', # cbgpPeer2State '4', # cbgpPeer2AdminStatus + OIDBytes('6'), # cbgpPeer2LocalAddr + '8', # cbgpPeer2LocalAs -> empty + '9', # cbgpPeer2LocalIdentifier '11', # cbgpPeer2RemoteAs + '12', # cbgpPeer2RemoteIdentifier '13', # cbgpPeer2InUpdates '14', # cbgpPeer2OutUpdates '15', # cbgpPeer2InTotalMessages @@ -214,6 +259,12 @@ register.snmp_section( '8.1.8', # cbgpPeer2WithdrawnPrefixes ] ), + 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'), @@ -232,31 +283,55 @@ register.snmp_section( def parse_cisco_bgp_peer_3(string_table: StringByteTable) -> Optional[Dict[str, BgpPeer]]: peer_table = {} for entry in string_table: - remote_addr_type, remote_addr, routing_instance, peer_state, admin_state, remote_as, in_updates, out_updates, \ - in_messages, out_messages, fsm_established_transitions, fsm_established_time, in_update_elapsed_time = entry + ( + remote_addr_type, + remote_addr, + routing_instance, + peer_state, + admin_state, + local_addr, + local_as, + local_id, + remote_as, + remote_id, + in_updates, + out_updates, + in_messages, + out_messages, + fsm_established_transitions, + fsm_established_time, + in_update_elapsed_time + ) = entry if remote_addr_type == '1': # IPv4 address remote_addr = '.'.join(f'{m}' for m in remote_addr) - routing_instance = None + local_addr = '.'.join(f'{m}' for m in local_addr) + if routing_instance != 'default': routing_instance = f'vrf {routing_instance}' + else: + routing_instance = None bgp_peer = bgp_get_peer_entry( - remote_addr=remote_addr, - peer_state=peer_state, admin_state=admin_state, - remote_as=remote_as, - in_updates=in_updates, - out_updates=out_updates, + fsm_established_time=fsm_established_time, + fsm_established_transitions=fsm_established_transitions, in_messages=in_messages, + in_update_elapsed_time=in_update_elapsed_time, + in_updates=in_updates, out_messages=out_messages, - fsm_established_transitions=fsm_established_transitions, - fsm_established_time=fsm_established_time, - in_update_elapsed_time=in_update_elapsed_time + out_updates=out_updates, + peer_state=peer_state, + remote_addr=remote_addr, + remote_as=remote_as, + remote_id=remote_id, + local_addr=local_addr, + local_as=local_as, + local_id=local_id, ) if bgp_peer: - bgp_peer[remote_addr].item['routing_instance'] = routing_instance if routing_instance: + bgp_peer[remote_addr].item['routing_instance'] = routing_instance item = f'{remote_addr} {routing_instance}' bgp_peer = {item: bgp_peer[remote_addr]} peer_table.update(bgp_peer) @@ -276,7 +351,11 @@ register.snmp_section( '4', # cbgpPeer3VrfName '5', # cbgpPeer3State '6', # cbgpPeer3AdminStatus + OIDBytes('8'), # cbgpPeer3LocalAddr + '10', # cbgpPeer3LocalAs + '11', # cbgpPeer3LocalIdentifier '13', # cbgpPeer3RemoteAs + '14', # cbgpPeer3RemoteIdentifier '15', # cbgpPeer3InUpdates '16', # cbgpPeer3OutUpdates '17', # cbgpPeer3InTotalMessages diff --git a/source/agent_based/inv_cisco_bgp_peer.py b/source/agent_based/inv_cisco_bgp_peer.py index bf074b41632e458cf51010180096fd37a3c191f2..c2db485afad5d09486b43b4c458483f65b8fb01d 100644 --- a/source/agent_based/inv_cisco_bgp_peer.py +++ b/source/agent_based/inv_cisco_bgp_peer.py @@ -15,13 +15,13 @@ from typing import List from cmk.base.plugins.agent_based.agent_based_api.v1 import ( - register, + OIDBytes, + OIDEnd, SNMPTree, - exists, - contains, all_of, - OIDEnd, - OIDBytes, + contains, + exists, + register, ) from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( StringByteTable @@ -29,9 +29,9 @@ from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( 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, + bgp_get_ip_address_from_oid, + bgp_render_ip_address, get_bgp_type, ) @@ -49,8 +49,18 @@ def parse_inv_cisco_bgp_peer(string_table: List[StringByteTable]): 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 + ( + oid_end, + state, + local_addr, + local_as, + local_id, + remote_as, + remote_id, + last_error, + fsm_established_time, + last_error_txt + ) = entry except ValueError: return diff --git a/source/packages/cisco_bgp_peer b/source/packages/cisco_bgp_peer index d758634055cbd2cee5cd0213981628186cecd3d7..16c0651c4acf24272e8f144bd8052cd17ed9e2b1 100644 --- a/source/packages/cisco_bgp_peer +++ b/source/packages/cisco_bgp_peer @@ -20,7 +20,7 @@ 'files': {'agent_based': ['cisco_bgp_peer.py', 'inv_cisco_bgp_peer.py']}, 'name': 'cisco_bgp_peer', 'title': 'Cisco BGP Peer', - 'version': '1.0.0-20230613', + 'version': '1.0.2-20241220', 'version.min_required': '2.0.0b1', - 'version.packaged': '2.2.0p24', - 'version.usable_until': None} + 'version.packaged': 'cmk-mkp-tool 0.2.0', + 'version.usable_until': '2.4.0b1'}