From daf602de5bdec8dad062fc6bc179fc69b16b2768 Mon Sep 17 00:00:00 2001 From: Maryam Mokhtarifar <maryam.mokhtarifar@geant.org> Date: Mon, 17 Mar 2025 14:42:06 +0100 Subject: [PATCH 1/2] Implement whois method in msr.py and update the response and change the schema of `/asn-peers` --- inventory_provider/routes/msr.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/inventory_provider/routes/msr.py b/inventory_provider/routes/msr.py index ac2aa9b9..231112ee 100644 --- a/inventory_provider/routes/msr.py +++ b/inventory_provider/routes/msr.py @@ -104,6 +104,7 @@ import json import ipaddress import logging import re +import subprocess import threading from collections import defaultdict from typing import Dict @@ -160,7 +161,6 @@ PEERING_LIST_SCHEMA = { 'items': {'$ref': '#/definitions/peering-instance'} } - IP_ADDRESS_LIST_SCHEMA = { '$schema': 'https://json-schema.org/draft-07/schema#', 'definitions': { @@ -441,7 +441,8 @@ ASN_PEER_LIST_SCHEMA = { 'remote-asn': {'type': 'integer'}, 'local-asn': {'type': 'integer'}, 'instance': {'type': 'string'}, - 'nren': {'type': 'string'} + 'nren': {'type': 'string'}, + 'whois-info': {'type': 'string'} }, # only vrr peerings have remote-asn # only group peerings have local-asn or instance @@ -451,7 +452,8 @@ ASN_PEER_LIST_SCHEMA = { 'address', 'group', 'hostname', - 'nren'], + 'nren', + 'whois-info'], 'additionalProperties': False } }, @@ -1397,6 +1399,25 @@ def _asn_peers(asn, group, instance): """ r = common.get_current_redis() + def _whois_str(asn: int) -> str: + args = ["whois", "-h", "whois.cymru.com", f"AS{asn}"] + env = {"PATH": "/bin:/usr/bin"} + r = None + try: + r = subprocess.check_output(args, env=env) + except (subprocess.CalledProcessError, OSError): + logger.exception(f'error calling {" ".join(args)}') + return "?" + + if not r: + logger.error("no whois result returned") + return "" + result = r.splitlines() + if not result: + logger.error("error executing whois") + return "" + return result[-1].decode("utf-8") + def _get_filtered_peers_for_asn(asn, nren, group, instance): peers = json.loads(r.get(f'router-peerings:peer-asn:{asn}')) @@ -1407,10 +1428,12 @@ def _asn_peers(asn, group, instance): return False # no value exists, cannot meet condition return peer[name] == value + whois_info = _whois_str(asn) for peer in peers: if _attribute_filter(peer, "group", group) and \ _attribute_filter(peer, "instance", instance): peer['nren'] = nren + peer['whois-info'] = whois_info yield peer def _get_filtered_peers(asn_nren_map, group, instance): -- GitLab From 5c41910d408d8992bfe6ff66d187bf2a60be3ca2 Mon Sep 17 00:00:00 2001 From: Maryam Mokhtarifar <maryam.mokhtarifar@geant.org> Date: Thu, 20 Mar 2025 09:31:15 +0100 Subject: [PATCH 2/2] Mock whois method in tests. --- test/test_msr_routes.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/test_msr_routes.py b/test/test_msr_routes.py index 7fd78dfb..15eaa488 100644 --- a/test/test_msr_routes.py +++ b/test/test_msr_routes.py @@ -338,6 +338,17 @@ def test_get_mdvpn_peerings(client, mocked_redis): assert response_data # test data is non-empty +@pytest.fixture +def whois(mocker): + check_output = mocker.patch( + "inventory_provider.routes.msr.subprocess.check_output" + ) + check_output.return_value = """AS Name +RCCN Fundacao para a Ciencia e a Tecnologia, I.P., PT""".encode( + "utf-8" + ) + + @pytest.mark.parametrize('endpoint_variant', [ "", # default, no filter "/1853", @@ -348,7 +359,7 @@ def test_get_mdvpn_peerings(client, mocked_redis): "/1853?instance=IAS", "/1853?group=IAS-NRENS&instance=IAS" ]) -def test_get_asn_peers_get(endpoint_variant, client, mocked_redis): +def test_get_asn_peers_get(endpoint_variant, client, mocked_redis, whois): rv = client.get( f'/msr/asn-peers{endpoint_variant}', headers=DEFAULT_REQUEST_HEADERS @@ -370,7 +381,7 @@ def test_get_asn_peers_get(endpoint_variant, client, mocked_redis): ("/1853", '{"instance": "IAS"}'), ("/1853", '{"group": "IAS-NRENS", "instance": "IAS"}') ]) -def test_get_asn_peers_post(endpoint_variant, post_body, client, mocked_redis): +def test_get_asn_peers_post(endpoint_variant, post_body, client, mocked_redis, whois): rv = client.post( f'/msr/asn-peers{endpoint_variant}', headers=DEFAULT_REQUEST_HEADERS, -- GitLab