From 7d28697e61cb5d697aa2e98edf02c0c31d805962 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sep 18 2009 14:50:44 +0000 Subject: Fix migration for qemu/kvm guests (bz 517548) Fix sparse allocation confusion (bz 504605) Czech translation typo (bz 504385) Use storage browser for iso installs (bz 504326) Fix max/current memory spin button interaction (bz 503786) Make memory and vcpu changes unconditionally persistent (bz 503784) Add pylint script --- diff --git a/virt-manager-0.7.0-czech-typo.patch b/virt-manager-0.7.0-czech-typo.patch new file mode 100644 index 0000000..be9b035 --- /dev/null +++ b/virt-manager-0.7.0-czech-typo.patch @@ -0,0 +1,12 @@ +diff -rup virt-manager-0.7.0/po/cs.po new/po/cs.po +--- virt-manager-0.7.0/po/cs.po 2009-09-17 15:24:54.852374000 -0400 ++++ new/po/cs.po 2009-09-17 15:22:11.927742000 -0400 +@@ -1809,7 +1809,7 @@ msgstr "Vyžadován typ hardware" + + #: ../src/vmm-add-hardware.glade.h:46 + msgid "Hardware type:" +-msgstr "Tzp hardware" ++msgstr "Typ hardware" + + #: ../src/vmm-add-hardware.glade.h:47 ../src/vmm-details.glade.h:44 + msgid "Keymap:" diff --git a/virt-manager-0.7.0-fix-memory-interaction.patch b/virt-manager-0.7.0-fix-memory-interaction.patch new file mode 100644 index 0000000..484d5d4 --- /dev/null +++ b/virt-manager-0.7.0-fix-memory-interaction.patch @@ -0,0 +1,264 @@ +diff -rup old/src/virtManager/details.py virt-manager-0.7.0/src/virtManager/details.py +--- old/src/virtManager/details.py 2009-09-17 17:23:42.640307000 -0400 ++++ virt-manager-0.7.0/src/virtManager/details.py 2009-09-17 17:24:09.098148000 -0400 +@@ -960,11 +960,12 @@ class vmmDetails(gobject.GObject): + curmem = self.window.get_widget("config-memory").get_adjustment() + maxmem = self.window.get_widget("config-maxmem").get_adjustment() + +- + if self.window.get_widget("config-memory-apply").get_property("sensitive"): +- if curmem.value > maxmem.value: +- curmem.value = maxmem.value +- curmem.upper = maxmem.value ++ memval = self.config_get_memory() ++ maxval = self.config_get_maxmem() ++ if maxval < memval: ++ maxmem.value = memval ++ maxmem.lower = memval + else: + curmem.value = int(round(self.vm.get_memory()/1024.0)) + maxmem.value = int(round(self.vm.maximum_memory()/1024.0)) +@@ -1504,54 +1505,74 @@ class vmmDetails(gobject.GObject): + self.vm.set_vcpu_count(vcpus) + self.window.get_widget("config-vcpus-apply").set_sensitive(False) + +- def config_memory_changed(self, src): +- self.window.get_widget("config-memory-apply").set_sensitive(True) ++ def config_get_maxmem(self): ++ maxadj = self.window.get_widget("config-maxmem").get_adjustment() ++ txtmax = self.window.get_widget("config-maxmem").get_text() ++ try: ++ maxmem = int(txtmax) ++ except: ++ maxmem = maxadj.value ++ return maxmem ++ ++ def config_get_memory(self): ++ memadj = self.window.get_widget("config-memory").get_adjustment() ++ txtmem = self.window.get_widget("config-memory").get_text() ++ try: ++ mem = int(txtmem) ++ except: ++ mem = memadj.value ++ return mem + + def config_maxmem_changed(self, src): + self.window.get_widget("config-memory-apply").set_sensitive(True) +- memory = self.window.get_widget("config-maxmem").get_adjustment().value +- memadj = self.window.get_widget("config-memory").get_adjustment() +- memadj.upper = memory +- if memadj.value > memory: +- memadj.value = memory ++ ++ def config_memory_changed(self, src): ++ self.window.get_widget("config-memory-apply").set_sensitive(True) ++ ++ maxadj = self.window.get_widget("config-maxmem").get_adjustment() ++ ++ mem = self.config_get_memory() ++ if maxadj.value < mem: ++ maxadj.value = mem ++ maxadj.lower = mem + + def config_memory_apply(self, src): + self.refresh_config_memory() + exc = None + curmem = None +- maxmem = self.window.get_widget("config-maxmem").get_adjustment() ++ maxmem = self.config_get_maxmem() + if self.window.get_widget("config-memory").get_property("sensitive"): +- curmem = self.window.get_widget("config-memory").get_adjustment() ++ curmem = self.config_get_memory() + +- logging.info("Setting max-memory for " + self.vm.get_name() + \ +- " to " + str(maxmem.value)) ++ logging.info("Setting max-memory for " + self.vm.get_name() + ++ " to " + str(maxmem)) + + actual_cur = self.vm.get_memory() + if curmem is not None: +- logging.info("Setting memory for " + self.vm.get_name() + \ +- " to " + str(curmem.value)) +- if (maxmem.value * 1024) < actual_cur: ++ logging.info("Setting memory for " + self.vm.get_name() + ++ " to " + str(curmem)) ++ if (maxmem * 1024) < actual_cur: + # Set current first to avoid error + try: +- self.vm.set_memory(curmem.value * 1024) +- self.vm.set_max_memory(maxmem.value * 1024) ++ self.vm.set_memory(curmem * 1024) ++ self.vm.set_max_memory(maxmem * 1024) + except Exception, e: + exc = e + else: + try: +- self.vm.set_max_memory(maxmem.value * 1024) +- self.vm.set_memory(curmem.value * 1024) ++ self.vm.set_max_memory(maxmem * 1024) ++ self.vm.set_memory(curmem * 1024) + except Exception, e: + exc = e + + else: + try: +- self.vm.set_max_memory(maxmem.value * 1024) ++ self.vm.set_max_memory(maxmem * 1024) + except Exception, e: + exc = e + + if exc: +- self.err.show_err(_("Error changing memory values: %s" % str(e)),\ ++ self.err.show_err(_("Error changing memory values: %s" % str(e)), + "".join(traceback.format_exc())) + else: + self.window.get_widget("config-memory-apply").set_sensitive(False) +diff -rup old/src/virtManager/details.py.orig virt-manager-0.7.0/src/virtManager/details.py.orig +--- old/src/virtManager/details.py.orig 2009-09-17 17:23:42.778305000 -0400 ++++ virt-manager-0.7.0/src/virtManager/details.py.orig 2009-09-17 17:24:08.925149000 -0400 +@@ -501,7 +501,7 @@ class vmmDetails(gobject.GObject): + self.update_scaling() + + def auth_login(self, ignore): +- self.set_password() ++ self.set_credentials() + self.activate_viewer_page() + + def toggle_toolbar(self, src): +@@ -1309,23 +1309,44 @@ class vmmDetails(gobject.GObject): + traceback.format_exc (stacktrace)) + logging.error(details) + +- def set_password(self, src=None): +- txt = self.window.get_widget("console-auth-password") +- self.vncViewer.set_credential(gtkvnc.CREDENTIAL_PASSWORD, +- txt.get_text()) ++ def set_credentials(self, src=None): ++ passwd = self.window.get_widget("console-auth-password") ++ if passwd.flags() & gtk.VISIBLE: ++ self.vncViewer.set_credential(gtkvnc.CREDENTIAL_PASSWORD, ++ passwd.get_text()) ++ username = self.window.get_widget("console-auth-username") ++ if username.flags() & gtk.VISIBLE: ++ self.vncViewer.set_credential(gtkvnc.CREDENTIAL_USERNAME, ++ username.get_text()) ++ ++ if self.window.get_widget("console-auth-remember").get_active(): ++ self.config.set_console_password(self.vm, passwd.get_text(), username.get_text()) + + def _vnc_auth_credential(self, src, credList): + for i in range(len(credList)): ++ if credList[i] not in (gtkvnc.CREDENTIAL_PASSWORD, gtkvnc.CREDENTIAL_USERNAME, gtkvnc.CREDENTIAL_CLIENTNAME): ++ self.err.show_err(summary=_("Unable to provide requested credentials to the VNC server"), ++ details=_("The credential type %s is not supported") % (str(credList[i])), ++ title=_("Unable to authenticate"), ++ async=True) ++ self.vncViewerRetriesScheduled = 10 ++ self.vncViewer.close() ++ self.activate_unavailable_page(_("Unsupported console authentication type")) ++ return ++ ++ withUsername = False ++ withPassword = False ++ for i in range(len(credList)): + logging.debug("Got credential request %s", str(credList[i])) + if credList[i] == gtkvnc.CREDENTIAL_PASSWORD: +- self.activate_auth_page() ++ withPassword = True ++ elif credList[i] == gtkvnc.CREDENTIAL_USERNAME: ++ withUsername = True + elif credList[i] == gtkvnc.CREDENTIAL_CLIENTNAME: + self.vncViewer.set_credential(credList[i], "libvirt-vnc") +- else: +- # Force it to stop re-trying +- self.vncViewerRetriesScheduled = 10 +- self.vncViewer.close() +- self.activate_unavailable_page(_("Unsupported console authentication type")) ++ ++ if withUsername or withPassword: ++ self.activate_auth_page(withPassword, withUsername) + + def activate_unavailable_page(self, msg): + self.window.get_widget("console-pages").set_current_page(PAGE_UNAVAILABLE) +@@ -1336,20 +1357,41 @@ class vmmDetails(gobject.GObject): + self.window.get_widget("console-pages").set_current_page(PAGE_SCREENSHOT) + self.window.get_widget("details-menu-vm-screenshot").set_sensitive(True) + +- def activate_auth_page(self): +- pw = self.config.get_console_password(self.vm) ++ def activate_auth_page(self, withPassword=True, withUsername=False): ++ (pw, username) = self.config.get_console_password(self.vm) + self.window.get_widget("details-menu-vm-screenshot").set_sensitive(False) ++ ++ if withPassword: ++ self.window.get_widget("console-auth-password").show() ++ self.window.get_widget("label-auth-password").show() ++ else: ++ self.window.get_widget("console-auth-password").hide() ++ self.window.get_widget("label-auth-password").hide() ++ ++ if withUsername: ++ self.window.get_widget("console-auth-username").show() ++ self.window.get_widget("label-auth-username").show() ++ else: ++ self.window.get_widget("console-auth-username").hide() ++ self.window.get_widget("label-auth-username").hide() ++ ++ self.window.get_widget("console-auth-username").set_text(username) + self.window.get_widget("console-auth-password").set_text(pw) +- self.window.get_widget("console-auth-password").grab_focus() ++ + if self.config.has_keyring(): + self.window.get_widget("console-auth-remember").set_sensitive(True) +- if pw != None and pw != "": ++ if pw != "" or username != "": + self.window.get_widget("console-auth-remember").set_active(True) + else: + self.window.get_widget("console-auth-remember").set_active(False) + else: + self.window.get_widget("console-auth-remember").set_sensitive(False) + self.window.get_widget("console-pages").set_current_page(PAGE_AUTHENTICATE) ++ if withUsername: ++ self.window.get_widget("console-auth-username").grab_focus() ++ else: ++ self.window.get_widget("console-auth-password").grab_focus() ++ + + def activate_viewer_page(self): + self.window.get_widget("console-pages").set_current_page(PAGE_VNCVIEWER) +diff -rup old/src/vmm-details.glade virt-manager-0.7.0/src/vmm-details.glade +--- old/src/vmm-details.glade 2009-09-17 17:23:42.448302000 -0400 ++++ virt-manager-0.7.0/src/vmm-details.glade 2009-09-17 17:25:42.970347000 -0400 +@@ -1436,7 +1436,6 @@ I/O: + + + 2 +- True + + + +@@ -1572,8 +1571,8 @@ I/O: + + True + True +- 50 50 32000 5 10 0 +- 1 ++ 50 50 32000 1 25 0 ++ 2 + True + GTK_UPDATE_IF_VALID + +@@ -1610,8 +1609,8 @@ I/O: + + True + True +- 50 50 32000 5 10 0 +- 1 ++ 50 50 32000 1 25 0 ++ 2 + True + GTK_UPDATE_IF_VALID + +Only in virt-manager-0.7.0/src: vmm-details.glade.orig +Only in virt-manager-0.7.0/src: vmm-details.glade.rej +Only in virt-manager-0.7.0/src: .vmm-details.glade.rej.swp diff --git a/virt-manager-0.7.0-fix-sparse-knob.patch b/virt-manager-0.7.0-fix-sparse-knob.patch new file mode 100644 index 0000000..9ad6525 --- /dev/null +++ b/virt-manager-0.7.0-fix-sparse-knob.patch @@ -0,0 +1,31 @@ +# HG changeset patch +# User Cole Robinson +# Date 1245180678 14400 +# Node ID bd26943d4dadf3be993c44ff8401c6426fd94488 +# Parent f9ad1d0c29d08bbb0ed94df9878d666904d018a2 +Correctly handle non sparse request in VM wizard. (Mark McLoughlin) + +We currently have it backwards, so a sparse request actually asks for +nonsparse. We didn't see this much, since until recently virtinst wasn't +allowing nonsparse volume allocation. + +diff -r f9ad1d0c29d0 -r bd26943d4dad src/virtManager/create.py +--- a/src/virtManager/create.py Thu Jun 04 16:28:40 2009 -0400 ++++ b/src/virtManager/create.py Tue Jun 16 15:31:18 2009 -0400 +@@ -820,14 +820,14 @@ + def get_storage_info(self): + path = None + size = self.window.get_widget("config-storage-size").get_value() +- nosparse = self.window.get_widget("config-storage-nosparse").get_active() ++ sparse = not self.window.get_widget("config-storage-nosparse").get_active() + if self.window.get_widget("config-storage-create").get_active(): + path = self.get_default_path(self.guest.name) + logging.debug("Default storage path is: %s" % path) + else: + path = self.window.get_widget("config-storage-entry").get_text() + +- return (path, size, nosparse) ++ return (path, size, sparse) + + def get_default_path(self, name): + path = "" diff --git a/virt-manager-0.7.0-iso-storage-browser.patch b/virt-manager-0.7.0-iso-storage-browser.patch new file mode 100644 index 0000000..c56337e --- /dev/null +++ b/virt-manager-0.7.0-iso-storage-browser.patch @@ -0,0 +1,179 @@ +diff -rup old/src/virtManager/choosecd.py virt-manager-0.7.0/src/virtManager/choosecd.py +--- old/src/virtManager/choosecd.py 2009-09-17 17:12:16.317469000 -0400 ++++ virt-manager-0.7.0/src/virtManager/choosecd.py 2009-09-17 17:12:26.626644000 -0400 +@@ -23,8 +23,8 @@ import logging + + import virtinst + +-from virtManager import util + from virtManager.opticalhelper import vmmOpticalDriveHelper ++from virtManager.storagebrowse import vmmStorageBrowser + from virtManager.error import vmmErrorDialog + + class vmmChooseCD(gobject.GObject): +@@ -39,10 +39,13 @@ class vmmChooseCD(gobject.GObject): + 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, + _("Unexpected Error"), + _("An unexpected error occurred")) ++ self.topwin = self.window.get_widget("vmm-choose-cd") ++ self.topwin.hide() ++ + self.config = config +- self.window.get_widget("vmm-choose-cd").hide() + self.dev_id_info = dev_id_info + self.conn = connection ++ self.storage_browser = None + + self.window.signal_autoconnect({ + "on_media_toggled": self.media_toggled, +@@ -130,9 +133,7 @@ class vmmChooseCD(gobject.GObject): + pass + + def browse_fv_iso_location(self, ignore1=None, ignore2=None): +- filename = self._browse_file(_("Locate ISO Image")) +- if filename != None: +- self.window.get_widget("iso-path").set_text(filename) ++ self._browse_file(_("Locate ISO Image")) + + def populate_opt_media(self): + try: +@@ -143,9 +144,17 @@ class vmmChooseCD(gobject.GObject): + logging.error("Unable to create optical-helper widget: '%s'", e) + self.window.get_widget("physical-media").set_sensitive(False) + +- def _browse_file(self, dialog_name, folder=None, _type=None): +- return util.browse_local(self.window.get_widget("vmm-choose-cd"), +- dialog_name, folder, _type) ++ def set_storage_path(self, src, path): ++ self.window.get_widget("iso-path").set_text(path) + ++ def _browse_file(self, dialog_name): ++ if self.storage_browser == None: ++ self.storage_browser = vmmStorageBrowser(self.config, self.conn) ++ #self.topwin) ++ self.storage_browser.connect("storage-browse-finish", ++ self.set_storage_path) ++ self.storage_browser.local_args = { "dialog_name": dialog_name } ++ self.storage_browser.show(self.conn) ++ return None + + gobject.type_register(vmmChooseCD) +diff -rup old/src/virtManager/create.py virt-manager-0.7.0/src/virtManager/create.py +--- old/src/virtManager/create.py 2009-09-17 17:12:16.371469000 -0400 ++++ virt-manager-0.7.0/src/virtManager/create.py 2009-09-17 17:14:56.395189000 -0400 +@@ -997,18 +997,16 @@ class vmmCreate(gobject.GObject): + nodetect_label.show() + + def browse_iso(self, ignore1=None, ignore2=None): +- f = self._browse_file(_("Locate ISO Image"), is_media=True) +- if f != None: +- self.window.get_widget("install-local-entry").set_text(f) ++ self._browse_file(_("Locate ISO Image"), ++ self.set_iso_storage_path) + self.window.get_widget("install-local-entry").activate() + + def toggle_enable_storage(self, src): + self.window.get_widget("config-storage-box").set_sensitive(src.get_active()) + + def browse_storage(self, ignore1): +- f = self._browse_file(_("Locate existing storage")) +- if f != None: +- self.window.get_widget("config-storage-entry").set_text(f) ++ self._browse_file(_("Locate existing storage"), ++ self.set_disk_storage_path) + + def toggle_storage_select(self, src): + act = src.get_active() +@@ -1017,13 +1015,11 @@ class vmmCreate(gobject.GObject): + def toggle_macaddr(self, src): + self.window.get_widget("config-macaddr").set_sensitive(src.get_active()) + +- def set_storage_path(self, src, path): +- notebook = self.window.get_widget("create-pages") +- curpage = notebook.get_current_page() +- if curpage == PAGE_INSTALL: +- self.window.get_widget("install-local-entry").set_text(path) +- elif curpage == PAGE_STORAGE: +- self.window.get_widget("config-storage-entry").set_text(path) ++ def set_iso_storage_path(self, ignore, path): ++ self.window.get_widget("install-local-entry").set_text(path) ++ ++ def set_disk_storage_path(self, ignore, path): ++ self.window.get_widget("config-storage-entry").set_text(path) + + # Navigation methods + def set_install_page(self): +@@ -1655,20 +1651,14 @@ class vmmCreate(gobject.GObject): + logging.exception("Error detecting distro.") + self.detectedDistro = (None, None) + +- def _browse_file(self, dialog_name, folder=None, is_media=False): +- +- if self.conn.is_remote() or not is_media: +- if self.storage_browser == None: +- self.storage_browser = vmmStorageBrowser(self.config, +- self.conn) +- self.storage_browser.connect("storage-browse-finish", +- self.set_storage_path) +- self.storage_browser.local_args = { "dialog_name": dialog_name, +- "start_folder": folder} +- self.storage_browser.show(self.conn) +- return None +- +- return util.browse_local(self.topwin, dialog_name, folder) ++ def _browse_file(self, dialog_name, callback, folder=None): ++ if self.storage_browser == None: ++ self.storage_browser = vmmStorageBrowser(self.config, self.conn) ++ ++ self.storage_browser.set_finish_cb(callback) ++ self.storage_browser.local_args = { "dialog_name": dialog_name, ++ "start_folder": folder} ++ self.storage_browser.show(self.conn) + + def show_help(self, ignore): + # No help available yet. +diff -rup old/src/virtManager/create.py.orig virt-manager-0.7.0/src/virtManager/create.py.orig +--- old/src/virtManager/create.py.orig 2009-09-17 17:12:16.548472000 -0400 ++++ virt-manager-0.7.0/src/virtManager/create.py.orig 2009-09-17 17:12:26.597639000 -0400 +@@ -822,14 +822,14 @@ class vmmCreate(gobject.GObject): + def get_storage_info(self): + path = None + size = self.window.get_widget("config-storage-size").get_value() +- nosparse = self.window.get_widget("config-storage-nosparse").get_active() ++ sparse = not self.window.get_widget("config-storage-nosparse").get_active() + if self.window.get_widget("config-storage-create").get_active(): + path = self.get_default_path(self.guest.name) + logging.debug("Default storage path is: %s" % path) + else: + path = self.window.get_widget("config-storage-entry").get_text() + +- return (path, size, nosparse) ++ return (path, size, sparse) + + def get_default_path(self, name): + path = "" +Only in virt-manager-0.7.0/src/virtManager: create.py.rej +Only in virt-manager-0.7.0/src/virtManager: .create.py.rej.swp +diff -rup old/src/virtManager/storagebrowse.py virt-manager-0.7.0/src/virtManager/storagebrowse.py +--- old/src/virtManager/storagebrowse.py 2009-09-17 17:12:16.503470000 -0400 ++++ virt-manager-0.7.0/src/virtManager/storagebrowse.py 2009-09-17 17:12:26.650639000 -0400 +@@ -47,6 +47,7 @@ class vmmStorageBrowser(gobject.GObject) + self.config = config + self.conn = conn + self.conn_signal_ids = [] ++ self.finish_cb_id = None + + self.topwin = self.window.get_widget("vmm-storage-browse") + self.err = vmmErrorDialog(self.topwin, +@@ -83,6 +84,11 @@ class vmmStorageBrowser(gobject.GObject) + self.addvol.close() + return 1 + ++ def set_finish_cb(self, callback): ++ if self.finish_cb_id: ++ self.disconnect(self.finish_cb_id) ++ self.finish_cb_id = self.connect("storage-browse-finish", callback) ++ + def set_initial_state(self): + pool_list = self.window.get_widget("pool-list") + virtManager.host.init_pool_list(pool_list, self.pool_selected) diff --git a/virt-manager-0.7.0-migrate-fixes.patch b/virt-manager-0.7.0-migrate-fixes.patch new file mode 100644 index 0000000..9e69660 --- /dev/null +++ b/virt-manager-0.7.0-migrate-fixes.patch @@ -0,0 +1,29 @@ +# HG changeset patch +# User Cole Robinson +# Date 1236630113 14400 +# Node ID 6126a50801deafa155b17b66cfc3008ffe584b24 +# Parent 3f37d0519b1750666e88e7eaef8d5dfaafc34237 +Fix conn uri lookup for domain migration. + +diff -rup virt-manager-0.6.1/src/virtManager/domain.py new/src/virtManager/domain.py +--- virt-manager-0.6.1/src/virtManager/domain.py 2009-09-13 20:25:12.000000000 -0400 ++++ new/src/virtManager/domain.py 2009-09-13 20:24:29.000000000 -0400 +@@ -1293,11 +1293,15 @@ class vmmDomain(gobject.GObject): + else: + self._disk_io = self._sample_disk_io_dummy + +- +- def migrate(self, dictcon): ++ def migrate(self, destconn): + flags = 0 + if self.lastStatus == libvirt.VIR_DOMAIN_RUNNING: + flags = libvirt.VIR_MIGRATE_LIVE +- self.vm.migrate(self.connection.vmm, flags, None, dictcon.get_short_hostname(), 0) ++ ++ newxml = self.get_xml() ++ ++ self.vm.migrate(destconn.vmm, flags, None, None, 0) ++ ++ destconn.define_domain(newxml) + + gobject.type_register(vmmDomain) diff --git a/virt-manager-0.7.0-pylint-script.patch b/virt-manager-0.7.0-pylint-script.patch new file mode 100644 index 0000000..4a1aeb9 --- /dev/null +++ b/virt-manager-0.7.0-pylint-script.patch @@ -0,0 +1,136 @@ +diff -rupN virt-manager-0.6.1/tests/Makefile.am new/tests/Makefile.am +--- virt-manager-0.6.1/tests/Makefile.am 1969-12-31 19:00:00.000000000 -0500 ++++ new/tests/Makefile.am 2009-03-18 13:05:51.516847000 -0400 +@@ -0,0 +1,4 @@ ++testsdir = $(pkgdatadir)/tests ++tests_DATA = $(wildcard $(srcdir)/*.sh) ++ ++EXTRA_DIST = $(tests_DATA) +diff -rupN virt-manager-0.6.1/tests/pylint-virt-manager.sh new/tests/pylint-virt-manager.sh +--- virt-manager-0.6.1/tests/pylint-virt-manager.sh 1969-12-31 19:00:00.000000000 -0500 ++++ new/tests/pylint-virt-manager.sh 2009-03-18 13:05:51.513848000 -0400 +@@ -0,0 +1,115 @@ ++#!/bin/sh ++ ++# pylint doesn't work well with a file named xxx.py.xxx ++cp src/virt-manager.py.in src/_virt-manager ++ ++cd src || exit 1 ++ ++IGNOREFILES="IPy.py" ++FILES="virtManager/ _virt-manager" ++ ++# Deliberately ignored warnings: ++# Don't print pylint config warning ++NO_PYL_CONFIG=".*No config file found.*" ++ ++# The gettext function is installed in the builtin namespace ++GETTEXT_VAR="Undefined variable '_'" ++ ++# These all work fine and are legit, just false positives ++GOBJECT_VAR="has no '__gobject_init__' member" ++EMIT_VAR="has no 'emit' member" ++ERROR_VBOX="vmmErrorDialog.__init__.*Class 'vbox' has no 'pack_start' member" ++EXCEPTHOOK="no '__excepthook__' member" ++CONNECT_VAR="no 'connect' member" ++DISCONNECT_VAR="no 'disconnect' member" ++ ++# os._exit is needed for forked processes. ++OS_EXIT="protected member _exit of a client class" ++ ++# Avahi API may have requirements on callback argument names, so ignore these ++# warnings ++BTYPE_LIST="(vmmConnect.add_service|vmmConnect.remove_service|vmmConnect.add_conn_to_list)" ++BUILTIN_TYPE="${BTYPE_LIST}.*Redefining built-in 'type'" ++ ++ ++DMSG="" ++addmsg() { ++ DMSG="${DMSG},$1" ++} ++ ++addchecker() { ++ DCHECKERS="${DCHECKERS},$1" ++} ++ ++# Disabled unwanted messages ++addmsg "C0103" # C0103: Name doesn't match some style regex ++addmsg "C0111" # C0111: No docstring ++addmsg "C0301" # C0301: Line too long ++addmsg "C0302" # C0302: Too many lines in module ++addmsg "C0324" # C0324: *Comma not followed by a space* ++addmsg "R0201" # R0201: Method could be a function ++addmsg "W0105" # W0105: String statement has no effect ++addmsg "W0141" # W0141: Complaining about 'map' and 'filter' ++addmsg "W0142" # W0142: *Used * or ** magic* ++addmsg "W0403" # W0403: Relative imports ++addmsg "W0603" # W0603: Using the global statement ++addmsg "W0702" # W0703: No exception type specified ++addmsg "W0703" # W0703: Catch 'Exception' ++addmsg "W0704" # W0704: Exception doesn't do anything ++ ++# Potentially useful messages, disabled for now ++addmsg "C0322" # C0322: *Operator not preceded by a space* ++addmsg "C0323" # C0323: *Operator not followed by a space* ++addmsg "W0201" # W0201: Defined outside __init__ ++addmsg "W0511" # W0511: FIXME and XXX: messages ++addmsg "W0613" # W0613: Unused arguments ++ ++# Disabled Checkers: ++addchecker "Design" # Things like "Too many func arguments", ++ # "Too man public methods" ++addchecker "Similarities" # Finds duplicate code (enable this later?) ++ ++# May want to enable this in the future ++SHOW_REPORT="n" ++ ++AWK=awk ++[ `uname -s` = 'SunOS' ] && AWK=nawk ++ ++pylint --ignore=IPy.py $FILES \ ++ --reports=$SHOW_REPORT \ ++ --output-format=colorized \ ++ --dummy-variables-rgx="dummy|ignore*" \ ++ --disable-msg=${DMSG}\ ++ --disable-checker=${DCHECKERS} 2>&1 | \ ++ egrep -ve "$NO_PYL_CONFIG" \ ++ -ve "$GOBJECT_VAR" \ ++ -ve "$EMIT_VAR" \ ++ -ve "$CONNECT_VAR" \ ++ -ve "$DISCONNECT_VAR" \ ++ -ve "$GETTEXT_VAR" \ ++ -ve "$OS_EXIT" \ ++ -ve "$BUILTIN_TYPE" \ ++ -ve "$ERROR_VBOX" \ ++ -ve "$EXCEPTHOOK" | \ ++$AWK '\ ++# Strip out any "*** Module name" lines if we dont list any errors for them ++BEGIN { found=0; cur_line="" } ++{ ++ if (found == 1) { ++ if ( /\*\*\*/ ) { ++ prev_line = $0 ++ } else { ++ print prev_line ++ print $0 ++ found = 0 ++ } ++ } else if ( /\*\*\*/ ) { ++ found = 1 ++ prev_line = $0 ++ } else { ++ print $0 ++ } ++}' ++ ++cd - > /dev/null ++rm src/_virt-manager +diff -rup virt-manager-0.6.1/Makefile.am new/Makefile.am +--- virt-manager-0.6.1/Makefile.am 2009-01-26 14:33:33.000000000 -0500 ++++ new/Makefile.am 2009-03-18 13:25:07.912999000 -0400 +@@ -11,4 +11,4 @@ rpm: clean + $(MAKE) dist && rpmbuild -ta $(distdir).tar.gz + + check-pylint: +- tests/pylint-virt-manager.sh ++ sh tests/pylint-virt-manager.sh diff --git a/virt-manager-0.7.0-vcpu-mem-persistent.patch b/virt-manager-0.7.0-vcpu-mem-persistent.patch new file mode 100644 index 0000000..eaccbd6 --- /dev/null +++ b/virt-manager-0.7.0-vcpu-mem-persistent.patch @@ -0,0 +1,320 @@ +Only in old/src/virtManager: create.py.orig +Only in old/src/virtManager: delete.py.orig +diff -rup old/src/virtManager/details.py virt-manager-0.7.0/src/virtManager/details.py +--- old/src/virtManager/details.py 2009-09-17 17:31:58.267831000 -0400 ++++ virt-manager-0.7.0/src/virtManager/details.py 2009-09-17 17:45:36.638881000 -0400 +@@ -1502,7 +1502,27 @@ class vmmDetails(gobject.GObject): + def config_vcpus_apply(self, src): + vcpus = self.window.get_widget("config-vcpus").get_adjustment().value + logging.info("Setting vcpus for " + self.vm.get_uuid() + " to " + str(vcpus)) +- self.vm.set_vcpu_count(vcpus) ++ hotplug_err = False ++ ++ try: ++ if self.vm.is_active(): ++ self.vm.hotplug_vcpus(vcpus) ++ except Exception, e: ++ logging.debug("VCPU hotplug failed: %s" % str(e)) ++ hotplug_err = True ++ ++ # Change persistent config ++ try: ++ self.vm.define_vcpus(vcpus) ++ except Exception, e: ++ self.err.show_err(_("Error changing vcpu value: %s" % str(e)), ++ "".join(traceback.format_exc())) ++ return False ++ ++ if hotplug_err: ++ self.err.show_info(_("These changes will take effect after the " ++ "next guest reboot. ")) ++ + self.window.get_widget("config-vcpus-apply").set_sensitive(False) + + def config_get_maxmem(self): +@@ -1538,44 +1558,38 @@ class vmmDetails(gobject.GObject): + + def config_memory_apply(self, src): + self.refresh_config_memory() +- exc = None ++ hotplug_err = False ++ + curmem = None + maxmem = self.config_get_maxmem() + if self.window.get_widget("config-memory").get_property("sensitive"): + curmem = self.config_get_memory() + +- logging.info("Setting max-memory for " + self.vm.get_name() + +- " to " + str(maxmem)) +- +- actual_cur = self.vm.get_memory() +- if curmem is not None: +- logging.info("Setting memory for " + self.vm.get_name() + +- " to " + str(curmem)) +- if (maxmem * 1024) < actual_cur: +- # Set current first to avoid error +- try: +- self.vm.set_memory(curmem * 1024) +- self.vm.set_max_memory(maxmem * 1024) +- except Exception, e: +- exc = e +- else: +- try: +- self.vm.set_max_memory(maxmem * 1024) +- self.vm.set_memory(curmem * 1024) +- except Exception, e: +- exc = e ++ if curmem: ++ curmem = int(curmem) * 1024 ++ if maxmem: ++ maxmem = int(maxmem) * 1024 + +- else: +- try: +- self.vm.set_max_memory(maxmem * 1024) +- except Exception, e: +- exc = e ++ try: ++ if self.vm.is_active(): ++ self.vm.hotplug_both_mem(curmem, maxmem) ++ except Exception, e: ++ logging.debug("Memory hotplug failed: %s" % str(e)) ++ hotplug_err = True + +- if exc: ++ # Change persistent config ++ try: ++ self.vm.define_both_mem(curmem, maxmem) ++ except Exception, e: + self.err.show_err(_("Error changing memory values: %s" % str(e)), + "".join(traceback.format_exc())) +- else: +- self.window.get_widget("config-memory-apply").set_sensitive(False) ++ return ++ ++ if hotplug_err: ++ self.err.show_info(_("These changes will take effect after the " ++ "next guest reboot. ")) ++ ++ self.window.get_widget("config-memory-apply").set_sensitive(False) + + def config_boot_options_changed(self, src): + self.window.get_widget("config-boot-options-apply").set_sensitive(True) +Only in old/src/virtManager: details.py.orig +diff -rup old/src/virtManager/domain.py virt-manager-0.7.0/src/virtManager/domain.py +--- old/src/virtManager/domain.py 2009-09-17 17:31:58.276831000 -0400 ++++ virt-manager-0.7.0/src/virtManager/domain.py 2009-09-17 17:47:15.693255000 -0400 +@@ -23,6 +23,7 @@ import libvirt + import libxml2 + import os + import logging ++import difflib + + from virtManager import util + import virtinst.util as vutil +@@ -113,6 +114,16 @@ class vmmDomain(gobject.GObject): + self.refresh_inactive_xml() + return self._orig_inactive_xml + ++ def get_xml_to_define(self): ++ # FIXME: This isn't sufficient, since we pull stuff like disk targets ++ # from the active XML. This all needs proper fixing in the long ++ # term. ++ if self.is_active(): ++ return self.get_inactive_xml() ++ else: ++ self.update_xml() ++ return self.get_xml() ++ + def refresh_inactive_xml(self): + flags = (libvirt.VIR_DOMAIN_XML_INACTIVE | + libvirt.VIR_DOMAIN_XML_SECURE) +@@ -124,6 +135,36 @@ class vmmDomain(gobject.GObject): + + self._orig_inactive_xml = self.vm.XMLDesc(flags) + ++ def redefine(self, xml_func, *args): ++ """ ++ Helper function for altering a redefining VM xml ++ ++ @param xml_func: Function to alter the running XML. Takes the ++ original XML as its first argument. ++ @param args: Extra arguments to pass to xml_func ++ """ ++ origxml = self.get_xml_to_define() ++ # Sanitize origxml to be similar to what we will get back ++ origxml = util.xml_parse_wrapper(origxml, lambda d, c: d.serialize()) ++ ++ newxml = xml_func(origxml, *args) ++ ++ if origxml == newxml: ++ logging.debug("Redefinition requested, but new xml was not" ++ " different") ++ return ++ ++ diff = "".join(difflib.unified_diff(origxml.splitlines(1), ++ newxml.splitlines(1), ++ fromfile="Original XML", ++ tofile="New XML")) ++ logging.debug("Redefining '%s' with XML diff:\n%s", ++ self.get_name(), diff) ++ self.get_connection().define_domain(newxml) ++ ++ # Invalidate cached XML ++ self.invalidate_xml() ++ + def release_handle(self): + del(self.vm) + self.vm = None +@@ -1126,16 +1167,6 @@ class vmmDomain(gobject.GObject): + if doc != None: + doc.freeDoc() + +- def get_xml_to_define(self): +- # FIXME: This isn't sufficient, since we pull stuff like disk targets +- # from the active XML. This all needs proper fixing in the long +- # term. +- if self.is_active(): +- return self.get_inactive_xml() +- else: +- self.update_xml() +- return self.get_xml() +- + def attach_device(self, xml): + """Hotplug device to running guest""" + if self.is_active(): +@@ -1232,23 +1263,80 @@ class vmmDomain(gobject.GObject): + doc.freeDoc() + self._change_cdrom(result, dev_id_info) + +- def set_vcpu_count(self, vcpus): ++ def hotplug_vcpu(self, vcpus): ++ self.vm.setVcpus() ++ ++ def hotplug_vcpus(self, vcpus): + vcpus = int(vcpus) +- self.vm.setVcpus(vcpus) ++ if vcpus != self.vcpu_count(): ++ self.vm.setVcpus(vcpus) ++ ++ def define_vcpus(self, vcpus): ++ vcpus = int(vcpus) ++ ++ def set_node(doc, ctx, val, xpath): ++ node = ctx.xpathEval(xpath) ++ node = (node and node[0] or None) ++ ++ if node: ++ node.setContent(str(val)) ++ return doc.serialize() ++ ++ def change_vcpu_xml(xml, vcpus): ++ return util.xml_parse_wrapper(xml, set_node, vcpus, ++ "/domain/vcpu[1]") ++ ++ self.redefine(change_vcpu_xml, vcpus) ++ ++ def hotplug_memory(self, memory): ++ if memory != self.get_memory(): ++ self.vm.setMemory(memory) ++ ++ def hotplug_maxmem(self, maxmem): ++ if maxmem != self.maximum_memory(): ++ self.vm.setMaxMemory(maxmem) ++ ++ def hotplug_both_mem(self, memory, maxmem): ++ logging.info("Hotplugging curmem=%s maxmem=%s for VM '%s'" % ++ (memory, maxmem, self.get_name())) ++ ++ if self.is_active(): ++ actual_cur = self.get_memory() ++ if memory: ++ if maxmem < actual_cur: ++ # Set current first to avoid error ++ self.hotplug_memory(memory) ++ self.hotplug_maxmem(maxmem) ++ else: ++ self.hotplug_maxmem(maxmem) ++ self.hotplug_memory(memory) ++ else: ++ self.hotplug_maxmem(maxmem) ++ ++ def define_both_mem(self, memory, maxmem): ++ # Make sure we correctly define the XML with new values, since ++ # setMem and setMaxMem don't (or, aren't supposed to) affect ++ # the persistent config ++ self.invalidate_xml() ++ ++ def set_mem_node(doc, ctx, memval, xpath): ++ node = ctx.xpathEval(xpath) ++ node = (node and node[0] or None) ++ ++ if node: ++ node.setContent(str(memval)) ++ return doc.serialize() ++ ++ def change_mem_xml(xml, memory, maxmem): ++ if memory: ++ xml = util.xml_parse_wrapper(xml, set_mem_node, memory, ++ "/domain/currentMemory[1]") ++ if maxmem: ++ xml = util.xml_parse_wrapper(xml, set_mem_node, maxmem, ++ "/domain/memory[1]") ++ return xml + +- def set_memory(self, memory): +- memory = int(memory) +- # capture updated information due to failing to get proper maxmem setting +- # if both current & max allocation are set simultaneously +- maxmem = self.vm.info() +- if (memory > maxmem[1]): +- logging.warning("Requested memory " + str(memory) + " over maximum " + str(self.maximum_memory())) +- memory = self.maximum_memory() +- self.vm.setMemory(memory) +- +- def set_max_memory(self, memory): +- memory = int(memory) +- self.vm.setMaxMemory(memory) ++ self.redefine(change_mem_xml, memory, maxmem) + + def get_autostart(self): + return self.vm.autostart() +Only in old/src/virtManager: domain.py.orig +diff -rup old/src/virtManager/util.py virt-manager-0.7.0/src/virtManager/util.py +--- old/src/virtManager/util.py 2009-09-17 17:52:15.948670000 -0400 ++++ virt-manager-0.7.0/src/virtManager/util.py 2009-09-17 17:52:58.963375000 -0400 +@@ -140,3 +140,23 @@ def dup_conn(config, conn, libconn=None) + newconn.connectThreadEvent.wait() + + return newconn.vmm ++ ++def xml_parse_wrapper(xml, parse_func, *args, **kwargs): ++ """ ++ Parse the passed xml string into an xpath context, which is passed ++ to parse_func, along with any extra arguments. ++ """ ++ ++ doc = None ++ ctx = None ++ ret = None ++ try: ++ doc = libxml2.parseDoc(xml) ++ ctx = doc.xpathNewContext() ++ ret = parse_func(doc, ctx, *args, **kwargs) ++ finally: ++ if ctx != None: ++ ctx.xpathFreeContext() ++ if doc != None: ++ doc.freeDoc() ++ return ret +diff -rup old/src/virtManager/util.py virt-manager-0.7.0/src/virtManager/util.py +--- old/src/virtManager/util.py 2009-09-17 17:55:17.930744000 -0400 ++++ virt-manager-0.7.0/src/virtManager/util.py 2009-09-17 17:55:31.355655000 -0400 +@@ -21,6 +21,7 @@ + import logging + import gtk + ++import libxml2 + import libvirt + + import virtManager diff --git a/virt-manager.spec b/virt-manager.spec index 1eb49ef..074d7d7 100644 --- a/virt-manager.spec +++ b/virt-manager.spec @@ -8,7 +8,7 @@ Name: virt-manager Version: 0.7.0 -Release: 5%{_extra_release} +Release: 6%{_extra_release} Summary: Virtual Machine Manager Group: Applications/Emulators @@ -27,6 +27,20 @@ Patch9: %{name}-%{version}-fix-window-resize.patch Patch10: %{name}-%{version}-vnc-auth-get-username.patch Patch11: %{name}-%{version}-handle-arch-config.patch Patch12: %{name}-%{version}-log-capabilities-at-startup.patch +# Fix migration for qemu/kvm guests (bz 517548) +Patch13: %{name}-%{version}-migrate-fixes.patch +# Fix sparse allocation confusion (bz 504605) +Patch14: %{name}-%{version}-fix-sparse-knob.patch +# Czech translation typo (bz 504385) +Patch15: %{name}-%{version}-czech-typo.patch +# Use storage browser for iso installs (bz 504326) +Patch16: %{name}-%{version}-iso-storage-browser.patch +# Fix max/current memory spin button interaction (bz 503786) +Patch17: %{name}-%{version}-fix-memory-interaction.patch +# Make memory and vcpu changes unconditionally persistent (bz 503784) +Patch18: %{name}-%{version}-vcpu-mem-persistent.patch +# Add pylint script +Patch19: %{name}-%{version}-pylint-script.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) # These two are just the oldest version tested @@ -111,6 +125,13 @@ management API. %patch10 -p1 %patch11 -p1 %patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 %build %configure @@ -188,6 +209,14 @@ fi %{_datadir}/dbus-1/services/%{name}.service %changelog +* Fri Sep 18 2009 Cole Robinson - 0.7.0-6.fc11 +- Fix migration for qemu/kvm guests (bz 517548) +- Fix sparse allocation confusion (bz 504605) +- Czech translation typo (bz 504385) +- Use storage browser for iso installs (bz 504326) +- Fix max/current memory spin button interaction (bz 503786) +- Make memory and vcpu changes unconditionally persistent (bz 503784) + * Thu May 21 2009 Mark McLoughlin - 0.7.0-5.fc11 - Fix 'opertaing' typo in 'New VM' dialog (#495128) - Allow details window to resize again (#491683)