[virt-manager/f19] Fix parsing rawhide .treeinfo (bz #989162) Fix spice with TLS (bz #904295) Reduce impact of memory l
Cole Robinson
crobinso at fedoraproject.org
Tue Sep 24 15:42:28 UTC 2013
commit ff5bbfd309de657cb282e5d4fb9864c24d524b58
Author: Cole Robinson <crobinso at redhat.com>
Date: Tue Sep 24 11:42:18 2013 -0400
Fix parsing rawhide .treeinfo (bz #989162)
Fix spice with TLS (bz #904295)
Reduce impact of memory leak (bz #972371)
0001-Fix-rawhide-URL-installs.patch | 24 ++
0002-console-Fix-spice-with-TLS-bz-904295.patch | 94 ++++++
...able-graph-data-func-if-graph-isn-t-visib.patch | 165 ++++++++++
...Check-can_set_row_none-before-setting-ico.patch | 46 +++
...r-ignore-VIR_ERR_NO_DOMAIN-when-a-domain-.patch | 147 +++++++++
...ge-some-row-creation-drop-unneeded-row-ke.patch | 316 ++++++++++++++++++++
...Separate-stats-and-state-update-callbacks.patch | 204 +++++++++++++
virt-manager.spec | 29 ++-
8 files changed, 1024 insertions(+), 1 deletions(-)
---
diff --git a/0001-Fix-rawhide-URL-installs.patch b/0001-Fix-rawhide-URL-installs.patch
new file mode 100644
index 0000000..71835c0
--- /dev/null
+++ b/0001-Fix-rawhide-URL-installs.patch
@@ -0,0 +1,24 @@
+From 17406905d786734e9d30b3a808314f7bb1e28891 Mon Sep 17 00:00:00 2001
+From: Lars Seipel <lars.seipel at gmail.com>
+Date: Mon, 29 Jul 2013 12:28:22 -0400
+Subject: [PATCH] Fix rawhide URL installs
+
+https://bugzilla.redhat.com/show_bug.cgi?id=989162
+(cherry picked from commit 72648c9185e3ccb27fb9896a4e7a48f1769c8a4e)
+---
+ virtinst/OSDistro.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/virtinst/OSDistro.py b/virtinst/OSDistro.py
+index 5ecfdf6..780823c 100644
+--- a/virtinst/OSDistro.py
++++ b/virtinst/OSDistro.py
+@@ -512,7 +512,7 @@ class FedoraDistro(RedHatDistro):
+ if ret:
+ lateststr, latestnum = self._latestFedoraVariant()
+ ver = self.treeinfo.get("general", "version")
+- if ver == "development":
++ if ver == "development" or ver == "rawhide":
+ self.os_variant = self._latestFedoraVariant()
+ elif ver:
+ vernum = int(str(ver).split("-")[0])
diff --git a/0002-console-Fix-spice-with-TLS-bz-904295.patch b/0002-console-Fix-spice-with-TLS-bz-904295.patch
new file mode 100644
index 0000000..3a12be1
--- /dev/null
+++ b/0002-console-Fix-spice-with-TLS-bz-904295.patch
@@ -0,0 +1,94 @@
+From 11eb5ff728413ca1b3c6404e4e42550add553355 Mon Sep 17 00:00:00 2001
+From: Cole Robinson <crobinso at redhat.com>
+Date: Sun, 1 Sep 2013 16:08:14 -0400
+Subject: [PATCH] console: Fix spice with TLS (bz #904295)
+
+We now use the same CA trust store as virt-viewer's default, which is:
+
+~/.spicec/spice_truststore.pem
+
+(cherry picked from commit cdc82e62a236d0e737851c693d6673f65ca278c1)
+
+Conflicts:
+ virtManager/console.py
+---
+ virtManager/console.py | 26 +++++++++++++++-----------
+ 1 file changed, 15 insertions(+), 11 deletions(-)
+
+diff --git a/virtManager/console.py b/virtManager/console.py
+index 001318e..90db31c 100644
+--- a/virtManager/console.py
++++ b/virtManager/console.py
+@@ -63,6 +63,7 @@ class ConnectionInfo(object):
+ self.gport = gdev.port and str(gdev.port) or None
+ self.gsocket = gdev.socket
+ self.gaddr = gdev.listen or "127.0.0.1"
++ self.gtlsport = gdev.tlsPort or None
+
+ self.transport, self.connuser = conn.get_transport()
+ self._connhost = conn.get_uri_hostname() or "127.0.0.1"
+@@ -80,19 +81,22 @@ class ConnectionInfo(object):
+ def get_conn_host(self):
+ host = self._connhost
+ port = self._connport
++ tlsport = None
+
+ if not self.need_tunnel():
+ port = self.gport
++ tlsport = self.gtlsport
+ if self.gaddr != "0.0.0.0":
+ host = self.gaddr
+
+- return host, port
++ return host, port, tlsport
+
+ def logstring(self):
+ return ("proto=%s trans=%s connhost=%s connuser=%s "
+- "connport=%s gaddr=%s gport=%s gsocket=%s" %
++ "connport=%s gaddr=%s gport=%s gtlsport=%s gsocket=%s" %
+ (self.gtype, self.transport, self._connhost, self.connuser,
+- self._connport, self.gaddr, self.gport, self.gsocket))
++ self._connport, self.gaddr, self.gport, self.gtlsport,
++ self.gsocket))
+ def console_active(self):
+ if self.gsocket:
+ return True
+@@ -111,7 +115,7 @@ class Tunnel(object):
+ if self.outfd is not None:
+ return -1
+
+- host, port = ginfo.get_conn_host()
++ host, port, ignore = ginfo.get_conn_host()
+
+ # Build SSH cmd
+ argv = ["ssh", "ssh"]
+@@ -406,7 +410,7 @@ class VNCViewer(Viewer):
+ return self.display.is_open()
+
+ def open_host(self, ginfo, password=None):
+- host, port = ginfo.get_conn_host()
++ host, port, ignore = ginfo.get_conn_host()
+
+ if not ginfo.gsocket:
+ logging.debug("VNC connection to %s:%s", host, port)
+@@ -553,14 +557,14 @@ class SpiceViewer(Viewer):
+ return self.display_channel.get_properties("width", "height")
+
+ def open_host(self, ginfo, password=None):
+- host, port = ginfo.get_conn_host()
+-
+- uri = "spice://"
+- uri += str(host) + "?port=" + str(port)
+- logging.debug("spice uri: %s", uri)
++ host, port, tlsport = ginfo.get_conn_host()
+
+ self.spice_session = SpiceClientGLib.Session()
+- self.spice_session.set_property("uri", uri)
++ SpiceClientGLib.set_session_option(self.spice_session)
++ self.spice_session.set_property("host", str(host))
++ self.spice_session.set_property("port", str(port))
++ if tlsport:
++ self.spice_session.set_property("tls-port", str(tlsport))
+ if password:
+ self.spice_session.set_property("password", password)
+ GObject.GObject.connect(self.spice_session, "channel-new",
diff --git a/0003-manager-Disable-graph-data-func-if-graph-isn-t-visib.patch b/0003-manager-Disable-graph-data-func-if-graph-isn-t-visib.patch
new file mode 100644
index 0000000..e2fe994
--- /dev/null
+++ b/0003-manager-Disable-graph-data-func-if-graph-isn-t-visib.patch
@@ -0,0 +1,165 @@
+From 0c452553f19bcaf9cf5ebc52d1d18014ffe10160 Mon Sep 17 00:00:00 2001
+From: Cole Robinson <crobinso at redhat.com>
+Date: Sun, 1 Sep 2013 21:35:23 -0400
+Subject: [PATCH] manager: Disable graph data func if graph isn't visible
+
+Seems like pygobject is a bit leaky with tree row accesses, and
+the cell cb hammers on that quite a bit, even if the graph isn't showing.
+
+(cherry picked from commit db7db9ab47dd00d746cf8a3359c1c26dbfcfa50e)
+---
+ virtManager/manager.py | 82 ++++++++++++++++++++++----------------------------
+ 1 file changed, 36 insertions(+), 46 deletions(-)
+
+diff --git a/virtManager/manager.py b/virtManager/manager.py
+index bdc21cf..ca9d909 100644
+--- a/virtManager/manager.py
++++ b/virtManager/manager.py
+@@ -270,15 +270,11 @@ class vmmManager(vmmGObjectUI):
+ self.config.on_stats_enable_net_poll_changed(self.enable_polling,
+ COL_NETWORK))
+
++ self.toggle_guest_cpu_usage_visible_widget()
++ self.toggle_host_cpu_usage_visible_widget()
++ self.toggle_disk_io_visible_widget()
++ self.toggle_network_traffic_visible_widget()
+
+- self.widget("menu_view_stats_guest_cpu").set_active(
+- self.config.is_vmlist_guest_cpu_usage_visible())
+- self.widget("menu_view_stats_host_cpu").set_active(
+- self.config.is_vmlist_host_cpu_usage_visible())
+- self.widget("menu_view_stats_disk").set_active(
+- self.config.is_vmlist_disk_io_visible())
+- self.widget("menu_view_stats_network").set_active(
+- self.config.is_vmlist_network_traffic_visible())
+
+ def init_toolbar(self):
+ self.widget("vm-new").set_icon_name("vm_new")
+@@ -428,7 +424,7 @@ class vmmManager(vmmGObjectUI):
+ nameCol.add_attribute(name_txt, 'foreground', ROW_COLOR)
+ nameCol.set_sort_column_id(COL_NAME)
+
+- def make_stats_column(title, datafunc, is_visible, colnum):
++ def make_stats_column(title, colnum):
+ col = Gtk.TreeViewColumn(title)
+ col.set_min_width(140)
+
+@@ -443,29 +439,15 @@ class vmmManager(vmmGObjectUI):
+ img.set_property("reversed", True)
+ col.pack_start(img, True)
+ col.add_attribute(img, 'visible', ROW_IS_VM)
+- col.set_cell_data_func(img, datafunc, None)
+
+- col.set_visible(is_visible)
+ col.set_sort_column_id(colnum)
+ vmlist.append_column(col)
+ return col
+
+- self.guestcpucol = make_stats_column(_("CPU usage"),
+- self.guest_cpu_usage_img,
+- self.config.is_vmlist_guest_cpu_usage_visible(),
+- COL_GUEST_CPU)
+- self.hostcpucol = make_stats_column(_("Host CPU usage"),
+- self.host_cpu_usage_img,
+- self.config.is_vmlist_host_cpu_usage_visible(),
+- COL_HOST_CPU)
+- self.diskcol = make_stats_column(_("Disk I/O"),
+- self.disk_io_img,
+- self.config.is_vmlist_disk_io_visible(),
+- COL_DISK)
+- self.netcol = make_stats_column(_("Network I/O"),
+- self.network_traffic_img,
+- self.config.is_vmlist_network_traffic_visible(),
+- COL_NETWORK)
++ self.guestcpucol = make_stats_column(_("CPU usage"), COL_GUEST_CPU)
++ self.hostcpucol = make_stats_column(_("Host CPU usage"), COL_HOST_CPU)
++ self.diskcol = make_stats_column(_("Disk I/O"), COL_DISK)
++ self.netcol = make_stats_column(_("Network I/O"), COL_NETWORK)
+
+ model.set_sort_func(COL_NAME, self.vmlist_name_sorter)
+ model.set_sort_func(COL_GUEST_CPU, self.vmlist_guest_cpu_usage_sorter)
+@@ -1196,25 +1178,33 @@ class vmmManager(vmmGObjectUI):
+ current_text = current_text + disabled_text
+ widget.set_label(current_text)
+
+- def toggle_network_traffic_visible_widget(self):
+- val = self.config.is_vmlist_network_traffic_visible()
+- self.netcol.set_visible(val)
+- self.widget("menu_view_stats_network").set_active(val)
++ def _toggle_graph_helper(self, do_show, col, datafunc, menu):
++ img = -1
++ for child in col.get_cells():
++ if isinstance(child, CellRendererSparkline):
++ img = child
++ datafunc = do_show and datafunc or None
+
+- def toggle_disk_io_visible_widget(self):
+- val = self.config.is_vmlist_disk_io_visible()
+- self.diskcol.set_visible(val)
+- self.widget("menu_view_stats_disk").set_active(val)
++ col.set_cell_data_func(img, datafunc, None)
++ col.set_visible(do_show)
++ self.widget(menu).set_active(do_show)
+
++ def toggle_network_traffic_visible_widget(self):
++ self._toggle_graph_helper(
++ self.config.is_vmlist_network_traffic_visible(), self.netcol,
++ self.network_traffic_img, "menu_view_stats_network")
++ def toggle_disk_io_visible_widget(self):
++ self._toggle_graph_helper(
++ self.config.is_vmlist_disk_io_visible(), self.diskcol,
++ self.disk_io_img, "menu_view_stats_disk")
+ def toggle_guest_cpu_usage_visible_widget(self):
+- val = self.config.is_vmlist_guest_cpu_usage_visible()
+- self.guestcpucol.set_visible(val)
+- self.widget("menu_view_stats_guest_cpu").set_active(val)
+-
++ self._toggle_graph_helper(
++ self.config.is_vmlist_guest_cpu_usage_visible(), self.guestcpucol,
++ self.guest_cpu_usage_img, "menu_view_stats_guest_cpu")
+ def toggle_host_cpu_usage_visible_widget(self):
+- val = self.config.is_vmlist_host_cpu_usage_visible()
+- self.hostcpucol.set_visible(val)
+- self.widget("menu_view_stats_host_cpu").set_active(val)
++ self._toggle_graph_helper(
++ self.config.is_vmlist_host_cpu_usage_visible(), self.hostcpucol,
++ self.host_cpu_usage_img, "menu_view_stats_host_cpu")
+
+ def toggle_stats_visible(self, src, stats_id):
+ visible = src.get_active()
+@@ -1236,7 +1226,7 @@ class vmmManager(vmmGObjectUI):
+ self.toggle_stats_visible(src, COL_NETWORK)
+
+ def guest_cpu_usage_img(self, column_ignore, cell, model, _iter, data):
+- obj = model.get_value(_iter, ROW_HANDLE)
++ obj = model[_iter][ROW_HANDLE]
+ if obj is None or not hasattr(obj, "conn"):
+ return
+
+@@ -1244,7 +1234,7 @@ class vmmManager(vmmGObjectUI):
+ cell.set_property('data_array', data)
+
+ def host_cpu_usage_img(self, column_ignore, cell, model, _iter, data):
+- obj = model.get_value(_iter, ROW_HANDLE)
++ obj = model[_iter][ROW_HANDLE]
+ if obj is None or not hasattr(obj, "conn"):
+ return
+
+@@ -1252,7 +1242,7 @@ class vmmManager(vmmGObjectUI):
+ cell.set_property('data_array', data)
+
+ def disk_io_img(self, column_ignore, cell, model, _iter, data):
+- obj = model.get_value(_iter, ROW_HANDLE)
++ obj = model[_iter][ROW_HANDLE]
+ if obj is None or not hasattr(obj, "conn"):
+ return
+
+@@ -1260,7 +1250,7 @@ class vmmManager(vmmGObjectUI):
+ cell.set_property('data_array', data)
+
+ def network_traffic_img(self, column_ignore, cell, model, _iter, data):
+- obj = model.get_value(_iter, ROW_HANDLE)
++ obj = model[_iter][ROW_HANDLE]
+ if obj is None or not hasattr(obj, "conn"):
+ return
+
diff --git a/0004-inspection-Check-can_set_row_none-before-setting-ico.patch b/0004-inspection-Check-can_set_row_none-before-setting-ico.patch
new file mode 100644
index 0000000..b9dc4e4
--- /dev/null
+++ b/0004-inspection-Check-can_set_row_none-before-setting-ico.patch
@@ -0,0 +1,46 @@
+From 89d78c1af3f84113ea0d18b4229e98d16c12bfef Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Fri, 28 Jun 2013 18:45:53 +0100
+Subject: [PATCH] inspection: Check can_set_row_none before setting icon to
+ None.
+
+Previously one could set the icon field of a tree model to None, but
+with Gtk3 and older versions of pygobject3 this would fail.
+
+Use can_set_row_none to test for this condition and work around it.
+
+The previous traceback was:
+
+Traceback (most recent call last):
+ File "/home/rjones/d/virt-manager/virtManager/manager.py", line 981, in vm_inspection_changed
+ self.get_inspection_icon_pixbuf(vm, 16, 16)
+ File "/usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py", line 1152, in __setitem__
+ self.model.set_value(self.iter, key, value)
+ File "/usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py", line 1298, in set_value
+ Gtk.TreeStore.set_value(self, treeiter, column, value)
+ File "/usr/lib64/python2.7/site-packages/gi/types.py", line 47, in function
+ return info.invoke(*args, **kwargs)
+TypeError: Argument 3 does not allow None as a value
+
+(cherry picked from commit 9d5c1cdb1c03a8c045ae94ab5324aa7dda68e695)
+---
+ virtManager/manager.py | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/virtManager/manager.py b/virtManager/manager.py
+index ca9d909..3682429 100644
+--- a/virtManager/manager.py
++++ b/virtManager/manager.py
+@@ -959,8 +959,10 @@ class vmmManager(vmmGObjectUI):
+ return
+
+ row = self.rows[self.vm_row_key(vm)]
+- row[ROW_INSPECTION_OS_ICON] = \
+- self.get_inspection_icon_pixbuf(vm, 16, 16)
++ new_icon = self.get_inspection_icon_pixbuf(vm, 16, 16)
++ if not can_set_row_none:
++ new_icon = new_icon or ""
++ row[ROW_INSPECTION_OS_ICON] = new_icon
+ model.row_changed(row.path, row.iter)
+
+ def get_inspection_icon_pixbuf(self, vm, w, h):
diff --git a/0005-virt-manager-ignore-VIR_ERR_NO_DOMAIN-when-a-domain-.patch b/0005-virt-manager-ignore-VIR_ERR_NO_DOMAIN-when-a-domain-.patch
new file mode 100644
index 0000000..69d4be6
--- /dev/null
+++ b/0005-virt-manager-ignore-VIR_ERR_NO_DOMAIN-when-a-domain-.patch
@@ -0,0 +1,147 @@
+From 6df408590cf0c4c094bcc5e8700700118e2d71c6 Mon Sep 17 00:00:00 2001
+From: Giuseppe Scrivano <gscrivan at redhat.com>
+Date: Fri, 16 Aug 2013 15:59:33 +0200
+Subject: [PATCH] virt-manager: ignore VIR_ERR_NO_DOMAIN when a domain was just
+ deleted
+
+Some callbacks could try to access a domain that was just deleted and
+not accessible anymore. Detect these cases and don't propagate the
+exception.
+
+Signed-off-by: Giuseppe Scrivano <gscrivan at redhat.com>
+(cherry picked from commit c1fa43ebb90c26c57f72faaf6c0b6a5c19221dd4)
+
+Conflicts:
+ virtManager/uihelpers.py
+---
+ virtManager/details.py | 10 ++++++++--
+ virtManager/domain.py | 14 +++++++++-----
+ virtManager/manager.py | 29 ++++++++++++++++++-----------
+ virtManager/uihelpers.py | 5 +++++
+ 4 files changed, 40 insertions(+), 18 deletions(-)
+
+diff --git a/virtManager/details.py b/virtManager/details.py
+index b2d496e..79db2cf 100644
+--- a/virtManager/details.py
++++ b/virtManager/details.py
+@@ -2598,8 +2598,14 @@ class vmmDetails(vmmGObjectUI):
+
+ # If the dialog is visible, we want to make sure the XML is always
+ # up to date
+- if self.is_visible():
+- self.vm.refresh_xml()
++ try:
++ if self.is_visible():
++ self.vm.refresh_xml()
++ except libvirt.libvirtError, e:
++ if uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
++ self.close()
++ return
++ raise
+
+ # Stats page needs to be refreshed every tick
+ if (page == PAGE_DETAILS and
+diff --git a/virtManager/domain.py b/virtManager/domain.py
+index bd3d964..486664f 100644
+--- a/virtManager/domain.py
++++ b/virtManager/domain.py
+@@ -32,6 +32,7 @@ from virtinst.VirtualCharDevice import VirtualCharSpicevmcDevice
+ import virtinst.support as support
+
+ from virtManager import util
++from virtManager import uihelpers
+ from virtManager.libvirtobject import vmmLibvirtObject
+
+
+@@ -406,7 +407,12 @@ class vmmDomain(vmmLibvirtObject):
+ caps=self.conn.get_capabilities())
+
+ def _reparse_xml(self, ignore=None):
+- self._guest = self._build_guest(self._get_domain_xml())
++ try:
++ self._guest = self._build_guest(self._get_domain_xml())
++ except libvirt.libvirtError, e:
++ if uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
++ return
++ raise
+
+
+ ##############################
+@@ -1566,14 +1572,12 @@ class vmmDomain(vmmLibvirtObject):
+ """
+ try:
+ info = self._backend.info()
++ self._update_status(info[0])
+ except libvirt.libvirtError, e:
+- if (hasattr(libvirt, "VIR_ERR_NO_DOMAIN") and
+- e.get_error_code() == getattr(libvirt, "VIR_ERR_NO_DOMAIN")):
+- # Possibly a transient domain that was removed on shutdown
++ if uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
+ return
+ raise
+
+- self._update_status(info[0])
+
+ def _update_status(self, status):
+ """
+diff --git a/virtManager/manager.py b/virtManager/manager.py
+index 3682429..97cb068 100644
+--- a/virtManager/manager.py
++++ b/virtManager/manager.py
+@@ -35,6 +35,7 @@ from virtManager.baseclass import vmmGObjectUI
+ from virtManager.graphwidgets import CellRendererSparkline
+ from virtManager import util as util
+
++import libvirt
+
+ # Number of data points for performance graphs
+ GRAPH_LEN = 40
+@@ -936,18 +937,24 @@ class vmmManager(vmmGObjectUI):
+ if self.vm_row_key(vm) not in self.rows:
+ return
+
+- row = self.rows[self.vm_row_key(vm)]
+- row[ROW_NAME] = vm.get_name()
+- row[ROW_STATUS] = vm.run_status()
+- row[ROW_STATUS_ICON] = vm.run_status_icon_name()
+- row[ROW_IS_VM_RUNNING] = vm.is_active()
+- row[ROW_MARKUP] = self._build_vm_markup(row)
+
+- if config_changed:
+- desc = vm.get_description()
+- if not can_set_row_none:
+- desc = desc or ""
+- row[ROW_HINT] = util.xml_escape(desc)
++ try:
++ row = self.rows[self.vm_row_key(vm)]
++ row[ROW_NAME] = vm.get_name()
++ row[ROW_STATUS] = vm.run_status()
++ row[ROW_STATUS_ICON] = vm.run_status_icon_name()
++ row[ROW_IS_VM_RUNNING] = vm.is_active()
++ row[ROW_MARKUP] = self._build_vm_markup(row)
++
++ if config_changed:
++ desc = vm.get_description()
++ if not can_set_row_none:
++ desc = desc or ""
++ row[ROW_HINT] = util.xml_escape(desc)
++ except libvirt.libvirtError, e:
++ if uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
++ return
++ raise
+
+ model.row_changed(row.path, row.iter)
+
+diff --git a/virtManager/uihelpers.py b/virtManager/uihelpers.py
+index ba69ee9..ff254ab 100644
+--- a/virtManager/uihelpers.py
++++ b/virtManager/uihelpers.py
+@@ -1027,3 +1027,8 @@ def build_keycombo_menu(cb):
+
+ menu.show_all()
+ return menu
++
++def exception_is_libvirt_error(e, error):
++ import libvirt
++ return (hasattr(libvirt, error) and
++ e.get_error_code() == getattr(libvirt, error))
diff --git a/0006-manager-Merge-some-row-creation-drop-unneeded-row-ke.patch b/0006-manager-Merge-some-row-creation-drop-unneeded-row-ke.patch
new file mode 100644
index 0000000..c4cc0fd
--- /dev/null
+++ b/0006-manager-Merge-some-row-creation-drop-unneeded-row-ke.patch
@@ -0,0 +1,316 @@
+From c3e576155228cc3f3f05d3953edadbf589b74d8c Mon Sep 17 00:00:00 2001
+From: Cole Robinson <crobinso at redhat.com>
+Date: Sun, 1 Sep 2013 18:36:58 -0400
+Subject: [PATCH] manager: Merge some row creation, drop unneeded row keys
+
+(cherry picked from commit 1bd6026515324430adbdd7a8b666e1b6a64879c3)
+
+Conflicts:
+ virtManager/manager.py
+---
+ virtManager/manager.py | 174 ++++++++++++++++++++++---------------------------
+ 1 file changed, 79 insertions(+), 95 deletions(-)
+
+diff --git a/virtManager/manager.py b/virtManager/manager.py
+index 97cb068..2770b2f 100644
+--- a/virtManager/manager.py
++++ b/virtManager/manager.py
+@@ -42,18 +42,16 @@ GRAPH_LEN = 40
+
+ # fields in the tree model data set
+ (ROW_HANDLE,
+-ROW_NAME,
++ROW_SORT_KEY,
+ ROW_MARKUP,
+-ROW_STATUS,
+ ROW_STATUS_ICON,
+-ROW_KEY,
+ ROW_HINT,
+ ROW_IS_CONN,
+ ROW_IS_CONN_CONNECTED,
+ ROW_IS_VM,
+ ROW_IS_VM_RUNNING,
+ ROW_COLOR,
+-ROW_INSPECTION_OS_ICON) = range(13)
++ROW_INSPECTION_OS_ICON) = range(11)
+
+ # Columns in the tree view
+ COL_NAME = 0
+@@ -78,6 +76,24 @@ def _style_get_prop(widget, propname):
+ return value.get_int()
+
+
++def _get_inspection_icon_pixbuf(vm, w, h):
++ # libguestfs gives us the PNG data as a string.
++ png_data = vm.inspection.icon
++ if png_data is None:
++ return None
++
++ try:
++ pb = GdkPixbuf.PixbufLoader()
++ pb.set_size(w, h)
++ pb.write(png_data)
++ pb.close()
++ return pb.get_pixbuf()
++ except:
++ logging.exception("Error loading inspection icon data")
++ vm.inspection.icon = None
++ return None
++
++
+ class vmmManager(vmmGObjectUI):
+ __gsignals__ = {
+ "action-show-connect": (GObject.SignalFlags.RUN_FIRST, None, []),
+@@ -380,11 +396,9 @@ class vmmManager(vmmGObjectUI):
+
+ rowtypes = []
+ rowtypes.insert(ROW_HANDLE, object) # backing object
+- rowtypes.insert(ROW_NAME, str) # object name
++ rowtypes.insert(ROW_SORT_KEY, str) # object name
+ rowtypes.insert(ROW_MARKUP, str) # row markup text
+- rowtypes.insert(ROW_STATUS, str) # object status string
+ rowtypes.insert(ROW_STATUS_ICON, str) # status icon name
+- rowtypes.insert(ROW_KEY, str) # key/uuid
+ rowtypes.insert(ROW_HINT, str) # row tooltip
+ rowtypes.insert(ROW_IS_CONN, bool) # if object is a connection
+ rowtypes.insert(ROW_IS_CONN_CONNECTED, bool) # if conn is connected
+@@ -764,8 +778,8 @@ class vmmManager(vmmGObjectUI):
+ hint += " (%s)" % _("Double click to connect")
+ return hint
+
+- def _build_conn_markup(self, conn, row):
+- name = util.xml_escape(row[ROW_NAME])
++ def _build_conn_markup(self, conn, name):
++ name = util.xml_escape(name)
+ text = name
+ if conn.state == conn.STATE_DISCONNECTED:
+ text += " - " + _("Not Connected")
+@@ -781,31 +795,44 @@ class vmmManager(vmmGObjectUI):
+ color = "#5b5b5b"
+ return color
+
+- def _build_vm_markup(self, row):
++ def _build_vm_markup(self, name, status):
+ domtext = ("<span size='smaller' weight='bold'>%s</span>" %
+- util.xml_escape(row[ROW_NAME]))
+- statetext = "<span size='smaller'>%s</span>" % row[ROW_STATUS]
++ util.xml_escape(name))
++ statetext = "<span size='smaller'>%s</span>" % status
+ return domtext + "\n" + statetext
+
+- def _build_vm_row(self, vm):
+- row = []
++ def _build_row(self, conn, vm):
++ if conn:
++ name = conn.get_pretty_desc_inactive(False)
++ markup = self._build_conn_markup(conn, name)
++ status = ("<span size='smaller'>%s</span>" %
++ conn.get_state_text())
++ status_icon = None
++ hint = self._build_conn_hint(conn)
++ color = self._build_conn_color(conn)
++ os_icon = None
++ else:
++ name = vm.get_name()
++ status = vm.run_status()
++ markup = self._build_vm_markup(name, status)
++ status_icon = vm.run_status_icon_name()
++ hint = vm.get_description()
++ color = None
++ os_icon = _get_inspection_icon_pixbuf(vm, 16, 16)
+
+- row.insert(ROW_HANDLE, vm)
+- row.insert(ROW_NAME, vm.get_name())
+- row.insert(ROW_MARKUP, "")
+- row.insert(ROW_STATUS, vm.run_status())
+- row.insert(ROW_STATUS_ICON, vm.run_status_icon_name())
+- row.insert(ROW_KEY, vm.get_uuid())
+- row.insert(ROW_HINT, util.xml_escape(vm.get_description()))
+- row.insert(ROW_IS_CONN, False)
+- row.insert(ROW_IS_CONN_CONNECTED, True)
+- row.insert(ROW_IS_VM, True)
+- row.insert(ROW_IS_VM_RUNNING, vm.is_active())
+- row.insert(ROW_COLOR, None)
+- row.insert(ROW_INSPECTION_OS_ICON,
+- self.get_inspection_icon_pixbuf(vm, 16, 16))
+-
+- row[ROW_MARKUP] = self._build_vm_markup(row)
++ row = []
++ row.insert(ROW_HANDLE, conn or vm)
++ row.insert(ROW_SORT_KEY, name)
++ row.insert(ROW_MARKUP, markup)
++ row.insert(ROW_STATUS_ICON, status_icon)
++ row.insert(ROW_HINT, util.xml_escape(hint))
++ row.insert(ROW_IS_CONN, bool(conn))
++ row.insert(ROW_IS_CONN_CONNECTED,
++ bool(conn) and conn.state != conn.STATE_DISCONNECTED)
++ row.insert(ROW_IS_VM, bool(vm))
++ row.insert(ROW_IS_VM_RUNNING, bool(vm) and vm.is_active())
++ row.insert(ROW_COLOR, color)
++ row.insert(ROW_INSPECTION_OS_ICON, os_icon)
+
+ return row
+
+@@ -814,7 +841,7 @@ class vmmManager(vmmGObjectUI):
+ if row_key in self.rows:
+ return
+
+- row = self._build_vm_row(vm)
++ row = self._build_row(None, vm)
+ parent = self.rows[conn.get_uri()].iter
+
+ _iter = model.append(parent, row)
+@@ -824,28 +851,8 @@ class vmmManager(vmmGObjectUI):
+ # Expand a connection when adding a vm to it
+ self.widget("vm-list").expand_row(model.get_path(parent), False)
+
+- def _build_conn_row(self, conn):
+- row = []
+- row.insert(ROW_HANDLE, conn)
+- row.insert(ROW_NAME, conn.get_pretty_desc_inactive(False))
+- row.insert(ROW_MARKUP, self._build_conn_markup(conn, row))
+- row.insert(ROW_STATUS, ("<span size='smaller'>%s</span>" %
+- conn.get_state_text()))
+- row.insert(ROW_STATUS_ICON, None)
+- row.insert(ROW_KEY, conn.get_uri())
+- row.insert(ROW_HINT, self._build_conn_hint(conn))
+- row.insert(ROW_IS_CONN, True)
+- row.insert(ROW_IS_CONN_CONNECTED,
+- conn.state != conn.STATE_DISCONNECTED)
+- row.insert(ROW_IS_VM, False)
+- row.insert(ROW_IS_VM_RUNNING, False)
+- row.insert(ROW_COLOR, self._build_conn_color(conn))
+- row.insert(ROW_INSPECTION_OS_ICON, None)
+-
+- return row
+-
+ def _append_conn(self, model, conn):
+- row = self._build_conn_row(conn)
++ row = self._build_row(conn, None)
+
+ _iter = model.append(None, row)
+ path = model.get_path(_iter)
+@@ -877,11 +884,11 @@ class vmmManager(vmmGObjectUI):
+ if row[ROW_IS_CONN]:
+ connrows.append(row)
+ for row in connrows:
+- descs.append(row[ROW_NAME])
++ descs.append(row[ROW_SORT_KEY])
+
+ for row in connrows:
+ conn = row[ROW_HANDLE]
+- name = row[ROW_NAME]
++ name = row[ROW_SORT_KEY]
+ if descs.count(name) <= 1:
+ continue
+
+@@ -919,7 +926,7 @@ class vmmManager(vmmGObjectUI):
+ missing = True
+ for row in range(model.iter_n_children(parent)):
+ _iter = model.iter_nth_child(parent, row)
+- if model.get_value(_iter, ROW_KEY) == vm.get_uuid():
++ if model.get_value(_iter, ROW_HANDLE) == vm:
+ missing = False
+ break
+
+@@ -931,20 +938,18 @@ class vmmManager(vmmGObjectUI):
+ self.vm_resources_sampled(vm)
+
+ def vm_resources_sampled(self, vm, config_changed=False):
+- vmlist = self.widget("vm-list")
+- model = vmlist.get_model()
+-
+- if self.vm_row_key(vm) not in self.rows:
++ row = self.rows.get(self.vm_row_key(vm), None)
++ if row is None:
+ return
+
+-
+ try:
+- row = self.rows[self.vm_row_key(vm)]
+- row[ROW_NAME] = vm.get_name()
+- row[ROW_STATUS] = vm.run_status()
++ name = vm.get_name()
++ status = vm.run_status()
++
++ row[ROW_SORT_KEY] = name
+ row[ROW_STATUS_ICON] = vm.run_status_icon_name()
+ row[ROW_IS_VM_RUNNING] = vm.is_active()
+- row[ROW_MARKUP] = self._build_vm_markup(row)
++ row[ROW_MARKUP] = self._build_vm_markup(name, status)
+
+ if config_changed:
+ desc = vm.get_description()
+@@ -956,53 +961,32 @@ class vmmManager(vmmGObjectUI):
+ return
+ raise
+
+- model.row_changed(row.path, row.iter)
++ self.widget("vm-list").get_model().row_changed(row.path, row.iter)
+
+ def vm_inspection_changed(self, vm):
+- vmlist = self.widget("vm-list")
+- model = vmlist.get_model()
+-
+- if self.vm_row_key(vm) not in self.rows:
++ row = self.rows.get(self.vm_row_key(vm), None)
++ if row is None:
+ return
+
+ row = self.rows[self.vm_row_key(vm)]
+- new_icon = self.get_inspection_icon_pixbuf(vm, 16, 16)
++ new_icon = _get_inspection_icon_pixbuf(vm, 16, 16)
+ if not can_set_row_none:
+ new_icon = new_icon or ""
+ row[ROW_INSPECTION_OS_ICON] = new_icon
+- model.row_changed(row.path, row.iter)
+-
+- def get_inspection_icon_pixbuf(self, vm, w, h):
+- # libguestfs gives us the PNG data as a string.
+- png_data = vm.inspection.icon
+- if png_data is None:
+- return None
+
+- try:
+- pb = GdkPixbuf.PixbufLoader()
+- pb.set_size(w, h)
+- pb.write(png_data)
+- pb.close()
+- return pb.get_pixbuf()
+- except:
+- logging.exception("Error loading inspection icon data")
+- vm.inspection.icon = None
+- return None
++ self.widget("vm-list").get_model().row_changed(row.path, row.iter)
+
+ def conn_state_changed(self, conn):
+ self.conn_resources_sampled(conn)
+ self.vm_selected()
+
+ def conn_resources_sampled(self, conn, newname=None):
+- vmlist = self.widget("vm-list")
+- model = vmlist.get_model()
++ model = self.widget("vm-list").get_model()
+ row = self.rows[conn.get_uri()]
+
+ if newname:
+- row[ROW_NAME] = newname
+- row[ROW_MARKUP] = self._build_conn_markup(conn, row)
+- row[ROW_STATUS] = ("<span size='smaller'>%s</span>" %
+- conn.get_state_text())
++ row[ROW_SORT_KEY] = newname
++ row[ROW_MARKUP] = self._build_conn_markup(conn, row[ROW_SORT_KEY])
+ row[ROW_IS_CONN_CONNECTED] = conn.state != conn.STATE_DISCONNECTED
+ row[ROW_COLOR] = self._build_conn_color(conn)
+ row[ROW_HINT] = self._build_conn_hint(conn)
+@@ -1131,8 +1115,8 @@ class vmmManager(vmmGObjectUI):
+ #################
+
+ def vmlist_name_sorter(self, model, iter1, iter2, ignore):
+- return cmp(model.get_value(iter1, ROW_NAME),
+- model.get_value(iter2, ROW_NAME))
++ return cmp(model.get_value(iter1, ROW_SORT_KEY),
++ model.get_value(iter2, ROW_SORT_KEY))
+
+ def vmlist_guest_cpu_usage_sorter(self, model, iter1, iter2, ignore):
+ obj1 = model.get_value(iter1, ROW_HANDLE)
diff --git a/0007-manager-Separate-stats-and-state-update-callbacks.patch b/0007-manager-Separate-stats-and-state-update-callbacks.patch
new file mode 100644
index 0000000..2a762e0
--- /dev/null
+++ b/0007-manager-Separate-stats-and-state-update-callbacks.patch
@@ -0,0 +1,204 @@
+From ed5dc524c54e72ee7f75749f11eb0606dddee8ea Mon Sep 17 00:00:00 2001
+From: Cole Robinson <crobinso at redhat.com>
+Date: Mon, 2 Sep 2013 09:09:31 -0400
+Subject: [PATCH] manager: Separate stats and state update callbacks
+
+There's no need to be resetting row keys like VM name, state, on every
+'resources-sampled' signals, since we have had finer grained status-changed
+and config-changed signals for a while. This seems to reduce the memory
+leak on F19 as well.
+
+(cherry picked from commit f141c77c452d4807b516bdc40a0e86235bf5243a)
+
+Conflicts:
+ virtManager/manager.py
+---
+ virtManager/manager.py | 100 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 53 insertions(+), 47 deletions(-)
+
+diff --git a/virtManager/manager.py b/virtManager/manager.py
+index 2770b2f..6773ff3 100644
+--- a/virtManager/manager.py
++++ b/virtManager/manager.py
+@@ -185,9 +185,9 @@ class vmmManager(vmmGObjectUI):
+ self.init_toolbar()
+ self.init_context_menus()
+
+- self.vm_selected()
+- self.widget("vm-list").get_selection().connect("changed",
+- self.vm_selected)
++ self.update_current_selection()
++ self.widget("vm-list").get_selection().connect(
++ "changed", self.update_current_selection)
+
+ self.max_disk_rate = 10.0
+ self.max_net_rate = 10.0
+@@ -750,9 +750,9 @@ class vmmManager(vmmGObjectUI):
+
+ def vm_added(self, conn, vmuuid):
+ vm = conn.get_vm(vmuuid)
++ vm.connect("config-changed", self.vm_config_changed)
+ vm.connect("status-changed", self.vm_status_changed)
+- vm.connect("resources-sampled", self.vm_resources_sampled)
+- vm.connect("config-changed", self.vm_resources_sampled, True)
++ vm.connect("resources-sampled", self.vm_row_updated)
+ vm.connect("inspection-changed", self.vm_inspection_changed)
+
+ vmlist = self.widget("vm-list")
+@@ -868,7 +868,7 @@ class vmmManager(vmmGObjectUI):
+
+ conn.connect("vm-added", self.vm_added)
+ conn.connect("vm-removed", self.vm_removed)
+- conn.connect("resources-sampled", self.conn_resources_sampled)
++ conn.connect("resources-sampled", self.conn_row_updated)
+ conn.connect("state-changed", self.conn_state_changed)
+ conn.connect("connect-error", self._connect_error)
+
+@@ -893,7 +893,7 @@ class vmmManager(vmmGObjectUI):
+ continue
+
+ newname = conn.get_pretty_desc_inactive(False, True)
+- self.conn_resources_sampled(conn, newname)
++ self.conn_state_changed(conn, newname=newname)
+
+ def remove_conn(self, engine_ignore, uri):
+ model = self.widget("vm-list").get_model()
+@@ -916,28 +916,13 @@ class vmmManager(vmmGObjectUI):
+ # State/UI updating methods #
+ #############################
+
+- def vm_status_changed(self, vm, oldstatus, newstatus):
+- ignore = newstatus
+- ignore = oldstatus
+- parent = self.rows[vm.conn.get_uri()].iter
+- vmlist = self.widget("vm-list")
+- model = vmlist.get_model()
+-
+- missing = True
+- for row in range(model.iter_n_children(parent)):
+- _iter = model.iter_nth_child(parent, row)
+- if model.get_value(_iter, ROW_HANDLE) == vm:
+- missing = False
+- break
+-
+- if missing:
+- self._append_vm(model, vm, vm.conn)
+-
+- # Update run/shutdown/pause button states
+- self.vm_selected()
+- self.vm_resources_sampled(vm)
++ def vm_row_updated(self, vm):
++ row = self.rows.get(self.vm_row_key(vm), None)
++ if row is None:
++ return
++ self.widget("vm-list").get_model().row_changed(row.path, row.iter)
+
+- def vm_resources_sampled(self, vm, config_changed=False):
++ def vm_config_changed(self, vm):
+ row = self.rows.get(self.vm_row_key(vm), None)
+ if row is None:
+ return
+@@ -951,17 +936,37 @@ class vmmManager(vmmGObjectUI):
+ row[ROW_IS_VM_RUNNING] = vm.is_active()
+ row[ROW_MARKUP] = self._build_vm_markup(name, status)
+
+- if config_changed:
+- desc = vm.get_description()
+- if not can_set_row_none:
+- desc = desc or ""
+- row[ROW_HINT] = util.xml_escape(desc)
++ desc = vm.get_description()
++ if not can_set_row_none:
++ desc = desc or ""
++ row[ROW_HINT] = util.xml_escape(desc)
+ except libvirt.libvirtError, e:
+ if uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
+ return
+ raise
+
+- self.widget("vm-list").get_model().row_changed(row.path, row.iter)
++ self.vm_row_updated(vm)
++
++ def vm_status_changed(self, vm, oldstatus, newstatus):
++ ignore = newstatus
++ ignore = oldstatus
++ parent = self.rows[vm.conn.get_uri()].iter
++ vmlist = self.widget("vm-list")
++ model = vmlist.get_model()
++
++ missing = True
++ for row in range(model.iter_n_children(parent)):
++ _iter = model.iter_nth_child(parent, row)
++ if model.get_value(_iter, ROW_HANDLE) == vm:
++ missing = False
++ break
++
++ if missing:
++ self._append_vm(model, vm, vm.conn)
++
++ # Update run/shutdown/pause button states
++ self.update_current_selection()
++ self.vm_config_changed(vm)
+
+ def vm_inspection_changed(self, vm):
+ row = self.rows.get(self.vm_row_key(vm), None)
+@@ -974,16 +979,10 @@ class vmmManager(vmmGObjectUI):
+ new_icon = new_icon or ""
+ row[ROW_INSPECTION_OS_ICON] = new_icon
+
+- self.widget("vm-list").get_model().row_changed(row.path, row.iter)
+-
+- def conn_state_changed(self, conn):
+- self.conn_resources_sampled(conn)
+- self.vm_selected()
++ self.vm_row_updated(vm)
+
+- def conn_resources_sampled(self, conn, newname=None):
+- model = self.widget("vm-list").get_model()
++ def conn_state_changed(self, conn, newname=None):
+ row = self.rows[conn.get_uri()]
+-
+ if newname:
+ row[ROW_SORT_KEY] = newname
+ row[ROW_MARKUP] = self._build_conn_markup(conn, row[ROW_SORT_KEY])
+@@ -994,20 +993,27 @@ class vmmManager(vmmGObjectUI):
+ if conn.get_state() in [vmmConnection.STATE_DISCONNECTED,
+ vmmConnection.STATE_CONNECTING]:
+ # Connection went inactive, delete any VM child nodes
+- parent = self.rows[conn.get_uri()].iter
++ parent = row.iter
+ if parent is not None:
++ model = self.widget("vm-list").get_model()
+ child = model.iter_children(parent)
+ while child is not None:
+- del self.rows[self.vm_row_key(model.get_value(child,
+- ROW_HANDLE))]
++ vm = model[child][ROW_HANDLE]
++ del self.rows[self.vm_row_key(vm)]
+ model.remove(child)
+ child = model.iter_children(parent)
+
++ self.conn_row_updated(conn)
++ self.update_current_selection()
++
++ def conn_row_updated(self, conn):
++ row = self.rows[conn.get_uri()]
++
+ self.max_disk_rate = max(self.max_disk_rate, conn.disk_io_max_rate())
+ self.max_net_rate = max(self.max_net_rate,
+ conn.network_traffic_max_rate())
+
+- model.row_changed(row.path, row.iter)
++ self.widget("vm-list").get_model().row_changed(row.path, row.iter)
+
+ def change_run_text(self, can_restore):
+ if can_restore:
+@@ -1019,7 +1025,7 @@ class vmmManager(vmmGObjectUI):
+ self.vmmenu_items["run"].get_child().set_label(text)
+ self.widget("vm-run").set_label(strip_text)
+
+- def vm_selected(self, ignore=None):
++ def update_current_selection(self, ignore=None):
+ vm = self.current_vm()
+
+ show_open = bool(vm)
diff --git a/virt-manager.spec b/virt-manager.spec
index f0aedb8..1b5f9f7 100644
--- a/virt-manager.spec
+++ b/virt-manager.spec
@@ -21,7 +21,7 @@
%define _version 0.10.0
-%define _release 1
+%define _release 2
# This macro is used for the continuous automated builds. It just
@@ -40,6 +40,17 @@ Group: Applications/Emulators
License: GPLv2+
URL: http://virt-manager.org/
Source0: http://virt-manager.org/download/sources/%{name}/%{name}-%{version}.tar.gz
+
+# Fix parsing rawhide .treeinfo (bz #989162)
+Patch0001: 0001-Fix-rawhide-URL-installs.patch
+# Fix spice with TLS (bz #904295)
+Patch0002: 0002-console-Fix-spice-with-TLS-bz-904295.patch
+# Reduce impact of memory leak (bz #972371)
+Patch0003: 0003-manager-Disable-graph-data-func-if-graph-isn-t-visib.patch
+Patch0004: 0004-inspection-Check-can_set_row_none-before-setting-ico.patch
+Patch0005: 0005-virt-manager-ignore-VIR_ERR_NO_DOMAIN-when-a-domain-.patch
+Patch0006: 0006-manager-Merge-some-row-creation-drop-unneeded-row-ke.patch
+Patch0007: 0007-manager-Separate-stats-and-state-update-callbacks.patch
BuildArch: noarch
@@ -104,6 +115,17 @@ machine).
%prep
%setup -q
+# Fix parsing rawhide .treeinfo (bz #989162)
+%patch0001 -p1
+# Fix spice with TLS (bz #904295)
+%patch0002 -p1
+# Reduce impact of memory leak (bz #972371)
+%patch0003 -p1
+%patch0004 -p1
+%patch0005 -p1
+%patch0006 -p1
+%patch0007 -p1
+
%build
%if %{qemu_user}
%define _qemu_user --qemu-user=%{qemu_user}
@@ -213,6 +235,11 @@ fi
%changelog
+* Tue Sep 24 2013 Cole Robinson <crobinso at redhat.com> - 0.10.0-2
+- Fix parsing rawhide .treeinfo (bz #989162)
+- Fix spice with TLS (bz #904295)
+- Reduce impact of memory leak (bz #972371)
+
* Wed Jun 19 2013 Cole Robinson <crobinso at redhat.com> - 0.10.0-1
- Rebased to version 0.10.0
- Fix screenshots (bz #969410)
More information about the scm-commits
mailing list