Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions tests/network/libs/vm_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from libs.net.udn import udn_primary_network
from libs.vm.affinity import new_pod_anti_affinity
from libs.vm.factory import base_vmspec, fedora_vm
from libs.vm.spec import Affinity
from libs.vm.vm import BaseVirtualMachine


Expand All @@ -15,16 +16,34 @@ def udn_vm(
binding: str,
template_labels: dict | None = None,
anti_affinity_namespaces: list[str] | None = None,
affinity: Affinity | None = None,
) -> BaseVirtualMachine:
"""Create a Fedora VM connected to a primary UDN using the specified binding.

Args:
namespace_name: Namespace in which the VM will be created.
name: Name of the VM.
client: Kubernetes dynamic client.
binding: UDN binding plugin name (e.g. UDN_BINDING_DEFAULT_PLUGIN_NAME).
template_labels: Optional labels to add to the VM pod template, also used as anti-affinity key.
anti_affinity_namespaces: Optional namespaces to scope the pod anti-affinity rule.
affinity: Optional explicit affinity rules. When set, takes precedence over auto-generated anti-affinity from template_labels.

Returns:
Configured BaseVirtualMachine object (not yet started).
"""
spec = base_vmspec()
iface, network = udn_primary_network(name="udn-primary", binding=binding)
spec.template.spec.domain.devices.interfaces = [iface] # type: ignore
spec.template.spec.networks = [network]
if affinity is not None:
spec.template.spec.affinity = affinity
if template_labels:
spec.template.metadata.labels = spec.template.metadata.labels or {} # type: ignore
spec.template.metadata.labels.update(template_labels) # type: ignore
# Use the first label key and first value as the anti-affinity label to use:
label, *_ = template_labels.items()
spec.template.spec.affinity = new_pod_anti_affinity(label=label, namespaces=anti_affinity_namespaces)
if affinity is None:
# Use the first label key and first value as the anti-affinity label to use:
label, *_ = template_labels.items()
spec.template.spec.affinity = new_pod_anti_affinity(label=label, namespaces=anti_affinity_namespaces)

return fedora_vm(namespace=namespace_name, name=name, client=client, spec=spec)
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from collections.abc import Generator

import pytest
from kubernetes.dynamic import DynamicClient
from ocp_resources.namespace import Namespace
from ocp_resources.user_defined_network import Layer2UserDefinedNetwork
Comment thread
azhivovk marked this conversation as resolved.

from libs.net.ip import filter_link_local_addresses
from libs.net.traffic_generator import TcpServer, VMTcpClient, client_server_active_connection
from libs.net.udn import UDN_BINDING_DEFAULT_PLUGIN_NAME
from libs.net.vmspec import lookup_iface_status
from libs.vm.affinity import new_node_affinity
from libs.vm.vm import BaseVirtualMachine
from tests.network.libs.nodes import RHCOS9_WORKER_LABEL
from tests.network.libs.vm_factory import udn_vm

_UDN_PRIMARY_IFACE_NAME = "udn-primary"


@pytest.fixture(scope="class")
def udn_server_vm(
admin_client: DynamicClient,
udn_namespace: Namespace,
namespaced_layer2_user_defined_network: Layer2UserDefinedNetwork,
) -> Generator[BaseVirtualMachine]:
with udn_vm(
namespace_name=udn_namespace.name,
name="server-vm",
client=admin_client,
binding=UDN_BINDING_DEFAULT_PLUGIN_NAME,
affinity=new_node_affinity(key=RHCOS9_WORKER_LABEL, exists=True),
) as vm:
vm.start(wait=True)
vm.wait_for_agent_connected()
lookup_iface_status(
vm=vm,
iface_name=_UDN_PRIMARY_IFACE_NAME,
predicate=lambda iface: (
"guest-agent" in iface["infoSource"]
Comment thread
azhivovk marked this conversation as resolved.
and bool(filter_link_local_addresses(ip_addresses=iface.get("ipAddresses", [])))
),
)
yield vm


@pytest.fixture(scope="class")
def udn_client_vm(
admin_client: DynamicClient,
udn_namespace: Namespace,
namespaced_layer2_user_defined_network: Layer2UserDefinedNetwork,
) -> Generator[BaseVirtualMachine]:
with udn_vm(
namespace_name=udn_namespace.name,
name="client-vm",
client=admin_client,
binding=UDN_BINDING_DEFAULT_PLUGIN_NAME,
affinity=new_node_affinity(key=RHCOS9_WORKER_LABEL, exists=True),
) as vm:
vm.start(wait=True)
vm.wait_for_agent_connected()
lookup_iface_status(
vm=vm,
iface_name=_UDN_PRIMARY_IFACE_NAME,
predicate=lambda iface: (
"guest-agent" in iface["infoSource"]
and bool(filter_link_local_addresses(ip_addresses=iface.get("ipAddresses", [])))
),
)
yield vm


@pytest.fixture(scope="class")
def udn_active_tcp_connection(
udn_client_vm: BaseVirtualMachine,
udn_server_vm: BaseVirtualMachine,
) -> Generator[tuple[VMTcpClient, TcpServer]]:
with client_server_active_connection(
client_vm=udn_client_vm,
server_vm=udn_server_vm,
spec_logical_network=_UDN_PRIMARY_IFACE_NAME,
) as connection:
yield connection
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@

import pytest

__test__ = False
from libs.net.traffic_generator import is_tcp_connection
from libs.vm.affinity import new_node_affinity
from tests.network.libs.nodes import RHCOS9_WORKER_LABEL
from utilities.virt import migrate_vm_and_verify


@pytest.mark.mixed_os_nodes
@pytest.mark.ipv4
Comment thread
azhivovk marked this conversation as resolved.
@pytest.mark.incremental
class TestConnectivity:
"""
Expand All @@ -23,7 +28,12 @@ class TestConnectivity:
"""

@pytest.mark.polarion("CNV-15952")
def test_connectivity_preserved_during_server_migration_to_rhcos10(self):
def test_connectivity_preserved_during_server_migration_to_rhcos10(
self,
admin_client,
udn_server_vm,
udn_active_tcp_connection,
):
"""
Test that an active TCP connection over a primary UDN
is preserved when the server VM migrates from an RHCOS 9 node to an RHCOS 10 node.
Expand All @@ -39,9 +49,20 @@ def test_connectivity_preserved_during_server_migration_to_rhcos10(self):
Expected:
- The active TCP connection from the client VM to the server VM is preserved during the migration
"""
udn_server_vm.set_template_affinity(affinity=new_node_affinity(key=RHCOS9_WORKER_LABEL, exists=False))
migrate_vm_and_verify(vm=udn_server_vm, client=admin_client)
client, server = udn_active_tcp_connection
assert is_tcp_connection(server=server, client=client), (
f"TCP connection lost after migrating {udn_server_vm.name} to RHCOS 10 node"
)

@pytest.mark.polarion("CNV-15965")
def test_connectivity_preserved_during_server_migration_to_rhcos9(self):
def test_connectivity_preserved_during_server_migration_to_rhcos9(
self,
admin_client,
udn_server_vm,
udn_active_tcp_connection,
):
"""
Test that an active TCP connection over a primary UDN
is preserved when the server VM migrates from an RHCOS 10 node to an RHCOS 9 node.
Expand All @@ -57,3 +78,9 @@ def test_connectivity_preserved_during_server_migration_to_rhcos9(self):
Expected:
- The active TCP connection from the client VM to the server VM is preserved during the migration
"""
udn_server_vm.set_template_affinity(affinity=new_node_affinity(key=RHCOS9_WORKER_LABEL, exists=True))
migrate_vm_and_verify(vm=udn_server_vm, client=admin_client)
client, server = udn_active_tcp_connection
assert is_tcp_connection(server=server, client=client), (
f"TCP connection lost after migrating {udn_server_vm.name} back to RHCOS 9 node"
)