mirror of
https://github.com/virt-manager/virt-manager.git
synced 2024-12-23 17:34:21 +03:00
Improve save/restore UI
Make the save command a member of the 'Shutdown' menu, and place 'restore' out of the way in Host details -> File. Emphasis on the old 'restore' will be diminished once we support managed save.
This commit is contained in:
parent
6b41d53c12
commit
225f4d344a
@ -226,7 +226,7 @@ class vmmDetails(gobject.GObject):
|
||||
"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_domain,
|
||||
"on_details_menu_save_activate": self.control_vm_save,
|
||||
"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,
|
||||
@ -374,7 +374,8 @@ class vmmDetails(gobject.GObject):
|
||||
self.window.get_widget("control-shutdown"),
|
||||
self.control_vm_shutdown,
|
||||
self.control_vm_reboot,
|
||||
self.control_vm_destroy)
|
||||
self.control_vm_destroy,
|
||||
self.control_vm_save)
|
||||
|
||||
icon_name = self.config.get_shutdown_icon_name()
|
||||
for name in ["details-menu-shutdown",
|
||||
@ -917,7 +918,7 @@ class vmmDetails(gobject.GObject):
|
||||
def control_vm_console(self, src):
|
||||
self.emit("action-show-console", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
||||
|
||||
def control_vm_save_domain(self, src):
|
||||
def control_vm_save(self, src):
|
||||
self.emit("action-save-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
|
||||
|
||||
def control_vm_destroy(self, src):
|
||||
|
@ -471,6 +471,8 @@ class vmmEngine(gobject.GObject):
|
||||
self.refresh_console(uri, uuid)
|
||||
def _do_save_domain(self, src, uri, uuid):
|
||||
self.save_domain(src, uri, uuid)
|
||||
def _do_restore_domain(self, src, uri):
|
||||
self.restore_domain(src, uri)
|
||||
def _do_destroy_domain(self, src, uri, uuid):
|
||||
self.destroy_domain(src, uri, uuid)
|
||||
def _do_suspend_domain(self, src, uri, uuid):
|
||||
@ -520,6 +522,7 @@ class vmmEngine(gobject.GObject):
|
||||
manager.connect("action-show-help", self._do_show_help)
|
||||
manager.connect("action-exit-app", self._do_exit_app)
|
||||
manager.connect("action-view-manager", self._do_show_manager)
|
||||
manager.connect("action-restore-domain", self._do_restore_domain)
|
||||
self.connections[uri]["windowHost"] = manager
|
||||
self.connections[uri]["windowHost"].show()
|
||||
|
||||
@ -601,6 +604,7 @@ class vmmEngine(gobject.GObject):
|
||||
self.windowManager.connect("action-shutdown-domain", self._do_shutdown_domain)
|
||||
self.windowManager.connect("action-reboot-domain", self._do_reboot_domain)
|
||||
self.windowManager.connect("action-destroy-domain", self._do_destroy_domain)
|
||||
self.windowManager.connect("action-save-domain", self._do_save_domain)
|
||||
self.windowManager.connect("action-migrate-domain", self._do_migrate_domain)
|
||||
self.windowManager.connect("action-clone-domain", self._do_clone_domain)
|
||||
self.windowManager.connect("action-show-console", self._do_show_console)
|
||||
@ -752,6 +756,41 @@ class vmmEngine(gobject.GObject):
|
||||
except Exception, e:
|
||||
asyncjob.set_error(str(e), "".join(traceback.format_exc()))
|
||||
|
||||
def restore_domain(self, src, uri):
|
||||
conn = self._lookup_connection(uri)
|
||||
if conn.is_remote():
|
||||
self.err.val_err(_("Restoring virtual machines over remote "
|
||||
"connections is not yet supported"))
|
||||
return
|
||||
|
||||
path = util.browse_local(src.window.get_widget("vmm-manager"),
|
||||
_("Restore Virtual Machine"),
|
||||
self.config, conn,
|
||||
browse_reason=self.config.CONFIG_DIR_RESTORE)
|
||||
|
||||
if not path:
|
||||
return
|
||||
|
||||
progWin = vmmAsyncJob(self.config, self.restore_saved_callback,
|
||||
[path, conn], _("Restoring Virtual Machine"))
|
||||
progWin.run()
|
||||
error, details = progWin.get_error()
|
||||
|
||||
if error is not None:
|
||||
self.err.show_err(error, details,
|
||||
title=_("Error restoring domain"))
|
||||
|
||||
def restore_saved_callback(self, file_to_load, conn, asyncjob):
|
||||
try:
|
||||
newconn = util.dup_conn(self.config, conn,
|
||||
return_conn_class=True)
|
||||
newconn.restore(file_to_load)
|
||||
except Exception, e:
|
||||
err = (_("Error restoring domain '%s': %s") %
|
||||
(file_to_load, str(e)))
|
||||
details = "".join(traceback.format_exc())
|
||||
asyncjob.set_error(err, details)
|
||||
|
||||
def destroy_domain(self, src, uri, uuid):
|
||||
conn = self._lookup_connection(uri)
|
||||
vm = conn.get_vm(uuid)
|
||||
|
@ -48,6 +48,8 @@ class vmmHost(gobject.GObject):
|
||||
gobject.TYPE_NONE, []),
|
||||
"action-view-manager": (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, []),
|
||||
"action-restore-domain": (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, (str,)),
|
||||
}
|
||||
def __init__(self, config, conn, engine):
|
||||
self.__gobject_init__()
|
||||
@ -114,6 +116,7 @@ class vmmHost(gobject.GObject):
|
||||
"on_menu_file_close_activate": self.close,
|
||||
"on_vmm_host_delete_event": self.close,
|
||||
|
||||
"on_menu_restore_saved_activate": self.restore_domain,
|
||||
"on_menu_help_contents_activate": self.show_help,
|
||||
|
||||
"on_net_add_clicked": self.add_network,
|
||||
@ -320,6 +323,9 @@ class vmmHost(gobject.GObject):
|
||||
def view_manager(self, src):
|
||||
self.emit("action-view-manager")
|
||||
|
||||
def restore_domain(self, src):
|
||||
self.emit("action-restore-domain", self.conn.get_uri())
|
||||
|
||||
def exit_app(self, src):
|
||||
self.emit("action-exit-app")
|
||||
|
||||
@ -347,6 +353,7 @@ class vmmHost(gobject.GObject):
|
||||
|
||||
def conn_state_changed(self, ignore1=None):
|
||||
state = (self.conn.get_state() == vmmConnection.STATE_ACTIVE)
|
||||
self.window.get_widget("menu_file_restore_saved").set_sensitive(state)
|
||||
self.window.get_widget("net-add").set_sensitive(state)
|
||||
self.window.get_widget("pool-add").set_sensitive(state)
|
||||
|
||||
|
@ -23,12 +23,10 @@ import gtk
|
||||
import gtk.glade
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
import virtManager.config as cfg
|
||||
import virtManager.uihelpers as uihelpers
|
||||
from virtManager.connection import vmmConnection
|
||||
from virtManager.asyncjob import vmmAsyncJob
|
||||
from virtManager.error import vmmErrorDialog
|
||||
from virtManager.delete import vmmDeleteDialog
|
||||
from virtManager.graphwidgets import CellRendererSparkline
|
||||
@ -105,6 +103,8 @@ class vmmManager(gobject.GObject):
|
||||
gobject.TYPE_NONE, (str, str)),
|
||||
"action-destroy-domain": (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, (str, str)),
|
||||
"action-save-domain": (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, (str, str)),
|
||||
"action-connect": (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, [str]),
|
||||
"action-show-help": (gobject.SIGNAL_RUN_FIRST,
|
||||
@ -165,7 +165,6 @@ class vmmManager(gobject.GObject):
|
||||
"on_menu_file_add_connection_activate": self.new_connection,
|
||||
"on_menu_file_quit_activate": self.exit_app,
|
||||
"on_menu_file_close_activate": self.close,
|
||||
"on_menu_restore_saved_activate": self.restore_saved,
|
||||
"on_vmm_close_clicked": self.close,
|
||||
"on_vm_open_clicked": self.open_vm_console,
|
||||
"on_vm_run_clicked": self.start_vm,
|
||||
@ -275,7 +274,8 @@ class vmmManager(gobject.GObject):
|
||||
self.window.get_widget("vm-shutdown"),
|
||||
self.poweroff_vm,
|
||||
self.reboot_vm,
|
||||
self.destroy_vm)
|
||||
self.destroy_vm,
|
||||
self.save_vm)
|
||||
|
||||
tool = self.window.get_widget("vm-toolbar")
|
||||
util.safe_set_prop(tool, "icon-size", gtk.ICON_SIZE_LARGE_TOOLBAR)
|
||||
@ -296,6 +296,7 @@ class vmmManager(gobject.GObject):
|
||||
destroy_icon = build_icon(icon_name)
|
||||
run_icon = build_stock(gtk.STOCK_MEDIA_PLAY)
|
||||
pause_icon = build_stock(gtk.STOCK_MEDIA_PAUSE)
|
||||
save_icon = build_stock(gtk.STOCK_SAVE)
|
||||
resume_icon = build_stock(gtk.STOCK_MEDIA_PAUSE)
|
||||
delete_icon = build_stock(gtk.STOCK_DELETE)
|
||||
|
||||
@ -345,6 +346,16 @@ class vmmManager(gobject.GObject):
|
||||
self.destroy_vm)
|
||||
self.vmmenushutdown.add(self.vmmenushutdown_items["forcepoweroff"])
|
||||
|
||||
self.vmmenushutdown_items["sep"] = gtk.SeparatorMenuItem()
|
||||
self.vmmenushutdown_items["sep"].show()
|
||||
self.vmmenushutdown.add(self.vmmenushutdown_items["sep"])
|
||||
|
||||
self.vmmenushutdown_items["save"] = gtk.ImageMenuItem(_("Sa_ve"))
|
||||
self.vmmenushutdown_items["save"].set_image(save_icon)
|
||||
self.vmmenushutdown_items["save"].show()
|
||||
self.vmmenushutdown_items["save"].connect("activate", self.save_vm)
|
||||
self.vmmenushutdown.add(self.vmmenushutdown_items["save"])
|
||||
|
||||
self.vmmenu_items["hsep1"] = gtk.SeparatorMenuItem()
|
||||
self.vmmenu_items["hsep1"].show()
|
||||
self.vmmenu.add(self.vmmenu_items["hsep1"])
|
||||
@ -608,41 +619,6 @@ class vmmManager(gobject.GObject):
|
||||
self.emit("action-show-console",
|
||||
conn.get_uri(), self.vm.get_uuid())
|
||||
|
||||
def restore_saved(self, src=None):
|
||||
conn = self.current_connection()
|
||||
if conn.is_remote():
|
||||
self.err.val_err(_("Restoring virtual machines over remote "
|
||||
"connections is not yet supported"))
|
||||
return
|
||||
|
||||
path = util.browse_local(self.window.get_widget("vmm-manager"),
|
||||
_("Restore Virtual Machine"),
|
||||
self.config, conn,
|
||||
browse_reason=self.config.CONFIG_DIR_RESTORE)
|
||||
|
||||
if not path:
|
||||
return
|
||||
|
||||
progWin = vmmAsyncJob(self.config, self.restore_saved_callback,
|
||||
[path], _("Restoring Virtual Machine"))
|
||||
progWin.run()
|
||||
error, details = progWin.get_error()
|
||||
|
||||
if error is not None:
|
||||
self.err.show_err(error, details,
|
||||
title=_("Error restoring domain"))
|
||||
|
||||
def restore_saved_callback(self, file_to_load, asyncjob):
|
||||
try:
|
||||
newconn = util.dup_conn(self.config, self.current_connection(),
|
||||
return_conn_class=True)
|
||||
newconn.restore(file_to_load)
|
||||
except Exception, e:
|
||||
err = (_("Error restoring domain '%s': %s") %
|
||||
(file_to_load, str(e)))
|
||||
details = "".join(traceback.format_exc())
|
||||
asyncjob.set_error(err, details)
|
||||
|
||||
def do_delete(self, ignore=None):
|
||||
conn = self.current_connection()
|
||||
vm = self.current_vm()
|
||||
@ -719,6 +695,12 @@ class vmmManager(gobject.GObject):
|
||||
self.emit("action-destroy-domain",
|
||||
vm.get_connection().get_uri(), vm.get_uuid())
|
||||
|
||||
def save_vm(self, ignore):
|
||||
vm = self.current_vm()
|
||||
if vm is not None:
|
||||
self.emit("action-save-domain",
|
||||
vm.get_connection().get_uri(), vm.get_uuid())
|
||||
|
||||
def pause_vm(self, ignore):
|
||||
vm = self.current_vm()
|
||||
if vm is not None:
|
||||
@ -1004,7 +986,6 @@ class vmmManager(gobject.GObject):
|
||||
else:
|
||||
show_pause = bool(vm and vm.is_pauseable())
|
||||
show_shutdown = bool(vm and vm.is_stoppable())
|
||||
restore = bool(conn and conn.get_state() == vmmConnection.STATE_ACTIVE)
|
||||
|
||||
self.window.get_widget("vm-open").set_sensitive(show_open)
|
||||
self.window.get_widget("vm-run").set_sensitive(show_run)
|
||||
@ -1015,7 +996,6 @@ class vmmManager(gobject.GObject):
|
||||
self.window.get_widget("menu_edit_details").set_sensitive(show_details)
|
||||
self.window.get_widget("menu_host_details").set_sensitive(host_details)
|
||||
self.window.get_widget("menu_edit_delete").set_sensitive(delete)
|
||||
self.window.get_widget("menu_file_restore_saved").set_sensitive(restore)
|
||||
|
||||
def popup_vm_menu_key(self, widget, event):
|
||||
if gtk.gdk.keyval_name(event.keyval) != "Menu":
|
||||
@ -1065,6 +1045,7 @@ class vmmManager(gobject.GObject):
|
||||
self.vmmenushutdown_items["poweroff"].set_sensitive(stop)
|
||||
self.vmmenushutdown_items["reboot"].set_sensitive(stop)
|
||||
self.vmmenushutdown_items["forcepoweroff"].set_sensitive(destroy)
|
||||
self.vmmenushutdown_items["save"].set_sensitive(destroy)
|
||||
self.vmmenu.popup(None, None, None, 0, event.time)
|
||||
else:
|
||||
# Pop up connection menu
|
||||
|
@ -595,7 +595,7 @@ def mediadev_set_default_selection(widget):
|
||||
####################################################################
|
||||
|
||||
def build_shutdown_button_menu(config, widget, shutdown_cb, reboot_cb,
|
||||
destroy_cb):
|
||||
destroy_cb, save_cb):
|
||||
icon_name = config.get_shutdown_icon_name()
|
||||
widget.set_icon_name(icon_name)
|
||||
menu = gtk.Menu()
|
||||
@ -604,6 +604,7 @@ def build_shutdown_button_menu(config, widget, shutdown_cb, reboot_cb,
|
||||
rebootimg = gtk.image_new_from_icon_name(icon_name, gtk.ICON_SIZE_MENU)
|
||||
shutdownimg = gtk.image_new_from_icon_name(icon_name, gtk.ICON_SIZE_MENU)
|
||||
destroyimg = gtk.image_new_from_icon_name(icon_name, gtk.ICON_SIZE_MENU)
|
||||
saveimg = gtk.image_new_from_icon_name(gtk.STOCK_SAVE, gtk.ICON_SIZE_MENU)
|
||||
|
||||
reboot = gtk.ImageMenuItem(_("_Reboot"))
|
||||
reboot.set_image(rebootimg)
|
||||
@ -623,6 +624,16 @@ def build_shutdown_button_menu(config, widget, shutdown_cb, reboot_cb,
|
||||
destroy.connect("activate", destroy_cb)
|
||||
menu.add(destroy)
|
||||
|
||||
sep = gtk.SeparatorMenuItem()
|
||||
sep.show()
|
||||
menu.add(sep)
|
||||
|
||||
save = gtk.ImageMenuItem(_("Sa_ve"))
|
||||
save.set_image(saveimg)
|
||||
save.show()
|
||||
save.connect("activate", save_cb)
|
||||
menu.add(save)
|
||||
|
||||
#####################################
|
||||
# Path permissions checker for qemu #
|
||||
#####################################
|
||||
|
@ -142,6 +142,26 @@
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="menuitem3">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="details-menu-save">
|
||||
<property name="label">_Save</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_details_menu_save_activate"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image123">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-save</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child internal-child="image">
|
||||
@ -152,14 +172,6 @@
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="details-menu-save">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Save</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_details_menu_save_activate"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator11">
|
||||
<property name="visible">True</property>
|
||||
|
@ -22,6 +22,28 @@
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menuitem4_menu">
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menu_file_restore_saved">
|
||||
<property name="label" translatable="yes">Restore Saved Machine...</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Restore a saved machine from a filesystem image</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_menu_restore_saved_activate"/>
|
||||
<accelerator key="r" signal="activate" modifiers="GDK_MOD1_MASK"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image3">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-open</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator4">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menu-file-view-manager">
|
||||
<property name="visible">True</property>
|
||||
@ -2023,7 +2045,7 @@ here</property>
|
||||
<property name="tooltip" translatable="yes">Stop Interface</property>
|
||||
<signal name="clicked" handler="on_interface_stop_clicked"/>
|
||||
<child>
|
||||
<widget class="GtkImage" id="image3">
|
||||
<widget class="GtkImage" id="image5">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-cancel</property>
|
||||
</widget>
|
||||
@ -2044,7 +2066,7 @@ here</property>
|
||||
<property name="tooltip" translatable="yes">Delete Interface</property>
|
||||
<signal name="clicked" handler="on_interface_delete_clicked"/>
|
||||
<child>
|
||||
<widget class="GtkImage" id="image5">
|
||||
<widget class="GtkImage" id="image9">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-delete</property>
|
||||
</widget>
|
||||
|
@ -23,28 +23,6 @@
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menuitem4_menu">
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menu_file_restore_saved">
|
||||
<property name="label" translatable="yes">Restore Saved Machine...</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Restore a saved machine from a filesystem image</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="on_menu_restore_saved_activate"/>
|
||||
<accelerator key="r" signal="activate" modifiers="GDK_MOD1_MASK"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image3">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-open</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator4">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="open_connection">
|
||||
<property name="label" translatable="yes">_Add Connection...</property>
|
||||
|
Loading…
Reference in New Issue
Block a user