Skip to content

Commit f41aa12

Browse files
authored
Merge branch 'cnv-4.20' into removeCNV-59679
2 parents 4afadcb + 96c5cc3 commit f41aa12

File tree

14 files changed

+107
-262
lines changed

14 files changed

+107
-262
lines changed

libs/net/vmspec.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import ipaddress
12
from collections.abc import Callable
23
from typing import Any, Final
34

45
from kubernetes.dynamic.client import ResourceField
6+
from ocp_resources.virtual_machine import VirtualMachine
57
from timeout_sampler import TimeoutExpiredError, TimeoutSampler, retry
68

79
from libs.vm.spec import Devices, Interface, Network, SpecDisk, VMISpec, Volume
810
from libs.vm.vm import BaseVirtualMachine
11+
from utilities.network import IpNotFound
912

1013
LOOKUP_IFACE_STATUS_TIMEOUT_SEC: Final[int] = 30
1114
WAIT_FOR_MISSING_IFACE_STATUS_TIMEOUT_SEC: Final[int] = 120
@@ -140,3 +143,42 @@ def add_volume_disk(vmi_spec: VMISpec, volume: Volume, disk: SpecDisk) -> VMISpe
140143
vmi_spec.domain.devices.disks = vmi_spec.domain.devices.disks or []
141144
vmi_spec.domain.devices.disks.append(disk)
142145
return vmi_spec
146+
147+
148+
def lookup_iface_status_ip(
149+
vm: VirtualMachine, iface_name: str, ip_family: int
150+
) -> ipaddress.IPv4Address | ipaddress.IPv6Address | None:
151+
"""
152+
Return the IP address of the specified family for a VM interface.
153+
154+
Args:
155+
vm: The virtual machine to query.
156+
iface_name: The name of the network interface.
157+
ip_family: The IP version (4 for IPv4, 6 for IPv6).
158+
159+
Returns:
160+
The IP address matching the specified family.
161+
162+
Raises:
163+
IpNotFound: If no IP address of the specified family is found.
164+
"""
165+
try:
166+
iface = lookup_iface_status(
167+
vm=vm,
168+
iface_name=iface_name,
169+
predicate=lambda iface_status: bool(
170+
_lookup_first_ip_address(ip_addresses=iface_status.get("ipAddresses", []), ip_family=ip_family)
171+
),
172+
timeout=120,
173+
)
174+
except VMInterfaceStatusNotFoundError:
175+
raise IpNotFound(f"IPv{ip_family} address not found for interface {iface_name} on VM {vm.name}.")
176+
177+
return _lookup_first_ip_address(ip_addresses=iface["ipAddresses"], ip_family=ip_family)
178+
179+
180+
def _lookup_first_ip_address(
181+
ip_addresses: list[str],
182+
ip_family: int,
183+
) -> ipaddress.IPv4Address | ipaddress.IPv6Address | None:
184+
return next((ip for ip_addr in ip_addresses if (ip := ipaddress.ip_address(ip_addr)).version == ip_family), None)

tests/install_upgrade_operators/json_patch/utils.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,15 @@ def get_metrics_value_with_annotation(prometheus, query_string, component_name):
6363
def filter_metric_by_component(metrics, metric_name, component_name):
6464
annotation_name = get_annotation_name_for_component(component_name=component_name)
6565
for metric in metrics:
66-
if metric["metric"]["annotation_name"] == annotation_name and metric["metric"]["__name__"] == metric_name:
67-
return int(metric["value"][1])
66+
if (
67+
metric.get("metric", {}).get("annotation_name") == annotation_name
68+
and metric.get("metric", {}).get("__name__") == metric_name
69+
):
70+
metric_value = metric.get("value", [])
71+
if len(metric_value) > 1:
72+
return int(metric_value[1])
73+
LOGGER.warning(f"No results found when filtering for {metric_name} and annotation {annotation_name} in {metrics}.")
74+
return 0
6875

6976

7077
def wait_for_metrics_value_update(prometheus, component_name, query_string, previous_value):
@@ -78,7 +85,7 @@ def wait_for_metrics_value_update(prometheus, component_name, query_string, prev
7885
)
7986
try:
8087
for sample in samples:
81-
if sample == previous_value + 1:
88+
if sample and sample == previous_value + 1:
8289
return sample
8390
except TimeoutExpiredError:
8491
LOGGER.error(f"Query string: {query_string} for component: {component_name}, previous value: {previous_value}.")

tests/network/bgp/conftest.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from libs.net.traffic_generator import PodTcpClient as TcpClient
1616
from libs.net.traffic_generator import TcpServer
1717
from libs.net.udn import create_udn_namespace
18-
from libs.net.vmspec import IP_ADDRESS, lookup_iface_status, lookup_primary_network
18+
from libs.net.vmspec import lookup_iface_status_ip, lookup_primary_network
1919
from libs.vm.vm import BaseVirtualMachine
2020
from tests.network.libs import cluster_user_defined_network as libcudn
2121
from tests.network.libs import nodenetworkconfigurationpolicy as libnncp
@@ -231,7 +231,9 @@ def tcp_client_external_network(
231231
) -> Generator[TcpClient]:
232232
with TcpClient(
233233
pod=frr_external_pod.pod,
234-
server_ip=lookup_iface_status(vm=vm_cudn, iface_name=lookup_primary_network(vm=vm_cudn).name)[IP_ADDRESS],
234+
server_ip=str(
235+
lookup_iface_status_ip(vm=vm_cudn, iface_name=lookup_primary_network(vm=vm_cudn).name, ip_family=4)
236+
),
235237
server_port=IPERF3_SERVER_PORT,
236238
bind_interface=EXTERNAL_PROVIDER_IP_V4.split("/")[0],
237239
) as client:

tests/network/localnet/liblocalnet.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77

88
from libs.net.traffic_generator import TcpServer
99
from libs.net.traffic_generator import VMTcpClient as TcpClient
10-
from libs.net.vmspec import IP_ADDRESS, add_network_interface, add_volume_disk, lookup_iface_status
10+
from libs.net.vmspec import (
11+
add_network_interface,
12+
add_volume_disk,
13+
lookup_iface_status_ip,
14+
)
1115
from libs.vm.affinity import new_pod_anti_affinity
1216
from libs.vm.factory import base_vmspec, fedora_vm
1317
from libs.vm.spec import CloudInitNoCloud, Interface, Metadata, Multus, Network
@@ -48,7 +52,7 @@ def create_traffic_client(
4852
) -> TcpClient:
4953
return TcpClient(
5054
vm=client_vm,
51-
server_ip=lookup_iface_status(vm=server_vm, iface_name=spec_logical_network)[IP_ADDRESS],
55+
server_ip=str(lookup_iface_status_ip(vm=server_vm, iface_name=spec_logical_network, ip_family=4)),
5256
server_port=_IPERF_SERVER_PORT,
5357
)
5458

@@ -151,11 +155,12 @@ def client_server_active_connection(
151155
server_vm: BaseVirtualMachine,
152156
spec_logical_network: str,
153157
port: int = _IPERF_SERVER_PORT,
158+
ip_family: int = 4,
154159
) -> Generator[tuple[TcpClient, TcpServer], None, None]:
155160
with TcpServer(vm=server_vm, port=port) as server:
156161
with TcpClient(
157162
vm=client_vm,
158-
server_ip=lookup_iface_status(vm=server_vm, iface_name=spec_logical_network)[IP_ADDRESS],
163+
server_ip=str(lookup_iface_status_ip(vm=server_vm, iface_name=spec_logical_network, ip_family=ip_family)),
159164
server_port=port,
160165
) as client:
161166
yield client, server

tests/network/provider_migration/test_ip_persistence.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55
from libs.net.traffic_generator import is_tcp_connection
6-
from libs.net.vmspec import IP_ADDRESS, lookup_iface_status, lookup_primary_network
6+
from libs.net.vmspec import lookup_iface_status, lookup_iface_status_ip, lookup_primary_network
77
from tests.network.localnet.liblocalnet import client_server_active_connection
88
from utilities.constants import PUBLIC_DNS_SERVER_IP
99
from utilities.virt import migrate_vm_and_verify
@@ -20,7 +20,12 @@ def test_mac_and_ip_preserved_after_vm_import(source_vm_network_data, imported_c
2020
target_vm_iface = lookup_iface_status(
2121
vm=imported_cudn_vm, iface_name=lookup_primary_network(vm=imported_cudn_vm).name
2222
)
23-
target_vm_mac, target_vm_ip = target_vm_iface.get("mac", None), target_vm_iface.get(IP_ADDRESS, None)
23+
target_vm_mac = target_vm_iface.get("mac", None)
24+
target_vm_ip = str(
25+
lookup_iface_status_ip(
26+
vm=imported_cudn_vm, iface_name=lookup_primary_network(vm=imported_cudn_vm).name, ip_family=4
27+
)
28+
)
2429

2530
with subtests.test("MAC preserved"):
2631
assert source_vm_mac == target_vm_mac, (

tests/network/user_defined_network/test_user_defined_network.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from libs.net.traffic_generator import TcpServer, is_tcp_connection
88
from libs.net.traffic_generator import VMTcpClient as TcpClient
9-
from libs.net.vmspec import lookup_iface_status, lookup_primary_network
9+
from libs.net.vmspec import lookup_iface_status_ip, lookup_primary_network
1010
from libs.vm import affinity
1111
from tests.network.libs.ip import random_ipv4_address
1212
from tests.network.libs.vm_factory import udn_vm
@@ -85,7 +85,9 @@ def server(vmb_udn):
8585
def client(vma_udn, vmb_udn):
8686
with TcpClient(
8787
vm=vma_udn,
88-
server_ip=lookup_iface_status(vm=vmb_udn, iface_name=lookup_primary_network(vm=vmb_udn).name)[IP_ADDRESS],
88+
server_ip=str(
89+
lookup_iface_status_ip(vm=vmb_udn, iface_name=lookup_primary_network(vm=vmb_udn).name, ip_family=4)
90+
),
8991
server_port=SERVER_PORT,
9092
) as client:
9193
assert client.is_running()
@@ -98,7 +100,7 @@ class TestPrimaryUdn:
98100
@pytest.mark.polarion("CNV-11624")
99101
@pytest.mark.single_nic
100102
def test_ip_address_in_running_vm_matches_udn_subnet(self, namespaced_layer2_user_defined_network, vma_udn):
101-
ip = lookup_iface_status(vm=vma_udn, iface_name=lookup_primary_network(vm=vma_udn).name)[IP_ADDRESS]
103+
ip = str(lookup_iface_status_ip(vm=vma_udn, iface_name=lookup_primary_network(vm=vma_udn).name, ip_family=4))
102104
(subnet,) = namespaced_layer2_user_defined_network.subnets
103105
assert ipaddress.ip_address(ip) in ipaddress.ip_network(subnet), (
104106
f"The VM's primary network IP address ({ip}) is not in the UDN defined subnet ({subnet})"
@@ -107,14 +109,14 @@ def test_ip_address_in_running_vm_matches_udn_subnet(self, namespaced_layer2_use
107109
@pytest.mark.polarion("CNV-11674")
108110
@pytest.mark.single_nic
109111
def test_ip_address_is_preserved_after_live_migration(self, vma_udn):
110-
ip_before_migration = lookup_iface_status(vm=vma_udn, iface_name=lookup_primary_network(vm=vma_udn).name)[
111-
IP_ADDRESS
112-
]
112+
ip_before_migration = str(
113+
lookup_iface_status_ip(vm=vma_udn, iface_name=lookup_primary_network(vm=vma_udn).name, ip_family=4)
114+
)
113115
assert ip_before_migration
114116
migrate_vm_and_verify(vm=vma_udn)
115-
ip_after_migration = lookup_iface_status(vm=vma_udn, iface_name=lookup_primary_network(vm=vma_udn).name)[
116-
IP_ADDRESS
117-
]
117+
ip_after_migration = str(
118+
lookup_iface_status_ip(vm=vma_udn, iface_name=lookup_primary_network(vm=vma_udn).name, ip_family=4)
119+
)
118120
assert ip_before_migration == ip_after_migration, (
119121
f"The IP address {ip_before_migration} was not preserved during live migration. "
120122
f"IP after migration: {ip_after_migration}."
@@ -123,13 +125,15 @@ def test_ip_address_is_preserved_after_live_migration(self, vma_udn):
123125
@pytest.mark.polarion("CNV-11434")
124126
@pytest.mark.single_nic
125127
def test_vm_egress_connectivity(self, vmb_udn):
126-
assert lookup_iface_status(vm=vmb_udn, iface_name=lookup_primary_network(vm=vmb_udn).name)[IP_ADDRESS]
128+
assert str(lookup_iface_status_ip(vm=vmb_udn, iface_name=lookup_primary_network(vm=vmb_udn).name, ip_family=4))
127129
vmb_udn.console(commands=[f"ping -c 3 {PUBLIC_DNS_SERVER_IP}"], timeout=TIMEOUT_1MINUTE)
128130

129131
@pytest.mark.polarion("CNV-11418")
130132
@pytest.mark.single_nic
131133
def test_basic_connectivity_between_udn_vms(self, vma_udn, vmb_udn):
132-
target_vm_ip = lookup_iface_status(vm=vmb_udn, iface_name=lookup_primary_network(vm=vmb_udn).name)[IP_ADDRESS]
134+
target_vm_ip = str(
135+
lookup_iface_status_ip(vm=vmb_udn, iface_name=lookup_primary_network(vm=vmb_udn).name, ip_family=4)
136+
)
133137
vma_udn.console(commands=[f"ping -c 3 {target_vm_ip}"], timeout=TIMEOUT_1MIN)
134138

135139
@pytest.mark.polarion("CNV-11427")

0 commit comments

Comments
 (0)