From c93c21b600c496fa3730b5f6f356dcd16d5ec728 Mon Sep 17 00:00:00 2001 From: mkwasile Date: Wed, 8 Jul 2026 08:19:52 +0200 Subject: [PATCH] fix: delegate VM RPyC readiness to RPyCConnection retry mechanism fix: Add retry_timeout and retry_time parameters to create_vm(), forwarded directly to RPyCConnection to handle connection retries natively. Signed-off-by: mwasile --- mfd_hyperv/hypervisor.py | 11 +++++- tests/unit/test_mfd_hyperv/test_hypervisor.py | 36 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mfd_hyperv/hypervisor.py b/mfd_hyperv/hypervisor.py index 2b688d8..270760e 100644 --- a/mfd_hyperv/hypervisor.py +++ b/mfd_hyperv/hypervisor.py @@ -85,6 +85,8 @@ def create_vm( owner: Optional[NetworkAdapterOwner] = None, hyperv: "HyperV" = None, connection_timeout: int = 3600, + retry_timeout: int = 60, + retry_time: int = 5, dynamic_mng_ip: bool = False, ) -> VM: """Create a new VM using the specified vm_params. @@ -93,6 +95,8 @@ def create_vm( :param owner: SUT host that will host new Vm :param hyperv: Hyperv object that will be used by Vm instance :param connection_timeout: timeout of RPyCConnection to VM + :param retry_timeout: total seconds RPyCConnection will retry on failure + :param retry_time: seconds between each RPyCConnection retry attempt :param dynamic_mng_ip: To enable or disable dynamic mng ip allocation """ commands = [ @@ -121,7 +125,12 @@ def create_vm( if dynamic_mng_ip: vm_params.mng_ip = mng_ip - vm_connection = RPyCConnection(ip=vm_params.mng_ip, connection_timeout=connection_timeout) + vm_connection = RPyCConnection( + ip=vm_params.mng_ip, + connection_timeout=connection_timeout, + retry_timeout=retry_timeout, + retry_time=retry_time, + ) vm = VM(vm_connection, vm_params, owner, hyperv, connection_timeout) self.vms.append(vm) diff --git a/tests/unit/test_mfd_hyperv/test_hypervisor.py b/tests/unit/test_mfd_hyperv/test_hypervisor.py index 6a54537..29bd057 100644 --- a/tests/unit/test_mfd_hyperv/test_hypervisor.py +++ b/tests/unit/test_mfd_hyperv/test_hypervisor.py @@ -853,3 +853,39 @@ def testget_file_size(self, hypervisor, mocker): hypervisor._connection.execute_powershell.assert_called_once_with( f"(Get-Item -Path {path}).Length", custom_exception=HyperVExecutionException ) + + def test_create_vm_custom_retry_params(self, mocker, hypervisor): + """Custom retry_timeout and retry_time are forwarded to RPyCConnection.""" + vm_params = VMParams( + name="vm_name", + cpu_count=4, + hw_threads_per_core=0, + memory=4096, + generation=2, + vm_dir_path="path", + diff_disk_path="diff_disk_path", + mng_interface_name="mng", + mng_mac_address=MACAddress("00:00:00:00:00:00"), + mng_ip="1.1.1.1", + vswitch_name="vswitch", + ) + output = """ + VMName : Base_W19_VM001 + IPAddresses : {10.91.218.16, fe80::6994:9bd4:d0aa:ff4d} + MacAddress : 525A005BDA10 + """ + hypervisor._connection.execute_powershell.return_value = ConnectionCompletedProcess( + return_code=0, args="command", stdout=output, stderr="stderr" + ) + mocker.patch("mfd_hyperv.hypervisor.HypervHypervisor.start_vm", return_value=None) + mock_rpyc = mocker.patch("mfd_hyperv.hypervisor.RPyCConnection", autospec=True) + mocker.patch("mfd_hyperv.hypervisor.VM", autospec=True) + + hypervisor.create_vm(vm_params, retry_timeout=120, retry_time=10) + + mock_rpyc.assert_called_once_with( + ip=vm_params.mng_ip, + connection_timeout=3600, + retry_timeout=120, + retry_time=10, + )