diff --git a/CHANGELOG b/CHANGELOG index 4a8c47b88a154df21415a61bc5d5a6e0d6195a95..9e210a7487a086b7355f920b1155d6fc079615e5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -30,3 +30,5 @@ 2023-01-21: changed to always yield fsm_established_time (not only if beep connects, but also on all other states) 2023-01-20: add description to BgpPeerItem (for Arista) 2023-01-22: fix output for admin_state +2023-02-16: changed for CMK 2.1 (moved gui files from local/share/.. to local/lib/..) + fix type error in discovery (CMK2.1 GUI only) diff --git a/agent_based/bgp_peer.py b/agent_based/bgp_peer.py index 0427531a4b1e2b6a45c72447df8b0b203efcdc82..7e9e957ed563c50b88fc387005c4a6f803ff8ace 100644 --- a/agent_based/bgp_peer.py +++ b/agent_based/bgp_peer.py @@ -28,7 +28,8 @@ # 2022-09-11: optimized internal flow: > alias > not found > admin down > peer state > ... # 2023-01-21: changed to always yield fsm_established_time (not only if beep connects, but also on all other states) # 2023-01-22: fix output for admin_state -# +# 2023-02-16: changed for CMK 2.1 (moved gui files from local/share/.. to local/lib/..) +# fix type error in discovery (CMK2.1 GUI only) # Example Agent Output: # BGP4-MIB @@ -251,8 +252,8 @@ register.check_plugin( 'peernotfound': 2, 'admindown': 1, 'noprefixlimit': 1, - 'accepted_prefixes_upper_levels': (None, None), - 'accepted_prefixes_lower_levels': (None, None), + # 'accepted_prefixes_upper_levels': (None, None), # Type error in discovery (cmk2.1 GUI only) + # 'accepted_prefixes_lower_levels': (None, None), # Type error in discovery (cmk2.1 GUI only) 'neighborstate': { '1': 2, # idle '2': 1, # connect diff --git a/bgp_peer.mkp b/bgp_peer.mkp index da9a24373c17cd78858b14befdcab5aabc16efee..aa3427a79c6ed30fcb8153f682e49be73db15190 100644 Binary files a/bgp_peer.mkp and b/bgp_peer.mkp differ diff --git a/gui/metrics/bgp_peer.py b/gui/metrics/bgp_peer.py new file mode 100644 index 0000000000000000000000000000000000000000..6db6b1677b107ec94e33c509400c5f7301b45317 --- /dev/null +++ b/gui/metrics/bgp_peer.py @@ -0,0 +1,225 @@ +#!/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 : 2021-08-21 +# +# BGP Peer metrics plugin +# +# +from cmk.gui.i18n import _ + +from cmk.gui.plugins.metrics.utils import ( + metric_info, + graph_info, + perfometer_info +) + +##################################################################################################################### +# +# define metrics for bgp peer perfdata +# +##################################################################################################################### + +metric_info['bgp_peer_inupdates'] = { + 'title': _('Updates received'), + 'unit': '1/s', + 'color': '22/a', +} +metric_info['bgp_peer_outupdates'] = { + 'title': _('Updates send'), + 'unit': '1/s', + 'color': '32/a', +} +metric_info['bgp_peer_intotalmessages'] = { + 'title': _('Messages received'), + 'unit': '1/s', + 'color': '42/a', +} +metric_info['bgp_peer_outtotalmessages'] = { + 'title': _('Messages send'), + 'unit': '1/s', + 'color': '13/a', +} +metric_info['bgp_peer_fsmestablishedtransitions'] = { + 'title': _('FSM transitions'), + 'unit': 'count', + 'color': '23/a', +} +metric_info['bgp_peer_fsmestablishedtime'] = { + 'title': _('FSM last change'), + 'unit': 's', + 'color': '26/a', +} +metric_info['bgp_peer_inupdateelapsedtime'] = { + 'title': _('Last update received'), + 'unit': 's', + 'color': '43/a', +} + +metric_info['bgp_peer_acceptedprefixes'] = { + 'title': _('Prefixes accepted'), + 'help': _('number of accepted prefixes'), + 'unit': 'count', + 'color': '11/a', +} +metric_info['bgp_peer_deniedprefixes'] = { + 'title': _('Prefixes denied'), + 'unit': '1/s', + 'color': '21/a', +} +metric_info['bgp_peer_advertisedprefixes'] = { + 'title': _('Prefixes advertised'), + 'unit': '1/s', + 'color': '31/a', +} +metric_info['bgp_peer_withdrawnprefixes'] = { + 'title': _('Prefixes withdrawn'), + 'unit': '1/s', + 'color': '41/a', +} +metric_info['bgp_peer_suppressedprefixes'] = { + 'title': _('Prefixes suppressed'), + 'unit': '1/s', + 'color': '12/a', +} + +# Juniper specific metrics +metric_info['bgp_peer_in_prefixes'] = { + 'title': _('Prefixes in'), + 'unit': 'count', + 'color': '11/a', +} +metric_info['bgp_peer_in_prefixes_rejected'] = { + 'title': _('Prefixes in rejected'), + 'unit': 'count', + 'color': '21/a', +} +metric_info['bgp_peer_in_prefixes_active'] = { + 'title': _('Prefixes in active'), + 'unit': 'count', + 'color': '31/a', +} +metric_info['bgp_peer_out_prefixes'] = { + 'title': _('Prefixes out'), + 'unit': 'count', + 'color': '41/a', +} + + +###################################################################################################################### +# +# how to graph perdata for bgp peer +# +###################################################################################################################### + +graph_info['bgp_peer.fms_transitions_last_change'] = { + 'title': _('FSM established last change'), + 'metrics': [ + ('bgp_peer_fsmestablishedtime', 'area'), + ], + 'range': (0, 'bgp_peer_fsmestablishedtime:max'), +} + +graph_info['bgp_peer.prefixes_accepted'] = { + 'title': _('Accepted Prefixes'), + 'metrics': [ + ('bgp_peer_acceptedprefixes', 'area'), + ], + 'scalars': [ + ('bgp_peer_acceptedprefixes:crit', _('crit')), + ('bgp_peer_acceptedprefixes:warn', _('warn')), + ], + 'range': (0, 'bgp_peer_acceptedprefixes:max'), +} + +graph_info['bgp_peer.prefixes_per_second'] = { + 'title': _('Prefixes/s'), + 'metrics': [ + ('bgp_peer_withdrawnprefixes', 'line'), + ('bgp_peer_suppressedprefixes', 'line'), + ('bgp_peer_deniedprefixes', 'line'), + ('bgp_peer_advertisedprefixes', 'line'), + ], + 'optional_metrics': [ + 'bgp_peer_withdrawnprefixes', + 'bgp_peer_suppressedprefixes', + 'bgp_peer_deniedprefixes', + 'bgp_peer_advertisedprefixes', + ], +} + +graph_info['bgp_peer.updates_in_out'] = { + 'title': _('Updates'), + 'metrics': [ + ('bgp_peer_outupdates', '-area'), + ('bgp_peer_inupdates', 'area'), + ] +} + +graph_info['bgp_peer.messages_in_out'] = { + 'title': _('Total messages'), + 'metrics': [ + ('bgp_peer_outtotalmessages', '-area'), + ('bgp_peer_intotalmessages', 'area'), + ] +} + +graph_info['bgp_peer.fms_transitions_from_to'] = { + 'title': _('FSM transitions from/to established'), + 'metrics': [ + ('bgp_peer_fsmestablishedtransitions', 'area'), + ], + 'range': (0, 'bgp_peer_fsmestablishedtransitions:max'), +} + + +graph_info['bgp_peer.time_since_last_update'] = { + 'title': _('Time since last update received'), + 'metrics': [ + ('bgp_peer_inupdateelapsedtime', 'area'), + ], + 'range': (0, 'bgp_peer_inupdateelapsedtime:mac'), +} + +# juniper prefixes +graph_info['bgp_peer.juniper_prefixes'] = { + 'title': _('Prefixes in/out'), + 'metrics': [ + ('bgp_peer_out_prefixes', '-line'), + ('bgp_peer_in_prefixes_rejected', 'line'), + ('bgp_peer_in_prefixes_active', 'line'), + ('bgp_peer_in_prefixes', 'line'), + ], +} + +###################################################################################################################### +# +# define perf-o-meter for bgp peer uptime + prefixes accepted/advertised +# +###################################################################################################################### + +perfometer_info.append(('stacked', [ + { + 'type': 'logarithmic', + 'metric': 'bgp_peer_fsmestablishedtime', + 'half_value': 2592000.0, # ome month + 'exponent': 2, + }, + { + 'type': 'logarithmic', + 'metric': 'bgp_peer_acceptedprefixes', + 'half_value': 500000.0, + 'exponent': 2, + } +])) + +perfometer_info.append({ + 'type': 'logarithmic', + 'metric': 'bgp_peer_fsmestablishedtime', + 'half_value': 2592000.0, # ome month + 'exponent': 2, +}) diff --git a/gui/views/inv_bgp_peer.py b/gui/views/inv_bgp_peer.py new file mode 100644 index 0000000000000000000000000000000000000000..f67054ca29363b724051f9db0549d5307c6f2049 --- /dev/null +++ b/gui/views/inv_bgp_peer.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from cmk.gui.i18n import _ +from cmk.gui.plugins.views.utils import ( + inventory_displayhints, +) +from cmk.gui.plugins.visuals.inventory import ( + FilterInvtableAdminStatus, + FilterInvtableTimestampAsAge, + FilterInvBool, +) +from cmk.gui.plugins.views.inventory import declare_invtable_view + +inventory_displayhints.update({ + '.networking.bgp_peers:': { + 'title': _('BGP Peers'), + 'keyorder': [ + 'remote_addr', + 'peer_state', 'last_change', 'in_service', + 'local_addr', 'remote_id', 'local_id', 'remote_as', 'local_as', + ], + 'view': 'invbgppeer_of_host', + }, + '.networking.bgp_peers:*.remote_addr': {'title': _('Remote address'), }, + '.networking.bgp_peers:*.local_addr': {'title': _('Local address'), }, + '.networking.bgp_peers:*.remote_id': {'title': _('Remote ID'), }, + '.networking.bgp_peers:*.local_id': {'title': _('Local ID'), }, + '.networking.bgp_peers:*.remote_as': {'title': _('Remote AS'), }, + '.networking.bgp_peers:*.local_as': {'title': _('Local AS'), }, + '.networking.bgp_peers:*.bgp_type': {'title': _('Type'), }, + '.networking.bgp_peers:*.version': {'title': _('Version'), }, + '.networking.bgp_peers:*.last_error': {'title': _('Last error'), }, + '.networking.bgp_peers:*.last_error_code': {'title': _('Last error code'), }, + '.networking.bgp_peers:*.address_family': {'title': _('Address family'), }, + '.networking.bgp_peers:*.as_name': {'title': _('Remote AS Name'), }, + '.networking.bgp_peers:*.as_org_name': {'title': _('Remote AS Org Name'), }, + '.networking.bgp_peers:*.peer_state': { + 'title': _('Peer state'), + 'short': _('State'), + 'paint': 'if_admin_status', + 'filter': FilterInvtableAdminStatus, + }, + '.networking.bgp_peers:*.in_service': { + 'title': _('In service'), + 'short': _('In service'), + 'paint': 'bool', + # 'filter': FilterInvBool, + }, + '.networking.bgp_peers:*.last_change': { + 'title': _('Last change'), + 'short': _('Last change'), + 'paint': 'timestamp_as_age_days', + 'filter': FilterInvtableTimestampAsAge, + }, +}) + +declare_invtable_view('invbgppeer', '.networking.bgp_peers:', _('BGP peers'), _('BGP peers')) diff --git a/gui/wato/bgp_peer.py b/gui/wato/bgp_peer.py new file mode 100644 index 0000000000000000000000000000000000000000..81489703db3d893e578d5d6cc06b47273a5f514c --- /dev/null +++ b/gui/wato/bgp_peer.py @@ -0,0 +1,250 @@ +#!/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 bgp_peers WATO plugin +# +# 2021-03-27: rewrite for CMK 2.0 +# 2021-08-21: modified for bgp_peer plugin (from cisco_bgp_peer) +# 2021-08-29: removed htmloutput and infotext_values option +# 2022-04-02: added bgp neighbour states +# 2022-04-29: added upper/lower prefix limit +# 2022-05-09: added discovery rule set +# 2022-05-11: added remote_as to build_item +# 2022-09-05: added internal_item to avoid warnings on cmk updates (THX to Jay2k1 for reporting the issue) + +from cmk.gui.i18n import _ +from cmk.gui.valuespec import ( + Dictionary, + Integer, + TextAscii, + ListOf, + Tuple, + TextUnicode, + MonitoringState, + ListChoice, +) + +from cmk.gui.plugins.wato.utils import ( + CheckParameterRulespecWithItem, + rulespec_registry, + RulespecGroupCheckParametersNetworking, + HostRulespec, + RulespecGroupCheckParametersDiscovery, +) + + +def _parameter_valuespec_bgp_peer(): + return Dictionary( + elements=[ + ('minuptime', + Tuple( + title=_('Minimum uptime for peer'), + orientation='horizontal', + help=_('Set the time in seconds, a peer must be up before the peer is considered sable.'), + elements=[ + Integer(title=_('Warning below'), unit='seconds', default_value=7200, minvalue=0), + Integer(title=_('Critical below'), unit='seconds', default_value=3600, minvalue=0) + ], + )), + ('accepted_prefixes_upper_levels', + Tuple( + title=_('Accepted prefixes upper levels'), + help=_('The values from WATO are preferred to the values from the device.'), + orientation='horizontal', + elements=[ + Integer(title=_('Warning at'), minvalue=0, unit=_('prefixes'), size=5), + Integer(title=_('Critical at'), minvalue=0, unit=_('prefixes'), size=5), + ], + )), + ('accepted_prefixes_lower_levels', + Tuple( + title=_('Accepted prefixes lower levels'), + orientation='horizontal', + elements=[ + Integer(title=_('Warning below'), minvalue=0, unit=_('prefixes'), size=5), + Integer(title=_('Critical below'), minvalue=0, unit=_('prefixes'), size=5), + ], + )), + ('peernotfound', + MonitoringState( + default_value=2, + title=_('State if peer is no not found.'), + help=_('Default monitoring state if the peer is not found in the SNMP data') + )), + ('admindown', + MonitoringState( + default_value=1, + title=_('State if peer is admin shutdown.'), + help=_('Monitoring state if the peer is admin shutdown') + )), + ('neighborstate', + Dictionary( + title=_('State to report for BGP neighbor state'), + help=_('Map each BGP state to a CheckMK monitoring state'), + elements=[ + ('1', + MonitoringState( + title=_('1 - idle'), + help=_( + 'This is the first stage of the BGP FSM. BGP detects a start event, tries to initiate a ' + 'TCP connection to the BGP peer, and also listens for a new connect from a peer router. ' + 'If an error causes BGP to go back to the Idle state for a second time, the ' + 'ConnectRetryTimer is set to 60 seconds and must decrement to zero before the connection ' + 'is initiated again. Further failures to leave the Idle state result in the ' + 'ConnectRetryTimer doubling in length from the previous time. ' + 'Default monitoring state is "CRIT"'), + default_value=2, + )), + ('2', + MonitoringState( + title=_('2 - connect'), + help=_( + 'In this state, BGP initiates the TCP connection. If the 3-way TCP handshake completes, ' + 'the established BGP Session BGP process resets the ConnectRetryTimer and sends the Open ' + 'message to the neighbor, and then changes to the OpenSent State.' + 'Default monitoring state is "WARN"'), + default_value=1, + )), + ('3', + MonitoringState( + title=_('3 - active'), + help=_('In this state, BGP starts a new 3-way TCP handshake. If a connection is established, ' + 'an Open message is sent, the Hold Timer is set to 4 minutes, and the state moves to ' + 'OpenSent. If this attempt for TCP connection fails, the state moves back to the Connect ' + 'state and resets the ConnectRetryTimer. ' + 'Default monitoring state is "WARN"'), + default_value=1, + )), + ('4', + MonitoringState( + title=_('4 - opensent'), + help=_( + 'In this state, an Open message has been sent from the originating router and is awaiting ' + 'an Open message from the other router. After the originating router receives the OPEN ' + 'message from the other router, both OPEN messages are checked for errors. If the Open ' + 'messages do not have any errors, the Hold Time is negotiated (using the lower value), ' + 'and a KEEPALIVE message is sent (assuming the value is not set to zero). The connection ' + 'state is then moved to OpenConfirm. If an error is found in the OPEN message, a ' + 'Notification message is sent, and the state is moved back to Idle.' + ' Default monitoring state is "WARN"'), + default_value=1, + )), + ('5', + MonitoringState( + title=_('5 - openconfirm'), + help=_('In this state, BGP waits for a Keepalive or Notification message. Upon receipt of a ' + 'neighbor’s Keepalive, the state is moved to Established. If the hold timer expires, a ' + 'stop event occurs, or a Notification message is received, and the state is moved to ' + 'Idle. ' + 'Default monitoring state is "WARN"'), + default_value=1, + )), + ('6', + MonitoringState( + title=_('6 - established'), + help=_( + 'In this state, the BGP session is established. BGP neighbors exchange routes via Update ' + 'messages. As Update and Keepalive messages are received, the Hold Timer is reset. If the ' + 'Hold Timer expires, an error is detected and BGP moves the neighbor back to the Idle ' + 'state. ' + 'Default monitoring state is "OK"'), + default_value=0, + )), + ])), + ('noprefixlimit', + MonitoringState( + default_value=1, + title=_('State if no admin prefix limit/warn threshold is 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.') + )), + ('peer_list', + ListOf( + Tuple( + orientation='horizontal', + elements=[ + TextUnicode( + title=_('BGP Peer'), + help=_('The configured value must match a BGP item reported by the monitored ' + 'device. For example: "10.194.115.98" or "2A10:1CD0:1020:135::20 IPv6 Unicast"'), + allow_empty=False, + size=50, + ), + 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 IP-address" field. The alias will ' + 'be shown in the check info'), + size=50, + ), + 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 IP-address" field is not found') + ), + ]), + add_label=_('Add BGP peer'), + movable=False, + title=_('BGP Peers'), + )), + ('internal_item', # added by plugin discovery function + TextUnicode()), + ], + hidden_keys=['internal_item'], + ) + + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name='bgp_peer', + group=RulespecGroupCheckParametersNetworking, + item_spec=lambda: TextAscii(title=_('BGP peer'), ), + match_type='dict', + parameter_valuespec=_parameter_valuespec_bgp_peer, + title=lambda: _('BGP peer'), + )) + + +def _valuespec_discovery_bgp_peer(): + item_parts = [ + # ('remote_address', 'Peer remote address'), + ('remote_as', 'Remote AS'), + ('address_family', 'Address family'), + ('routing_instance', 'Routing instance/VRF'), + + ] + return Dictionary( + title=_('BGP peer'), + elements=[ + ('build_item', + ListChoice( + title=_('Information not to use in the item name'), + help=_( + 'The Peer remote address is always used as the item name. By default the check will add the ' + 'address-family and the routing instance/VRF if available. You can decide to not use these ' + 'additional information in the item name. Do so only if your peers have only one address-' + 'family configured and you don\'t have the same peer remote address in different routing ' + 'instances/VRFs configured.' + ), + choices=item_parts, + default_value=['remote_as'], + )), + ], + ) + + +rulespec_registry.register( + HostRulespec( + group=RulespecGroupCheckParametersDiscovery, + match_type='dict', + name='discovery_bgp_peer', + valuespec=_valuespec_discovery_bgp_peer, + )) diff --git a/gui/wato/inv_bgp_peer.py b/gui/wato/inv_bgp_peer.py new file mode 100644 index 0000000000000000000000000000000000000000..f4832c661908036a3d309eb0b9f13b8dcba7db90 --- /dev/null +++ b/gui/wato/inv_bgp_peer.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2022-04-24 +# +# 2022-04-24: added option for BGP down time +# added option to remove some columns from inventory +# 2022-04-28: added Whois options + +from cmk.gui.i18n import _ +from cmk.gui.plugins.wato.utils import ( + HostRulespec, + rulespec_registry, +) +from cmk.gui.valuespec import ( + Dictionary, + ListChoice, + Age, + DropdownChoice, + Integer, +) + +from cmk.gui.plugins.wato.inventory import ( + RulespecGroupInventory, +) + + +def _valuespec_inv_bgp_peer(): + removecolumns = [ + # ('remote_as', 'Remote AS'), + # ('remote_id', 'Remote ID'), + # ('local_addr', 'Local address'), + # ('local_as', 'Local AS'), + # ('local_id', 'Local ID'), + ('address_family', 'Address family'), + ('last_error', 'Last error'), + ('last_error_code', 'Last error code'), + # ('prev_state', 'Previous state'), + ('as_name', 'Remote AS name'), + ('as_org_name', 'Remote AS Org Name'), + ('bgp_type', 'Type'), + ('version', 'Version'), + ] + + return Dictionary( + title=_('BGP peer'), + elements=[ + ('not_in_service_time', + Age( + title=_('Time peer is not up until considered not in service'), + default_value=2592000, # 30 days in seconds, + )), + ('remove_columns', + ListChoice( + title=_('List of columns to remove'), + help=_('Information to remove from inventory'), + choices=removecolumns, + default_value=[], + )), + ('whois_enable', + Dictionary( + title=_('Add whois data to the inventory'), + help=_( + 'The whois data will be fetched via RDAP from the registries. For this the the plugin tries to' + 'find the best registry via the RDAP bootstrap data from https://data.iana.org/rdap/asn.json.' + 'The query it self will go to the found registry via http(s). Note: the request might be get ' + 'redirected if there a different authoritative registry for the ASn' + ), + elements=[ + ('whois_rir', + DropdownChoice( + title='Preferred RIR to fetch whois data', + help=_( + 'This registry will be used if the plugin can not determine the authoritative registry ' + 'based on the bootstrap data.' + ), + choices=[ + ('afrinic', _('AFRINIC (https://rdap.afrinic.net/rdap)')), + ('apnic', _('APNIC (https://rdap.apnic.net)')), + ('arin', _('ARIN (https://rdap.arin.net/registry)')), + ('ripe', _('RIPE (https://rdap.db.ripe.net)')), + ('lacnic', _('LACNIC (https://rdap.apnic.net)')), + ] + )), + ('whois_timeout', + Integer( + title='Timeout for connections to RIRs', + help=_('The connection timeout for each whois request.'), + default_value=5, + minvalue=1, + unit=_('seconds'), + )), + ] + )), + ], + ) + + +rulespec_registry.register( + HostRulespec( + group=RulespecGroupInventory, + match_type='dict', + name='inv_parameters:inv_bgp_peer', + valuespec=_valuespec_inv_bgp_peer, + )) diff --git a/packages/bgp_peer b/packages/bgp_peer index c76af23a17df191ea13259769fca72c49cc26610..abed79f42927b19cb73d5de2901d52106350ebaa 100644 --- a/packages/bgp_peer +++ b/packages/bgp_peer @@ -13,14 +13,13 @@ 'inv_bgp_peer.py', 'utils/bgp_peer.py'], 'checkman': ['bgp_peer'], - 'web': ['plugins/metrics/bgp_peer.py', - 'plugins/views/inv_bgp_peer.py', - 'plugins/wato/bgp_peer.py', - 'plugins/wato/inv_bgp_peer.py']}, + 'gui': ['metrics/bgp_peer.py', + 'views/inv_bgp_peer.py', + 'wato/bgp_peer.py', + 'wato/inv_bgp_peer.py']}, 'name': 'bgp_peer', - 'num_files': 8, - 'title': 'BGP Peer State Check', - 'version': '20230123.v1.9', - 'version.min_required': '2.0.0', - 'version.packaged': '2021.09.20', + 'title': 'BGP Peer', + 'version': '20230217.v2.0.0', + 'version.min_required': '2.1.0', + 'version.packaged': '2.1.0p21', 'version.usable_until': None} \ No newline at end of file