From 226a3077463be7de9dbcb358f0d0fde4aac2b05f Mon Sep 17 00:00:00 2001 From: Erik Reid <erik.reid@geant.org> Date: Wed, 10 Aug 2022 13:08:38 +0200 Subject: [PATCH] initial raft /msr/services updated with redundant asn --- inventory_provider/routes/msr.py | 56 ++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/inventory_provider/routes/msr.py b/inventory_provider/routes/msr.py index 8c052a67..cdd3cc64 100644 --- a/inventory_provider/routes/msr.py +++ b/inventory_provider/routes/msr.py @@ -260,7 +260,8 @@ SYSTEM_CORRELATION_SERVICES_LIST_SCHEMA = { 'service_type': {'type': 'string'}, # TODO: enum? 'project': {'type': 'string'}, # TODO: remove this? 'customer': {'type': 'string'}, - 'endpoints': {'$ref': '#/definitions/endpoints'} + 'endpoints': {'$ref': '#/definitions/endpoints'}, + 'redundant_asn': {'type': 'integer'} }, 'required': [ 'circuit_id', 'sid', 'name', 'speed', 'status', 'monitored', @@ -905,39 +906,51 @@ def get_system_correlation_services(): r = common.get_current_redis() response = _ignore_cache_or_retrieve(request, cache_key, r) if not response: - peering_info = defaultdict(defaultdict) - key_pattern = 'netconf-interfaces:*' + # dict of dicts: + # peering_info[hostname][interface_name] = dict of ifc details + peering_info = defaultdict(dict) - host_if_extraction_re = re.compile( - r'^netconf-interfaces:(.+?):') + host_if_extraction_re = re.compile(r'^netconf-interfaces:(.+?):') for doc in common.load_json_docs( config_params=current_app.config['INVENTORY_PROVIDER_CONFIG'], - key_pattern=key_pattern, + key_pattern='netconf-interfaces:*', num_threads=20): matches = host_if_extraction_re.match(doc['key']) if matches: peering_info[matches[1]][doc['value']['name']] = doc['value'] + def _load_redundant_peers(): + # REPORTING-312: limited to eGEANT group, + # but this can be expanded here in future + redundant_access_groups = ['eGEANT'] + for g in redundant_access_groups: + doc = r.get(f'juniper-peerings:group:{g}') + for peer in json.loads(doc.decode('utf-8')): + yield peer['address'], peer['remote-asn'] + + # dict of peers & asn's: [peer address] -> asn + redundant_access_group_peers = dict(_load_redundant_peers()) + def _ip_endpoint_extractor(endpoint_details: Dict): - hostname = ims_equipment_to_hostname( - endpoint_details['equipment']) + hostname = ims_equipment_to_hostname(endpoint_details['equipment']) interface = endpoint_details['port'].lower() ip_endpoint = { 'hostname': hostname, 'interface': interface, } - addresses = {} - host_info = peering_info.get(hostname, {}) + host_info = peering_info[hostname] interface_info = host_info.get(interface, {}) + + addresses = {} ipv4 = interface_info.get('ipv4') ipv6 = interface_info.get('ipv6') if ipv4: addresses['v4'] = ipv4[0] if ipv6: addresses['v6'] = ipv6[0] - if ipv4 or ipv6: + if addresses: ip_endpoint['addresses'] = addresses return ip_endpoint @@ -952,12 +965,23 @@ def get_system_correlation_services(): if not endpoint_details['geant_equipment']: return potential_hostname = ims_equipment_to_hostname( - endpoint_details['equipment']) + endpoint_details['equipment']) if potential_hostname in peering_info.keys(): return _ip_endpoint_extractor(endpoint_details) else: return _optical_endpoint_extractor(endpoint_details) + def _get_redundancy_asn(service): + for ep in service['endpoints']: + addresses = ep.get('addresses', {}) + for ifc_address in addresses.values(): + for p, asn in redundant_access_group_peers.items(): + peer = ipaddress.ip_address(p) + ifc = ipaddress.ip_interface(ifc_address) + if peer in ifc.network: + return asn + return None + sid_services = json.loads(r.get('ims:sid_services').decode('utf-8')) response = [] @@ -977,11 +1001,15 @@ def get_system_correlation_services(): endpoint = _endpoint_extractor(d) if endpoint: service_info['endpoints'].append(endpoint) + if service_info.get('endpoints'): + asn = _get_redundancy_asn(service_info) + if asn: + service_info['redundant_asn'] = asn response.append(service_info) - jsonschema.validate(response, - SYSTEM_CORRELATION_SERVICES_LIST_SCHEMA) + jsonschema.validate( + response, SYSTEM_CORRELATION_SERVICES_LIST_SCHEMA) if response: response = json.dumps(response, indent=2) -- GitLab