diff --git a/virtManager/details.py b/virtManager/details.py index bd4fcbcfb..eeeea4b96 100644 --- a/virtManager/details.py +++ b/virtManager/details.py @@ -339,14 +339,6 @@ def _label_for_os_type(os_type): class vmmDetails(vmmGObjectUI): __gsignals__ = { - "action-save-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-destroy-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-suspend-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-resume-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-run-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-shutdown-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-reset-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-reboot-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []), "action-view-manager": (GObject.SignalFlags.RUN_FIRST, None, []), "action-migrate-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), @@ -470,16 +462,6 @@ class vmmDetails(vmmGObjectUI): "on_details_cancel_customize_clicked": self._customize_cancel_clicked, "on_details_menu_virtual_manager_activate": self.control_vm_menu, - "on_details_menu_run_activate": self.control_vm_run, - "on_details_menu_poweroff_activate": self.control_vm_shutdown, - "on_details_menu_reboot_activate": self.control_vm_reboot, - "on_details_menu_save_activate": self.control_vm_save, - "on_details_menu_reset_activate": self.control_vm_reset, - "on_details_menu_destroy_activate": self.control_vm_destroy, - "on_details_menu_pause_activate": self.control_vm_pause, - "on_details_menu_clone_activate": self.control_vm_clone, - "on_details_menu_migrate_activate": self.control_vm_migrate, - "on_details_menu_delete_activate": self.control_vm_delete, "on_details_menu_screenshot_activate": self.control_vm_screenshot, "on_details_menu_usb_redirection": self.control_vm_usb_redirection, "on_details_menu_view_toolbar_activate": self.toggle_toolbar, @@ -1433,13 +1415,9 @@ class vmmDetails(vmmGObjectUI): self.set_pause_state(not do_pause) if do_pause: - self.emit("action-suspend-domain", - self.vm.conn.get_uri(), - self.vm.get_connkey()) + vmmenu.VMActionUI.suspend(self, self.vm) else: - self.emit("action-resume-domain", - self.vm.conn.get_uri(), - self.vm.get_connkey()) + vmmenu.VMActionUI.resume(self, self.vm) def control_vm_menu(self, src_ignore): can_usb = bool(self.console.details_viewer_has_usb_redirection() and @@ -1449,40 +1427,10 @@ class vmmDetails(vmmGObjectUI): def control_vm_run(self, src_ignore): if self.has_unapplied_changes(self.get_hw_row()): return - self.emit("action-run-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) + vmmenu.VMActionUI.run(self, self.vm) def control_vm_shutdown(self, src_ignore): - self.emit("action-shutdown-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) - - def control_vm_reboot(self, src_ignore): - self.emit("action-reboot-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) - - def control_vm_save(self, src_ignore): - self.emit("action-save-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) - - def control_vm_reset(self, src_ignore): - self.emit("action-reset-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) - - def control_vm_destroy(self, src_ignore): - self.emit("action-destroy-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) - - def control_vm_clone(self, src_ignore): - self.emit("action-clone-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) - - def control_vm_migrate(self, src_ignore): - self.emit("action-migrate-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) - - def control_vm_delete(self, src_ignore): - self.emit("action-delete-domain", - self.vm.conn.get_uri(), self.vm.get_connkey()) + vmmenu.VMActionUI.shutdown(self, self.vm) def control_vm_screenshot(self, src): ignore = src diff --git a/virtManager/engine.py b/virtManager/engine.py index acb93746b..e05d4b128 100644 --- a/virtManager/engine.py +++ b/virtManager/engine.py @@ -39,7 +39,6 @@ from .preferences import vmmPreferences from .manager import vmmManager from .migrate import vmmMigrateDialog from .details import vmmDetails -from .asyncjob import vmmAsyncJob from .create import vmmCreate from .host import vmmHost from .error import vmmErrorDialog @@ -176,14 +175,6 @@ class vmmEngine(vmmGObject): def _init_systray(self): self._systray = vmmSystray() self._systray.connect("action-toggle-manager", self._do_toggle_manager) - self._systray.connect("action-suspend-domain", self._do_suspend_domain) - self._systray.connect("action-resume-domain", self._do_resume_domain) - self._systray.connect("action-run-domain", self._do_run_domain) - self._systray.connect("action-shutdown-domain", self._do_shutdown_domain) - self._systray.connect("action-reboot-domain", self._do_reboot_domain) - self._systray.connect("action-destroy-domain", self._do_destroy_domain) - self._systray.connect("action-reset-domain", self._do_reset_domain) - self._systray.connect("action-save-domain", self._do_save_domain) self._systray.connect("action-show-domain", self._do_show_vm) self._systray.connect("action-migrate-domain", self._do_show_migrate) self._systray.connect("action-delete-domain", self._do_delete_domain) @@ -781,14 +772,6 @@ class vmmEngine(vmmGObject): conn = self._lookup_conn(uri) obj = vmmDetails(conn.get_vm(connkey)) - obj.connect("action-save-domain", self._do_save_domain) - obj.connect("action-destroy-domain", self._do_destroy_domain) - obj.connect("action-reset-domain", self._do_reset_domain) - obj.connect("action-suspend-domain", self._do_suspend_domain) - obj.connect("action-resume-domain", self._do_resume_domain) - obj.connect("action-run-domain", self._do_run_domain) - obj.connect("action-shutdown-domain", self._do_shutdown_domain) - obj.connect("action-reboot-domain", self._do_reboot_domain) obj.connect("action-exit-app", self.exit_app) obj.connect("action-view-manager", self._do_show_manager) obj.connect("action-migrate-domain", self._do_show_migrate) @@ -829,14 +812,6 @@ class vmmEngine(vmmGObject): return self.windowManager obj = vmmManager() - obj.connect("action-suspend-domain", self._do_suspend_domain) - obj.connect("action-resume-domain", self._do_resume_domain) - obj.connect("action-run-domain", self._do_run_domain) - obj.connect("action-shutdown-domain", self._do_shutdown_domain) - obj.connect("action-reboot-domain", self._do_reboot_domain) - obj.connect("action-destroy-domain", self._do_destroy_domain) - obj.connect("action-reset-domain", self._do_reset_domain) - obj.connect("action-save-domain", self._do_save_domain) obj.connect("action-migrate-domain", self._do_show_migrate) obj.connect("action-delete-domain", self._do_delete_domain) obj.connect("action-clone-domain", self._do_show_clone) @@ -1059,178 +1034,6 @@ class vmmEngine(vmmGObject): logging.debug("Error handling cli command", exc_info=True) self._exit_app_if_no_windows() - - ####################################### - # Domain actions run/destroy/save ... # - ####################################### - - def _do_save_domain(self, src, uri, connkey): - conn = self._lookup_conn(uri) - vm = conn.get_vm(connkey) - - if not src.err.chkbox_helper(self.config.get_confirm_poweroff, - self.config.set_confirm_poweroff, - text1=_("Are you sure you want to save '%s'?") % vm.get_name()): - return - - _cancel_cb = None - if vm.getjobinfo_supported: - _cancel_cb = (self._save_cancel, vm) - - def cb(asyncjob): - vm.save(meter=asyncjob.get_meter()) - def finish_cb(error, details): - if error is not None: - error = _("Error saving domain: %s") % error - src.err.show_err(error, details=details) - - progWin = vmmAsyncJob(cb, [], - finish_cb, [], - _("Saving Virtual Machine"), - _("Saving virtual machine memory to disk "), - src.topwin, cancel_cb=_cancel_cb) - progWin.run() - - def _save_cancel(self, asyncjob, vm): - logging.debug("Cancelling save job") - if not vm: - return - - try: - vm.abort_job() - except Exception as e: - logging.exception("Error cancelling save job") - asyncjob.show_warning(_("Error cancelling save job: %s") % str(e)) - return - - asyncjob.job_canceled = True - return - - def _do_destroy_domain(self, src, uri, connkey): - conn = self._lookup_conn(uri) - vm = conn.get_vm(connkey) - - if not src.err.chkbox_helper( - self.config.get_confirm_forcepoweroff, - self.config.set_confirm_forcepoweroff, - text1=_("Are you sure you want to force poweroff '%s'?" % - vm.get_name()), - text2=_("This will immediately poweroff the VM without " - "shutting down the OS and may cause data loss.")): - return - - logging.debug("Destroying vm '%s'", vm.get_name()) - vmmAsyncJob.simple_async_noshow(vm.destroy, [], src, - _("Error shutting down domain")) - - def _do_suspend_domain(self, src, uri, connkey): - conn = self._lookup_conn(uri) - vm = conn.get_vm(connkey) - - if not src.err.chkbox_helper(self.config.get_confirm_pause, - self.config.set_confirm_pause, - text1=_("Are you sure you want to pause '%s'?" % - vm.get_name())): - return - - logging.debug("Pausing vm '%s'", vm.get_name()) - vmmAsyncJob.simple_async_noshow(vm.suspend, [], src, - _("Error pausing domain")) - - def _do_resume_domain(self, src, uri, connkey): - conn = self._lookup_conn(uri) - vm = conn.get_vm(connkey) - - logging.debug("Unpausing vm '%s'", vm.get_name()) - vmmAsyncJob.simple_async_noshow(vm.resume, [], src, - _("Error unpausing domain")) - - def _do_run_domain(self, src, uri, connkey): - conn = self._lookup_conn(uri) - vm = conn.get_vm(connkey) - - logging.debug("Starting vm '%s'", vm.get_name()) - - if vm.has_managed_save(): - def errorcb(error, details): - # This is run from the main thread - res = src.err.show_err( - _("Error restoring domain") + ": " + error, - details=details, - text2=_( - "The domain could not be restored. Would you like\n" - "to remove the saved state and perform a regular\n" - "start up?"), - dialog_type=Gtk.MessageType.WARNING, - buttons=Gtk.ButtonsType.YES_NO, - modal=True) - - if not res: - return - - try: - vm.remove_saved_image() - self._do_run_domain(src, uri, connkey) - except Exception as e: - src.err.show_err(_("Error removing domain state: %s") - % str(e)) - - # VM will be restored, which can take some time, so show progress - title = _("Restoring Virtual Machine") - text = _("Restoring virtual machine memory from disk") - vmmAsyncJob.simple_async(vm.startup, [], src, - title, text, "", errorcb=errorcb) - - else: - # Regular startup - errorintro = _("Error starting domain") - vmmAsyncJob.simple_async_noshow(vm.startup, [], src, errorintro) - - def _do_shutdown_domain(self, src, uri, connkey): - conn = self._lookup_conn(uri) - vm = conn.get_vm(connkey) - - if not src.err.chkbox_helper(self.config.get_confirm_poweroff, - self.config.set_confirm_poweroff, - text1=_("Are you sure you want to poweroff '%s'?" % - vm.get_name())): - return - - logging.debug("Shutting down vm '%s'", vm.get_name()) - vmmAsyncJob.simple_async_noshow(vm.shutdown, [], src, - _("Error shutting down domain")) - - def _do_reboot_domain(self, src, uri, connkey): - conn = self._lookup_conn(uri) - vm = conn.get_vm(connkey) - - if not src.err.chkbox_helper(self.config.get_confirm_poweroff, - self.config.set_confirm_poweroff, - text1=_("Are you sure you want to reboot '%s'?" % - vm.get_name())): - return - - logging.debug("Rebooting vm '%s'", vm.get_name()) - vmmAsyncJob.simple_async_noshow(vm.reboot, [], src, - _("Error rebooting domain")) - - def _do_reset_domain(self, src, uri, connkey): - conn = self._lookup_conn(uri) - vm = conn.get_vm(connkey) - - if not src.err.chkbox_helper( - self.config.get_confirm_forcepoweroff, - self.config.set_confirm_forcepoweroff, - text1=_("Are you sure you want to force reset '%s'?" % - vm.get_name()), - text2=_("This will immediately reset the VM without " - "shutting down the OS and may cause data loss.")): - return - - logging.debug("Resetting vm '%s'", vm.get_name()) - vmmAsyncJob.simple_async_noshow(vm.reset, [], src, - _("Error resetting domain")) - def _do_delete_domain(self, src, uri, connkey): conn = self._lookup_conn(uri) vm = conn.get_vm(connkey) diff --git a/virtManager/manager.py b/virtManager/manager.py index d38fc4e4b..d0a8a1ffd 100644 --- a/virtManager/manager.py +++ b/virtManager/manager.py @@ -96,14 +96,6 @@ class vmmManager(vmmGObjectUI): "action-show-host": (GObject.SignalFlags.RUN_FIRST, None, [str]), "action-show-preferences": (GObject.SignalFlags.RUN_FIRST, None, []), "action-show-create": (GObject.SignalFlags.RUN_FIRST, None, [str]), - "action-suspend-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-resume-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-run-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-shutdown-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-reset-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-reboot-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-destroy-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-save-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-migrate-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-delete-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-clone-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), @@ -534,34 +526,14 @@ class vmmManager(vmmGObjectUI): self.set_pause_state(not do_pause) if do_pause: - self.pause_vm(None) + vmmenu.VMActionUI.suspend(self, self.current_vm()) else: - self.resume_vm(None) + vmmenu.VMActionUI.resume(self, self.current_vm()) def start_vm(self, ignore): - vm = self.current_vm() - if vm is None: - return - self.emit("action-run-domain", vm.conn.get_uri(), vm.get_connkey()) - - def poweroff_vm(self, ignore): - vm = self.current_vm() - if vm is None: - return - self.emit("action-shutdown-domain", - vm.conn.get_uri(), vm.get_connkey()) - - def pause_vm(self, ignore): - vm = self.current_vm() - if vm is None: - return - self.emit("action-suspend-domain", vm.conn.get_uri(), vm.get_connkey()) - - def resume_vm(self, ignore): - vm = self.current_vm() - if vm is None: - return - self.emit("action-resume-domain", vm.conn.get_uri(), vm.get_connkey()) + vmmenu.VMActionUI.run(self, self.current_vm()) + def poweroff_vm(self, _src): + vmmenu.VMActionUI.shutdown(self, self.current_vm()) def close_conn(self, ignore): conn = self.current_conn() diff --git a/virtManager/systray.py b/virtManager/systray.py index 90e654567..efc381ee3 100644 --- a/virtManager/systray.py +++ b/virtManager/systray.py @@ -32,14 +32,6 @@ class vmmSystray(vmmGObject): __gsignals__ = { "action-toggle-manager": (GObject.SignalFlags.RUN_FIRST, None, []), "action-view-manager": (GObject.SignalFlags.RUN_FIRST, None, []), - "action-suspend-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-resume-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-run-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-shutdown-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-reset-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-reboot-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-destroy-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), - "action-save-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-migrate-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-delete-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-clone-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), diff --git a/virtManager/vmmenu.py b/virtManager/vmmenu.py index 153c85248..c86ed6d7a 100644 --- a/virtManager/vmmenu.py +++ b/virtManager/vmmenu.py @@ -18,8 +18,12 @@ # MA 02110-1301 USA. # +import logging + from gi.repository import Gtk +from .asyncjob import vmmAsyncJob + #################################################################### # Build toolbar shutdown button menu (manager and details toolbar) # @@ -34,8 +38,8 @@ class _VMMenu(Gtk.Menu): self._init_state() - def _add_action(self, label, signal, - iconname="system-shutdown", addcb=True): + def _add_action(self, label, widgetname, cb, + iconname="system-shutdown"): if label.startswith("gtk-"): item = Gtk.ImageMenuItem.new_from_stock(label, None) else: @@ -49,19 +53,17 @@ class _VMMenu(Gtk.Menu): Gtk.IconSize.MENU) item.set_image(icon) - item.vmm_widget_name = signal - if addcb: - item.connect("activate", self._action_cb) + item.vmm_widget_name = widgetname + if cb: + def _cb(_menuitem): + _vm = self._current_vm_cb() + if _vm: + return cb(self._parent, _vm) + item.connect("activate", _cb) + self.add(item) return item - def _action_cb(self, src): - vm = self._current_vm_cb() - if not vm: - return - self._parent.emit("action-%s-domain" % src.vmm_widget_name, - vm.conn.get_uri(), vm.get_connkey()) - def _init_state(self): raise NotImplementedError() def update_widget_states(self, vm): @@ -69,13 +71,17 @@ class _VMMenu(Gtk.Menu): class VMShutdownMenu(_VMMenu): + """ + Shutdown submenu for reboot, forceoff, reset, etc. + """ def _init_state(self): - self._add_action(_("_Reboot"), "reboot") - self._add_action(_("_Shut Down"), "shutdown") - self._add_action(_("F_orce Reset"), "reset") - self._add_action(_("_Force Off"), "destroy") + self._add_action(_("_Reboot"), "reboot", VMActionUI.reboot) + self._add_action(_("_Shut Down"), "shutdown", VMActionUI.shutdown) + self._add_action(_("F_orce Reset"), "reset", VMActionUI.reset) + self._add_action(_("_Force Off"), "destroy", VMActionUI.destroy) self.add(Gtk.SeparatorMenuItem()) - self._add_action(_("Sa_ve"), "save", iconname=Gtk.STOCK_SAVE) + self._add_action(_("Sa_ve"), "save", VMActionUI.save, + iconname=Gtk.STOCK_SAVE) self.show_all() @@ -84,8 +90,8 @@ class VMShutdownMenu(_VMMenu): "reboot": bool(vm and vm.is_stoppable()), "shutdown": bool(vm and vm.is_stoppable()), "reset": bool(vm and vm.is_stoppable()), - "save": bool(vm and vm.is_destroyable()), "destroy": bool(vm and vm.is_destroyable()), + "save": bool(vm and vm.is_destroyable()), } for child in self.get_children(): @@ -103,21 +109,37 @@ class VMShutdownMenu(_VMMenu): class VMActionMenu(_VMMenu): + """ + VM submenu for run, pause, shutdown, clone, etc + """ def _init_state(self): - self._add_action(_("_Run"), "run", Gtk.STOCK_MEDIA_PLAY) - self._add_action(_("_Pause"), "suspend", Gtk.STOCK_MEDIA_PAUSE) - self._add_action(_("R_esume"), "resume", Gtk.STOCK_MEDIA_PAUSE) - s = self._add_action(_("_Shut Down"), "shutdown", addcb=False) + self._add_action(_("_Run"), "run", VMActionUI.run, + iconname=Gtk.STOCK_MEDIA_PLAY) + self._add_action(_("_Pause"), "suspend", VMActionUI.suspend, + Gtk.STOCK_MEDIA_PAUSE) + self._add_action(_("R_esume"), "resume", VMActionUI.resume, + Gtk.STOCK_MEDIA_PAUSE) + s = self._add_action(_("_Shut Down"), "shutdown", None) s.set_submenu(VMShutdownMenu(self._parent, self._current_vm_cb)) + def _make_emit_cb(_name): + def _emit_cb(_src, _vm): + return _src.emit(_name, _vm.conn.get_uri(), _vm.get_name()) + return _emit_cb + self.add(Gtk.SeparatorMenuItem()) - self._add_action(_("Clone..."), "clone", None) - self._add_action(_("Migrate..."), "migrate", None) - self._add_action(_("_Delete"), "delete", Gtk.STOCK_DELETE) + self._add_action(_("Clone..."), "clone", + _make_emit_cb("action-clone-domain"), iconname=None) + self._add_action(_("Migrate..."), "migrate", + _make_emit_cb("action-migrate-domain"), iconname=None) + self._add_action(_("_Delete"), "delete", + _make_emit_cb("action-delete-domain"), + iconname=Gtk.STOCK_DELETE) if self._show_open: self.add(Gtk.SeparatorMenuItem()) - self._add_action(Gtk.STOCK_OPEN, "show", None) + self._add_action(Gtk.STOCK_OPEN, "show", + _make_emit_cb("action-show-domain"), iconname=None) self.show_all() @@ -148,3 +170,162 @@ class VMActionMenu(_VMMenu): for child in self.get_children(): if getattr(child, "vmm_widget_name", None) == "run": child.get_child().set_label(text) + + +class VMActionUI(object): + """ + Singleton object for handling VM actions, asking for confirmation, + showing errors/progress dialogs, etc. + """ + + @staticmethod + def save_cancel(asyncjob, vm): + logging.debug("Cancelling save job") + if not vm: + return + + try: + vm.abort_job() + except Exception as e: + logging.exception("Error cancelling save job") + asyncjob.show_warning(_("Error cancelling save job: %s") % str(e)) + return + + asyncjob.job_canceled = True + return + + @staticmethod + def save(src, vm): + if not src.err.chkbox_helper(src.config.get_confirm_poweroff, + src.config.set_confirm_poweroff, + text1=_("Are you sure you want to save '%s'?") % vm.get_name()): + return + + _cancel_cb = None + if vm.getjobinfo_supported: + _cancel_cb = (VMActionUI.save_cancel, vm) + + def cb(asyncjob): + vm.save(meter=asyncjob.get_meter()) + def finish_cb(error, details): + if error is not None: + error = _("Error saving domain: %s") % error + src.err.show_err(error, details=details) + + progWin = vmmAsyncJob(cb, [], + finish_cb, [], + _("Saving Virtual Machine"), + _("Saving virtual machine memory to disk "), + src.topwin, cancel_cb=_cancel_cb) + progWin.run() + + @staticmethod + def destroy(src, vm): + if not src.err.chkbox_helper( + src.config.get_confirm_forcepoweroff, + src.config.set_confirm_forcepoweroff, + text1=_("Are you sure you want to force poweroff '%s'?" % + vm.get_name()), + text2=_("This will immediately poweroff the VM without " + "shutting down the OS and may cause data loss.")): + return + + logging.debug("Destroying vm '%s'", vm.get_name()) + vmmAsyncJob.simple_async_noshow(vm.destroy, [], src, + _("Error shutting down domain")) + + @staticmethod + def suspend(src, vm): + if not src.err.chkbox_helper(src.config.get_confirm_pause, + src.config.set_confirm_pause, + text1=_("Are you sure you want to pause '%s'?" % + vm.get_name())): + return + + logging.debug("Pausing vm '%s'", vm.get_name()) + vmmAsyncJob.simple_async_noshow(vm.suspend, [], src, + _("Error pausing domain")) + + @staticmethod + def resume(src, vm): + logging.debug("Unpausing vm '%s'", vm.get_name()) + vmmAsyncJob.simple_async_noshow(vm.resume, [], src, + _("Error unpausing domain")) + + @staticmethod + def run(src, vm): + logging.debug("Starting vm '%s'", vm.get_name()) + + if vm.has_managed_save(): + def errorcb(error, details): + # This is run from the main thread + res = src.err.show_err( + _("Error restoring domain") + ": " + error, + details=details, + text2=_( + "The domain could not be restored. Would you like\n" + "to remove the saved state and perform a regular\n" + "start up?"), + dialog_type=Gtk.MessageType.WARNING, + buttons=Gtk.ButtonsType.YES_NO, + modal=True) + + if not res: + return + + try: + vm.remove_saved_image() + VMActionUI.run(src, vm) + except Exception as e: + src.err.show_err(_("Error removing domain state: %s") + % str(e)) + + # VM will be restored, which can take some time, so show progress + title = _("Restoring Virtual Machine") + text = _("Restoring virtual machine memory from disk") + vmmAsyncJob.simple_async(vm.startup, [], src, + title, text, "", errorcb=errorcb) + + else: + # Regular startup + errorintro = _("Error starting domain") + vmmAsyncJob.simple_async_noshow(vm.startup, [], src, errorintro) + + @staticmethod + def shutdown(src, vm): + if not src.err.chkbox_helper(src.config.get_confirm_poweroff, + src.config.set_confirm_poweroff, + text1=_("Are you sure you want to poweroff '%s'?" % + vm.get_name())): + return + + logging.debug("Shutting down vm '%s'", vm.get_name()) + vmmAsyncJob.simple_async_noshow(vm.shutdown, [], src, + _("Error shutting down domain")) + + @staticmethod + def reboot(src, vm): + if not src.err.chkbox_helper(src.config.get_confirm_poweroff, + src.config.set_confirm_poweroff, + text1=_("Are you sure you want to reboot '%s'?" % + vm.get_name())): + return + + logging.debug("Rebooting vm '%s'", vm.get_name()) + vmmAsyncJob.simple_async_noshow(vm.reboot, [], src, + _("Error rebooting domain")) + + @staticmethod + def reset(src, vm): + if not src.err.chkbox_helper( + src.config.get_confirm_forcepoweroff, + src.config.set_confirm_forcepoweroff, + text1=_("Are you sure you want to force reset '%s'?" % + vm.get_name()), + text2=_("This will immediately reset the VM without " + "shutting down the OS and may cause data loss.")): + return + + logging.debug("Resetting vm '%s'", vm.get_name()) + vmmAsyncJob.simple_async_noshow(vm.reset, [], src, + _("Error resetting domain"))