Skip to content

Commit 5901acd

Browse files
committed
vmupdate: wait only for PCI-assigned VM shutdown
1 parent 2111706 commit 5901acd

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

vmupdate/qube_connection.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,19 @@ def __exit__(self, exc_type, exc_val, exc_tb):
9696
if self.qube.is_running() and not self._initially_running:
9797
self.logger.info('Shutdown %s', self.qube.name)
9898
self.qube.shutdown()
99-
asyncio.run(wait_for_domain_shutdown([self.qube]))
99+
if self._has_assigned_pci_devices(self.qube):
100+
asyncio.run(wait_for_domain_shutdown([self.qube]))
100101

101102
self.__connected = False
102103

104+
@staticmethod
105+
def _has_assigned_pci_devices(vm) -> bool:
106+
"""Return True when VM has assigned PCI devices."""
107+
try:
108+
return any(vm.devices['pci'].get_assigned_devices())
109+
except Exception: # best effort check only
110+
return False
111+
103112
def transfer_agent(self, src_dir: str) -> ProcessResult:
104113
"""
105114
Copy a directory content to the workdir in the qube.

vmupdate/tests/test_qube_connection.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def test_wait_for_shutdown_when_vm_started_by_update(_arun, wait_shutdown):
2020
vm = Mock()
2121
vm.name = "hvm1"
2222
vm.is_running.side_effect = [False, True]
23+
vm.devices = {'pci': Mock()}
24+
vm.devices['pci'].get_assigned_devices.return_value = ["00_1f.2"]
2325
status_notifier = Mock()
2426
logger = Mock()
2527

@@ -35,10 +37,33 @@ def test_wait_for_shutdown_when_vm_started_by_update(_arun, wait_shutdown):
3537

3638
@patch("vmupdate.qube_connection.wait_for_domain_shutdown")
3739
@patch("vmupdate.qube_connection.asyncio.run")
38-
def test_do_not_shutdown_if_vm_was_already_running(_arun, wait_shutdown):
40+
def test_do_not_wait_for_shutdown_without_assigned_pci(_arun, wait_shutdown):
3941
vm = Mock()
4042
vm.name = "hvm2"
43+
vm.is_running.side_effect = [False, True]
44+
vm.devices = {'pci': Mock()}
45+
vm.devices['pci'].get_assigned_devices.return_value = []
46+
status_notifier = Mock()
47+
logger = Mock()
48+
49+
with QubeConnection(
50+
vm, "/tmp/qubes-update", cleanup=False, logger=logger,
51+
show_progress=False, status_notifier=status_notifier):
52+
pass
53+
54+
vm.shutdown.assert_called_once_with()
55+
wait_shutdown.assert_not_called()
56+
_arun.assert_not_called()
57+
58+
59+
@patch("vmupdate.qube_connection.wait_for_domain_shutdown")
60+
@patch("vmupdate.qube_connection.asyncio.run")
61+
def test_do_not_shutdown_if_vm_was_already_running(_arun, wait_shutdown):
62+
vm = Mock()
63+
vm.name = "hvm3"
4164
vm.is_running.return_value = True
65+
vm.devices = {'pci': Mock()}
66+
vm.devices['pci'].get_assigned_devices.return_value = ["00_1f.2"]
4267
status_notifier = Mock()
4368
logger = Mock()
4469

0 commit comments

Comments
 (0)