diff --git a/inventory_provider/routes/msr.py b/inventory_provider/routes/msr.py index ae0c98ab79e48a272256e67056f539ca40db9066..6f327d4ff9ce949355bf9c63a12c443ec2c68b37 100644 --- a/inventory_provider/routes/msr.py +++ b/inventory_provider/routes/msr.py @@ -880,15 +880,37 @@ def bgp_all_peerings(): @routes.route('/mdvpn', methods=['GET', 'POST']) @common.require_accepts_json def mdvpn(): - def _make_bgplu_index(bgplu): + def _get_consistent_description(description): + """ + The same interface in VRR peerings can have multiple names. + These names are (currently) the same but with a different local prefix, + with no ordering guaranteed by the redis cache. + As only one description is returned by this endpoint for each + IPv4 address, this serves as a quick and dirty way of merging these + multiple descriptions into one an external user can use to identify + the peering reliably. + :param description: The raw description for a VRR peering + :return: The same description with location prefix removed + """ + # it is incredibly likely this will need revision later down the line + expected_prefixes = [ + "MD-VPN-VRR-PARIS-", + "MD-VPN-VRR-LJUBLJANA-" + ] + for prefix in expected_prefixes: + if description.startswith(prefix): + return description.replace(prefix, '') + return description + + def _make_group_index(group, index_key): index = {} - for peering in bgplu: - asn = peering['remote-asn'] - if asn in index: - peering_list = index[asn] + for peering in group: + key = peering.get(index_key) + if key in index: + peering_list = index[key] peering_list.append(peering) else: - index[asn] = [peering] + index[key] = [peering] return index def _bgplu_peerings(asn, bgplu_index): @@ -904,19 +926,44 @@ def mdvpn(): peerings.append(formatted_peering) return peerings - def _peerings_for_nren(asn, bgplu_index): + def _vpnrr_peerings(asn, vpnrr_index): + peerings = [] + if asn in vpnrr_index: + vrr_peering_group = vpnrr_index[asn] + # rearrange into index using ipv4 as key + # this will collect related entries under the same ipv4 + ip_index = _make_group_index(vrr_peering_group, 'address') + for ip in ip_index: + ip_details = ip_index[ip] # a list of all info for given ipv4 + hostnames = [item['hostname'] for item in ip_details] + description = ip_details[0]['description'] + + formatted_peering = { + "description": _get_consistent_description(description), + "v4": ip, + "hostname": hostnames + } + peerings.append(formatted_peering) + return peerings + + def _peerings_for_nren(asn, bgplu_index, vpnrr_index): return { "asn": asn, "AP": _bgplu_peerings(asn, bgplu_index), - "VRR": [] + "VRR": _vpnrr_peerings(asn, vpnrr_index) } r = common.get_current_redis() bgplu = json.loads(r.get('juniper-peerings:group:BGPLU').decode('utf-8')) - bgplu_index = _make_bgplu_index(bgplu) + vpnrr = json.loads(r.get('juniper-peerings:group:VPN-RR').decode('utf-8')) + bgplu_index = _make_group_index(bgplu, 'remote-asn') + vpnrr_index = _make_group_index(vpnrr, 'remote-asn') config = current_app.config['INVENTORY_PROVIDER_CONFIG'] nren_asn_map = config['nren-asn-map'] - nren_details = [_peerings_for_nren(int(asn), bgplu_index) for asn in - nren_asn_map] + nren_details = [ + _peerings_for_nren(int(asn), + bgplu_index, + vpnrr_index) + for asn in nren_asn_map] response = json.dumps(nren_details) return Response(response, mimetype='application/json')