diff --git a/inventory_provider/routes/ims_classifier.py b/inventory_provider/routes/ims_classifier.py
index 02bc9f3b1a4119cbac9c6e3fe48c35537447a5d0..61e1487a4273092393f15e5da5276677c419741e 100644
--- a/inventory_provider/routes/ims_classifier.py
+++ b/inventory_provider/routes/ims_classifier.py
@@ -1,4 +1,5 @@
 import ipaddress
+import itertools
 import json
 import logging
 import re
@@ -12,9 +13,6 @@ routes = Blueprint("ims-inventory-data-classifier-support-routes", __name__)
 logger = logging.getLogger(__name__)
 
 
-
-
-
 def _LOCATION(equipment, name, abbreviation):
     return {
         'equipment': equipment,
@@ -54,24 +52,30 @@ def _locations_from_router(router_name):
     }]
 
 
-def _location_from_service_dict(s):
-    location = {
-        'a': _LOCATION(
-            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'] = _LOCATION(
-            equipment=s['other_end_equipment'],
-            name=s['other_end_pop_name'],
-            abbreviation=s['other_end_pop_abbreviation'])
-
-    return location
+# once the switchover is done then will refactor to get rid of
+# _locations_from_router
+def _location_from_equipment(equipment_name):
+    return _locations_from_router(equipment_name)
+
+
+# def _location_from_service_dict(s):
+#     location = {
+#         'a': _LOCATION(
+#             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'] = _LOCATION(
+#             equipment=s['other_end_equipment'],
+#             name=s['other_end_pop_name'],
+#             abbreviation=s['other_end_pop_abbreviation'])
+#
+#     return location
 
 
 class ClassifierRequestError(Exception):
@@ -115,23 +119,28 @@ def related_interfaces(hostname, interface):
 
 
 def get_top_level_services(circuit_id, r):
-    tls = []
-    results = r.get("ims:services:children:{}".format(circuit_id))
+    tls = {}
+    key = "ims:circuit_hierarchy:{}".format(circuit_id)
+    results = r.get(key)
     if results:
         results = json.loads(results.decode('utf-8'))
 
+        # should only ever be one, may refactor this
         for c in results:
-            temp_parents = \
-                get_top_level_services(c['parent_circuit_id'], r)
-            if not temp_parents:
-                tls.append(
-                    {'name': c['parent_circuit'],
-                     'status': c['parent_circuit_status'],
-                     'circuit_type': c['parent_circuit_type'].lower(),
-                     'project': c['parent_project']
-                     })
-            tls.extend(temp_parents)
-    return tls
+            if c['sub-circuits']:
+                for sub in c['sub-circuits']:
+                    temp_parents = \
+                        get_top_level_services(sub, r)
+                    tls.update({t['id']: t for t in temp_parents})
+            else:
+                tls[c['id']] = {
+                    'id': c['id'],
+                    'name': c['name'],
+                    'status': c['status'],
+                    'circuit_type': c['product'].lower(),
+                    'project': c['project']
+                }
+    return list(tls.values())
 
 
 def get_ims_equipment_name(equipment_name: str) -> str:
@@ -176,8 +185,10 @@ def get_juniper_link_info(source_equipment: str, interface: str):
             result['services'] = json.loads(services.decode('utf=8'))
             for s in result['services']:
                 top_level_services.extend(get_top_level_services(s['id'], r))
-            result['locations'] += [
-                _location_from_service_dict(s) for s in result['services']]
+
+                result['locations'] += _location_from_equipment(s['equipment'])
+                result['locations'] += \
+                    _location_from_equipment(s['other_end_equipment'])
 
         ifc_info = r.get(f'netconf-interfaces:{source_equipment}:{interface}')
         if ifc_info:
@@ -342,7 +353,7 @@ def peer_info(address):
 
     r = common.get_current_redis()
 
-    cache_key = f'classifier-cache:peer:{address}'
+    cache_key = f'ims-classifier-cache:peer:{address}'
 
     # result = r.get(cache_key)
     result = False
@@ -360,21 +371,24 @@ def peer_info(address):
             info = info.decode('utf-8')
             info = json.loads(info)
             result['ix-public-peer-info'] = ix_peering_info(info)
-            result['locations'] += _locations_from_router(info['router'])
+            result['locations'] += _location_from_equipment(info['router'])
 
         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'] += _locations_from_router(info['router'])
+            result['locations'] += _location_from_equipment(info['router'])
 
         interfaces = list(find_interfaces_and_services(address))
         if interfaces:
             result['interfaces'] = interfaces
             for i in interfaces:
-                result['locations'] += [
-                    _location_from_service_dict(s) for s in i['services']]
+                for s in i['services']:
+                    result['locations'] += \
+                        _location_from_equipment(s['equipment'])
+                    result['locations'] += \
+                        _location_from_equipment(s['other_end_equipment'])
 
         result['locations'] = _remove_duplicates_from_list(result['locations'])
         result = json.dumps(result)
@@ -382,3 +396,97 @@ def peer_info(address):
         r.set(cache_key, result.encode('utf-8'))
 
     return Response(result, mimetype="application/json")
+
+
+@routes.route("/infinera-fiberlink-info/<ne_name_str>/<object_name_str>",
+              methods=['GET', 'POST'])
+@common.require_accepts_json
+def get_fiberlink_trap_metadata(ne_name_str, object_name_str):
+    objects = object_name_str.split('_')
+    shelves = [x.split('-')[0] for x in objects]
+    p = r'([a-zA-Z\d]+?-(OLA|DTNX)\d+(-\d)?)'
+    matches = re.findall(p, ne_name_str)
+    if len(matches) != 2 or len(shelves) != 2:
+        raise ClassifierProcessingError(
+            f'unable to parse {ne_name_str} {object_name_str } '
+            'into two elements')
+
+    r = common.get_current_redis()
+
+    # double check that we only need to check the two nodes and not the objects
+    cache_key = f'ims-classifier-cache:fiberlink:{ne_name_str}:{object_name_str}'
+
+    # result = r.get(cache_key)
+    result = False
+
+    if result:
+        result = result.decode('utf-8')
+    else:
+        equipment_a = matches[0][0]
+        equipment_b = matches[1][0]
+        nes_a = f'{equipment_a}-{shelves[0]}'
+        nes_b = f'{equipment_b}-{shelves[1]}'
+        result = []
+        df_a = r.get(f'ims:ne_fibre_spans:{nes_a}')
+        df_b = r.get(f'ims:ne_fibre_spans:{nes_b}')
+
+        if df_a and df_b:
+            a = json.loads(df_a.decode('utf-8'))
+            b = json.loads(df_b.decode('utf-8'))
+
+            matches = [x for x in itertools.product(a, b) if
+                       x[0]['df_route_id'] == x[1]['df_route_id']]
+            if matches:
+                match = matches[0]
+                locations_a = _location_from_equipment(equipment_a)
+                locations_b = _location_from_equipment(equipment_b)
+                if locations_a:
+                    loc_a = locations_a[0]['a']
+                else:
+                    loc_a = _LOCATION(equipment_a, '', '')
+                if locations_b:
+                    loc_b = locations_b[0]['a']
+                else:
+                    loc_b = _LOCATION(equipment_b, '', '')
+
+                # added locations in preparation for refactoring to be in-line
+                # with other location data. Once Dashboard has been altered to
+                # use this for fiberlink alarms the 'ends' attribute can be
+                # removed
+                result = {
+                    'locations': [
+                        {
+                            'a': loc_a,
+                            'b': loc_b
+                        }
+                    ],
+                    'ends': {
+                        'a': {
+                            'pop': loc_a['name'],
+                            'pop_abbreviation': loc_a['abbreviation'],
+                            'equipment': loc_a['equipment']
+                        },
+                        'b': {
+                            'pop': loc_b['name'],
+                            'pop_abbreviation': loc_b['abbreviation'],
+                            'equipment': loc_b['equipment']
+                        },
+                    },
+                    'df_route': {
+                        'id': match[0]['df_route_id'],
+                        'name': match[0]['df_route'],
+                        'status': match[0]['df_status'],
+                    },
+                    'related-services':
+                        get_top_level_services(match[0]['df_route_id'], r)
+                }
+                result = json.dumps(result)
+                r.set(cache_key, result)
+        if not result:
+            return Response(
+                response="no available info for "
+                         f"{ne_name_str} {object_name_str}",
+                status=404,
+                mimetype="text/html")
+
+    return Response(result, mimetype="application/json")