[virt-tools-list] [PATCH 1/3] virt-manager: add support for domain title

Giuseppe Scrivano gscrivan at redhat.com
Tue Sep 10 14:07:09 UTC 2013


Commit b79ba8382e2205c416d7c4836ac9ee08c72e2c56 in libvirt adds a
<title> attribute to the domain XML, that is used by the user to
identify more easily the VM. This feature is not supported by all
HVs. This patch allows to see and modify the title from the details
window.

Something similar was requested here:
https://bugzilla.redhat.com/show_bug.cgi?id=798949

Signed-off-by: Giuseppe Scrivano <gscrivan at redhat.com>
---
 ui/vmm-details.ui      | 84 +++++++++++++++++++++++++++++++++-----------------
 virtManager/details.py | 18 ++++++++++-
 virtManager/domain.py  | 51 ++++++++++++++++++++++++++++--
 3 files changed, 121 insertions(+), 32 deletions(-)

diff --git a/ui/vmm-details.ui b/ui/vmm-details.ui
index 9ce87f4..2b42408 100644
--- a/ui/vmm-details.ui
+++ b/ui/vmm-details.ui
@@ -781,7 +781,7 @@
                                         <property name="visible">True</property>
                                         <property name="can_focus">False</property>
                                         <property name="border_width">3</property>
-                                        <property name="n_rows">5</property>
+                                        <property name="n_rows">6</property>
                                         <property name="n_columns">2</property>
                                         <property name="column_spacing">6</property>
                                         <property name="row_spacing">6</property>
@@ -884,49 +884,39 @@
                                           </packing>
                                         </child>
                                         <child>
-                                          <object class="GtkLabel" id="label24">
+                                          <object class="GtkEntry" id="overview-name">
                                             <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="xalign">0</property>
-                                            <property name="yalign">0</property>
-                                            <property name="label" translatable="yes">Description:</property>
+                                            <property name="can_focus">True</property>
+                                            <signal name="changed" handler="on_overview_name_changed" swapped="no"/>
                                           </object>
                                           <packing>
-                                            <property name="top_attach">3</property>
-                                            <property name="bottom_attach">4</property>
-                                            <property name="x_options">GTK_FILL</property>
+                                            <property name="left_attach">1</property>
+                                            <property name="right_attach">2</property>
                                             <property name="y_options">GTK_FILL</property>
                                           </packing>
                                         </child>
                                         <child>
-                                          <object class="GtkScrolledWindow" id="scrolledwindow2">
+                                          <object class="GtkAlignment" id="alignment14">
                                             <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="shadow_type">in</property>
-                                            <property name="min_content_height">80</property>
+                                            <property name="can_focus">False</property>
                                             <child>
-                                              <object class="GtkTextView" id="overview-description">
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">True</property>
-                                                <property name="wrap_mode">word</property>
-                                              </object>
+                                              <placeholder/>
                                             </child>
                                           </object>
                                           <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="right_attach">2</property>
-                                            <property name="top_attach">3</property>
-                                            <property name="bottom_attach">5</property>
+                                            <property name="top_attach">5</property>
+                                            <property name="bottom_attach">6</property>
+                                            <property name="x_options">GTK_FILL</property>
                                             <property name="y_options">GTK_FILL</property>
                                           </packing>
                                         </child>
                                         <child>
-                                          <object class="GtkAlignment" id="alignment14">
+                                          <object class="GtkLabel" id="label24">
                                             <property name="visible">True</property>
                                             <property name="can_focus">False</property>
-                                            <child>
-                                              <placeholder/>
-                                            </child>
+                                            <property name="xalign">0</property>
+                                            <property name="yalign">0</property>
+                                            <property name="label" translatable="yes">Description:</property>
                                           </object>
                                           <packing>
                                             <property name="top_attach">4</property>
@@ -936,14 +926,52 @@
                                           </packing>
                                         </child>
                                         <child>
-                                          <object class="GtkEntry" id="overview-name">
+                                          <object class="GtkLabel" id="label81">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="xalign">0</property>
+                                            <property name="label" translatable="yes">Title:</property>
+                                          </object>
+                                          <packing>
+                                            <property name="top_attach">3</property>
+                                            <property name="bottom_attach">4</property>
+                                            <property name="x_options">GTK_FILL</property>
+                                            <property name="y_options"/>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkEntry" id="overview-title">
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
-                                            <signal name="changed" handler="on_overview_name_changed" swapped="no"/>
+                                            <signal name="changed" handler="on_overview_title_changed" swapped="no"/>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="right_attach">2</property>
+                                            <property name="top_attach">3</property>
+                                            <property name="bottom_attach">4</property>
+                                            <property name="y_options">GTK_FILL</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkScrolledWindow" id="scrolledwindow2">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="shadow_type">in</property>
+                                            <property name="min_content_height">80</property>
+                                            <child>
+                                              <object class="GtkTextView" id="overview-description">
+                                                <property name="visible">True</property>
+                                                <property name="can_focus">True</property>
+                                                <property name="wrap_mode">word</property>
+                                              </object>
+                                            </child>
                                           </object>
                                           <packing>
                                             <property name="left_attach">1</property>
                                             <property name="right_attach">2</property>
+                                            <property name="top_attach">4</property>
+                                            <property name="bottom_attach">6</property>
                                             <property name="y_options">GTK_FILL</property>
                                           </packing>
                                         </child>
diff --git a/virtManager/details.py b/virtManager/details.py
index a4fddd4..21b93fa 100644
--- a/virtManager/details.py
+++ b/virtManager/details.py
@@ -43,6 +43,7 @@ from virtinst import util
 
 # Parameters that can be editted in the details window
 (EDIT_NAME,
+EDIT_TITLE,
 EDIT_ACPI,
 EDIT_APIC,
 EDIT_CLOCK,
@@ -93,7 +94,7 @@ EDIT_WATCHDOG_ACTION,
 EDIT_CONTROLLER_MODEL,
 
 EDIT_TPM_TYPE,
-) = range(1, 40)
+) = range(1, 41)
 
 
 # Columns in hw list model
@@ -434,6 +435,7 @@ class vmmDetails(vmmGObjectUI):
             "on_details_pages_switch_page": self.switch_page,
 
             "on_overview_name_changed": lambda *x: self.enable_apply(x, EDIT_NAME),
+            "on_overview_title_changed": lambda *x: self.enable_apply(x, EDIT_TITLE),
             "on_overview_acpi_changed": self.config_acpi_changed,
             "on_overview_apic_changed": self.config_apic_changed,
             "on_overview_clock_changed": lambda *x: self.enable_apply(x, EDIT_CLOCK),
@@ -1993,6 +1995,11 @@ class vmmDetails(vmmGObjectUI):
             name = self.widget("overview-name").get_text()
             add_define(self.vm.define_name, name)
 
+        if self.edited(EDIT_TITLE):
+            title = self.widget("overview-title").get_text()
+            add_define(self.vm.define_title, title)
+            add_hotplug(self.vm.define_title, title)
+
         if self.edited(EDIT_ACPI):
             enable_acpi = self.widget("overview-acpi").get_active()
             if self.widget("overview-acpi").get_inconsistent():
@@ -2556,6 +2563,15 @@ class vmmDetails(vmmGObjectUI):
         desc = self.vm.get_description() or ""
         desc_widget = self.widget("overview-description")
         desc_widget.get_buffer().set_text(desc)
+        title = self.vm.get_title()
+        if title is not None:
+            self.widget("overview-title").set_sensitive(True)
+            self.widget("overview-title").set_text(self.vm.get_title() or "")
+        else:
+            # TITLE is None when the HV doesn't support the <title> metadata,
+            # so disable the possibility of changing it.
+            self.widget("overview-title").set_sensitive(False)
+            self.widget("overview-title").set_text("")
 
         # Hypervisor Details
         self.widget("overview-hv").set_text(self.vm.get_pretty_hv_type())
diff --git a/virtManager/domain.py b/virtManager/domain.py
index cf2825d..ca000c3 100644
--- a/virtManager/domain.py
+++ b/virtManager/domain.py
@@ -200,6 +200,7 @@ class vmmDomain(vmmLibvirtObject):
         self._is_management_domain = None
         self._id = None
         self._name = None
+        self._title = None
         self._snapshot_list = None
 
         self._inactive_xml_flags = 0
@@ -326,9 +327,38 @@ class vmmDomain(vmmLibvirtObject):
     ###########################
 
     def get_name(self):
-        if self._name is None:
-            self._name = self._backend.name()
-        return self._name
+        return self._backend.name()
+
+    def get_descriptive_name(self):
+        # When available, include the title in the name
+        name = self.get_name()
+        title = self.get_title()
+        if title:
+            return "%s - %s" % (name, title)
+        return name
+
+    def get_title(self):
+        # Return None when the hypervisor doesn't support a title for the
+        # domain
+        if self._title is None:
+            try:
+                self._title = self._backend.metadata(
+                    libvirt.VIR_DOMAIN_METADATA_TITLE,
+                    None,
+                    0)
+            except libvirt.libvirtError, e:
+                # For us there is no difference between no metadata and an
+                # empty title.
+                err_no_metadata = "VIR_ERR_NO_DOMAIN_METADATA"
+                err_no_support = "VIR_ERR_NO_SUPPORT"
+                if uihelpers.exception_is_libvirt_error(e, err_no_metadata):
+                    return ""
+                elif uihelpers.exception_is_libvirt_error(e, err_no_support):
+                    return None
+                else:
+                    raise e
+
+        return self._title or ""
 
     def get_id(self):
         if self._id is None:
@@ -387,6 +417,7 @@ class vmmDomain(vmmLibvirtObject):
         vmmLibvirtObject._invalidate_xml(self)
         self._guest_to_define = None
         self._name = None
+        self._title = None
         self._id = None
 
     def _get_guest_to_define(self):
@@ -487,6 +518,20 @@ class vmmDomain(vmmLibvirtObject):
 
         self.emit("config-changed")
 
+    def define_title(self, title):
+        logging.debug("Changing guest title to '%s'", title)
+        try:
+            self._title = self._backend.setMetadata(
+                libvirt.VIR_DOMAIN_METADATA_TITLE,
+                title,
+                None,
+                None,
+                0)
+        finally:
+            self._invalidate_xml()
+
+        self.emit("config-changed")
+
     # Device Add/Remove
     def add_device(self, devobj):
         """
-- 
1.8.3.1




More information about the virt-tools-list mailing list