[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