tests: vpp_qemu_utils with concurrency handling

Type: test

Enhance vpp_qemu_utils functions with mutex locking, handle namespace
and
host interface existence, unique namespace/interface name, error
handling and retries, check error code explicitly.

Change-Id: I1ea66eeefbc1fee9b58e8b9886f4dd6fd8d33444
Signed-off-by: Ivan Ivanets <iivanets@cisco.com>
This commit is contained in:
Ivan Ivanets
2024-10-31 18:55:27 +00:00
committed by Dave Wallace
parent a2bc88bb69
commit 9765e27635
4 changed files with 372 additions and 233 deletions

View File

@ -1,13 +1,14 @@
from config import config from config import config
from asfframework import VppAsfTestCase, VppTestRunner from asfframework import VppAsfTestCase, VppTestRunner, get_testcase_dirname
import unittest import unittest
import subprocess import subprocess
import tempfile import tempfile
import os
from vpp_qemu_utils import ( from vpp_qemu_utils import (
create_host_interface, create_host_interface,
delete_host_interfaces, delete_all_host_interfaces,
create_namespace, create_namespace,
delete_namespace, delete_all_namespaces,
) )
@ -28,23 +29,36 @@ class TestHttpStaticVapi(VppAsfTestCase):
cls.temp2 = tempfile.NamedTemporaryFile() cls.temp2 = tempfile.NamedTemporaryFile()
cls.temp2.write(b"Hello world2") cls.temp2.write(b"Hello world2")
cls.ns_history_name = (
f"{config.tmp_dir}/{get_testcase_dirname(cls.__name__)}/history_ns.txt"
)
cls.if_history_name = (
f"{config.tmp_dir}/{get_testcase_dirname(cls.__name__)}/history_if.txt"
)
try: try:
create_namespace("HttpStatic") # CleanUp
except Exception: delete_all_namespaces(cls.ns_history_name)
cls.logger.warning("Unable to create a namespace, retrying.") delete_all_host_interfaces(cls.if_history_name)
delete_namespace("HttpStatic")
create_namespace("HttpStatic")
create_host_interface("vppHost", "vppOut", "HttpStatic", "10.10.1.1/24") cls.ns_name = create_namespace(cls.ns_history_name)
cls.host_if_name, cls.vpp_if_name = create_host_interface(
cls.if_history_name, cls.ns_name, "10.10.1.1/24"
)
cls.vapi.cli("create host-interface name vppOut") except Exception as e:
cls.vapi.cli("set int state host-vppOut up") cls.logger.warning(f"Unable to complete setup: {e}")
cls.vapi.cli("set int ip address host-vppOut 10.10.1.2/24") raise unittest.SkipTest("Skipping tests due to setup failure.")
cls.vapi.cli(f"create host-interface name {cls.vpp_if_name}")
cls.vapi.cli(f"set int state host-{cls.vpp_if_name} up")
cls.vapi.cli(f"set int ip address host-{cls.vpp_if_name} 10.10.1.2/24")
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
delete_namespace("HttpStatic") delete_all_namespaces(cls.ns_history_name)
delete_host_interfaces("vppHost") delete_all_host_interfaces(cls.if_history_name)
cls.temp.close() cls.temp.close()
cls.temp2.close() cls.temp2.close()
super(TestHttpStaticVapi, cls).tearDownClass() super(TestHttpStaticVapi, cls).tearDownClass()
@ -61,7 +75,7 @@ class TestHttpStaticVapi(VppAsfTestCase):
"ip", "ip",
"netns", "netns",
"exec", "exec",
"HttpStatic", self.ns_name,
"curl", "curl",
"-v", "-v",
f"10.10.1.2/{self.temp.name[5:]}", f"10.10.1.2/{self.temp.name[5:]}",
@ -77,7 +91,7 @@ class TestHttpStaticVapi(VppAsfTestCase):
"ip", "ip",
"netns", "netns",
"exec", "exec",
"HttpStatic", self.ns_name,
"curl", "curl",
f"10.10.1.2/{self.temp2.name[5:]}", f"10.10.1.2/{self.temp2.name[5:]}",
], ],
@ -103,23 +117,35 @@ class TestHttpStaticCli(VppAsfTestCase):
cls.temp2 = tempfile.NamedTemporaryFile() cls.temp2 = tempfile.NamedTemporaryFile()
cls.temp2.write(b"Hello world2") cls.temp2.write(b"Hello world2")
cls.ns_history_name = (
f"{config.tmp_dir}/{get_testcase_dirname(cls.__name__)}/history_ns.txt"
)
cls.if_history_name = (
f"{config.tmp_dir}/{get_testcase_dirname(cls.__name__)}/history_if.txt"
)
try: try:
create_namespace("HttpStatic2") delete_all_namespaces(cls.ns_history_name)
except Exception: delete_all_host_interfaces(cls.if_history_name)
cls.logger.warning("Unable to create namespace, retrying.")
delete_namespace("HttpStatic2")
create_namespace("HttpStatic2")
create_host_interface("vppHost2", "vppOut2", "HttpStatic2", "10.10.1.1/24") cls.ns_name = create_namespace(cls.ns_history_name)
cls.host_if_name, cls.vpp_if_name = create_host_interface(
cls.if_history_name, cls.ns_name, "10.10.1.1/24"
)
cls.vapi.cli("create host-interface name vppOut2") except Exception as e:
cls.vapi.cli("set int state host-vppOut2 up") cls.logger.warning(f"Unable to complete setup: {e}")
cls.vapi.cli("set int ip address host-vppOut2 10.10.1.2/24") raise unittest.SkipTest("Skipping tests due to setup failure.")
cls.vapi.cli(f"create host-interface name {cls.vpp_if_name}")
cls.vapi.cli(f"set int state host-{cls.vpp_if_name} up")
cls.vapi.cli(f"set int ip address host-{cls.vpp_if_name} 10.10.1.2/24")
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
delete_namespace("HttpStatic2") delete_all_namespaces(cls.ns_history_name)
delete_host_interfaces("vppHost2") delete_all_host_interfaces(cls.if_history_name)
cls.temp.close() cls.temp.close()
cls.temp2.close() cls.temp2.close()
super(TestHttpStaticCli, cls).tearDownClass() super(TestHttpStaticCli, cls).tearDownClass()
@ -135,7 +161,7 @@ class TestHttpStaticCli(VppAsfTestCase):
"ip", "ip",
"netns", "netns",
"exec", "exec",
"HttpStatic2", self.ns_name,
"curl", "curl",
f"10.10.1.2/{self.temp.name[5:]}", f"10.10.1.2/{self.temp.name[5:]}",
], ],
@ -149,7 +175,7 @@ class TestHttpStaticCli(VppAsfTestCase):
"ip", "ip",
"netns", "netns",
"exec", "exec",
"HttpStatic2", self.ns_name,
"curl", "curl",
f"10.10.1.2/{self.temp2.name[5:]}", f"10.10.1.2/{self.temp2.name[5:]}",
], ],

View File

@ -1,12 +1,13 @@
from config import config from config import config
from asfframework import VppAsfTestCase, VppTestRunner from asfframework import VppAsfTestCase, VppTestRunner, get_testcase_dirname
import unittest import unittest
import subprocess import subprocess
import os
from vpp_qemu_utils import ( from vpp_qemu_utils import (
create_host_interface, create_host_interface,
delete_host_interfaces, delete_all_host_interfaces,
create_namespace, create_namespace,
delete_namespace, delete_all_namespaces,
) )
@ -22,17 +23,36 @@ class TestProm(VppAsfTestCase):
def setUpClass(cls): def setUpClass(cls):
super(TestProm, cls).setUpClass() super(TestProm, cls).setUpClass()
create_namespace("HttpStaticProm") cls.ns_history_name = (
create_host_interface("vppHost", "vppOut", "HttpStaticProm", "10.10.1.1/24") f"{config.tmp_dir}/{get_testcase_dirname(cls.__name__)}/history_ns.txt"
)
cls.if_history_name = (
f"{config.tmp_dir}/{get_testcase_dirname(cls.__name__)}/history_if.txt"
)
cls.vapi.cli("create host-interface name vppOut") try:
cls.vapi.cli("set int state host-vppOut up") # CleanUp
cls.vapi.cli("set int ip address host-vppOut 10.10.1.2/24") delete_all_namespaces(cls.ns_history_name)
delete_all_host_interfaces(cls.if_history_name)
cls.ns_name = create_namespace(cls.ns_history_name)
cls.host_if_name, cls.vpp_if_name = create_host_interface(
cls.if_history_name, cls.ns_name, "10.10.1.1/24"
)
except Exception as e:
cls.logger.warning(f"Unable to complete setup: {e}")
raise unittest.SkipTest("Skipping tests due to setup failure.")
cls.vapi.cli(f"create host-interface name {cls.vpp_if_name}")
cls.vapi.cli(f"set int state host-{cls.vpp_if_name} up")
cls.vapi.cli(f"set int ip address host-{cls.vpp_if_name} 10.10.1.2/24")
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
delete_namespace(["HttpStaticProm"]) delete_all_namespaces(cls.ns_history_name)
delete_host_interfaces("vppHost") delete_all_host_interfaces(cls.if_history_name)
super(TestProm, cls).tearDownClass() super(TestProm, cls).tearDownClass()
def test_prom(self): def test_prom(self):
@ -46,7 +66,7 @@ class TestProm(VppAsfTestCase):
"ip", "ip",
"netns", "netns",
"exec", "exec",
"HttpStaticProm", self.ns_name,
"curl", "curl",
f"10.10.1.2/stats.prom", f"10.10.1.2/stats.prom",
], ],

View File

@ -3,9 +3,9 @@ import unittest
from ipaddress import ip_address, ip_interface from ipaddress import ip_address, ip_interface
from vpp_qemu_utils import ( from vpp_qemu_utils import (
create_namespace, create_namespace,
delete_namespace, delete_all_namespaces,
create_host_interface, create_host_interface,
delete_host_interfaces, delete_all_host_interfaces,
set_interface_mtu, set_interface_mtu,
disable_interface_gso, disable_interface_gso,
add_namespace_route, add_namespace_route,
@ -18,6 +18,7 @@ from config import config
from vpp_papi import VppEnum from vpp_papi import VppEnum
import time import time
import sys import sys
import os
from vm_test_config import test_config from vm_test_config import test_config
# #
@ -226,7 +227,16 @@ class TestVPPInterfacesQemu:
# prevent conflicts when TEST_JOBS > 1 # prevent conflicts when TEST_JOBS > 1
self.client_namespace = test_config["client_namespace"] + str(test["id"]) self.client_namespace = test_config["client_namespace"] + str(test["id"])
self.server_namespace = test_config["server_namespace"] + str(test["id"]) self.server_namespace = test_config["server_namespace"] + str(test["id"])
create_namespace([self.client_namespace, self.server_namespace]) self.ns_history_file = (
f"{config.tmp_dir}/vpp-unittest-{self.__class__.__name__}/history_ns.txt"
)
self.if_history_name = (
f"{config.tmp_dir}/vpp-unittest-{self.__class__.__name__}/history_if.txt"
)
delete_all_namespaces(self.ns_history_file)
create_namespace(
self.ns_history_file, ns=[self.client_namespace, self.server_namespace]
)
# Set a unique iPerf port for parallel server and client runs # Set a unique iPerf port for parallel server and client runs
self.iperf_port = 5000 + test["id"] self.iperf_port = 5000 + test["id"]
# IPerf client & server ingress/egress interface indexes in VPP # IPerf client & server ingress/egress interface indexes in VPP
@ -258,11 +268,11 @@ class TestVPPInterfacesQemu:
"iprf_server_interface_on_vpp" "iprf_server_interface_on_vpp"
] + str(test["id"]) ] + str(test["id"])
# Handle client interface types # Handle client interface types
delete_all_host_interfaces(self.if_history_name)
for client_if_type in client_if_types: for client_if_type in client_if_types:
if client_if_type == "af_packet": if client_if_type == "af_packet":
create_host_interface( create_host_interface(
self.iprf_client_host_interface_on_linux, self.if_history_name,
self.iprf_client_host_interface_on_vpp,
self.client_namespace, self.client_namespace,
( (
layer2["client_ip4_prefix"] layer2["client_ip4_prefix"]
@ -274,6 +284,8 @@ class TestVPPInterfacesQemu:
if x_connect_mode == "L2" if x_connect_mode == "L2"
else layer3["client_ip6_prefix"] else layer3["client_ip6_prefix"]
), ),
vpp_if_name=self.iprf_client_host_interface_on_vpp,
host_if_name=self.iprf_client_host_interface_on_linux,
) )
self.ingress_if_idx = self.create_af_packet( self.ingress_if_idx = self.create_af_packet(
version=client_if_version, version=client_if_version,
@ -352,11 +364,12 @@ class TestVPPInterfacesQemu:
for server_if_type in server_if_types: for server_if_type in server_if_types:
if server_if_type == "af_packet": if server_if_type == "af_packet":
create_host_interface( create_host_interface(
self.iprf_server_host_interface_on_linux, self.if_history_name,
self.iprf_server_host_interface_on_vpp,
self.server_namespace, self.server_namespace,
server_ip4_prefix, server_ip4_prefix,
server_ip6_prefix, server_ip6_prefix,
vpp_if_name=self.iprf_server_host_interface_on_vpp,
host_if_name=self.iprf_server_host_interface_on_linux,
) )
self.egress_if_idx = self.create_af_packet( self.egress_if_idx = self.create_af_packet(
version=server_if_version, version=server_if_version,
@ -480,12 +493,7 @@ class TestVPPInterfacesQemu:
except Exception: except Exception:
pass pass
try: try:
delete_host_interfaces( delete_all_host_interfaces(self.if_history_name)
self.iprf_client_host_interface_on_linux,
self.iprf_server_host_interface_on_linux,
self.iprf_client_host_interface_on_vpp,
self.iprf_server_host_interface_on_vpp,
)
except Exception: except Exception:
pass pass
try: try:
@ -506,12 +514,7 @@ class TestVPPInterfacesQemu:
except Exception: except Exception:
pass pass
try: try:
delete_namespace( delete_all_namespaces(self.ns_history_file)
[
self.client_namespace,
self.server_namespace,
]
)
except Exception: except Exception:
pass pass
try: try:

File diff suppressed because it is too large Load Diff