Skip to content

Commit f93539b

Browse files
authored
Merge branch 'cnv-4.20' into updateWinDeployment-cnv-4.20
2 parents 5bd5ec2 + 74227d7 commit f93539b

File tree

23 files changed

+262
-223
lines changed

23 files changed

+262
-223
lines changed

conftest.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
"node_remediation",
7878
"swap",
7979
"numa",
80-
"bgp",
8180
]
8281

8382
TEAM_MARKERS = {

containers/utility/Dockerfile

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ RUN if [ "$TARGETARCH" = "s390x" ] ; then \
44
yum install yum-utils -y ; \
55
yum-config-manager --add-repo='https://buildlogs.centos.org/centos/9-stream/nfv/s390x/openvswitch-2' ; \
66
else \
7-
yum install epel-release centos-release-nfv-openvswitch -y ; \
8-
fi ; \
9-
yum update -y && yum install iproute tcpdump qemu-img NetworkManager xfreerdp xauth xorg-x11-server-Xvfb which nftables stress-ng nmap -y && yum install --nogpgcheck openvswitch3.1 -y && yum clean all
7+
yum install -y epel-release centos-release-nfv-openvswitch; \
8+
fi; \
9+
yum -y update && \
10+
yum install -y \
11+
NetworkManager \
12+
dhcp-client \
13+
iperf3 \
14+
iproute \
15+
nftables \
16+
nmap \
17+
openvswitch3.1 --nogpgcheck \
18+
procps-ng \
19+
qemu-img \
20+
stress-ng \
21+
tcpdump \
22+
which \
23+
xauth \
24+
xfreerdp \
25+
xorg-x11-server-Xvfb && \
26+
yum clean all && \
27+
rm -rf /var/cache/yum

libs/net/traffic_generator.py

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from ocp_resources.pod import Pod
66
from ocp_utilities.exceptions import CommandExecFailed
7-
from timeout_sampler import TimeoutExpiredError, TimeoutSampler, retry
7+
from timeout_sampler import retry
88

99
from libs.vm.vm import BaseVirtualMachine
1010

@@ -15,7 +15,7 @@
1515
LOGGER = logging.getLogger(__name__)
1616

1717

18-
class BaseClient(ABC):
18+
class BaseTcpClient(ABC):
1919
"""Base abstract class for network traffic generator client."""
2020

2121
def __init__(self, server_ip: str, server_port: int):
@@ -24,7 +24,7 @@ def __init__(self, server_ip: str, server_port: int):
2424
self._cmd = f"{_IPERF_BIN} --client {self._server_ip} --time 0 --port {self.server_port} --connect-timeout 300"
2525

2626
@abstractmethod
27-
def __enter__(self) -> "BaseClient":
27+
def __enter__(self) -> "BaseTcpClient":
2828
pass
2929

3030
@abstractmethod
@@ -36,7 +36,7 @@ def is_running(self) -> bool:
3636
pass
3737

3838

39-
class Server:
39+
class TcpServer:
4040
"""
4141
Represents a server running on a virtual machine for testing network performance.
4242
Implemented with iperf3
@@ -55,11 +55,13 @@ def __init__(
5555
self._port = port
5656
self._cmd = f"{_IPERF_BIN} --server --port {self._port} --one-off"
5757

58-
def __enter__(self) -> "Server":
58+
def __enter__(self) -> "TcpServer":
5959
self._vm.console(
6060
commands=[f"{self._cmd} &"],
6161
timeout=_DEFAULT_CMD_TIMEOUT_SEC,
6262
)
63+
self._ensure_is_running()
64+
6365
return self
6466

6567
def __exit__(self, exc_type: BaseException, exc_value: BaseException, traceback: object) -> None:
@@ -72,10 +74,13 @@ def vm(self) -> BaseVirtualMachine:
7274
def is_running(self) -> bool:
7375
return _is_process_running(vm=self._vm, cmd=self._cmd)
7476

77+
@retry(wait_timeout=30, sleep=2, exceptions_dict={})
78+
def _ensure_is_running(self) -> bool:
79+
return self.is_running()
80+
7581

76-
class Client(BaseClient):
77-
"""
78-
Represents a client that connects to a server to test network performance.
82+
class VMTcpClient(BaseTcpClient):
83+
"""Represents a TCP client that connects to a server to test network performance.
7984
Implemented with iperf3
8085
8186
Args:
@@ -93,11 +98,13 @@ def __init__(
9398
super().__init__(server_ip=server_ip, server_port=server_port)
9499
self._vm = vm
95100

96-
def __enter__(self) -> "Client":
101+
def __enter__(self) -> "VMTcpClient":
97102
self._vm.console(
98103
commands=[f"{self._cmd} &"],
99104
timeout=_DEFAULT_CMD_TIMEOUT_SEC,
100105
)
106+
self._ensure_is_running()
107+
101108
return self
102109

103110
def __exit__(self, exc_type: BaseException, exc_value: BaseException, traceback: object) -> None:
@@ -110,6 +117,10 @@ def vm(self) -> BaseVirtualMachine:
110117
def is_running(self) -> bool:
111118
return _is_process_running(vm=self._vm, cmd=self._cmd)
112119

120+
@retry(wait_timeout=30, sleep=2, exceptions_dict={})
121+
def _ensure_is_running(self) -> bool:
122+
return self.is_running()
123+
113124

114125
def _stop_process(vm: BaseVirtualMachine, cmd: str) -> None:
115126
try:
@@ -118,25 +129,18 @@ def _stop_process(vm: BaseVirtualMachine, cmd: str) -> None:
118129
LOGGER.warning(str(e))
119130

120131

121-
def _is_process_running( # type: ignore[return]
122-
vm: BaseVirtualMachine, cmd: str
123-
) -> bool:
132+
def _is_process_running(vm: BaseVirtualMachine, cmd: str) -> bool:
124133
try:
125-
for sample in TimeoutSampler(
126-
wait_timeout=60,
127-
sleep=5,
128-
func=vm.console,
134+
vm.console(
129135
commands=[f"pgrep -fx '{cmd}'"],
130136
timeout=_DEFAULT_CMD_TIMEOUT_SEC,
131-
):
132-
if sample:
133-
return True
134-
except TimeoutExpiredError as e:
135-
LOGGER.warning(f"Process is not running on VM {vm.name}. Error: {str(e.last_exp)}")
137+
)
138+
return True
139+
except CommandExecFailed:
136140
return False
137141

138142

139-
class PodClient(BaseClient):
143+
class PodTcpClient(BaseTcpClient):
140144
"""Represents a TCP client that connects to a server to test network performance.
141145
142146
Expects pod to have iperf3 container.
@@ -155,7 +159,7 @@ def __init__(self, pod: Pod, server_ip: str, server_port: int, bind_interface: s
155159
self._container = _IPERF_BIN
156160
self._cmd += f" --bind {bind_interface}" if bind_interface else ""
157161

158-
def __enter__(self) -> "PodClient":
162+
def __enter__(self) -> "PodTcpClient":
159163
# run the command in the background using nohup to ensure it keeps running after the exec session ends
160164
self._pod.execute(
161165
command=["sh", "-c", f"nohup {self._cmd} >/tmp/{_IPERF_BIN}.log 2>&1 &"], container=self._container
@@ -178,5 +182,5 @@ def _ensure_is_running(self) -> bool:
178182
return self.is_running()
179183

180184

181-
def is_tcp_connection(server: Server, client: Client | PodClient) -> bool:
185+
def is_tcp_connection(server: TcpServer, client: BaseTcpClient) -> bool:
182186
return server.is_running() and client.is_running()

libs/vm/affinity.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def new_label(key_prefix: str) -> tuple[str, str]:
1515
return f"{key_prefix}-{uuid.uuid4().hex[:8]}", "true"
1616

1717

18-
def new_pod_anti_affinity(label: tuple[str, str]) -> Affinity:
18+
def new_pod_anti_affinity(label: tuple[str, str], namespaces: list[str] | None = None) -> Affinity:
1919
(key, value) = label
2020
return Affinity(
2121
podAntiAffinity=PodAntiAffinity(
@@ -25,6 +25,7 @@ def new_pod_anti_affinity(label: tuple[str, str]) -> Affinity:
2525
matchExpressions=[LabelSelectorRequirement(key=key, values=[value], operator="In")]
2626
),
2727
topologyKey=f"{Resource.ApiGroup.KUBERNETES_IO}/hostname",
28+
namespaces=namespaces,
2829
)
2930
]
3031
)

libs/vm/spec.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class PodAffinityTerm:
110110
labelSelector: LabelSelector # noqa: N815
111111
topologyKey: str # noqa: N815
112112
namespaceSelector: dict[str, Any] | None = None # noqa: N815
113+
namespaces: list[str] | None = None
113114

114115

115116
@dataclass

tests/conftest.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,13 +1076,6 @@ def sriov_workers(schedulable_nodes):
10761076
yield [node for node in schedulable_nodes if node.labels.get(sriov_worker_label) == "true"]
10771077

10781078

1079-
@pytest.fixture(scope="session")
1080-
def vlan_base_iface(worker_node1, nodes_available_nics):
1081-
# Select the last NIC from the list as a way to ensure that the selected NIC
1082-
# is not already used (e.g. as a bond's port).
1083-
return nodes_available_nics[worker_node1.name][-1]
1084-
1085-
10861079
@pytest.fixture(scope="session")
10871080
def sriov_ifaces(sriov_nodes_states, workers_utility_pods):
10881081
node = sriov_nodes_states[0]

tests/install_upgrade_operators/product_install/conftest.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
from ocp_resources.installplan import InstallPlan
1010
from ocp_resources.persistent_volume import PersistentVolume
1111
from ocp_resources.resource import get_client
12+
from ocp_resources.storage_class import StorageClass
1213
from pytest_testconfig import py_config
14+
from timeout_sampler import TimeoutSampler
1315

1416
from tests.install_upgrade_operators.product_install.constants import (
1517
HCO_NOT_INSTALLED_ALERT,
@@ -27,6 +29,7 @@
2729
PENDING_STR,
2830
PRODUCTION_CATALOG_SOURCE,
2931
TIMEOUT_5MIN,
32+
TIMEOUT_5SEC,
3033
TIMEOUT_10MIN,
3134
StorageClassNames,
3235
)
@@ -58,6 +61,8 @@
5861
HppCsiStorageClass,
5962
HPPWithStoragePool,
6063
create_hpp_storage_class,
64+
get_default_storage_class,
65+
persist_storage_class_default,
6166
)
6267

6368
INSTALLATION_VERSION_MISMATCH = "98"
@@ -313,3 +318,37 @@ def cnv_version_to_install_info(is_production_source, ocp_current_version, cnv_i
313318
if not latest_z_stream:
314319
pytest.exit(reason="CNV version can't be determined for this run", returncode=INSTALLATION_VERSION_MISMATCH)
315320
return latest_z_stream
321+
322+
323+
@pytest.fixture()
324+
def default_storage_class_from_config(admin_client):
325+
# if its not on the matrix - we dont need to test it.
326+
default_storage_class_name = py_config["default_storage_class"]
327+
if not any(default_storage_class_name in sc_dict for sc_dict in py_config["storage_class_matrix"]):
328+
pytest.xfail(f"Storage class {default_storage_class_name} not found in the storage class matrix")
329+
# Some storageclasses are created asynchronously, for example ocs-virt,
330+
# so we need to wait for them to be created
331+
LOGGER.info(f"Waiting for storage class {default_storage_class_name} to be created")
332+
default_storage_class = StorageClass(client=admin_client, name=default_storage_class_name)
333+
for sample in TimeoutSampler(
334+
wait_timeout=TIMEOUT_5MIN,
335+
sleep=TIMEOUT_5SEC,
336+
func=lambda: default_storage_class.exists,
337+
):
338+
if sample:
339+
break
340+
341+
return default_storage_class
342+
343+
344+
@pytest.fixture()
345+
def updated_default_storage_class_from_config(admin_client, default_storage_class_from_config):
346+
# Swaps the current default StorageClass with the one defined in our config.
347+
try:
348+
current_default_sc = get_default_storage_class()
349+
if current_default_sc.name == default_storage_class_from_config.name:
350+
return
351+
persist_storage_class_default(default=False, storage_class=current_default_sc)
352+
except ValueError:
353+
LOGGER.info("No default storage class exists, setting the config one as default")
354+
persist_storage_class_default(default=True, storage_class=default_storage_class_from_config)

tests/install_upgrade_operators/product_install/test_install_openshift_virtualization.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
wait_for_firing_alert_clean_up,
2727
wait_for_gauge_metrics_value,
2828
)
29+
from utilities.storage import (
30+
verify_boot_sources_reimported,
31+
)
2932

3033
CNV_INSTALLATION_TEST = "test_cnv_installation"
3134
CNV_ALERT_CLEANUP_TEST = "test_cnv_installation_alert_cleanup"
@@ -170,6 +173,17 @@ def test_cnv_resources_installed_namespace_scoped(
170173
raise ResourceMismatch(f"Unexpected namespaced resources found post cnv installation: {mismatch_namespaced}")
171174

172175

176+
@pytest.mark.polarion("CNV-12453")
177+
@pytest.mark.order(after=CNV_INSTALLATION_TEST)
178+
# Dependency: CNV must be installed before storage class configuration can be verified
179+
@pytest.mark.dependency(depends=[CNV_INSTALLATION_TEST])
180+
@pytest.mark.usefixtures("updated_default_storage_class_from_config")
181+
def test_default_storage_class_set(admin_client, golden_images_namespace):
182+
assert verify_boot_sources_reimported(
183+
admin_client=admin_client, namespace=golden_images_namespace.name, consecutive_checks_count=3
184+
), "Failed to re-import boot sources"
185+
186+
173187
@pytest.mark.polarion("CNV-10528")
174188
def test_install_hpp(admin_client, schedulable_nodes, installed_hpp, created_cnv_namespace):
175189
validate_hpp_installation(

tests/network/bgp/README.md

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,3 @@ An external BGP router is required for real-world BGP connectivity, as customers
88
cluster. For testing, the router is implemented as a pod running FRR within the cluster, serving the same role as an
99
external router. The external BGP router (a pod in this case) must be on the same network as the cluster nodes
1010
to enable direct BGP sessions.
11-
12-
### Cluster Requirements
13-
14-
The current implementation requires:
15-
- Each node must have at least two NICs.
16-
- All secondary NICs must be connected to the same VLAN as the main IP of the `br-ex` interface.
17-
18-
### Environment Variables
19-
20-
Set these before running tests:
21-
22-
- `PRIMARY_NODE_NETWORK_VLAN_TAG`: the VLAN number of the `br-ex` main IP. Setting this variable implies that a cluster
23-
reflects the requirements mentioned above.
24-
- `EXTERNAL_FRR_STATIC_IPV4`: reserved IPv4 in CIDR format for the external FRR pod (e.g., 192.0.2.10/24)
25-
within the PRIMARY_NODE_NETWORK_VLAN_TAG network.
26-
27-
```bash
28-
export PRIMARY_NODE_NETWORK_VLAN_TAG=<vlan_id>
29-
export EXTERNAL_FRR_STATIC_IPV4=<static_ip_cidr>
30-
```

0 commit comments

Comments
 (0)