From 6778f8b22a4c69009abd64abb50142e7a8d6c26e Mon Sep 17 00:00:00 2001
From: Erik Reid <erik.reid@geant.org>
Date: Wed, 15 Jan 2020 20:49:24 +0100
Subject: [PATCH] added location data to juniper-link-info response

---
 inventory_provider/routes/classifier.py | 110 +++++++++++++-----------
 1 file changed, 58 insertions(+), 52 deletions(-)

diff --git a/inventory_provider/routes/classifier.py b/inventory_provider/routes/classifier.py
index 1eff7e84..be1349a4 100644
--- a/inventory_provider/routes/classifier.py
+++ b/inventory_provider/routes/classifier.py
@@ -18,6 +18,49 @@ def _unique_dicts_from_list(l):
     return list(tmp_dict.values())
 
 
+def _location_from_router(router_name):
+    r = common.get_current_redis()
+    result = r.get(f'opsdb:location:{router_name}')
+    if not result:
+        logger.error(f'error looking up location for {router_name}')
+        return None
+
+    result = json.loads(result.decode('utf-8'))
+    if not result:
+        logger.error(f'sanity failure: empty list for location {router_name}')
+        return None
+
+    return {
+        'a': {
+            'equipment': result[0]['equipment-name'],
+            'name': result[0]['pop']['name'],
+            'abbreviation': result[0]['pop']['abbreviation']
+        }
+    }
+
+
+def _location_from_service_dict(s):
+    location = {
+        'a': {
+            'equipment': s['equipment'],
+            'name': s['pop_name'],
+            'abbreviation': s['pop_abbreviation']
+        }
+    }
+
+    if all(s[n] for n in (
+            'other_end_equipment',
+            'other_end_pop_name',
+            'other_end_pop_abbreviation')):
+        location['b'] = {
+            'equipment': s['other_end_equipment'],
+            'name': s['other_end_pop_name'],
+            'abbreviation': s['other_end_pop_abbreviation']
+        }
+
+    return location
+
+
 class ClassifierRequestError(Exception):
     status_code = 500
 
@@ -91,7 +134,14 @@ def get_juniper_link_info(source_equipment, interface):
     if result:
         result = result.decode('utf-8')
     else:
-        result = {}
+
+        result = {
+            'locations': []
+        }
+
+        router_location = _location_from_router(source_equipment)
+        result['locations'] += [router_location]
+
         top_level_services = []
 
         services = r.get(
@@ -100,6 +150,8 @@ def get_juniper_link_info(source_equipment, interface):
             result['services'] = json.loads(services.decode('utf=8'))
             for s in result['services']:
                 top_level_services.extend(get_top_level_services(s['id'], r))
+            l = [_location_from_service_dict(s) for s in result['services']]
+            result['locations'] += l
 
         ifc_info = r.get(
             'netconf-interfaces:%s:%s' % (source_equipment, interface))
@@ -137,6 +189,7 @@ def get_juniper_link_info(source_equipment, interface):
         if top_level_services:
             result['related-services'] = top_level_services
 
+        result['locations'] = _unique_dicts_from_list(result['locations'])
         result = json.dumps(result)
         # cache this data for the next call
         r.set(cache_key, result.encode('utf-8'))
@@ -207,51 +260,6 @@ def find_interfaces(address):
                 yield ifc
 
 
-def _location_from_router(router_name):
-    r = common.get_current_redis()
-    result = r.get(f'opsdb:location:{router_name}')
-    empty_response ={
-        'a': {'equipment': '', 'name': '', 'abbreviation': ''}
-    }
-    if not result:
-        logger.error(f'error looking up location for {router_name}')
-        return empty_response
-
-    result = json.loads(result.decode('utf-8'))
-    if not result:
-        logger.error(f'sanity failure: empty list for location {router_name}')
-        return empty_response
-
-    return {
-        'a': {
-            'equipment': result[0]['equipment-name'],
-            'name': result[0]['pop']['name'],
-            'abbreviation': result[0]['pop']['abbreviation']
-        }
-    }
-
-
-def _location_from_service_dict(s):
-    location = {
-        'a': {
-            'equipment': s['equipment'],
-            'name': s['pop_name'],
-            'abbreviation': s['pop_abbreviation']
-        }
-    }
-
-    if all(s[n] for n in (
-            'other_end_equipment',
-            'other_end_pop_name',
-            'other_end_pop_abbreviation')):
-        location['b'] = {
-            'equipment': s['other_end_equipment'],
-            'name': s['other_end_pop_name'],
-            'abbreviation': s['other_end_pop_abbreviation']
-        }
-
-    return location
-
 
 def find_interfaces_and_services(address_str):
     """
@@ -314,18 +322,16 @@ def peer_info(address):
             info = info.decode('utf-8')
             info = json.loads(info)
             result['ix-public-peer-info'] = ix_peering_info(info)
-            result['locations'] += [
-                _location_from_router(info['router'])
-            ]
+            router_location = _location_from_router(info['router'])
+            result['locations'] += [router_location]
 
         info = r.get('vpn_rr_peer:%s' % address)
         if info:
             info = info.decode('utf-8')
             info = json.loads(info)
             result['vpn-rr-peer-info'] = info
-            result['locations'] += [
-                _location_from_router(info['router'])
-            ]
+            router_location = _location_from_router(info['router'])
+            result['locations'] += [router_location]
 
         interfaces = list(find_interfaces_and_services(address))
         if interfaces:
-- 
GitLab