diff --git a/inventory_provider/routes/msr.py b/inventory_provider/routes/msr.py index 1ae5c5d8b4dffd6e3df5ac47588302480631d304..7032c671c361f1c1648b596f7ded042c35c8a407 100644 --- a/inventory_provider/routes/msr.py +++ b/inventory_provider/routes/msr.py @@ -140,7 +140,7 @@ PEERING_LIST_SCHEMA = { 'description': {'type': 'string'}, 'logical-system': {'type': 'string'}, 'group': {'type': 'string'}, - 'hostname': {'type': 'string'}, + 'hostname': {'type': 'string', 'format': 'hostname'}, 'remote-asn': {'type': 'integer'}, 'local-asn': {'type': 'integer'}, 'instance': {'type': 'string'} @@ -371,6 +371,17 @@ DOMAIN_TO_POP_MAPPING = { IP_SERVICES_LIST_SCHEMA = { '$schema': 'http://json-schema.org/draft-07/schema#', 'definitions': { + 'minimal-peering-schema': { + # cf. PEERING_LIST_SCHEMA + 'type': 'object', + 'properties': { + 'address': {'type': 'string'}, + 'group': {'type': 'string'}, + 'hostname': {'type': 'string', 'format': 'hostname'} + }, + 'required': ['address', 'group', 'hostname'], + 'additionalProperties': True + }, 'service': { 'type': 'object', 'properties': { @@ -398,9 +409,13 @@ IP_SERVICES_LIST_SCHEMA = { 'services': { 'type': 'array', 'items': {'$ref': '#/definitions/service'} + }, + 'peerings': { + 'type': 'array', + 'items': {'$ref': '#/definitions/minimal-peering-schema'} } }, - 'required': ['hostname', 'port', 'address', 'services'], + 'required': ['hostname', 'port', 'address', 'services', 'peerings'], 'additionalProperties': False } }, @@ -1498,25 +1513,37 @@ def _load_ip_services(): } } - def _merged_result(): - for key, ifc in netconf_interfaces.items(): - _services = map( - _service_info, - ims_interface_services.get(key, [])) - _services = list(_dedupe(_services)) - - for address in ifc['ipv4'] + ifc['ipv6']: - try: - yield { - 'hostname': ifc['hostname'], - 'port': ifc['name'], - 'address': address, - 'services': _services - } - except TypeError: - raise - - yield from _merged_result() + # pre-compute remote ipaddress objects, and group to avoid duplicates + r = common.get_current_redis() + all_peerings = {} + for _remote in json.loads(r.get('juniper-peerings:all').decode('utf-8')): + remote_info = all_peerings.setdefault(_remote['address'], { + 'address': ipaddress.ip_address(_remote['address']), + 'info': [] + }) + remote_info['info'].append(_remote) + + def _remotes_in_network(ifc_address): + network = ipaddress.ip_interface(ifc_address).network + for _r in all_peerings.values(): + if _r['address'] in network: + yield from _r['info'] + + for key, ifc in netconf_interfaces.items(): + _services = map( + _service_info, + ims_interface_services.get(key, [])) + _services = list(_dedupe(_services)) + + for address in ifc['ipv4'] + ifc['ipv6']: + + yield { + 'hostname': ifc['hostname'], + 'port': ifc['name'], + 'address': address, + 'services': _services, + 'peerings': list(_remotes_in_network(address)) + } @routes.route('/ip-services', methods=['GET', 'POST'])