From 68a52f40d6acad9aa478c6d5041feb1ce2d564fd Mon Sep 17 00:00:00 2001 From: Erik Reid <erik.reid@geant.org> Date: Thu, 12 Dec 2019 20:40:40 +0100 Subject: [PATCH] add customers to interface list --- inventory_provider/tasks/worker.py | 83 ++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/inventory_provider/tasks/worker.py b/inventory_provider/tasks/worker.py index 9e7c90fc..a744560b 100644 --- a/inventory_provider/tasks/worker.py +++ b/inventory_provider/tasks/worker.py @@ -574,12 +574,14 @@ def refresh_finalizer(self, pending_task_ids_json): logger.debug('<<< refresh_finalizer') -def _build_service_category_interface_list(update_callback=lambda s: None): - logger.debug('>>> _build_interface_services') - - r = get_next_redis(InventoryTask.config) +def _build_service_interface_user_list(): def _interfaces(): + """ + yields interface info from netconf + :return: + """ + r = get_next_redis(InventoryTask.config) for k in r.scan_iter('netconf-interfaces:*'): k = k.decode('utf-8') (_, router_name, ifc_name) = k.split(':') @@ -594,6 +596,77 @@ def _build_service_category_interface_list(update_callback=lambda s: None): 'description': info['description'] } + def _lookup_interface_services(wanted_interfaces): + """ + yields interface info from opsdb (with service id) + ... only interfaces in wanted_interfaces + :param wanted_interfaces: + :return: + """ + r = get_next_redis(InventoryTask.config) + for k in r.scan_iter('opsdb:interface_services:*'): + k = k.decode('utf-8') + (_, _, router, ifc_name) = k.split(':') + + router_interface_key = f'{router}:{ifc_name}' + if router_interface_key not in wanted_interfaces: + continue + + info = r.get(k).decode('utf-8') + info = json.loads(info) + + for service in info: + yield { + 'router': router, + 'interface': ifc_name, + 'service_id': service['id'] + } + + # dict: 'router:interface' -> {'router', 'interface', 'description'} + netconf_interface_map = dict([ + (f'{i["router"]}:{i["interface"]}', i) for i in _interfaces()]) + + # dict: 'router:interface' -> [list of service_ids] + opsdb_interface_map = {} + for i in _lookup_interface_services(netconf_interface_map.keys()): + key = f'{i["router"]}:{i["interface"]}' + opsdb_interface_map.setdefault(key, []).append(i['service_id']) + + # dict service_id[int] -> [list of users] + service_user_map = {} + with db.connection(InventoryTask.config["ops-db"]) as cx: + service_ids = set() + for l in opsdb_interface_map.values(): + for id in l: + service_ids.add(id) + for user in opsdb.get_service_users(cx, list(service_ids)): + service_user_map.setdefault( + user['service_id'], []).append(user['user']) + + def _users(ifc_key): + """ + ifc = 'router:ifc_name' + :param ifc: + :return: list of users + """ + for service_id in opsdb_interface_map.get(ifc_key, []): + for user in service_user_map.get(service_id, []): + yield user + + for k, v in netconf_interface_map.items(): + users = _users(k) + if not users: + yield v + else: + for u in users: + info = {'user': u} + info.update(v) + yield info + + +def _build_service_category_interface_list(update_callback=lambda s: None): + logger.debug('>>> _build_interface_services') + def _classify(ifc): if ifc['description'].startswith('SRV_MDVPN'): return 'mdvpn' @@ -605,7 +678,7 @@ def _build_service_category_interface_list(update_callback=lambda s: None): rp = r.pipeline() update_callback('loading all known interfaces') - interfaces = list(_interfaces()) + interfaces = list(_build_service_interface_user_list()) update_callback(f'loaded {len(interfaces)} interfaces, ' 'saving by service category') -- GitLab