Skip to content

Commit 2b70f2a

Browse files
authored
Update platform api server to support IPv6 (#20942)
What is the motivation for this PR? Change platform api server so that HTTP requests can be received though IPv6 as an option This will fix platform_tests/api/* tests using a mgmt IPv6 configuration.
1 parent df450ea commit 2b70f2a

File tree

3 files changed

+55
-14
lines changed

3 files changed

+55
-14
lines changed

tests/common/fixtures/duthost_utils.py

100644100755
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import ipaddress
99
import time
1010
import json
11+
import re
1112

1213
from pytest_ansible.errors import AnsibleConnectionFailure
1314
from paramiko.ssh_exception import AuthenticationException
@@ -854,6 +855,30 @@ def wait_for_processes_and_bgp(dut):
854855
return duthosts
855856

856857

858+
@pytest.fixture(scope="module")
859+
def duthost_mgmt_ip(duthost):
860+
"""
861+
Gets the management IP address (v4 or v6) on eth0.
862+
Defaults to IPv4 on a dual stack configuration.
863+
"""
864+
ipv4_regex = re.compile(r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/\d+")
865+
ipv6_regex = re.compile(r"([a-fA-F0-9:]+)/\d+")
866+
867+
mgmt_interface = duthost.shell("show ip interface | egrep '^eth0 '", module_ignore_errors=True)["stdout"]
868+
if mgmt_interface:
869+
match = ipv4_regex.search(mgmt_interface)
870+
if match:
871+
return {"mgmt_ip": match.group(1), "version": "v4"}
872+
873+
mgmt_interface = duthost.shell("show ipv6 interface | egrep '^eth0 '", module_ignore_errors=True)["stdout"]
874+
if mgmt_interface:
875+
match = ipv6_regex.search(mgmt_interface)
876+
if match:
877+
return {"mgmt_ip": match.group(1), "version": "v6"}
878+
879+
pt_assert(False, "Failed to find duthost mgmt ip")
880+
881+
857882
def assert_addr_in_output(addr_set: Dict[str, List], hostname: str,
858883
expect_exists: bool, cmd_output: str, cmd_desc: str):
859884
"""

tests/common/helpers/platform_api/scripts/platform_api_server.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import inspect
33
import json
44
import os
5+
import socket
56
import sys
67
import syslog
78

@@ -18,6 +19,10 @@
1819
platform = sonic_platform.platform.Platform()
1920

2021

22+
class HTTPServerV6(HTTPServer):
23+
address_family = socket.AF_INET6
24+
25+
2126
def obj_serialize(obj):
2227
''' JSON serializer for objects not serializable by default json library code
2328
We simply return a dictionary containing the object's class and module
@@ -103,11 +108,15 @@ def do_platform_api(self):
103108
if __name__ == '__main__':
104109
parser = argparse.ArgumentParser()
105110
parser.add_argument('-p', '--port', type=int, help='port to listen to', required=True)
111+
parser.add_argument('-6', '--ipv6', action='store_true', help='Set server to use IPv6', )
106112
args = parser.parse_args()
107113

108114
syslog.openlog(SYSLOG_IDENTIFIER)
109115

110-
httpd = HTTPServer(('', args.port), PlatformAPITestService)
116+
if args.ipv6:
117+
httpd = HTTPServerV6(('::', args.port), PlatformAPITestService)
118+
else:
119+
httpd = HTTPServer(('', args.port), PlatformAPITestService)
111120
httpd.serve_forever()
112121

113122
syslog.closelog()

tests/common/platform/device_utils.py

100644100755
Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
from tests.common.platform.reboot_timing_constants import SERVICE_PATTERNS, OTHER_PATTERNS, SAIREDIS_PATTERNS, \
2020
OFFSET_ITEMS, TIME_SPAN_ITEMS, REQUIRED_PATTERNS
2121
from tests.common.devices.duthosts import DutHosts
22-
from tests.common.plugins.ansible_fixtures import ansible_adhoc # noqa F401
22+
from tests.common.plugins.ansible_fixtures import ansible_adhoc # noqa: F401
23+
from tests.common.fixtures.duthost_utils import duthost_mgmt_ip # noqa: F401
2324

2425
"""
2526
Helper script for fanout switch operations
@@ -52,7 +53,7 @@
5253
SERVER_FILE = 'platform_api_server.py'
5354
SERVER_PORT = 8000
5455
IPTABLES_PREPEND_RULE_CMD = 'iptables -I INPUT 1 -p tcp -m tcp --dport {} -j ACCEPT'.format(SERVER_PORT)
55-
56+
IP6TABLES_PREPEND_RULE_CMD = 'ip6tables -I INPUT 1 -p tcp -m tcp --dport {} -j ACCEPT'.format(SERVER_PORT)
5657
test_report = dict()
5758

5859

@@ -1080,9 +1081,10 @@ def advanceboot_neighbor_restore(duthosts, enum_rand_one_per_hwsku_frontend_host
10801081

10811082

10821083
@pytest.fixture(scope='function')
1083-
def start_platform_api_service(duthosts, enum_rand_one_per_hwsku_hostname, localhost, request):
1084+
def start_platform_api_service(duthosts, enum_rand_one_per_hwsku_hostname, duthost_mgmt_ip, # noqa: F811
1085+
localhost, request):
10841086
duthost = duthosts[enum_rand_one_per_hwsku_hostname]
1085-
dut_ip = duthost.mgmt_ip
1087+
dut_ip = duthost_mgmt_ip['mgmt_ip']
10861088

10871089
res = localhost.wait_for(host=dut_ip,
10881090
port=SERVER_PORT,
@@ -1097,12 +1099,15 @@ def start_platform_api_service(duthosts, enum_rand_one_per_hwsku_hostname, local
10971099

10981100
supervisor_conf = [
10991101
'[program:platform_api_server]',
1100-
'command=/usr/bin/python{} /opt/platform_api_server.py --port {}'.format('3' if py3_platform_api_available
1101-
else '2', SERVER_PORT),
1102+
'command=/usr/bin/python{} /opt/platform_api_server.py --port {} {}'.format(
1103+
'3' if py3_platform_api_available else '2',
1104+
SERVER_PORT,
1105+
'--ipv6' if duthost_mgmt_ip['version'] == 'v6' else ''),
11021106
'autostart=True',
11031107
'autorestart=True',
11041108
'stdout_logfile=syslog',
11051109
'stderr_logfile=syslog',
1110+
'startsec=0',
11061111
]
11071112
dest_path = os.path.join(os.sep, 'tmp', 'platform_api_server.conf')
11081113
pmon_path = os.path.join(os.sep, 'etc', 'supervisor', 'conf.d', 'platform_api_server.conf')
@@ -1116,7 +1121,10 @@ def start_platform_api_service(duthosts, enum_rand_one_per_hwsku_hostname, local
11161121
duthost.command('docker cp {} pmon:{}'.format(dest_path, pmon_path))
11171122

11181123
# Prepend an iptables rule to allow incoming traffic to the HTTP server
1119-
duthost.command(IPTABLES_PREPEND_RULE_CMD)
1124+
if duthost_mgmt_ip['version'] == 'v6':
1125+
duthost.command(IP6TABLES_PREPEND_RULE_CMD)
1126+
else:
1127+
duthost.command(IPTABLES_PREPEND_RULE_CMD)
11201128

11211129
# Reload the supervisor config and Start the HTTP server
11221130
duthost.command('docker exec -i pmon supervisorctl reread')
@@ -1127,9 +1135,8 @@ def start_platform_api_service(duthosts, enum_rand_one_per_hwsku_hostname, local
11271135

11281136

11291137
@pytest.fixture(scope='function')
1130-
def platform_api_conn(duthosts, enum_rand_one_per_hwsku_hostname, start_platform_api_service):
1131-
duthost = duthosts[enum_rand_one_per_hwsku_hostname]
1132-
dut_ip = duthost.mgmt_ip
1138+
def platform_api_conn(duthost_mgmt_ip, start_platform_api_service): # noqa: F811
1139+
dut_ip = duthost_mgmt_ip['mgmt_ip']
11331140

11341141
conn = http.client.HTTPConnection(dut_ip, 8000)
11351142
try:
@@ -1140,7 +1147,7 @@ def platform_api_conn(duthosts, enum_rand_one_per_hwsku_hostname, start_platform
11401147

11411148
@pytest.fixture(scope='module')
11421149
def add_platform_api_server_port_nat_for_dpu(
1143-
ansible_adhoc, tbinfo, request, duthosts, enum_rand_one_per_hwsku_hostname): # noqa F811
1150+
ansible_adhoc, tbinfo, request, duthosts, enum_rand_one_per_hwsku_hostname): # noqa: F811
11441151
'''
11451152
This fixture is used to add a NAT rule to the DPU's eth0-midplane interface
11461153
to forward traffic from NPU to the platform API server on DPU.
@@ -1168,15 +1175,15 @@ def add_platform_api_server_port_nat_for_dpu(
11681175
{SERVER_PORT} -j DNAT --to-destination {dpu_ip}:{SERVER_PORT}')
11691176

11701177

1171-
def get_ansible_ssh_port(duthost, ansible_adhoc): # noqa F811
1178+
def get_ansible_ssh_port(duthost, ansible_adhoc): # noqa: F811
11721179
host = ansible_adhoc(become=True, args=[], kwargs={})[duthost.hostname]
11731180
vm = host.options["inventory_manager"].get_host(duthost.hostname).vars
11741181
ansible_ssh_port = vm.get("ansible_ssh_port", None)
11751182
logger.info(f'ansible_ssh_port for {duthost.hostname} is {ansible_ssh_port}')
11761183
return ansible_ssh_port
11771184

11781185

1179-
def create_npu_host_based_on_dpu_info(ansible_adhoc, tbinfo, request, duthost): # noqa F811
1186+
def create_npu_host_based_on_dpu_info(ansible_adhoc, tbinfo, request, duthost): # noqa: F811
11801187
'''
11811188
Create a NPU host object based on DPU info
11821189
E.g

0 commit comments

Comments
 (0)