Skip to content

Commit e970d75

Browse files
azhivovkclaude
andcommitted
net: add localnet connectivity tests for dual-stream cluster
OVN localnet bridges rely on kernel bridge and OVS components that differ between RHCOS versions. These tests verify that secondary localnet network connectivity is preserved when the server VM migrates between RHCOS 9 and RHCOS 10 nodes in both directions. Signed-off-by: Asia Khromov <azhivovk@redhat.com> Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 9e25afa commit e970d75

2 files changed

Lines changed: 141 additions & 3 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import ipaddress
2+
from collections.abc import Generator
3+
4+
import pytest
5+
from kubernetes.dynamic import DynamicClient
6+
from ocp_resources.namespace import Namespace
7+
from ocp_resources.node import Node
8+
9+
import tests.network.libs.cluster_user_defined_network as libcudn
10+
import tests.network.libs.nodenetworkconfigurationpolicy as libnncp
11+
from libs.net.ip import cidr_addresses_by_family
12+
from libs.net.traffic_generator import TcpServer, VMTcpClient, active_tcp_connections
13+
from libs.net.vmspec import wait_for_ifaces_status
14+
from libs.vm.spec import Interface, Multus, Network
15+
from libs.vm.vm import BaseVirtualMachine
16+
from tests.network.libs import cloudinit
17+
from tests.network.libs.cloudinit import EthernetDevice
18+
from tests.network.localnet.liblocalnet import LOCALNET_BR_EX_INTERFACE, localnet_vm
19+
20+
_LOCALNET_IFACE_GUEST_NAME = "eth1"
21+
_SERVER_HOST_ADDRESS = 1
22+
_CLIENT_HOST_ADDRESS = 2
23+
24+
25+
@pytest.fixture(scope="module")
26+
def localnet_server_vm(
27+
unprivileged_client: DynamicClient,
28+
namespace_localnet_1: Namespace,
29+
cudn_localnet: libcudn.ClusterUserDefinedNetwork,
30+
nncp_localnet: libnncp.NodeNetworkConfigurationPolicy,
31+
rhcos9_node: Node,
32+
) -> Generator[BaseVirtualMachine]:
33+
addresses = cidr_addresses_by_family(net_seed=0, host_address=_SERVER_HOST_ADDRESS)
34+
with localnet_vm(
35+
namespace=namespace_localnet_1.name,
36+
name="server-vm",
37+
client=unprivileged_client,
38+
networks=[
39+
Network(name="default", pod={}),
40+
Network(name=LOCALNET_BR_EX_INTERFACE, multus=Multus(networkName=cudn_localnet.name)),
41+
],
42+
interfaces=[
43+
Interface(name="default", masquerade={}),
44+
Interface(name=LOCALNET_BR_EX_INTERFACE, bridge={}),
45+
],
46+
network_data=cloudinit.NetworkData(ethernets={_LOCALNET_IFACE_GUEST_NAME: EthernetDevice(addresses=addresses)}),
47+
node=rhcos9_node,
48+
) as vm:
49+
vm.start(wait=True)
50+
vm.wait_for_agent_connected()
51+
wait_for_ifaces_status(
52+
vm=vm,
53+
ip_addresses_by_spec_net_name={
54+
LOCALNET_BR_EX_INTERFACE: [str(ipaddress.ip_interface(addr).ip) for addr in addresses]
55+
},
56+
)
57+
yield vm
58+
59+
60+
@pytest.fixture(scope="module")
61+
def localnet_client_vm(
62+
unprivileged_client: DynamicClient,
63+
namespace_localnet_1: Namespace,
64+
cudn_localnet: libcudn.ClusterUserDefinedNetwork,
65+
nncp_localnet: libnncp.NodeNetworkConfigurationPolicy,
66+
rhcos9_node: Node,
67+
) -> Generator[BaseVirtualMachine]:
68+
addresses = cidr_addresses_by_family(net_seed=0, host_address=_CLIENT_HOST_ADDRESS)
69+
with localnet_vm(
70+
namespace=namespace_localnet_1.name,
71+
name="client-vm",
72+
client=unprivileged_client,
73+
networks=[
74+
Network(name="default", pod={}),
75+
Network(name=LOCALNET_BR_EX_INTERFACE, multus=Multus(networkName=cudn_localnet.name)),
76+
],
77+
interfaces=[
78+
Interface(name="default", masquerade={}),
79+
Interface(name=LOCALNET_BR_EX_INTERFACE, bridge={}),
80+
],
81+
network_data=cloudinit.NetworkData(ethernets={_LOCALNET_IFACE_GUEST_NAME: EthernetDevice(addresses=addresses)}),
82+
node=rhcos9_node,
83+
) as vm:
84+
vm.start(wait=True)
85+
vm.wait_for_agent_connected()
86+
wait_for_ifaces_status(
87+
vm=vm,
88+
ip_addresses_by_spec_net_name={
89+
LOCALNET_BR_EX_INTERFACE: [str(ipaddress.ip_interface(addr).ip) for addr in addresses]
90+
},
91+
)
92+
yield vm
93+
94+
95+
@pytest.fixture(scope="module")
96+
def localnet_active_tcp_connection(
97+
localnet_client_vm: BaseVirtualMachine,
98+
localnet_server_vm: BaseVirtualMachine,
99+
) -> Generator[list[tuple[VMTcpClient, TcpServer]]]:
100+
with active_tcp_connections(
101+
client_vm=localnet_client_vm,
102+
server_vm=localnet_server_vm,
103+
iface_name=LOCALNET_BR_EX_INTERFACE,
104+
) as connections:
105+
yield connections

tests/network/localnet/rhel9_rhel10_cluster/test_connectivity.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88
- mixed_os_nodes
99
"""
1010

11+
import ipaddress
12+
1113
import pytest
1214

13-
__test__ = False
15+
from libs.net.traffic_generator import is_tcp_connection
16+
from tests.network.libs.nodes import update_vm_node_selector
17+
from utilities.virt import migrate_vm_and_verify
1418

1519

20+
@pytest.mark.mixed_os_nodes
1621
@pytest.mark.incremental
1722
class TestConnectivity:
1823
"""
@@ -23,7 +28,13 @@ class TestConnectivity:
2328
"""
2429

2530
@pytest.mark.polarion("CNV-15951")
26-
def test_connectivity_preserved_during_server_migration_to_rhcos10(self):
31+
def test_connectivity_preserved_during_server_migration_to_rhcos10(
32+
self,
33+
subtests,
34+
localnet_server_vm,
35+
rhcos10_node,
36+
localnet_active_tcp_connection,
37+
):
2738
"""
2839
Test that an active TCP connection over a secondary localnet network
2940
is preserved when the server VM migrates from an RHCOS 9 node to an RHCOS 10 node.
@@ -39,9 +50,22 @@ def test_connectivity_preserved_during_server_migration_to_rhcos10(self):
3950
Expected:
4051
- The active TCP connection from the client VM to the server VM is preserved during the migration
4152
"""
53+
update_vm_node_selector(vm=localnet_server_vm, node=rhcos10_node)
54+
migrate_vm_and_verify(vm=localnet_server_vm)
55+
for client, server in localnet_active_tcp_connection:
56+
with subtests.test(msg=f"IPv{ipaddress.ip_address(client.server_ip).version} after migration to RHCOS 10"):
57+
assert is_tcp_connection(server=server, client=client), (
58+
f"TCP connection lost after migrating {localnet_server_vm.name} to RHCOS 10 node"
59+
)
4260

4361
@pytest.mark.polarion("CNV-15966")
44-
def test_connectivity_preserved_during_server_migration_to_rhcos9(self):
62+
def test_connectivity_preserved_during_server_migration_to_rhcos9(
63+
self,
64+
subtests,
65+
localnet_server_vm,
66+
rhcos9_node,
67+
localnet_active_tcp_connection,
68+
):
4569
"""
4670
Test that an active TCP connection over a secondary localnet network
4771
is preserved when the server VM migrates from an RHCOS 10 node to an RHCOS 9 node.
@@ -57,3 +81,12 @@ def test_connectivity_preserved_during_server_migration_to_rhcos9(self):
5781
Expected:
5882
- The active TCP connection from the client VM to the server VM is preserved during the migration
5983
"""
84+
update_vm_node_selector(vm=localnet_server_vm, node=rhcos9_node)
85+
migrate_vm_and_verify(vm=localnet_server_vm)
86+
for client, server in localnet_active_tcp_connection:
87+
with subtests.test(
88+
msg=f"IPv{ipaddress.ip_address(client.server_ip).version} after migration back to RHCOS 9"
89+
):
90+
assert is_tcp_connection(server=server, client=client), (
91+
f"TCP connection lost after migrating {localnet_server_vm.name} back to RHCOS 9 node"
92+
)

0 commit comments

Comments
 (0)