[virt-tools-list] [virt-manager][PATCH v3] Add delete VM option in console viewer.
Leonardo Garcia
lagarcia at linux.vnet.ibm.com
Mon Jun 17 17:06:29 UTC 2013
From: Leonardo Garcia <lagarcia at br.ibm.com>
---
ui/vmm-delete.ui | 46 +++++++++++++++++++++++++++++++++++++++++++++-
ui/vmm-details.ui | 15 +++++++++++++++
virtManager/console.py | 10 ++++++++--
virtManager/delete.py | 35 +++++++++++++++++++++++++++++++++--
virtManager/details.py | 6 ++++++
virtManager/engine.py | 16 ++++++++++++++++
virtManager/manager.py | 20 ++------------------
7 files changed, 125 insertions(+), 23 deletions(-)
diff --git a/ui/vmm-delete.ui b/ui/vmm-delete.ui
index fa1e75e..7cbab36 100644
--- a/ui/vmm-delete.ui
+++ b/ui/vmm-delete.ui
@@ -116,6 +116,50 @@
</packing>
</child>
<child>
+ <object class="GtkAlignment" id="delete-warn-running-vm-align">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">6</property>
+ <child>
+ <object class="GtkHBox" id="delete-warn-running-vm-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkImage" id="delete-warn-running-vm-icon">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-dialog-warning</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="delete-warn-running-vm-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes"><small>This VM is currently running and will be forced off before being deleted</small></property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkCheckButton" id="delete-remove-storage">
<property name="label" translatable="yes">Delete _associated storage files</property>
<property name="visible">True</property>
@@ -129,7 +173,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">1</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
diff --git a/ui/vmm-details.ui b/ui/vmm-details.ui
index ddb2a71..ea4b53e 100644
--- a/ui/vmm-details.ui
+++ b/ui/vmm-details.ui
@@ -314,6 +314,21 @@
</object>
</child>
<child>
+ <object class="GtkMenuItem" id="details-menu-delete">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Delete...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_details_menu_delete_activate" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="separator2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
<object class="GtkMenuItem" id="details-menu-vm-screenshot">
<property name="visible">True</property>
<property name="can_focus">False</property>
diff --git a/virtManager/console.py b/virtManager/console.py
index b9186ce..001318e 100644
--- a/virtManager/console.py
+++ b/virtManager/console.py
@@ -651,7 +651,10 @@ class vmmConsolePages(vmmGObjectUI):
self.page_changed()
def is_visible(self):
- return self.topwin.get_visible()
+ if self.topwin:
+ return self.topwin.get_visible()
+ else:
+ return False
def _cleanup(self):
self.vm = None
@@ -892,6 +895,9 @@ class vmmConsolePages(vmmGObjectUI):
##########################
def view_vm_status(self):
+ if not self.vm:
+ # window has been closed and no pages to update are available.
+ return
status = self.vm.status()
if status == libvirt.VIR_DOMAIN_SHUTOFF:
self.activate_unavailable_page(_("Guest not running"))
@@ -900,7 +906,6 @@ class vmmConsolePages(vmmGObjectUI):
self.activate_unavailable_page(_("Guest has crashed"))
def close_viewer(self):
- viewport = self.widget("console-gfx-viewport")
if self.viewer is None:
return
@@ -908,6 +913,7 @@ class vmmConsolePages(vmmGObjectUI):
self.viewer = None
w = v.display
+ viewport = self.widget("console-gfx-viewport")
if w and w in viewport.get_children():
viewport.remove(w)
diff --git a/virtManager/delete.py b/virtManager/delete.py
index b7cb50d..ce55105 100644
--- a/virtManager/delete.py
+++ b/virtManager/delete.py
@@ -99,6 +99,10 @@ class vmmDeleteDialog(vmmGObjectUI):
self.widget("delete-cancel").grab_focus()
+ # Show warning message if VM is running
+ vm_active = self.vm.is_active()
+ self.widget("delete-warn-running-vm-box").set_visible(vm_active)
+
# Disable storage removal by default
self.widget("delete-remove-storage").set_active(True)
self.widget("delete-remove-storage").toggled()
@@ -140,10 +144,38 @@ class vmmDeleteDialog(vmmGObjectUI):
if not ret:
return
+ conn = self.conn
+ vm = self.vm
self.topwin.set_sensitive(False)
self.topwin.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))
- title = _("Deleting virtual machine '%s'") % self.vm.get_name()
+ if vm.is_active():
+ def tmpcb(job, *args, **kwargs):
+ ignore = job
+ vm.destroy()
+ docb = tmpcb
+ title = _("Forcing VM Power off")
+ text = _("Powering off the VM in order to proceed with its deletion.")
+
+ syncjob = vmmAsyncJob(docb, [], title, text, self.topwin,
+ async=False)
+ error, details = syncjob.run()
+
+ if error is not None:
+ self.topwin.set_sensitive(True)
+ self.topwin.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.TOP_LEFT_ARROW))
+
+ self.err.show_err(error, details=details)
+
+ conn.tick(noStatsUpdate=True)
+
+ self.close()
+ return
+
+ logging.debug("Forced power off of vm '%s in order to proceed with "
+ "its deletion'", vm.get_name())
+
+ title = _("Deleting virtual machine '%s'") % vm.get_name()
text = title
if devs:
text = title + _(" and selected storage (this may take a while)")
@@ -154,7 +186,6 @@ class vmmDeleteDialog(vmmGObjectUI):
self.topwin.set_sensitive(True)
self.topwin.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.TOP_LEFT_ARROW))
- conn = self.conn
if error is not None:
self.err.show_err(error, details=details)
diff --git a/virtManager/details.py b/virtManager/details.py
index fb4b493..b2d496e 100644
--- a/virtManager/details.py
+++ b/virtManager/details.py
@@ -329,6 +329,7 @@ class vmmDetails(vmmGObjectUI):
"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]),
+ "action-delete-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
"action-clone-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
"details-closed": (GObject.SignalFlags.RUN_FIRST, None, []),
"details-opened": (GObject.SignalFlags.RUN_FIRST, None, []),
@@ -412,6 +413,7 @@ class vmmDetails(vmmGObjectUI):
"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_view_toolbar_activate": self.toggle_toolbar,
"on_details_menu_view_manager_activate": self.view_manager,
@@ -1580,6 +1582,10 @@ class vmmDetails(vmmGObjectUI):
self.emit("action-migrate-domain",
self.vm.conn.get_uri(), self.vm.get_uuid())
+ def control_vm_delete(self, src_ignore):
+ self.emit("action-delete-domain",
+ self.vm.conn.get_uri(), self.vm.get_uuid())
+
def control_vm_screenshot(self, src):
ignore = src
try:
diff --git a/virtManager/engine.py b/virtManager/engine.py
index 8950451..b636ac2 100644
--- a/virtManager/engine.py
+++ b/virtManager/engine.py
@@ -48,6 +48,7 @@ from virtManager.create import vmmCreate
from virtManager.host import vmmHost
from virtManager.error import vmmErrorDialog
from virtManager.systray import vmmSystray
+from virtManager.delete import vmmDeleteDialog
# Enable this to get a report of leaked objects on app shutdown
# gtk3/pygobject has issues here as of Fedora 18
@@ -95,6 +96,7 @@ class vmmEngine(vmmGObject):
self.last_timeout = 0
self.systray = None
+ self.delete_dialog = None
self.application = Gtk.Application(
application_id="com.redhat.virt-manager",
flags=0)
@@ -376,6 +378,10 @@ class vmmEngine(vmmGObject):
self.windowMigrate.cleanup()
self.windowMigrate = None
+ if self.delete_dialog:
+ self.delete_dialog.cleanup()
+ self.delete_dialog = None
+
# Do this last, so any manually 'disconnected' signals
# take precedence over cleanup signal removal
for uri in self.conns:
@@ -605,6 +611,7 @@ class vmmEngine(vmmGObject):
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)
+ obj.connect("action-delete-domain", self._do_delete_domain)
obj.connect("action-clone-domain", self._do_show_clone)
obj.connect("details-opened", self.increment_window_counter)
obj.connect("details-closed", self.decrement_window_counter)
@@ -648,6 +655,7 @@ class vmmEngine(vmmGObject):
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)
obj.connect("action-show-vm", self._do_show_vm)
obj.connect("action-show-preferences", self._do_show_preferences)
@@ -991,3 +999,11 @@ class vmmEngine(vmmGObject):
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, uuid):
+ conn = self._lookup_conn(uri)
+ vm = conn.get_vm(uuid)
+
+ if not self.delete_dialog:
+ self.delete_dialog = vmmDeleteDialog()
+ self.delete_dialog.show(vm, src.topwin)
diff --git a/virtManager/manager.py b/virtManager/manager.py
index 3620268..8a90eed 100644
--- a/virtManager/manager.py
+++ b/virtManager/manager.py
@@ -95,6 +95,7 @@ class vmmManager(vmmGObjectUI):
"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]),
"action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []),
"manager-closed": (GObject.SignalFlags.RUN_FIRST, None, []),
@@ -106,7 +107,6 @@ class vmmManager(vmmGObjectUI):
def __init__(self):
vmmGObjectUI.__init__(self, "vmm-manager.ui", "vmm-manager")
- self.delete_dialog = None
self.ignore_pause = False
# Mapping of VM UUID -> tree model rows to
@@ -227,10 +227,6 @@ class vmmManager(vmmGObjectUI):
self.hostcpucol = None
self.netcol = None
- if self.delete_dialog:
- self.delete_dialog.cleanup()
- self.delete_dialog = None
-
self.vmmenu.destroy()
self.vmmenu = None
self.vmmenu_items = None
@@ -586,7 +582,7 @@ class vmmManager(vmmGObjectUI):
if vm is None:
self._do_delete_conn(conn)
else:
- self._do_delete_vm(vm)
+ self.emit("action-delete-domain", conn.get_uri(), vm.get_uuid())
def _do_delete_conn(self, conn):
if conn is None:
@@ -599,14 +595,6 @@ class vmmManager(vmmGObjectUI):
self.emit("remove-conn", conn.get_uri())
- def _do_delete_vm(self, vm):
- if vm.is_active():
- return
-
- if not self.delete_dialog:
- self.delete_dialog = vmmDeleteDialog()
- self.delete_dialog.show(vm, self.topwin)
-
def set_pause_state(self, state):
src = self.widget("vm-pause")
try:
@@ -1065,8 +1053,6 @@ class vmmManager(vmmGObjectUI):
show_details = bool(vm)
host_details = bool(len(self.rows))
- delete = bool((vm and vm.is_runable()) or
- (not vm and conn))
show_run = bool(vm and vm.is_runable())
is_paused = bool(vm and vm.is_paused())
if is_paused:
@@ -1086,7 +1072,6 @@ class vmmManager(vmmGObjectUI):
self.widget("menu_edit_details").set_sensitive(show_details)
self.widget("menu_host_details").set_sensitive(host_details)
- self.widget("menu_edit_delete").set_sensitive(delete)
def popup_vm_menu_key(self, widget_ignore, event):
if Gdk.keyval_name(event.keyval) != "Menu":
@@ -1131,7 +1116,6 @@ class vmmManager(vmmGObjectUI):
self.vmmenu_items["resume"].set_sensitive(paused)
self.vmmenu_items["migrate"].set_sensitive(stop)
self.vmmenu_items["clone"].set_sensitive(not ro)
- self.vmmenu_items["delete"].set_sensitive(run)
self.vmmenushutdown_items["poweroff"].set_sensitive(stop)
self.vmmenushutdown_items["reboot"].set_sensitive(stop)
--
1.7.1
More information about the virt-tools-list
mailing list