diff --git a/tests/uitests/data/keyfile/confirm-all.ini b/tests/uitests/data/keyfile/confirm-all.ini new file mode 100644 index 00000000..192e555e --- /dev/null +++ b/tests/uitests/data/keyfile/confirm-all.ini @@ -0,0 +1,18 @@ +[org/virt-manager/virt-manager/vmlist-fields] +disk-usage=false +network-traffic=false + +[org/virt-manager/virt-manager/connections] +uris=[] +autoconnect=[] + +[org/virt-manager/virt-manager/new-vm] +graphics-type='system' + +[org/virt-manager/virt-manager/confirm] +poweroff=true +pause=true + +[org/virt-manager/virt-manager] +manager-window-width=550 +manager-window-height=550 diff --git a/tests/uitests/test_manager.py b/tests/uitests/test_manager.py index 5746053a..d961ef9c 100644 --- a/tests/uitests/test_manager.py +++ b/tests/uitests/test_manager.py @@ -62,6 +62,105 @@ class Manager(uiutils.UITestCase): self._testVMLifecycle() + def testVMLifecycleExtra(self): + """ + Test vmmenu lifecycle options + """ + self.app.open(keyfile="confirm-all.ini") + manager = self.app.topwin + + def confirm_is_running(): + run = manager.find("Run", "push button") + uiutils.check(lambda: not run.sensitive) + + def confirm_is_shutdown(): + shutdown = manager.find("Shut Down", "push button") + uiutils.check(lambda: not shutdown.sensitive) + + def confirm_is_paused(): + pause = manager.find("Pause", "toggle button") + uiutils.check(lambda: pause.checked) + + def confirm_not_paused(): + pause = manager.find("Pause", "toggle button") + uiutils.check(lambda: not pause.checked) + + def test_action(action, shutdown=True, confirm=True): + def _select(): + cell = manager.find("test-many-devices", "table cell") + cell.click(button=3) + menu = self.app.root.find("vm-action-menu") + uiutils.check(lambda: menu.onscreen) + if shutdown: + smenu = menu.find("Shut Down", "menu") + smenu.click() + uiutils.check(lambda: smenu.onscreen) + item = smenu.find(action, "menu item") + else: + item = menu.find(action, "menu item") + uiutils.check(lambda: item.onscreen) + item.click() + + _select() + if confirm: + self._click_alert_button("Are you sure", "No") + _select() + self._click_alert_button("Are you sure", "Yes") + + + test_action("Force Reset") + confirm_is_running() + test_action("Reboot") + confirm_is_running() + test_action("Shut Down") + confirm_is_shutdown() + test_action("Run", shutdown=False, confirm=False) + confirm_is_running() + test_action("Force Off") + confirm_is_shutdown() + test_action("Run", shutdown=False, confirm=False) + confirm_is_running() + test_action("Pause", shutdown=False) + confirm_is_paused() + test_action("Resume", shutdown=False, confirm=False) + confirm_not_paused() + test_action("Save") + confirm_is_shutdown() + test_action("Restore", shutdown=False, confirm=False) + confirm_is_running() + + def testManagedManagedSaveCornerCases(self): + """ + Test managed save special behavior + """ + self.app.open(extra_opts=["--test-options=test-managed-save"]) + + manager = self.app.topwin + run = manager.find("Run", "push button") + smenu = manager.find("Menu", "toggle button") + save = manager.find("Save", "menu item") + + c = manager.find("test-many-devices", "table cell") + c.click() + + # Save it, attempt a cancel operation + smenu.click() + save.click() + progwin = self.app.root.find("Saving Virtual Machine", "frame") + # Attempt cancel which will fail, then find the error message + progwin.find("Cancel", "push button").click() + progwin.find("Error cancelling save job") + uiutils.check(lambda: not progwin.showing, timeout=5) + uiutils.check(lambda: run.sensitive) + + # Restore will fail and offer to remove managed save + run.click() + self._click_alert_button("remove the saved state", "No") + uiutils.check(lambda: run.sensitive) + run.click() + self._click_alert_button("remove the saved state", "Yes") + uiutils.check(lambda: not run.sensitive) + def testManagerColumns(self): # Enable all stat options # Need to expand the window size so all columns are onscreen diff --git a/virtManager/lib/testmock.py b/virtManager/lib/testmock.py index 127e27c4..4e56ee5d 100644 --- a/virtManager/lib/testmock.py +++ b/virtManager/lib/testmock.py @@ -37,6 +37,9 @@ class CLITestOptionsClass: * config-libguestfs: Override the first-run default of disabling libguestfs support, so it is enabled + + * test-managed-save: Triggers a couple conditions for testing + managed save issues """ def __init__(self, test_options_str, test_first_run): optset = set() @@ -68,6 +71,7 @@ class CLITestOptionsClass: self.gsettings_keyfile = _get_value("gsettings-keyfile") self.break_setfacl = _get("break-setfacl") self.config_libguestfs = _get("config-libguestfs") + self.test_managed_save = _get("test-managed-save") if optset: # pragma: no cover raise RuntimeError("Unknown --test-options keys: %s" % optset) diff --git a/virtManager/object/domain.py b/virtManager/object/domain.py index 3a3d510b..727aacd1 100644 --- a/virtManager/object/domain.py +++ b/virtManager/object/domain.py @@ -1318,9 +1318,12 @@ class vmmDomain(vmmLibvirtObject): @vmmLibvirtObject.lifecycle_action def startup(self): - sync_time = self.has_managed_save() + has_managed = self.has_managed_save() + if has_managed and self.config.CLITestOptions.test_managed_save: + raise RuntimeError("fake error for managed save") + self._backend.create() - if sync_time: + if has_managed: self._async_set_time() @vmmLibvirtObject.lifecycle_action @@ -1365,6 +1368,8 @@ class vmmDomain(vmmLibvirtObject): if meter: start_job_progress_thread(self, meter, _("Saving domain to disk")) + if self.config.CLITestOptions.test_managed_save: + time.sleep(3) self._backend.managedSave(0) def has_managed_save(self): diff --git a/virtManager/vmmenu.py b/virtManager/vmmenu.py index 5d953fb9..12eaa588 100644 --- a/virtManager/vmmenu.py +++ b/virtManager/vmmenu.py @@ -69,6 +69,7 @@ class VMShutdownMenu(_VMMenu): self._add_action(_("Sa_ve"), "save", VMActionUI.save, iconname=Gtk.STOCK_SAVE) + self.get_accessible().set_name("vmm-shutdown-menu") self.show_all() def update_widget_states(self, vm): @@ -85,13 +86,6 @@ class VMShutdownMenu(_VMMenu): if name in statemap: child.set_sensitive(statemap[name]) - if name == "reset": - child.set_tooltip_text(None) - if vm and not vm.conn.support.conn_domain_reset(): - child.set_tooltip_text(_("Hypervisor does not support " - "domain reset.")) - child.set_sensitive(False) - class VMActionMenu(_VMMenu): """ @@ -120,6 +114,7 @@ class VMActionMenu(_VMMenu): self._add_action(Gtk.STOCK_OPEN, "show", VMActionUI.show, iconname=None) + self.get_accessible().set_name("vm-action-menu") self.show_all() def update_widget_states(self, vm): @@ -161,7 +156,7 @@ class VMActionUI(object): def save_cancel(asyncjob, vm): log.debug("Cancelling save job") if not vm: - return + return # pragma: no cover try: vm.abort_job() @@ -170,8 +165,7 @@ class VMActionUI(object): asyncjob.show_warning(_("Error cancelling save job: %s") % str(e)) return - asyncjob.job_canceled = True - return + asyncjob.job_canceled = True # pragma: no cover @staticmethod def save(src, vm): @@ -187,7 +181,7 @@ class VMActionUI(object): def cb(asyncjob): vm.save(meter=asyncjob.get_meter()) def finish_cb(error, details): - if error is not None: + if error is not None: # pragma: no cover error = _("Error saving domain: %s") % error src.err.show_err(error, details=details) @@ -255,7 +249,7 @@ class VMActionUI(object): try: vm.remove_saved_image() VMActionUI.run(src, vm) - except Exception as e: + except Exception as e: # pragma: no cover src.err.show_err(_("Error removing domain state: %s") % str(e)) diff --git a/virtinst/support.py b/virtinst/support.py index d7474ab7..e3bb7c3f 100644 --- a/virtinst/support.py +++ b/virtinst/support.py @@ -254,7 +254,6 @@ class SupportCache: conn_domain_capabilities = _make( function="virConnect.getDomainCapabilities", run_args=(None, None, None, None)) - conn_domain_reset = _make(version="0.9.7", hv_version={"qemu": 0}) conn_vmport = _make( version="1.2.16", hv_version={"qemu": "2.2.0", "test": 0}) conn_mem_stats_period = _make(