From ff58f68ae9e1d7c59b6b83ba222c9f7852d63153 Mon Sep 17 00:00:00 2001
From: "th.l" <thl-cmk@outlook.com>
Date: Tue, 17 Jan 2023 20:59:08 +0100
Subject: [PATCH] update project

---
 agent_based/arista_bgp_peer.py       | 144 +++++++++++++++++++++++++++
 agent_based/inv_arista_bgp_peer.py   | 119 ++++++++++++++++++++++
 agent_based/utils/arista_bgp_peer.py |  41 ++++++++
 arista_bgp_peer.mkp                  | Bin 0 -> 3180 bytes
 packages/arista_bgp_peer             |  27 +++++
 5 files changed, 331 insertions(+)
 create mode 100644 agent_based/arista_bgp_peer.py
 create mode 100644 agent_based/inv_arista_bgp_peer.py
 create mode 100644 agent_based/utils/arista_bgp_peer.py
 create mode 100644 arista_bgp_peer.mkp
 create mode 100644 packages/arista_bgp_peer

diff --git a/agent_based/arista_bgp_peer.py b/agent_based/arista_bgp_peer.py
new file mode 100644
index 0000000..9570c4b
--- /dev/null
+++ b/agent_based/arista_bgp_peer.py
@@ -0,0 +1,144 @@
+#!/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  : 2023-01-16
+#
+# Monitor status of Arista Networks BGP Peers (IPv4 and IPv6)
+#
+#
+#
+
+import copy
+from typing import List, Dict, Optional, Tuple
+from dataclasses import dataclass
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    register,
+    SNMPTree,
+    startswith,
+    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 (
+    BgpPeer,
+    bgp_get_peer_entry,
+    bgp_get_ip_address_from_oid,
+)
+
+from cmk.base.plugins.agent_based.utils.arista_bgp_peer import (
+    arista_afi_safi_mapping,
+)
+
+
+@dataclass
+class AristaPrefixes:
+    afi: str
+    safi: str
+    accepted_prefixes: int
+    metric_count: List[Tuple[str, int]]
+    metric_rate: List[Tuple[str, int]]
+
+
+def parse_arista_bgp_peer(string_table: List[StringByteTable]) -> Optional[Dict[str, BgpPeer]]:
+    BgpPeerTable, BgpPrefixCountersTable = string_table
+
+    peer_table = {}
+    peer_prefixes = {}
+
+    for entry in BgpPrefixCountersTable:
+        oid_end, in_prefixes, in_prefixes_accepted, out_prefixes = entry
+        oid_end_split = oid_end.split('.')
+        afi = oid_end_split[-2]
+        safi = oid_end_split[-1]
+        index = '.'.join(oid_end_split[:-2])
+        prefixes = AristaPrefixes(
+            afi=afi,
+            safi=safi,
+            accepted_prefixes=int(in_prefixes_accepted),
+            metric_rate=[],
+            metric_count=[
+                ('in_prefixes', int(in_prefixes)),
+                ('out_prefixes', int(out_prefixes)),
+            ],
+        )
+
+        if peer_prefixes.get(index):
+            peer_prefixes[index].append(prefixes)
+        else:
+            peer_prefixes[index] = [prefixes]
+
+    for entry in BgpPeerTable:
+        oid_end, remote_as, remote_id, admin_state, peer_state, in_updates, out_updates, in_messages, out_messages, \
+        fsm_established_transitions, fsm_established_time, in_update_elapsed_time = entry
+
+        remote_addr = bgp_get_ip_address_from_oid(f'{oid_end[2:]}')
+
+        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,
+            in_messages=in_messages,
+            out_messages=out_messages,
+            fsm_established_transitions=fsm_established_transitions,
+            fsm_established_time=fsm_established_time,
+            in_update_elapsed_time=in_update_elapsed_time
+        )
+
+        prefixes = peer_prefixes.get(oid_end, [])
+        for address_family in prefixes:
+            address_family_str = arista_afi_safi_mapping(address_family.afi, address_family.safi)
+            item = f'{remote_addr} {address_family_str}'
+            peer_table[item] = copy.deepcopy(bgp_peer[remote_addr])
+            peer_table[item].accepted_prefixes = address_family.accepted_prefixes
+            peer_table[item].metric_count += address_family.metric_count
+            peer_table[item].metric_rate += address_family.metric_rate
+            peer_table[item].item['address_family'] = address_family_str
+            peer_table[item].item['routing_instance'] = ''
+    return peer_table
+
+
+register.snmp_section(
+    name='arista_bgp_peer',
+    parse_function=parse_arista_bgp_peer,
+    parsed_section_name='bgp_peer',
+    supersedes=['bgp_peer', 'arista_bgp'],
+    fetch=[
+        SNMPTree(
+            base='.1.3.6.1.4.1.30065.4.1.1',  # AARISTA-BGP4V2-MIB::aristaBgp4V2Objects
+            oids=[
+                OIDEnd(),
+                '2.1.10',  # aristaBgp4V2PeerRemoteAs
+                OIDBytes('2.1.11'),  # aristaBgp4V2PeerRemoteIdentifier
+                '2.1.12',  # aristaBgp4V2PeerAdminStatus
+                '2.1.13',  # aristaBgp4V2PeerState
+                '7.1.1',  # aristaBgp4V2PeerInUpdates
+                '7.1.2',  # aristaBgp4V2PeerOutUpdates
+                '7.1.3',  # aristaBgp4V2PeerInTotalMessages
+                '7.1.4',  # aristaBgp4V2PeerOutTotalMessages
+                '7.1.5',  # aristaBgp4V2PeerFsmEstablishedTransitions
+                '4.1.1',  # aristaBgp4V2PeerFsmEstablishedTime
+                '4.1.2',  # aristaBgp4V2PeerInUpdatesElapsedTime
+                ]),
+        SNMPTree(
+            base='.1.3.6.1.4.1.30065.4.1.1.8.1',  # ARISTA-BGP4V2-MIB::aristaBgp4V2PrefixGaugesEntry
+            oids=[
+                OIDEnd(),  # index.afi.safi
+                '3',  # aristaBgp4V2PrefixInPrefixes
+                '4',  # aristaBgp4V2PrefixInPrefixesAccepted
+                '5',  # aristaBgp4V2PrefixOutPrefixes
+            ]
+        ),
+    ],
+    detect=startswith('.1.3.6.1.2.1.1.2.0', '.1.3.6.1.4.1.30065'),  # ARISTA-SMI-MIB::arista
+),
diff --git a/agent_based/inv_arista_bgp_peer.py b/agent_based/inv_arista_bgp_peer.py
new file mode 100644
index 0000000..b6380f9
--- /dev/null
+++ b/agent_based/inv_arista_bgp_peer.py
@@ -0,0 +1,119 @@
+#!/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  : 2023-01-17
+#
+# inventory of Arista Networks BGP Peers (IPv4 and IPv6)
+#
+#
+
+
+from typing import List
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    register,
+    SNMPTree,
+    OIDBytes,
+    startswith,
+    OIDEnd,
+)
+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_error_code_as_hex,
+    bgp_render_ip_address,
+    get_bgp_type,
+    bgp_get_ip_address_from_oid,
+)
+from cmk.base.plugins.agent_based.utils.arista_bgp_peer import (
+    arista_afi_safi_mapping,
+)
+
+
+def parse_inv_arista_bgp_peer(string_table: List[StringByteTable]):
+    peers, address_families = string_table
+
+    bgp_peers = []
+
+    peer_families = {}
+    for entry in address_families:
+        oid_end, in_prefixes = entry
+        oid_end_split = oid_end.split('.')
+        afi = oid_end_split[-2]
+        safi = oid_end_split[-1]
+        index = '.'.join(oid_end_split[:-2])
+
+        if peer_families.get(index):
+            peer_families[index] = peer_families[index] + [arista_afi_safi_mapping(afi, safi)]
+        else:
+            peer_families[index] = [arista_afi_safi_mapping(afi, safi)]
+
+    for entry in peers:
+        oid_end, local_addr_type, local_addr, local_as, local_id, remote_as, remote_id, state, last_error_received, \
+        fsm_established_time, fsm_established_trans = entry
+
+        remote_addr = bgp_get_ip_address_from_oid(f'{oid_end[2:]}')
+
+        # assuming IPv4 address format
+        local_id = bgp_render_ip_address('1', local_id)
+        remote_id = bgp_render_ip_address('1', remote_id)
+
+        bgp_peer: InvBgpPeer = {
+            'remote_addr': remote_addr,
+            '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_received),
+            'last_error': bgp_error_as_string(last_error_received),
+            'status_columns': {},
+            'address_family': ', '.join(peer_families.get(oid_end, []))
+        }
+        bgp_peers.append(bgp_peer)
+
+    return bgp_peers
+
+
+register.snmp_section(
+    name='inv_arista_bgp_peer',
+    parse_function=parse_inv_arista_bgp_peer,
+    parsed_section_name='inv_bgp_peer',
+    supersedes=['inv_bgp_peer'],
+    fetch=[
+        SNMPTree(
+            base='.1.3.6.1.4.1.30065.4.1.1',   # AARISTA-BGP4V2-MIB::aristaBgp4V2Objects
+            oids=[
+                OIDEnd(),
+                '2.1.2',  # aristaBgp4V2PeerLocalAddrType
+                OIDBytes('2.1.3'),  # aristaBgp4V2PeerLocalAddr
+                '2.1.7',  # aristaBgp4V2PeerLocalAs
+                OIDBytes('2.1.8'),  # aristaBgp4V2PeerLocalIdentifier
+                '2.1.10',  # aristaBgp4V2PeerRemoteAs
+                OIDBytes('2.1.11'),  # aristaBgp4V2PeerRemoteIdentifier
+                '2.1.13',  # aristaBgp4V2PeerState
+                OIDBytes('3.1.1'),  # aristaBgp4V2PeerLastErrorCodeReceived
+                '4.1.1',  # aristaBgp4V2PeerFsmEstablishedTime
+                '7.1.5',  # aristaBgp4V2PeerFsmEstablishedTransitions
+            ]
+        ),
+        SNMPTree(
+            base='.1.3.6.1.4.1.30065.4.1.1.8.1',  # ARISTA-BGP4V2-MIB::aristaBgp4V2PrefixGaugesEntry
+            oids=[
+                OIDEnd(),  # index.addr-type.addr_length.addr.afi[-2].safi[-1]
+                '3',  # aristaBgp4V2PrefixInPrefixes
+            ]
+        ),
+    ],
+    detect=startswith('.1.3.6.1.2.1.1.2.0', '.1.3.6.1.4.1.30065'),  # ARISTA-SMI-MIB::arista
+),
diff --git a/agent_based/utils/arista_bgp_peer.py b/agent_based/utils/arista_bgp_peer.py
new file mode 100644
index 0000000..ac76ea6
--- /dev/null
+++ b/agent_based/utils/arista_bgp_peer.py
@@ -0,0 +1,41 @@
+#!/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  : 2023-01-16
+#
+# include file, will be used with arista_bgp_peer and inv_arista_bgp_peer
+#
+#
+
+def arista_address_type(st: str):
+    names = {
+        '0': 'unknown',
+        '1': 'ipv4',
+        '2': 'ipv6',
+    }
+    return names.get(st, st)
+
+
+def arista_address_family(st: str):
+    names = {
+        '0': 'unknown',
+        '1': 'ipv4',
+        '2': 'ipv6',
+    }
+    return names.get(st, st)
+
+
+def arista_afi_safi_mapping(afi: str, safi: str) -> str:
+    names = {
+        (1, 1): 'IPv4 unicast',
+        (1, 2): 'IPv4 multicast',
+        (2, 1): 'IPv6 unicast',
+        (2, 2): 'IPv6 multicast',
+        (1, 4): 'MPLS IPv4',
+        (2, 4): 'MPLS IPv6',
+    }
+    return names.get((int(afi), int(safi)), f'AFI {afi} SAFI {safi}')
diff --git a/arista_bgp_peer.mkp b/arista_bgp_peer.mkp
new file mode 100644
index 0000000000000000000000000000000000000000..1908d9891cb3b68929da876be0815e96e0e4c532
GIT binary patch
literal 3180
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
J(uC5`{0~#6Got_i

literal 0
HcmV?d00001

diff --git a/packages/arista_bgp_peer b/packages/arista_bgp_peer
new file mode 100644
index 0000000..9aaf4ed
--- /dev/null
+++ b/packages/arista_bgp_peer
@@ -0,0 +1,27 @@
+{'author': 'Th.L. (thl-cmk[at]outlook[dot]com)',
+ 'description': 'Monitors Arista Networks BGP Peers.\n'
+                '\n'
+                '- creates one service for each peer/address family  (IPv4 '
+                'and  IPv6)\n'
+                '- performance data include: peer uptime, prefixes accepted,  '
+                'advertised,\n'
+                '- this package contains also a inventory plugin\n'
+                '\n'
+                'NOTE: this plugin will supersede the original arista_bgp '
+                'plugin\n'
+                '\n'
+                'NOTE: to use this plugin you must also install my bgp_peer '
+                'plugin '
+                '(https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/bgp_peer)\n'
+                '\n',
+ 'download_url': 'https://thl-cmk.hopto.org/gitlab/arista/arista_bgp_peer',
+ 'files': {'agent_based': ['arista_bgp_peer.py',
+                           'inv_arista_bgp_peer.py',
+                           'utils/arista_bgp_peer.py']},
+ 'name': 'arista_bgp_peer',
+ 'num_files': 3,
+ 'title': 'Arista BGP peer',
+ 'version': '20230117.v0.01',
+ 'version.min_required': '2.0.0',
+ 'version.packaged': '2021.09.20',
+ 'version.usable_until': None}
\ No newline at end of file
-- 
GitLab