From 101c70cfdaa5e5ce801f4413848a4f8381221b1c Mon Sep 17 00:00:00 2001
From: Robert Latta <robert.latta@geant.org>
Date: Fri, 26 Mar 2021 14:46:37 +0000
Subject: [PATCH] added IMS based MSR data/route/test

---
 inventory_provider/routes/msr.py   |  54 +++++++++++++----------------
 inventory_provider/tasks/worker.py |  38 +++++++++++++++-----
 test/data/router-info.json         | Bin 73406239 -> 73429819 bytes
 test/test_msr_routes.py            |  15 ++++----
 4 files changed, 61 insertions(+), 46 deletions(-)

diff --git a/inventory_provider/routes/msr.py b/inventory_provider/routes/msr.py
index 9e128ba4..cead3b83 100644
--- a/inventory_provider/routes/msr.py
+++ b/inventory_provider/routes/msr.py
@@ -94,38 +94,32 @@ def access_services():
     .. asjson::
        inventory_provider.routes.msr.ACCESS_SERVICES_LIST_SCHEMA
 
-    :param name:
     :return:
     """
-    # todo - replace with IMS implementation
-    return Response(
-        response='no access services found',
-        status=404,
-        mimetype="text/html")
-    # redis = common.get_current_redis()
-    #
-    # def _services():
-    #     for k in redis.scan_iter('opsdb:access_services:*'):
-    #         service = redis.get(k.decode('utf-8')).decode('utf-8')
-    #         yield json.loads(service)
-    #
-    # cache_key = 'classifier-cache:msr:access-services'
-    # result = redis.get(cache_key)
-    #
-    # if result:
-    #     result = json.loads(result.decode('utf-8'))
-    # else:
-    #     result = list(_services())
-    #     # cache this data for the next call
-    #     redis.set(cache_key, json.dumps(result).encode('utf-8'))
-    #
-    # if not result:
-    #     return Response(
-    #         response='no access services found',
-    #         status=404,
-    #         mimetype="text/html")
-    #
-    # return jsonify(result)
+    redis = common.get_current_redis()
+
+    def _services():
+        for k in redis.scan_iter('ims:access_services:*'):
+            service = redis.get(k.decode('utf-8')).decode('utf-8')
+            yield json.loads(service)
+
+    cache_key = 'classifier-cache:msr:access-services'
+    result = redis.get(cache_key)
+
+    if result:
+        result = json.loads(result.decode('utf-8'))
+    else:
+        result = list(_services())
+        # cache this data for the next call
+        redis.set(cache_key, json.dumps(result).encode('utf-8'))
+
+    if not result:
+        return Response(
+            response='no access services found',
+            status=404,
+            mimetype="text/html")
+
+    return jsonify(result)
 
 
 def _handle_peering_group_request(name, cache_key, group_key_base):
diff --git a/inventory_provider/tasks/worker.py b/inventory_provider/tasks/worker.py
index 02f93249..c87da938 100644
--- a/inventory_provider/tasks/worker.py
+++ b/inventory_provider/tasks/worker.py
@@ -408,7 +408,7 @@ def launch_refresh_cache_all(config):
 
         monitor.clear_joblog(get_current_redis(config))
 
-        # first batch of subtasks: refresh cached IMS data
+        # first batch of subtasks: refresh cached IMS location data
         subtasks = [
             update_neteng_managed_device_list.apply_async(),
             update_equipment_locations.apply_async(),
@@ -431,13 +431,10 @@ def launch_refresh_cache_all(config):
 @log_task_entry_and_exit
 def internal_refresh_phase_2(self):
     # second batch of subtasks:
-    #   alarms db status cache
-    #   juniper netconf & snmp data
+    #   ims circuit information
     try:
 
         subtasks = [
-            # update_circuit_hierarchy.apply_async(),
-            # update_interfaces_to_services.apply_async()
             update_circuit_hierarchy_and_port_id_services.apply_async()
         ]
 
@@ -475,12 +472,11 @@ def update_circuit_hierarchy_and_port_id_services(self, use_current=False):
 
     locations = {k: v for k, v in ims_data.get_node_locations(ds1)}
     tls_names = list(ims_data.get_service_types(ds1))
-    # logger.debug(json.dumps(locations['TS1.GEN.CH'], indent=2))
-    # return
     hierarchy = None
     port_id_details = defaultdict(list)
     port_id_services = defaultdict(list)
     interface_services = defaultdict(list)
+    access_services = {}
 
     def _convert_to_bits(value, unit):
         unit = unit.lower()
@@ -494,6 +490,8 @@ def update_circuit_hierarchy_and_port_id_services(self, use_current=False):
 
     def _get_speed(circuit_id):
         c = hierarchy[circuit_id]
+        if c['status'] != 'operational':
+            return 0
         pattern = re.compile(r'^(\d+)([a-zA-z]+)$')
         m = pattern.match(c['speed'])
         if m:
@@ -522,7 +520,6 @@ def update_circuit_hierarchy_and_port_id_services(self, use_current=False):
         for x in ims_data.get_port_details(ds2):
             pd = port_id_details[x['port_id']]
             pd.append(x)
-        # port_id_details = list(ims_data.get_port_details(ds2))
         logger.debug("Port details complete")
 
     def _populate_circuit_info():
@@ -634,6 +631,9 @@ def update_circuit_hierarchy_and_port_id_services(self, use_current=False):
                 circ['calculated-speed'] = _get_speed(circ['id'])
                 _format_service(circ)
 
+                if circ['service_type'].lower() == 'geant ip':
+                    access_services[circ['id']] = circ
+
             interface_services[k].extend(circuits)
 
     if use_current:
@@ -643,10 +643,16 @@ def update_circuit_hierarchy_and_port_id_services(self, use_current=False):
     rp = r.pipeline()
     for k in r.scan_iter('ims:circuit_hierarchy:*', count=1000):
         rp.delete(k)
+    rp.execute()
+    rp = r.pipeline()
     for k in r.scan_iter('ims:interface_services:*', count=1000):
         rp.delete(k)
     rp.execute()
     rp = r.pipeline()
+    for k in r.scan_iter('ims:access_services:*', count=1000):
+        rp.delete(k)
+    rp.execute()
+    rp = r.pipeline()
     for circ in hierarchy.values():
         rp.set(f'ims:circuit_hierarchy:{circ["id"]}', json.dumps([circ]))
     rp.execute()
@@ -656,6 +662,22 @@ def update_circuit_hierarchy_and_port_id_services(self, use_current=False):
             f'ims:interface_services:{k}',
             json.dumps(v))
     rp.execute()
+    rp = r.pipeline()
+
+    for v in access_services.values():
+        rp.set(
+            f'ims:access_services:{v["name"]}',
+            json.dumps({
+                'id': v['id'],
+                'name': v['name'],
+                'pop_name': v['pop_name'],
+                'other_end_pop_name': v['other_end_pop_name'],
+                'equipment': v['equipment'],
+                'other_end_equipment': v['other_end_equipment'],
+                'speed_value': v['calculated-speed'],
+                'speed_unit': 'n/a'
+            }))
+    rp.execute()
 
 
 @app.task(base=InventoryTask, bind=True, name='update_equipment_locations')
diff --git a/test/data/router-info.json b/test/data/router-info.json
index e3bed7251440eab498899defb87d58b686c1073a..d8bbbe465c13622414e10a0614b0e74c2c70ba70 100644
GIT binary patch
delta 15995
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

delta 3115
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
StSGE3tSVbpmllm&b<O|7-g*lF

diff --git a/test/test_msr_routes.py b/test/test_msr_routes.py
index d328b847..40332106 100644
--- a/test/test_msr_routes.py
+++ b/test/test_msr_routes.py
@@ -4,7 +4,7 @@ import jsonschema
 import pytest
 
 from inventory_provider.routes.msr import PEERING_LIST_SCHEMA, \
-    PEERING_GROUP_LIST_SCHEMA
+    PEERING_GROUP_LIST_SCHEMA, ACCESS_SERVICES_LIST_SCHEMA
 
 DEFAULT_REQUEST_HEADERS = {
     "Content-type": "application/json",
@@ -19,13 +19,12 @@ def test_access_services(client):
     rv = client.get(
         '/msr/access-services',
         headers=DEFAULT_REQUEST_HEADERS)
-    assert rv.status_code == 404
-    # assert rv.status_code == 200
-    # assert rv.is_json
-    # response_data = json.loads(rv.data.decode('utf-8'))
-    # jsonschema.validate(response_data, ACCESS_SERVICES_LIST_SCHEMA)
-    #
-    # assert response_data  # test data is non-empty
+    assert rv.status_code == 200
+    assert rv.is_json
+    response_data = json.loads(rv.data.decode('utf-8'))
+    jsonschema.validate(response_data, ACCESS_SERVICES_LIST_SCHEMA)
+
+    assert response_data  # test data is non-empty
 
 
 def test_logical_system_peerings_all(client):
-- 
GitLab