Skip to content

Commit 6828df3

Browse files
committed
Merge branch 'main' into testCustomCliDownload
2 parents 890c67a + be2fb31 commit 6828df3

94 files changed

Lines changed: 2145 additions & 2901 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ repos:
1313
stages: [pre-commit]
1414

1515
- repo: https://github.com/astral-sh/ruff-pre-commit
16-
rev: v0.12.11
16+
rev: v0.13.0
1717
hooks:
1818
- id: ruff
1919
stages: [pre-commit]
@@ -65,7 +65,7 @@ repos:
6565
- id: gitleaks
6666

6767
- repo: https://github.com/pre-commit/mirrors-mypy
68-
rev: v1.17.1
68+
rev: v1.18.1
6969
hooks:
7070
- id: mypy
7171
exclude: "test_(.*).py$"

libs/infra/images.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ class Cirros:
1919
DEFAULT_MEMORY_SIZE: str = "64M"
2020

2121

22+
@dataclass
23+
class Alpine:
24+
QCOW2_IMG: str | None = None
25+
DIR: str = f"{BASE_IMAGES_DIR}/alpine-images"
26+
DEFAULT_DV_SIZE: str = "1Gi"
27+
DEFAULT_MEMORY_SIZE: str = "128M"
28+
29+
2230
@dataclass
2331
class Rhel:
2432
RHEL7_9_IMG: str | None = None

libs/net/netattachdef.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,39 @@
1111
_DEFAULT_CNI_VERSION: Final[str] = "0.3.1"
1212

1313

14+
@dataclass
15+
class Ipam:
16+
"""
17+
IP Address Management (IPAM) base class
18+
Ref: https://www.cni.dev/plugins/current/ipam/
19+
"""
20+
21+
type: str = field(init=False)
22+
23+
24+
@dataclass
25+
class IpamRoute:
26+
dst: str
27+
gw: str | None = None
28+
29+
30+
@dataclass
31+
class IpamStatic(Ipam):
32+
"""
33+
IPAM static plugin
34+
Ref: https://www.cni.dev/plugins/current/ipam/static/
35+
"""
36+
37+
type: str = field(default="static", init=False)
38+
addresses: list["IpamStatic.Address"]
39+
routes: list[IpamRoute] | None = None
40+
41+
@dataclass
42+
class Address:
43+
address: str
44+
gateway: str | None = None
45+
46+
1447
@dataclass
1548
class CNIPluginConfig:
1649
type: str = field(init=False)
@@ -50,6 +83,19 @@ class Topology(Enum):
5083
LOCALNET = "localnet"
5184

5285

86+
@dataclass
87+
class CNIPluginMacvlanConfig(CNIPluginConfig):
88+
"""
89+
CNI Macvlan Plugin
90+
Ref: https://www.cni.dev/plugins/current/main/macvlan/
91+
"""
92+
93+
type: str = field(default="macvlan", init=False)
94+
master: str
95+
ipam: Ipam | None = None
96+
mode: str = "bridge"
97+
98+
5399
@dataclass
54100
class NetConfig:
55101
"""

libs/net/udn.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
1+
from collections.abc import Generator
12
from typing import Final
23

4+
from kubernetes.dynamic import DynamicClient
5+
from ocp_resources.namespace import Namespace
6+
37
from libs.vm.spec import Interface, NetBinding, Network
8+
from utilities.infra import create_ns
49

510
UDN_BINDING_PLUGIN_NAME: Final[str] = "l2bridge"
611

712

813
def udn_primary_network(name: str) -> tuple[Interface, Network]:
914
return Interface(name=name, binding=NetBinding(name=UDN_BINDING_PLUGIN_NAME)), Network(name=name, pod={})
15+
16+
17+
def create_udn_namespace(
18+
name: str,
19+
client: DynamicClient,
20+
labels: dict[str, str] | None = None,
21+
) -> Generator[Namespace]:
22+
return create_ns(
23+
name=name,
24+
labels={"k8s.ovn.org/primary-user-defined-network": "", **(labels or {})},
25+
admin_client=client,
26+
)

pyproject.toml

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ exclude = [".git", ".venv", ".mypy_cache", ".tox", "__pycache__"]
99

1010
[tool.ruff.lint.isort]
1111
order-by-type = true
12-
known-third-party = ["ocp_resources", "ocp_utilities", "timeout_sampler", "pyhelper_utils"]
12+
known-third-party = [
13+
"ocp_resources",
14+
"ocp_utilities",
15+
"timeout_sampler",
16+
"pyhelper_utils",
17+
]
1318

1419
[tool.mypy]
1520
warn_unused_configs = true
1621
warn_redundant_casts = true
1722

1823
[[tool.mypy.overrides]]
19-
module = [
20-
"libs.*",
21-
"tests.network.libs.*",
22-
"tests.network.localnet.*"
23-
]
24+
module = ["libs.*", "tests.network.libs.*", "tests.network.localnet.*"]
2425
disallow_untyped_calls = true
2526
disallow_untyped_defs = true
2627
disallow_incomplete_defs = true
@@ -78,17 +79,18 @@ dependencies = [
7879
"marshmallow~=3.26.1",
7980
"python-simple-logger>=2.0.13",
8081
"pytest-html>=4.1.1",
82+
"openshift-python-wrapper>=11.0.93",
8183
]
8284

8385
[project.optional-dependencies]
8486
# Dependencies for utilities unit testing
8587
utilities-test = [
86-
"pytest>=8.3.3",
87-
"pytest-cov>=4.1.0",
88-
"pytest-mock>=3.12.0",
89-
"pytest-xdist>=3.5.0",
90-
"pytest-timeout>=2.2.0",
91-
"pytest-watch>=4.2.0",
88+
"pytest>=8.3.3",
89+
"pytest-cov>=4.1.0",
90+
"pytest-mock>=3.12.0",
91+
"pytest-xdist>=3.5.0",
92+
"pytest-timeout>=2.2.0",
93+
"pytest-watch>=4.2.0",
9294
]
9395

9496
[tool.hatch.build.targets.wheel]
@@ -123,33 +125,33 @@ addopts = """
123125
[tool.coverage.run]
124126
source = ["utilities"]
125127
omit = [
126-
"*/tests/*",
127-
"*/__pycache__/*",
128-
"*/manifests/*",
129-
"*.pyc",
130-
"*/test_*.py",
131-
"__init__.py",
132-
"utilities/unittests/conftest.py",
133-
# TODO: Add coverage to these large modules when individual fixes are needed
134-
"utilities/hco.py",
135-
"utilities/infra.py",
136-
"utilities/network.py",
137-
"utilities/operator.py",
138-
"utilities/storage.py",
139-
"utilities/virt.py",
128+
"*/tests/*",
129+
"*/__pycache__/*",
130+
"*/manifests/*",
131+
"*.pyc",
132+
"*/test_*.py",
133+
"__init__.py",
134+
"utilities/unittests/conftest.py",
135+
# TODO: Add coverage to these large modules when individual fixes are needed
136+
"utilities/hco.py",
137+
"utilities/infra.py",
138+
"utilities/network.py",
139+
"utilities/operator.py",
140+
"utilities/storage.py",
141+
"utilities/virt.py",
140142
]
141143

142144
[tool.coverage.report]
143145
precision = 2
144146
exclude_lines = [
145-
"pragma: no cover",
146-
"def __repr__",
147-
"if TYPE_CHECKING:",
148-
"raise AssertionError",
149-
"raise NotImplementedError",
150-
"if __name__ == .__main__.:",
151-
"pass",
152-
"except ImportError:",
147+
"pragma: no cover",
148+
"def __repr__",
149+
"if TYPE_CHECKING:",
150+
"raise AssertionError",
151+
"raise NotImplementedError",
152+
"if __name__ == .__main__.:",
153+
"pass",
154+
"except ImportError:",
153155
]
154156
show_missing = true
155157
skip_covered = false

pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ markers =
3636
gpu: Tests that require cluster with gpu cards
3737
sriov: Tests that require sriov net-cards on nodes
3838
single_nic: Tests that don`t require mutli-nic nodes, required for conformance tests for new archs, platforms etc.
39+
bgp: Tests that require special VLAN configuration on node NICs
3940

4041
## Configuration requirements
4142
ipv4: Tests that require IPv4

tests/chaos/OWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
reviewers:
22
- qwang1
3+
- sarahbx

tests/chaos/oadp/conftest.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@
33

44
import pytest
55

6-
from utilities.constants import BACKUP_STORAGE_LOCATION, FILE_NAME_FOR_BACKUP, TEXT_TO_TEST, TIMEOUT_3MIN, TIMEOUT_10MIN
6+
from utilities.constants import (
7+
BACKUP_STORAGE_LOCATION,
8+
FILE_NAME_FOR_BACKUP,
9+
TEXT_TO_TEST,
10+
TIMEOUT_3MIN,
11+
TIMEOUT_10MIN,
12+
)
713
from utilities.infra import ExecCommandOnPod, wait_for_node_status
814
from utilities.oadp import VeleroBackup, create_rhel_vm
915
from utilities.storage import write_file
16+
from utilities.virt import node_mgmt_console, wait_for_node_schedulable_status
1017

1118
LOGGER = logging.getLogger(__name__)
1219

@@ -64,3 +71,11 @@ def rebooted_vm_source_node(rhel_vm_with_dv_running, oadp_backup_in_progress, wo
6471
LOGGER.info(f"Waiting for node {vm_node.name} to come back online")
6572
wait_for_node_status(node=vm_node, status=True, wait_timeout=TIMEOUT_10MIN)
6673
return
74+
75+
76+
@pytest.fixture()
77+
def drain_vm_source_node(rhel_vm_with_dv_running, oadp_backup_in_progress):
78+
vm_node = rhel_vm_with_dv_running.vmi.node
79+
with node_mgmt_console(node=vm_node, node_mgmt="drain"):
80+
wait_for_node_schedulable_status(node=vm_node, status=False)
81+
yield vm_node

tests/chaos/oadp/test_oadp.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,32 @@ def test_reboot_vm_node_during_backup(
3939
oadp_backup_in_progress.wait_for_status(
4040
status=oadp_backup_in_progress.Backup.Status.PARTIALLYFAILED, timeout=TIMEOUT_10MIN
4141
)
42+
43+
44+
@pytest.mark.destructive
45+
@pytest.mark.chaos
46+
@pytest.mark.parametrize(
47+
"rhel_vm_with_dv_running",
48+
[
49+
pytest.param(
50+
{
51+
"vm_name": "vm-node-drain-12020",
52+
"rhel_image": RHEL_LATEST["image_name"],
53+
},
54+
marks=pytest.mark.polarion("CNV-12020"),
55+
),
56+
],
57+
indirect=True,
58+
)
59+
def test_drain_vm_node_during_backup(
60+
oadp_backup_in_progress,
61+
drain_vm_source_node,
62+
):
63+
"""
64+
Drain the worker node where the VM is located during OADP backup using DataMover.
65+
Validate that backup eventually Completed.
66+
"""
67+
LOGGER.info(f"Waiting for backup to reach '{oadp_backup_in_progress.Backup.Status.COMPLETED}' during node drain.")
68+
oadp_backup_in_progress.wait_for_status(
69+
status=oadp_backup_in_progress.Backup.Status.COMPLETED, timeout=TIMEOUT_10MIN
70+
)

0 commit comments

Comments
 (0)