From 558e802fd77aba659df4d1b5909fd8ddb5571e0a Mon Sep 17 00:00:00 2001
From: Erik Reid <erik.reid@geant.org>
Date: Mon, 18 Jan 2021 08:56:04 +0100
Subject: [PATCH] also walk logical systems [VRR only] communities

---
 inventory_provider/snmp.py | 79 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 75 insertions(+), 4 deletions(-)

diff --git a/inventory_provider/snmp.py b/inventory_provider/snmp.py
index 05d10c2a..6bd56f45 100644
--- a/inventory_provider/snmp.py
+++ b/inventory_provider/snmp.py
@@ -13,6 +13,7 @@ from pysnmp.error import PySnmpError
 RFC1213_MIB_IFDESC = '1.3.6.1.2.1.2.2.1.2'
 # BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerState
 JNX_BGP_M2_PEER_STATE = '1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2'
+JNX_LOGICAL_SYSTEMS = ['VRR']
 logger = logging.getLogger(__name__)
 
 
@@ -132,16 +133,71 @@ def walk(agent_hostname, community, base_oid):  # pragma: no cover
             f'snmp error communicating with {agent_hostname}: {e}')
 
 
-def get_router_snmp_indexes(hostname, community):
+def _get_router_snmp_indexes(hostname, community):
     for ifc in walk(hostname, community, RFC1213_MIB_IFDESC):
         m = re.match(r'.*\.(\d+)$', ifc['oid'])
         assert m, f'sanity failure parsing oid: {ifc["oid"]}'
         yield {
             'name': ifc['value'],
-            'index': int(m.group(1))
+            'index': int(m.group(1)),
+            'community': community
         }
 
 
+def _walk_util(hostname, default_community, walk_handler):
+    """
+    Run walk_handler for default_community and
+
+    :param hostname:
+    :param community: base community name
+    :param walk_handler: a method that takes params (hostname, community)
+        and yields things
+    :return: generator yielding whatever walk_handler yields
+    """
+    # do the default community last, in case of duplicates
+    communities = [
+        f'{ls}/default@{default_community}'
+        for ls in JNX_LOGICAL_SYSTEMS]
+    communities.append(default_community)
+
+    for c in communities:
+        yield from walk_handler(hostname, c)
+
+
+def get_router_snmp_indexes(hostname, community):
+    """
+    return interface names and snmp indexes
+
+    items are structured like:
+        {name: str, index: str, community: str}
+
+    :param hostname:
+    :param community: base community name
+    :return: generator yielding dicts
+    """
+    _walk_util(hostname, community, _get_router_snmp_indexes)
+
+
+def get_peer_state_info(hostname, community):
+    """
+    return peering states from all logical systems
+
+    items are structured like:
+        {local: str, remote: str, oid: str, community: str}
+
+    :param hostname:
+    :param community: base community name
+    :return: generator yielding dicts
+    """
+    # do the default community last, in case of duplicates
+    communities = [f'{ls}/default@{community}' for ls in JNX_LOGICAL_SYSTEMS]
+    communities.append(community)
+    for c in communities:
+        for peering in _get_peer_state_info(hostname, c):
+            peering['community'] = c
+            yield peering
+
+
 def _v6bytes(int_str_list):
     assert len(int_str_list) == 16
     return struct.pack('!16B', *map(int, int_str_list))
@@ -152,7 +208,8 @@ def _v4str(int_str_list):
     return '.'.join(int_str_list)
 
 
-def get_peer_state_info(hostname, community):
+def _get_peer_state_info(hostname, community):
+
     oid_prefix = f'.{JNX_BGP_M2_PEER_STATE}.'
     for ifc in walk(hostname, community, JNX_BGP_M2_PEER_STATE):
 
@@ -178,10 +235,24 @@ def get_peer_state_info(hostname, community):
         yield {
             'local': local.exploded,
             'remote': remote.exploded,
-            'oid': ifc['oid']
+            'oid': ifc['oid'],
+            'community': community
         }
 
 
+def get_peer_state_info(hostname, community):
+    """
+    return peering states from all logical systems
+
+    items are structured like:
+        {local: str, remote: str, oid: str, community: str}
+
+    :param hostname:
+    :param community: base community name
+    :return: generator yielding dicts
+    """
+    _walk_util(hostname, community, _get_peer_state_info)
+
 # if __name__ == '__main__':
 #
 #
-- 
GitLab