From 3035b431e739b4797cf88304083fdfdab6f76ebc Mon Sep 17 00:00:00 2001 From: Asia Khromov Date: Thu, 30 Apr 2026 16:34:39 +0300 Subject: [PATCH] net, hotplug, sriov: Refactor setup and test steps test_connectivity_of_hot_plugged_sriov_interface is failing: VMInterfaceStatusNotFoundError: Network interface named sriov-hot-plug-test-network was not found in VM sriov-hot-plug-vm1 And VM1 must-gather logs are missing due to early teardown, which makes it difficult to debug and understand the root cause of the failure. VM1 is torndown by exit of Resource class (which VirtualMachineForTests inherits from). Context managers unwind as the exception propagates through the stack, before any outer exception handler (pytest's hook) can see it. Currently the same fixture creates the VM (via with VirtualMachineForTests(...)) and performs the hot-plug. When hot-plug fails, Python's exception propagation triggers VirtualMachineForTests.__exit__ (inherited from Resource), which deletes the VM before the exception reaches pytest's pytest_exception_interact hook. As a result, must-gather runs after the VM is already deleted and cannot capture its state. The fix is to create fixtures for VM creation and move SR-IOV interface hotplug to test- then must-gather runs right after setup/test error. Signed-off-by: Asia Khromov Assisted-by: Claude Sonnet 4.6 --- tests/network/l2_bridge/libl2bridge.py | 22 -------- .../l2_bridge/test_bridge_nic_hot_plug.py | 53 ++++++++++--------- 2 files changed, 28 insertions(+), 47 deletions(-) diff --git a/tests/network/l2_bridge/libl2bridge.py b/tests/network/l2_bridge/libl2bridge.py index 839e08519c..a940fb4dc0 100644 --- a/tests/network/l2_bridge/libl2bridge.py +++ b/tests/network/l2_bridge/libl2bridge.py @@ -312,28 +312,6 @@ def get_primary_and_hot_plugged_mac_addresses(vm, hot_plugged_interface): ] -def create_vm_with_hot_plugged_sriov_interface( - namespace_name, - vm_name, - sriov_network_for_hot_plug, - ipv4_address, - client, -): - with create_vm_for_hot_plug( - namespace_name=namespace_name, - vm_name=vm_name, - client=client, - ) as vm: - hot_plug_interface_and_set_address( - vm=vm, - hot_plugged_interface_name=sriov_network_for_hot_plug.name, - net_attach_def_name=f"{namespace_name}/{sriov_network_for_hot_plug.name}", - ipv4_address=ipv4_address, - sriov=True, - ) - yield vm - - def wait_for_no_packet_loss_after_connection(src_vm, dst_ip, interface=None): sleep_count_value = 10 diff --git a/tests/network/l2_bridge/test_bridge_nic_hot_plug.py b/tests/network/l2_bridge/test_bridge_nic_hot_plug.py index 69f95653f9..7dd743e53f 100644 --- a/tests/network/l2_bridge/test_bridge_nic_hot_plug.py +++ b/tests/network/l2_bridge/test_bridge_nic_hot_plug.py @@ -9,7 +9,6 @@ check_mac_released, create_bridge_interface_for_hot_plug, create_vm_for_hot_plug, - create_vm_with_hot_plugged_sriov_interface, create_vm_with_secondary_interface_on_setup, get_kubemacpool_controller_log, get_primary_and_hot_plugged_mac_addresses, @@ -395,35 +394,23 @@ def hot_unplug_secondary_interface_from_setup( @pytest.fixture() -def vm1_with_hot_plugged_sriov_interface( - namespace, - unprivileged_client, - sriov_network_for_hot_plug, - index_number, -): - yield from create_vm_with_hot_plugged_sriov_interface( +def sriov_hot_plug_vm1(namespace, unprivileged_client): + with create_vm_for_hot_plug( namespace_name=namespace.name, vm_name=f"{SRIOV}-{HOT_PLUG_STR}-vm1", - sriov_network_for_hot_plug=sriov_network_for_hot_plug, - ipv4_address=random_ipv4_address(net_seed=0, host_address=next(index_number)), client=unprivileged_client, - ) + ) as vm: + yield vm @pytest.fixture() -def vm2_with_hot_plugged_sriov_interface( - namespace, - unprivileged_client, - sriov_network_for_hot_plug, - index_number, -): - yield from create_vm_with_hot_plugged_sriov_interface( +def sriov_hot_plug_vm2(namespace, unprivileged_client): + with create_vm_for_hot_plug( namespace_name=namespace.name, vm_name=f"{SRIOV}-{HOT_PLUG_STR}-vm2", - sriov_network_for_hot_plug=sriov_network_for_hot_plug, - ipv4_address=random_ipv4_address(net_seed=0, host_address=next(index_number)), client=unprivileged_client, - ) + ) as vm: + yield vm @pytest.fixture(scope="module") @@ -584,14 +571,30 @@ def test_mac_of_hot_plugged_interface_returned_to_kubemacpool_after_vm_delete( @pytest.mark.polarion("CNV-10647") def test_connectivity_of_hot_plugged_sriov_interface( self, - vm1_with_hot_plugged_sriov_interface, - vm2_with_hot_plugged_sriov_interface, + sriov_hot_plug_vm1, + sriov_hot_plug_vm2, sriov_network_for_hot_plug, + namespace, + index_number, ): + hot_plug_interface_and_set_address( + vm=sriov_hot_plug_vm1, + hot_plugged_interface_name=sriov_network_for_hot_plug.name, + net_attach_def_name=f"{namespace.name}/{sriov_network_for_hot_plug.name}", + ipv4_address=random_ipv4_address(net_seed=0, host_address=next(index_number)), + sriov=True, + ) + hot_plug_interface_and_set_address( + vm=sriov_hot_plug_vm2, + hot_plugged_interface_name=sriov_network_for_hot_plug.name, + net_attach_def_name=f"{namespace.name}/{sriov_network_for_hot_plug.name}", + ipv4_address=random_ipv4_address(net_seed=0, host_address=next(index_number)), + sriov=True, + ) assert_ping_successful( - src_vm=vm1_with_hot_plugged_sriov_interface, + src_vm=sriov_hot_plug_vm1, dst_ip=lookup_iface_status_ip( - vm=vm2_with_hot_plugged_sriov_interface, + vm=sriov_hot_plug_vm2, iface_name=sriov_network_for_hot_plug.name, ip_family=4, ),