From cd28ae90c790a00990acb90884a9df73967fd3a9 Mon Sep 17 00:00:00 2001
From: "th.l" <thl-cmk@outlook.com>
Date: Sun, 1 May 2022 18:14:06 +0200
Subject: [PATCH] update project

---
 agent_based/huawei_bgp_peer.py |  75 ++++++++++++++++++---------------
 huawei_bgp_peer.mkp            | Bin 3255 -> 3323 bytes
 2 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/agent_based/huawei_bgp_peer.py b/agent_based/huawei_bgp_peer.py
index 7c5fff3..7746ade 100644
--- a/agent_based/huawei_bgp_peer.py
+++ b/agent_based/huawei_bgp_peer.py
@@ -12,7 +12,9 @@
 # Monitor status of Huawei BGP Peers (IPv4 and IPv6)
 #
 # 2020-07-20: added BGP prefix counter
+# 2022-04-30: code cleanup/streamlining
 #
+
 # snmpwalk sample
 # .1.3.6.1.4.1.2011.5.25.177.1.1.2.1.1.0.2.1.2.16.32.32.9.200.0.2.0.1.0.0.0.0.31.100.0.7 = Gauge32: 4
 # .1.3.6.1.4.1.2011.5.25.177.1.1.2.1.2.0.2.1.2.16.32.32.9.200.0.2.0.1.0.0.0.0.31.100.0.7 = Gauge32: 16374
@@ -55,7 +57,7 @@
 # HUAWEI-BGP-VPN-MIB::hwBgpPeerEntry.11.0.ipv4.unicast.ipv4."79.200.120.2" = INTEGER: 2
 
 
-from typing import List, Dict, Optional
+from typing import List, Dict
 
 from cmk.base.plugins.agent_based.agent_based_api.v1 import (
     register,
@@ -68,13 +70,13 @@ from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
 )
 
 from cmk.base.plugins.agent_based.utils.bgp_peer import (
-    bgp_get_peer,
+    bgp_get_ip_address_from_oid,
     BgpPeer,
     bgp_get_peer_entry,
 )
 
 
-def _huawei_get_adress_family(OID_END):
+def _huawei_get_adress_family(afi, safi):
     # HWBgpAfi ::= TEXTUAL-CONVENTION
     #    STATUS current
     #    DESCRIPTION
@@ -101,15 +103,13 @@ def _huawei_get_adress_family(OID_END):
         132: 'route-target',
     }
 
-    OID_END = OID_END.split('.')
-
-    adress_family = HWBgpAfi.get(int(OID_END[1]), OID_END[1])
-    sub_family = HWBgpSafi.get(int(OID_END[2]), OID_END[2])
+    address_family = HWBgpAfi.get(int(afi), afi)
+    sub_family = HWBgpSafi.get(int(safi), safi)
 
-    return '%s %s' % (adress_family, sub_family)
+    return f'{address_family} {sub_family}'
 
 
-def _huawei_bgp_PeerUnAvaiReason(st):
+def _huawei_bgp_peer_unavail_reason(st):
     reason = {
         '1': 'Configuration lead peer down',
         '2': 'Receive notification',
@@ -127,43 +127,39 @@ def parse_huawei_bgp_peer(string_table: List[StringTable]) -> Dict[str, BgpPeer]
 
     peer_table = {}
     for entry in hwbgpPeer2Entry:
-        oid_end, hwBgpPeerRemoteAddr, hwBgpPeerState, hwBgpPeerFsmEstablishedCounter, hwBgpPeerFsmEstablishedTime, \
-        hwBgpPeerUnAvaiReason = entry
+        oid_end, remote_address, state, fsm_established_counter, fsm_established_time, unavail_reason = entry
 
         bgp_peer = bgp_get_peer_entry([
-            hwBgpPeerRemoteAddr,
-            hwBgpPeerState,
+            remote_address,
+            state,
             '2',  # admin_state not admin_down
             None,  # in_updates
             None,  # out_updates
             None,  # in_messages
             None,  # out_messages
-            hwBgpPeerFsmEstablishedCounter,
-            hwBgpPeerFsmEstablishedTime,
+            fsm_established_counter,
+            fsm_established_time,
             None,  # in_update_elapsed_time
             ]
         )
         if bgp_peer:
-            adressfamily = _huawei_get_adress_family(oid_end)
-            remote_address = list(bgp_peer.keys())[0]
-            index = f'{remote_address} {adressfamily}'
-            bgp_peer[remote_address].peer_unavail_reason = int(hwBgpPeerUnAvaiReason)
-            bgp_peer[remote_address].peer_unavail_reason_str = _huawei_bgp_PeerUnAvaiReason(int(hwBgpPeerUnAvaiReason))
-            bgp_peer = {index: bgp_peer[remote_address]}
+            afi, safi = oid_end.split('.')[1:3]
+            adress_family = _huawei_get_adress_family(afi, safi)
+            item = f'{remote_address} {adress_family}'
+            bgp_peer[remote_address].peer_unavail_reason = int(unavail_reason)
+            bgp_peer[remote_address].peer_unavail_reason_str = _huawei_bgp_peer_unavail_reason(int(unavail_reason))
+            bgp_peer = {item: bgp_peer[remote_address]}
             peer_table.update(bgp_peer)
 
-    #     peer = {
-    #         'hwpeerunavireason': _huawei_bgp_PeerUnAvaiReason(hwBgpPeerUnAvaiReason),
-    #     }
-    #
     # add BGP route counter
     for entry in hwBgpPeerRouteEntry:
-        oid_end, hwBgpPeerPrefixRcvCounter, hwBgpPeerPrefixActiveCounter, hwBgpPeerPrefixAdvCounter = entry
+        oid_end, prefix_rcv_counter, prefix_active_counter, prefix_adv_counter = entry
+        afi, safi = oid_end.split('.')[1:3]
         counter = []
         for key, value in [
-            ('prefixrcvcounter', hwBgpPeerPrefixRcvCounter),
-            ('prefixactivecounter', hwBgpPeerPrefixActiveCounter),
-            ('prefixadvcounter', hwBgpPeerPrefixAdvCounter),
+            ('prefixrcvcounter', prefix_rcv_counter),
+            ('prefixactivecounter', prefix_active_counter),
+            ('prefixadvcounter', prefix_adv_counter),
         ]:
             try:
                 counter.append((key, int(value)))
@@ -171,9 +167,9 @@ def parse_huawei_bgp_peer(string_table: List[StringTable]) -> Dict[str, BgpPeer]
                 pass
 
         # adjust oid_end to match cisco oid_end
-        service = '%s %s' % (bgp_get_peer(f'{oid_end[6:]}.1.1'), _huawei_get_adress_family(oid_end))
-        if service in peer_table.keys():
-            peer_table[service].metric_count += counter
+        item = f'{bgp_get_ip_address_from_oid(f"{oid_end[6:]}.1.1")} {_huawei_get_adress_family(afi, safi)}'
+        if item in peer_table.keys():
+            peer_table[item].metric_count += counter
 
     return peer_table
 
@@ -187,7 +183,7 @@ register.snmp_section(
         SNMPTree(
             base='.1.3.6.1.4.1.2011.5.25.177.1.1.2.1',  # HUAWEI-BGP-VPN-MIB::hwBgpPeerEntry
             oids=[
-                OIDEnd(),  # 0.ipv4/ipv6.adressFamily.ipv4/ipv6.RemotePeerIP
+                OIDEnd(),  # 0.afi.safi.adresstype.length.RemotePeerIP
                 # '1',  # hwBgpPeerNegotiatedVersion
                 # '2',  # hwBgpPeerRemoteAs
                 '4',  # hwBgpPeerRemoteAddr
@@ -202,12 +198,23 @@ register.snmp_section(
         SNMPTree(
             base='.1.3.6.1.4.1.2011.5.25.177.1.1.3.1',  # HUAWEI-BGP-VPN-MIB::hwBgpPeerRouteEntry
             oids=[
-                OIDEnd(),  # 0.ipv4/ipv6.adressFamily.ipv4/ipv6.RemotePeerIP
+                OIDEnd(),  # 0.afi.safi.adresstype.length.RemotePeerIP
                 '1',  # hwBgpPeerPrefixRcvCounter
                 '2',  # hwBgpPeerPrefixActiveCounter
                 '3',  # hwBgpPeerPrefixAdvCounter
             ]
         ),
+        # ToDo: sample need to add counters :-(
+        # SNMPTree(
+        #     base='.1.3.6.1.4.1.2011.5.25.177.1.1.4.1',  # HUAWEI-BGP-VPN-MIB::hwBgpPeerMessageEntry
+        #     oids=[
+        #         OIDEnd(),  # 0.afi.safi.adresstype.length.RemotePeerIP(?)
+        #         '1',  # hwBgpPeerInTotalMsgCounter
+        #         '2',  # hwBgpPeerOutTotalMsgCounter
+        #         '4',  # hwBgpPeerInUpdateMsgCounter
+        #         '9',  # hwBgpPeerOutUpdateMsgCounter
+        #     ]
+        # ),
     ],
     detect=startswith('.1.3.6.1.2.1.1.2.0', '.1.3.6.1.4.1.2011')
 )
diff --git a/huawei_bgp_peer.mkp b/huawei_bgp_peer.mkp
index 0daaee78511b9f9e8a49389f2c78a3bbb26fb746..f675408e006c0873df195f239d39afc3ee38a059 100644
GIT binary patch
literal 3323
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
PYEMZ*{fFc&3CVu|0)=W_

literal 3255
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

-- 
GitLab