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
committed by
Dave Wallace
parent
a2bc88bb69
commit
9765e27635
@ -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:]}",
|
||||||
],
|
],
|
||||||
|
@ -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",
|
||||||
],
|
],
|
||||||
|
@ -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
Reference in New Issue
Block a user