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 asfframework import VppAsfTestCase, VppTestRunner
from asfframework import VppAsfTestCase, VppTestRunner, get_testcase_dirname
import unittest
import subprocess
import tempfile
import os
from vpp_qemu_utils import (
create_host_interface,
delete_host_interfaces,
delete_all_host_interfaces,
create_namespace,
delete_namespace,
delete_all_namespaces,
)
@ -28,23 +29,36 @@ class TestHttpStaticVapi(VppAsfTestCase):
cls.temp2 = tempfile.NamedTemporaryFile()
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:
create_namespace("HttpStatic")
except Exception:
cls.logger.warning("Unable to create a namespace, retrying.")
delete_namespace("HttpStatic")
create_namespace("HttpStatic")
# CleanUp
delete_all_namespaces(cls.ns_history_name)
delete_all_host_interfaces(cls.if_history_name)
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")
cls.vapi.cli("set int state host-vppOut up")
cls.vapi.cli("set int ip address host-vppOut 10.10.1.2/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
def tearDownClass(cls):
delete_namespace("HttpStatic")
delete_host_interfaces("vppHost")
delete_all_namespaces(cls.ns_history_name)
delete_all_host_interfaces(cls.if_history_name)
cls.temp.close()
cls.temp2.close()
super(TestHttpStaticVapi, cls).tearDownClass()
@ -61,7 +75,7 @@ class TestHttpStaticVapi(VppAsfTestCase):
"ip",
"netns",
"exec",
"HttpStatic",
self.ns_name,
"curl",
"-v",
f"10.10.1.2/{self.temp.name[5:]}",
@ -77,7 +91,7 @@ class TestHttpStaticVapi(VppAsfTestCase):
"ip",
"netns",
"exec",
"HttpStatic",
self.ns_name,
"curl",
f"10.10.1.2/{self.temp2.name[5:]}",
],
@ -103,23 +117,35 @@ class TestHttpStaticCli(VppAsfTestCase):
cls.temp2 = tempfile.NamedTemporaryFile()
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:
create_namespace("HttpStatic2")
except Exception:
cls.logger.warning("Unable to create namespace, retrying.")
delete_namespace("HttpStatic2")
create_namespace("HttpStatic2")
delete_all_namespaces(cls.ns_history_name)
delete_all_host_interfaces(cls.if_history_name)
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")
cls.vapi.cli("set int state host-vppOut2 up")
cls.vapi.cli("set int ip address host-vppOut2 10.10.1.2/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
def tearDownClass(cls):
delete_namespace("HttpStatic2")
delete_host_interfaces("vppHost2")
delete_all_namespaces(cls.ns_history_name)
delete_all_host_interfaces(cls.if_history_name)
cls.temp.close()
cls.temp2.close()
super(TestHttpStaticCli, cls).tearDownClass()
@ -135,7 +161,7 @@ class TestHttpStaticCli(VppAsfTestCase):
"ip",
"netns",
"exec",
"HttpStatic2",
self.ns_name,
"curl",
f"10.10.1.2/{self.temp.name[5:]}",
],
@ -149,7 +175,7 @@ class TestHttpStaticCli(VppAsfTestCase):
"ip",
"netns",
"exec",
"HttpStatic2",
self.ns_name,
"curl",
f"10.10.1.2/{self.temp2.name[5:]}",
],

View File

@ -1,12 +1,13 @@
from config import config
from asfframework import VppAsfTestCase, VppTestRunner
from asfframework import VppAsfTestCase, VppTestRunner, get_testcase_dirname
import unittest
import subprocess
import os
from vpp_qemu_utils import (
create_host_interface,
delete_host_interfaces,
delete_all_host_interfaces,
create_namespace,
delete_namespace,
delete_all_namespaces,
)
@ -22,17 +23,36 @@ class TestProm(VppAsfTestCase):
def setUpClass(cls):
super(TestProm, cls).setUpClass()
create_namespace("HttpStaticProm")
create_host_interface("vppHost", "vppOut", "HttpStaticProm", "10.10.1.1/24")
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"
)
cls.vapi.cli("create host-interface name vppOut")
cls.vapi.cli("set int state host-vppOut up")
cls.vapi.cli("set int ip address host-vppOut 10.10.1.2/24")
try:
# CleanUp
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
def tearDownClass(cls):
delete_namespace(["HttpStaticProm"])
delete_host_interfaces("vppHost")
delete_all_namespaces(cls.ns_history_name)
delete_all_host_interfaces(cls.if_history_name)
super(TestProm, cls).tearDownClass()
def test_prom(self):
@ -46,7 +66,7 @@ class TestProm(VppAsfTestCase):
"ip",
"netns",
"exec",
"HttpStaticProm",
self.ns_name,
"curl",
f"10.10.1.2/stats.prom",
],

View File

@ -3,9 +3,9 @@ import unittest
from ipaddress import ip_address, ip_interface
from vpp_qemu_utils import (
create_namespace,
delete_namespace,
delete_all_namespaces,
create_host_interface,
delete_host_interfaces,
delete_all_host_interfaces,
set_interface_mtu,
disable_interface_gso,
add_namespace_route,
@ -18,6 +18,7 @@ from config import config
from vpp_papi import VppEnum
import time
import sys
import os
from vm_test_config import test_config
#
@ -226,7 +227,16 @@ class TestVPPInterfacesQemu:
# prevent conflicts when TEST_JOBS > 1
self.client_namespace = test_config["client_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
self.iperf_port = 5000 + test["id"]
# IPerf client & server ingress/egress interface indexes in VPP
@ -258,11 +268,11 @@ class TestVPPInterfacesQemu:
"iprf_server_interface_on_vpp"
] + str(test["id"])
# Handle client interface types
delete_all_host_interfaces(self.if_history_name)
for client_if_type in client_if_types:
if client_if_type == "af_packet":
create_host_interface(
self.iprf_client_host_interface_on_linux,
self.iprf_client_host_interface_on_vpp,
self.if_history_name,
self.client_namespace,
(
layer2["client_ip4_prefix"]
@ -274,6 +284,8 @@ class TestVPPInterfacesQemu:
if x_connect_mode == "L2"
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(
version=client_if_version,
@ -352,11 +364,12 @@ class TestVPPInterfacesQemu:
for server_if_type in server_if_types:
if server_if_type == "af_packet":
create_host_interface(
self.iprf_server_host_interface_on_linux,
self.iprf_server_host_interface_on_vpp,
self.if_history_name,
self.server_namespace,
server_ip4_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(
version=server_if_version,
@ -480,12 +493,7 @@ class TestVPPInterfacesQemu:
except Exception:
pass
try:
delete_host_interfaces(
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,
)
delete_all_host_interfaces(self.if_history_name)
except Exception:
pass
try:
@ -506,12 +514,7 @@ class TestVPPInterfacesQemu:
except Exception:
pass
try:
delete_namespace(
[
self.client_namespace,
self.server_namespace,
]
)
delete_all_namespaces(self.ns_history_file)
except Exception:
pass
try:

File diff suppressed because it is too large Load Diff