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