diff --git a/inventory_provider/routes/ims_classifier.py b/inventory_provider/routes/ims_classifier.py index 2e5edb3e206afb0917dbbd63acbf13a6472d8f59..c8677a057a46639fe85fd73ce9402584eb00f29c 100644 --- a/inventory_provider/routes/ims_classifier.py +++ b/inventory_provider/routes/ims_classifier.py @@ -236,6 +236,54 @@ def get_full_service_info(s: dict, r: Redis) -> dict: return service +def get_interface_services_and_locs(ims_source_equipment, ims_interface, r): + result = { + 'locations': [], + 'services': [], + 'related-services': [] + } + services_dict = {} + rs_dict = {} + port_info = r.get( + f'ims:interface_port_ids:{ims_source_equipment}:{ims_interface}') + if port_info: + port_info = json.loads(port_info.decode('utf-8')) + port_id_services = r.get( + f'ims:port_id_services:{port_info["port_id"]}') + + if port_id_services: + port_id_services = json.loads(port_id_services.decode('utf-8')) + for ps in port_id_services: + services_dict[ps['id']] = get_full_service_info(ps, r) + port_a_id = ps.get('port_a_id', None) + port_b_id = ps.get('port_b_id', None) + rs_dict.update( + {x['id']: x for x in get_top_level_services_by_port_id( + port_a_id, r + )}) + rs_dict.update( + {x['id']: x for x in get_top_level_services_by_port_id( + port_b_id, r + )}) + loc = build_locations( + _location_from_port_id(port_a_id, r), + _location_from_port_id(port_b_id, r) + ) + if loc: + result['locations'].append(loc) + result['services'] = list(services_dict.values()) + result['related-services'] = list(rs_dict.values()) + + if not result.get('locations'): + result['locations'] = [ + build_locations( + _location_from_equipment(ims_source_equipment, r)) + ] + + result['locations'] = _remove_duplicates_from_list(result['locations']) + return result + + @routes.route("/juniper-link-info/<source_equipment>/<path:interface>", methods=['GET', 'POST']) @common.require_accepts_json @@ -280,46 +328,12 @@ def get_juniper_link_info(source_equipment: str, interface: str) -> Response: else: result['interface']['bundle_members'] = [] - result['locations'] = [] - services_dict = {} - rs_dict = {} - port_info = r.get( - f'ims:interface_port_ids:{ims_source_equipment}:{ims_interface}') - if port_info: - port_info = json.loads(port_info.decode('utf-8')) - port_id_services = r.get( - f'ims:port_id_services:{port_info["port_id"]}') - - if port_id_services: - port_id_services = json.loads(port_id_services.decode('utf-8')) - for ps in port_id_services: - services_dict[ps['id']] = get_full_service_info(ps, r) - port_a_id = ps.get('port_a_id', None) - port_b_id = ps.get('port_b_id', None) - rs_dict.update( - {x['id']: x for x in get_top_level_services_by_port_id( - port_a_id, r - )}) - rs_dict.update( - {x['id']: x for x in get_top_level_services_by_port_id( - port_b_id, r - )}) - loc = build_locations( - _location_from_port_id(port_a_id, r), - _location_from_port_id(port_b_id, r) - ) - if loc: - result['locations'].append(loc) - result['services'] = list(services_dict.values()) - result['related-services'] = list(rs_dict.values()) - - if not result.get('locations'): - result['locations'] = [ - build_locations( - _location_from_equipment(ims_source_equipment, r)) - ] + result.update(get_interface_services_and_locs( + ims_source_equipment, + ims_interface, + r + )) - result['locations'] = _remove_duplicates_from_list(result['locations']) result = json.dumps(result) # cache this data for the next call r.set(cache_key, result.encode('utf-8')) @@ -390,53 +404,21 @@ def find_interfaces(address) -> Iterator: yield ifc -def find_interfaces_and_services(address_str: str) -> Iterator[dict]: - """ - - :param address_str: an ipaddress object - :return: - """ - - try: - address = ipaddress.ip_address(address_str) - except ValueError: - raise ClassifierProcessingError( - f'unable to parse {address_str} as an ip address') - - r = common.get_current_redis() - for interface in find_interfaces(address): - - ims_equipment = get_ims_equipment_name(interface["router"]) - ims_interface = get_ims_interface(interface["interface name"]) - - services = r.get( - f'ims:interface_services:{ims_equipment}:{ims_interface}') - if not services: - services = [] - else: - services = json.loads(services.decode('utf=8')) - - yield { - 'interface': interface, - 'services': services - } - - -@routes.route("/peer-info/<address>", methods=['GET', 'POST']) +@routes.route("/peer-info/<address_str>", methods=['GET', 'POST']) @common.require_accepts_json -def peer_info(address: str) -> Response: +def peer_info(address_str: str) -> Response: # canonicalize the input address first ... try: - obj = ipaddress.ip_address(address) - address = obj.exploded + obj = ipaddress.ip_address(address_str) + address_str = obj.exploded except ValueError: raise ClassifierProcessingError( - f'unable to parse {address} as an ip address') + f'unable to parse {address_str} as an ip address') r = common.get_current_redis() - cache_key = f'ims-classifier-cache:peer:{address}' + cache_key = f'ims-classifier-cache:peer:{address_str}' # result = r.get(cache_key) result = False @@ -446,10 +428,11 @@ def peer_info(address: str) -> Response: else: result = { - 'locations': [] + 'interfaces': [], + 'locations': [], } - info = r.get(f'ix_public_peer:{address}') + info = r.get(f'ix_public_peer:{address_str}') if info: info = info.decode('utf-8') info = json.loads(info) @@ -458,7 +441,7 @@ def peer_info(address: str) -> Response: _location_from_equipment( get_ims_equipment_name(info['router']), r))) - info = r.get(f'vpn_rr_peer:{address}') + info = r.get(f'vpn_rr_peer:{address_str}') if info: info = info.decode('utf-8') info = json.loads(info) @@ -467,25 +450,29 @@ def peer_info(address: str) -> Response: _location_from_equipment( get_ims_equipment_name(info['router']), r))) - interfaces = list(find_interfaces_and_services(address)) - rs_dict = {} - if interfaces: - result['interfaces'] = interfaces - for i in interfaces: - for s in i['services']: - - # use a dict to get rid of duplicates - for rs in get_related_services( - s['equipment'], s['interface_name'], r): - rs_dict[rs['id']] = rs - - result['locations'].append( - build_locations( - _location_from_equipment(s['equipment'], r), - _location_from_equipment( - s['other_end_equipment'], r)) - ) - result['related-services'] = list(rs_dict.values()) + try: + address = ipaddress.ip_address(address_str) + except ValueError: + raise ClassifierProcessingError( + f'unable to parse {address_str} as an ip address') + + for interface in find_interfaces(address): + ims_equipment = get_ims_equipment_name(interface["router"]) + ims_interface = get_ims_interface(interface["interface name"]) + + services_and_locs = get_interface_services_and_locs( + ims_equipment, + ims_interface, + r + ) + + result['interfaces'].append( + { + 'interface': interface, + 'services': services_and_locs['services'] + } + ) + result['locations'].extend(services_and_locs['locations']) result['locations'] = _remove_duplicates_from_list(result['locations']) result = json.dumps(result)