diff --git a/inventory_provider/routes/classifier.py b/inventory_provider/routes/classifier.py index 16cab7001476c1fef49b742c59c10d32133681c4..a9fd126ea71fe12fe77125a0af74b875afa3596d 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