From 67bffc9e306d34f06d28c85bdcb3d2f2545da501 Mon Sep 17 00:00:00 2001
From: Erik Reid <erik.reid@geant.org>
Date: Wed, 15 Jan 2020 20:22:19 +0100
Subject: [PATCH] add location info to peer-info response

---
 inventory_provider/routes/classifier.py | 75 +++++++++++++++++++++++--
 1 file changed, 70 insertions(+), 5 deletions(-)

diff --git a/inventory_provider/routes/classifier.py b/inventory_provider/routes/classifier.py
index 16cab700..a9fd126e 100644
--- a/inventory_provider/routes/classifier.py
+++ b/inventory_provider/routes/classifier.py
@@ -13,6 +13,11 @@ routes = Blueprint("inventory-data-classifier-support-routes", __name__)
 logger = logging.getLogger(__name__)
 
 
+def _unique_dicts_from_list(l):
+    tmp_dict = dict([(json.dumps(item, sort_keys=True), item) for item in l])
+    return list(tmp_dict.values())
+
+
 class ClassifierRequestError(Exception):
     status_code = 500
 
@@ -202,6 +207,52 @@ 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):
     """
 
@@ -243,32 +294,46 @@ def peer_info(address):
         address = obj.exploded
     except ValueError:
         raise ClassifierProcessingError(
-            'unable to parse %r as an ip address' % address)
+            f'unable to parse {address} as an ip address')
 
     r = common.get_current_redis()
 
-    cache_key = 'classifier-cache:peer:%s' % address
+    cache_key = f'classifier-cache:peer:{address}'
 
     result = r.get(cache_key)
+    result = None
     if result:
         result = result.decode('utf-8')
     else:
 
-        result = {}
+        result = {
+            'locations': []
+        }
 
         info = r.get('ix_public_peer:%s' % address)
         if info:
             info = info.decode('utf-8')
-            result['ix-public-peer-info'] = ix_peering_info(json.loads(info))
+            info = json.loads(info)
+            result['ix-public-peer-info'] = ix_peering_info(info)
+            result['locations'] += [
+                _location_from_router(info['router'])
+            ]
 
         info = r.get('vpn_rr_peer:%s' % address)
         if info:
             info = info.decode('utf-8')
-            result['vpn-rr-peer-info'] = json.loads(info)
+            info = json.loads(info)
+            result['vpn-rr-peer-info'] = info
+            result['locations'] += [
+                _location_from_router(info['router'])
+            ]
 
         interfaces = list(find_interfaces_and_services(address))
         if interfaces:
             result['interfaces'] = interfaces
+            for i in interfaces:
+                l = [_location_from_service_dict(s) for s in i['services']]
+                result['locations'] += l
 
         result = json.dumps(result)
         # cache this data for the next call
-- 
GitLab