diff --git a/src/virtManager/addhardware.py b/src/virtManager/addhardware.py index b25d5249a..87f272d7d 100644 --- a/src/virtManager/addhardware.py +++ b/src/virtManager/addhardware.py @@ -989,25 +989,35 @@ class vmmAddHardware(vmmGObjectUI): ###################### def setup_device(self): - if (self._dev.virtual_device_type == + if (self._dev.virtual_device_type != virtinst.VirtualDevice.VIRTUAL_DEV_DISK): - progWin = vmmAsyncJob(self.do_file_allocate, - [self._dev], - title=_("Creating Storage File"), - text=_("Allocation of disk storage may take " - "a few minutes to complete.")) - progWin.run() - - error, details = progWin.get_error() - if error: - return (error, details) - - else: self._dev.setup_dev(self.conn.vmm) + return + + def do_file_allocate(asyncjob, disk): + meter = vmmCreateMeter(asyncjob) + + # If creating disk via storage API, we need to thread + # off a new connection + if disk.vol_install: + newconn = util.dup_lib_conn(disk.conn) + disk.conn = newconn + logging.debug("Starting background file allocate process") + disk.setup_dev(self.conn.vmm, meter=meter) + logging.debug("Allocation completed") + + progWin = vmmAsyncJob(do_file_allocate, + [self._dev], + title=_("Creating Storage File"), + text=_("Allocation of disk storage may take " + "a few minutes to complete.")) + + return progWin.run() + def add_device(self): ret = self.setup_device() - if ret: + if ret and ret[0]: # Encountered an error return (True, ret) @@ -1046,24 +1056,6 @@ class vmmAddHardware(vmmGObjectUI): return (False, None) - def do_file_allocate(self, disk, asyncjob): - meter = vmmCreateMeter(asyncjob) - newconn = None - try: - # If creating disk via storage API, we need to thread - # off a new connection - if disk.vol_install: - newconn = util.dup_lib_conn(disk.conn) - disk.conn = newconn - logging.debug("Starting background file allocate process") - disk.setup_dev(self.conn.vmm, meter=meter) - logging.debug("Allocation completed") - except Exception, e: - details = (_("Unable to complete install: '%s'") % - "".join(traceback.format_exc())) - error = _("Unable to complete install: '%s'") % str(e) - asyncjob.set_error(error, details) - ########################### # Page validation methods # diff --git a/src/virtManager/asyncjob.py b/src/virtManager/asyncjob.py index e63d10f64..645bd4c34 100644 --- a/src/virtManager/asyncjob.py +++ b/src/virtManager/asyncjob.py @@ -20,6 +20,8 @@ import logging import threading +import traceback + import gtk import gobject @@ -30,38 +32,35 @@ from virtManager.baseclass import vmmGObjectUI # code in the run() method every now & then class asyncJobWorker(threading.Thread): def __init__(self, callback, args): - threading.Thread.__init__(self, target=callback, args=args) + args = [callback] + args + threading.Thread.__init__(self, target=cb_wrapper, args=args) def run(self): threading.Thread.run(self) +def cb_wrapper(callback, asyncjob, *args, **kwargs): + try: + callback(asyncjob, *args, **kwargs) + except Exception, e: + asyncjob.set_error(e, "".join(traceback.format_exc())) + # Displays a progress bar while executing the "callback" method. class vmmAsyncJob(vmmGObjectUI): - def __init__(self, callback, args=None, - text=_("Please wait a few moments..."), - title=_("Operation in progress"), + def __init__(self, callback, args, title, text, run_main=True, cancel_back=None, cancel_args=None): vmmGObjectUI.__init__(self, "vmm-progress.glade", "vmm-progress") - self.topwin.set_title(title) - - self.window.signal_autoconnect({ - "on_async_job_delete_event" : self.delete, - "on_async_job_cancel_clicked" : self.cancel, - }) - self.run_main = bool(run_main) self.cancel_job = cancel_back self.cancel_args = cancel_args or [] - self.cancel_args.append(self) + self.cancel_args = [self] + self.cancel_args if self.cancel_job: self.window.get_widget("cancel-async-job").show() else: self.window.get_widget("cancel-async-job").hide() self.job_canceled = False - # Callback sets this if there is an error self._error_info = None self._data = None @@ -69,11 +68,18 @@ class vmmAsyncJob(vmmGObjectUI): self.pbar = self.window.get_widget("pbar") self.window.get_widget("pbar-text").set_text(text) - args.append(self) + args = [self] + args self.bg_thread = asyncJobWorker(callback, args) self.bg_thread.setDaemon(True) self.is_pulsing = True + self.window.signal_autoconnect({ + "on_async_job_delete_event" : self.delete, + "on_async_job_cancel_clicked" : self.cancel, + }) + + self.topwin.set_title(title) + def run(self): timer = util.safe_timeout_add(100, self.exit_if_necessary) self.topwin.present() @@ -98,6 +104,7 @@ class vmmAsyncJob(vmmGObjectUI): self.exit_if_necessary(force_exit=True) self.topwin.destroy() + return self._get_error() def delete(self, ignore1=None, ignore2=None): thread_active = (self.bg_thread.isAlive() or not self.run_main) @@ -175,7 +182,7 @@ class vmmAsyncJob(vmmGObjectUI): def set_error(self, error, details): self._error_info = (error, details) - def get_error(self): + def _get_error(self): if not self._error_info: return (None, None) return self._error_info diff --git a/src/virtManager/baseclass.py b/src/virtManager/baseclass.py index b82b403c4..0f209311d 100644 --- a/src/virtManager/baseclass.py +++ b/src/virtManager/baseclass.py @@ -38,7 +38,7 @@ class vmmGObject(gobject.GObject): def get_hal_helper(self): from virtManager import halhelper - return virtManager.halhelper.get_hal_helper() + return halhelper.get_hal_helper() class vmmGObjectUI(vmmGObject): def __init__(self, filename, windowname): diff --git a/src/virtManager/clone.py b/src/virtManager/clone.py index 4fa4fcd6e..f2a1d21ac 100644 --- a/src/virtManager/clone.py +++ b/src/virtManager/clone.py @@ -709,51 +709,39 @@ class vmmCloneVM(vmmGObjectUI): if self.clone_design.clone_devices: text = title + _(" and selected storage (this may take a while)") - progWin = vmmAsyncJob(self._async_clone, [], - title=title, text=text) - progWin.run() - error, details = progWin.get_error() + progWin = vmmAsyncJob(self._async_clone, [], title, text) + error, details = progWin.run() self.topwin.set_sensitive(True) self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW)) if error is not None: - self.err.show_err(error, details) + error = (_("Error creating virtual machine clone '%s': %s") % + (self.clone_design.clone_name, error)) + self.err.show_err(error, error + "\n" + details) else: self.close() self.conn.tick(noStatsUpdate=True) def _async_clone(self, asyncjob): newconn = None - error = None - details = None try: - try: - self.orig_vm.set_cloning(True) + self.orig_vm.set_cloning(True) - # Open a seperate connection to install on since this is async - logging.debug("Threading off connection to clone VM.") - newconn = util.dup_conn(self.conn).vmm - meter = vmmCreateMeter(asyncjob) + # Open a seperate connection to install on since this is async + logging.debug("Threading off connection to clone VM.") + newconn = util.dup_conn(self.conn).vmm + meter = vmmCreateMeter(asyncjob) - self.clone_design.orig_connection = newconn - for d in self.clone_design.clone_virtual_disks: - d.conn = newconn + self.clone_design.orig_connection = newconn + for d in self.clone_design.clone_virtual_disks: + d.conn = newconn - self.clone_design.setup() - CloneManager.start_duplicate(self.clone_design, meter) - finally: - self.orig_vm.set_cloning(False) - - except Exception, e: - error = (_("Error creating virtual machine clone '%s': %s") % - (self.clone_design.clone_name, str(e))) - details = "".join(traceback.format_exc()) - - if error: - asyncjob.set_error(error, details) - return + self.clone_design.setup() + CloneManager.start_duplicate(self.clone_design, meter) + finally: + self.orig_vm.set_cloning(False) def change_storage_browse(self, ignore): diff --git a/src/virtManager/create.py b/src/virtManager/create.py index 69e39601e..a11d57df8 100644 --- a/src/virtManager/create.py +++ b/src/virtManager/create.py @@ -21,7 +21,6 @@ import gobject import gtk -import sys import time import traceback import threading @@ -1583,16 +1582,14 @@ class vmmCreate(vmmGObjectUI): "and retrieval of the installation " "images may take a few minutes to " "complete.")) - progWin.run() - error, details = progWin.get_error() - - if error != None: - self.err.show_err(error, details) + error, details = progWin.run() self.topwin.set_sensitive(True) self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW)) if error: + error = (_("Unable to complete install: '%s'") % error) + self.err.show_err(error, error + "\n" + details) self.failed_guest = self.guest return @@ -1610,51 +1607,33 @@ class vmmCreate(vmmGObjectUI): self.close() - def do_install(self, guest, asyncjob): + def do_install(self, asyncjob, guest): meter = vmmCreateMeter(asyncjob) - error = None - details = None - try: - logging.debug("Starting background install process") - guest.conn = util.dup_conn(self.conn).vmm - for dev in guest.get_all_devices(): - dev.conn = guest.conn + logging.debug("Starting background install process") - dom = guest.start_install(False, meter = meter) - if dom == None: - error = _("Guest installation failed to complete") - details = error - logging.error("Guest install did not return a domain") - else: - logging.debug("Install completed") + guest.conn = util.dup_conn(self.conn).vmm + for dev in guest.get_all_devices(): + dev.conn = guest.conn - # Make sure we pick up the domain object - self.conn.tick(noStatsUpdate=True) - vm = self.conn.get_vm(guest.uuid) + guest.start_install(False, meter = meter) + logging.debug("Install completed") - if vm.is_shutoff(): - # Domain is already shutdown, but no error was raised. - # Probably means guest had no 'install' phase, as in - # for live cds. Try to restart the domain. - vm.startup() - else: - # Register a status listener, which will restart the - # guest after the install has finished - util.connect_opt_out(vm, "status-changed", - self.check_install_status, guest) + # Make sure we pick up the domain object + self.conn.tick(noStatsUpdate=True) + vm = self.conn.get_vm(guest.uuid) - except: - (_type, value, stacktrace) = sys.exc_info () + if vm.is_shutoff(): + # Domain is already shutdown, but no error was raised. + # Probably means guest had no 'install' phase, as in + # for live cds. Try to restart the domain. + vm.startup() + else: + # Register a status listener, which will restart the + # guest after the install has finished + util.connect_opt_out(vm, "status-changed", + self.check_install_status, guest) - # Detailed error message, in English so it can be Googled. - details = ("Unable to complete install '%s'" % - (str(_type) + " " + str(value) + "\n" + - traceback.format_exc (stacktrace))) - error = (_("Unable to complete install: '%s'") % str(value)) - - if error: - asyncjob.set_error(error, details) def check_install_status(self, vm, ignore1, ignore2, virtinst_guest=None): if vm.is_crashed(): diff --git a/src/virtManager/createinterface.py b/src/virtManager/createinterface.py index ddd556015..4d55a54bf 100644 --- a/src/virtManager/createinterface.py +++ b/src/virtManager/createinterface.py @@ -21,7 +21,6 @@ import gobject import gtk -import sys import traceback import logging @@ -1115,44 +1114,28 @@ class vmmCreateInterface(vmmGObjectUI): title=_("Creating virtual interface"), text=_("The virtual interface is now being " "created.")) - progWin.run() - error, details = progWin.get_error() - - if error != None: - self.err.show_err(error, details) + error, details = progWin.run() self.topwin.set_sensitive(True) self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW)) if error: - return + error = _("Error creating interface: '%s'") % error + self.err.show_err(error, error + "\n" + details) + else: + # FIXME: Hmm, shouldn't we emit a signal here rather than do this? + self.conn.tick(noStatsUpdate=True) + self.close() - # FIXME: Hmm, shouldn't we emit a signal here rather than do this? - self.conn.tick(noStatsUpdate=True) - self.close() - - - def do_install(self, activate, asyncjob): + def do_install(self, asyncjob, activate): meter = vmmCreateMeter(asyncjob) error = None details = None - try: - self.interface.conn = util.dup_conn(self.conn).vmm - self.interface.install(meter, create=activate) - logging.debug("Install completed") - except: - (_type, value, stacktrace) = sys.exc_info () - - # Detailed error message, in English so it can be Googled. - details = ("Error creating interface: '%s'" % - (str(_type) + " " + str(value) + "\n" + - traceback.format_exc (stacktrace))) - error = (_("Error creating interface: '%s'") % str(value)) - - if error: - asyncjob.set_error(error, details) + self.interface.conn = util.dup_conn(self.conn).vmm + self.interface.install(meter, create=activate) + logging.debug("Install completed") def show_help(self, ignore): # No help available yet. diff --git a/src/virtManager/createpool.py b/src/virtManager/createpool.py index a4072c85c..b18354d43 100644 --- a/src/virtManager/createpool.py +++ b/src/virtManager/createpool.py @@ -396,35 +396,31 @@ class vmmCreatePool(vmmGObjectUI): title=_("Creating storage pool..."), text=_("Creating the storage pool may take a " "while...")) - progWin.run() - error, details = progWin.get_error() - - if error is not None: - self.err.show_err(error, details) + error, details = progWin.run() self.topwin.set_sensitive(True) self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW)) - if not error: + if error: + error = _("Error creating pool: %s") % error + self.err.show_err(error, error + "\n" + details) + else: self.close() - def _async_pool_create(self, asyncjob): + def _async_pool_create(self, asyncjob, *args, **kwargs): + print args, kwargs newconn = None - try: - # Open a seperate connection to install on since this is async - newconn = util.dup_lib_conn(self._pool.conn) - meter = vmmCreateMeter(asyncjob) - self._pool.conn = newconn + + # Open a seperate connection to install on since this is async + newconn = util.dup_lib_conn(self._pool.conn) + meter = vmmCreateMeter(asyncjob) + self._pool.conn = newconn - logging.debug("Starting backround pool creation.") - build = self.window.get_widget("pool-build").get_active() - poolobj = self._pool.install(create=True, meter=meter, build=build) - poolobj.setAutostart(True) - logging.debug("Pool creating succeeded.") - except Exception, e: - error = _("Error creating pool: %s") % str(e) - details = "".join(traceback.format_exc()) - asyncjob.set_error(error, details) + logging.debug("Starting backround pool creation.") + build = self.window.get_widget("pool-build").get_active() + poolobj = self._pool.install(create=True, meter=meter, build=build) + poolobj.setAutostart(True) + logging.debug("Pool creating succeeded.") def page_changed(self, notebook_ignore, page_ignore, page_number): if page_number == PAGE_NAME: diff --git a/src/virtManager/createvol.py b/src/virtManager/createvol.py index bcebe255f..a66f3d6cb 100644 --- a/src/virtManager/createvol.py +++ b/src/virtManager/createvol.py @@ -203,38 +203,31 @@ class vmmCreateVolume(vmmGObjectUI): self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) progWin = vmmAsyncJob(self._async_vol_create, [], - title=_("Creating storage volume..."), - text=_("Creating the storage volume may take a " - "while...")) - progWin.run() - error, details = progWin.get_error() - - if error is not None: - self.show_err(error, details) + _("Creating storage volume..."), + _("Creating the storage volume may take a " + "while...")) + error, details = progWin.run() self.topwin.set_sensitive(True) self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW)) - if not error: + if error: + error = _("Error creating vol: %s") % error + self.show_err(error, error + "\n" + details) + else: self.emit("vol-created") self.close() def _async_vol_create(self, asyncjob): - newconn = None - try: - newconn = util.dup_conn(self.conn).vmm + newconn = util.dup_conn(self.conn).vmm - # Lookup different pool obj - newpool = newconn.storagePoolLookupByName(self.parent_pool.get_name()) - self.vol.pool = newpool + # Lookup different pool obj + newpool = newconn.storagePoolLookupByName(self.parent_pool.get_name()) + self.vol.pool = newpool - meter = vmmCreateMeter(asyncjob) - logging.debug("Starting backround vol creation.") - self.vol.install(meter=meter) - except Exception, e: - error = _("Error creating vol: %s") % str(e) - details = "".join(traceback.format_exc()) - asyncjob.set_error(error, details) + meter = vmmCreateMeter(asyncjob) + logging.debug("Starting backround vol creation.") + self.vol.install(meter=meter) def validate(self): name = self.window.get_widget("vol-name").get_text() diff --git a/src/virtManager/delete.py b/src/virtManager/delete.py index 2a571fc24..a91519b81 100644 --- a/src/virtManager/delete.py +++ b/src/virtManager/delete.py @@ -132,8 +132,7 @@ class vmmDeleteDialog(vmmGObjectUI): progWin = vmmAsyncJob(self._async_delete, [devs], title=title, text=text) - progWin.run() - error, details = progWin.get_error() + error, details = progWin.run() self.topwin.set_sensitive(True) self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW)) @@ -145,11 +144,9 @@ class vmmDeleteDialog(vmmGObjectUI): self.conn.tick(noStatsUpdate=True) - def _async_delete(self, paths, asyncjob): + def _async_delete(self, asyncjob, paths): newconn = None storage_errors = [] - error = None - details = None try: # Open a seperate connection to install on since this is async diff --git a/src/virtManager/domain.py b/src/virtManager/domain.py index 96885c547..dd114c1b6 100644 --- a/src/virtManager/domain.py +++ b/src/virtManager/domain.py @@ -200,6 +200,7 @@ class vmmDomainBase(vmmLibvirtObject): # attempt may result in a lookup failure. If device is present # in the active XML, assume all is good. if find_device(self._get_guest(), origdev): + logging.debug("Device in active config but not inactive config.") return raise RuntimeError(_("Could not find specified device in the " diff --git a/src/virtManager/engine.py b/src/virtManager/engine.py index db6bcff4e..4e4748625 100644 --- a/src/virtManager/engine.py +++ b/src/virtManager/engine.py @@ -104,9 +104,9 @@ def check_packagekit(errbox): progWin = vmmAsyncJob(_do_async_search, [session, pk_control], _("Searching for available hypervisors..."), + _("Searching for available hypervisors..."), run_main=False) - progWin.run() - error, ignore = progWin.get_error() + error, ignore = progWin.run() if error: return @@ -146,7 +146,7 @@ def check_packagekit(errbox): return (True, LIBVIRT_DAEMON in do_install) -def _do_async_search(session, pk_control, asyncjob): +def _do_async_search(asyncjob, session, pk_control): found = [] try: for name in PACKAGEKIT_PACKAGES: @@ -827,15 +827,16 @@ class vmmEngine(vmmGObject): progWin = vmmAsyncJob(self._save_callback, [vm, path], _("Saving Virtual Machine"), + _("Saving Virtual Machine"), cancel_back=_cancel_back, cancel_args=_cancel_args) - progWin.run() - error, details = progWin.get_error() + error, details = progWin.run() if error is not None: - src.err.show_err(_("Error saving domain: %s") % error, details) + error = _("Error saving domain: %s") % error + src.err.show_err(error, error + "\n" + details) - def _save_cancel(self, vm, asyncjob): + def _save_cancel(self, asyncjob, vm): logging.debug("Cancelling save job") if not vm: return @@ -850,18 +851,17 @@ class vmmEngine(vmmGObject): asyncjob.job_canceled = True return - def _save_callback(self, vm, file_to_save, asyncjob): + def _save_callback(self, asyncjob, vm, file_to_save): try: conn = util.dup_conn(vm.connection) newvm = conn.get_vm(vm.get_uuid()) newvm.save(file_to_save) except Exception, e: - if not (isinstance(e, libvirt.libvirtError) and - asyncjob.job_canceled): - # If job is cancelled, we should not report the error - # to user. - asyncjob.set_error(str(e), "".join(traceback.format_exc())) + # If job is cancelled, don't report error to user. + if isinstance(e, libvirt.libvirtError) and asyncjob.job_canceled: + return + raise e def _do_restore_domain(self, src, uri): conn = self._lookup_connection(uri) @@ -879,23 +879,19 @@ class vmmEngine(vmmGObject): return progWin = vmmAsyncJob(self._restore_saved_callback, - [path, conn], _("Restoring Virtual Machine")) - progWin.run() - error, details = progWin.get_error() + [path, conn], + _("Restoring Virtual Machine"), + _("Restoring Virtual Machine")) + error, details = progWin.run() if error is not None: - src.err.show_err(error, details, - title=_("Error restoring domain")) + error = _("Error restoring domain: %s") % error + src.err.show_err(error, error + "\n" + details) - def _restore_saved_callback(self, file_to_load, conn, asyncjob): - try: - newconn = util.dup_conn(conn) - newconn.restore(file_to_load) - except Exception, e: - err = (_("Error restoring domain '%s': %s") % - (file_to_load, str(e))) - details = "".join(traceback.format_exc()) - asyncjob.set_error(err, details) + def _restore_saved_callback(self, asyncjob, file_to_load, conn): + ignore = asyncjob + newconn = util.dup_conn(conn) + newconn.restore(file_to_load) def _do_destroy_domain(self, src, uri, uuid): conn = self._lookup_connection(uri) diff --git a/src/virtManager/interface.py b/src/virtManager/interface.py index 2ca3feb01..4168008e1 100644 --- a/src/virtManager/interface.py +++ b/src/virtManager/interface.py @@ -21,6 +21,7 @@ import virtinst from virtinst import Interface +from virtManager import util from virtManager.libvirtobject import vmmLibvirtObject class vmmInterface(vmmLibvirtObject): @@ -118,7 +119,7 @@ class vmmInterface(vmmLibvirtObject): return doc.serialize() - self._redefine_xml(set_start_xml) + self._redefine(util.xml_parse_wrapper, set_start_xml) def get_slaves(self): @@ -211,4 +212,19 @@ class vmmInterface(vmmLibvirtObject): ret = " %s\n" % ret return ret + 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._xml_to_redefine() + # 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) + self._redefine_xml(newxml) + vmmLibvirtObject.type_register(vmmInterface) diff --git a/src/virtManager/libvirtobject.py b/src/virtManager/libvirtobject.py index 72d1af2ca..91c220fcd 100644 --- a/src/virtManager/libvirtobject.py +++ b/src/virtManager/libvirtobject.py @@ -51,9 +51,6 @@ class vmmLibvirtObject(vmmGObject): self._xml = None self._is_xml_valid = False - # Cached XML that accumulates changes to define - self._xml_to_define = None - # These should be set by the child classes if necessary self._inactive_xml_flags = 0 self._active_xml_flags = 0 @@ -128,7 +125,7 @@ class vmmLibvirtObject(vmmGObject): # Internal API functions # ########################## - def __xml_to_redefine(self): + def _xml_to_redefine(self): return _sanitize_xml(self.get_xml(inactive=True)) def _redefine_helper(self, origxml, newxml): @@ -143,13 +140,15 @@ class vmmLibvirtObject(vmmGObject): self.get_name(), diff) self._define(newxml) + else: + logging.debug("Redefine requested, but XML didn't change!") # Make sure we have latest XML self.refresh_xml(forcesignal=True) return def _redefine_xml(self, newxml): - origxml = self.__xml_to_redefine() + origxml = self._xml_to_redefine() return self._redefine_helper(origxml, newxml) vmmGObject.type_register(vmmLibvirtObject) diff --git a/src/virtManager/migrate.py b/src/virtManager/migrate.py index 54aac0206..c489e1322 100644 --- a/src/virtManager/migrate.py +++ b/src/virtManager/migrate.py @@ -447,22 +447,21 @@ class vmmMigrateDialog(vmmGObjectUI): progWin = vmmAsyncJob(self._async_migrate, [self.vm, destconn, uri, rate, live, secure, max_downtime], - title=_("Migrating VM '%s'" % self.vm.get_name()), - text=(_("Migrating VM '%s' from %s to %s. " - "This may take awhile.") % - (self.vm.get_name(), srchost, dsthost)), + _("Migrating VM '%s'" % self.vm.get_name()), + (_("Migrating VM '%s' from %s to %s. " + "This may take awhile.") % + (self.vm.get_name(), srchost, dsthost)), cancel_back=_cancel_back, cancel_args=_cancel_args) - progWin.run() - error, details = progWin.get_error() - - if error: - self.err.show_err(error, details) + error, details = progWin.run() self.topwin.set_sensitive(True) self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW)) - if error is None: + if error: + error = _("Unable to migrate guest: %s") % error + self.err.show_err(error, error + "\n" + details) + else: self.conn.tick(noStatsUpdate=True) destconn.tick(noStatsUpdate=True) self.close() @@ -482,7 +481,7 @@ class vmmMigrateDialog(vmmGObjectUI): logging.warning("Error setting migrate downtime: %s" % e) return False - def cancel_migration(self, vm, asyncjob): + def cancel_migration(self, asyncjob, vm): logging.debug("Cancelling migrate job") if not vm: return @@ -497,43 +496,37 @@ class vmmMigrateDialog(vmmGObjectUI): asyncjob.job_canceled = True return - def _async_migrate(self, origvm, origdconn, migrate_uri, rate, live, - secure, max_downtime, asyncjob): - errinfo = None + def _async_migrate(self, asyncjob, + origvm, origdconn, migrate_uri, rate, live, + secure, max_downtime): try: - try: - ignore = vmmCreateMeter(asyncjob) + ignore = vmmCreateMeter(asyncjob) - srcconn = util.dup_conn(origvm.get_connection()) - dstconn = util.dup_conn(origdconn) + srcconn = util.dup_conn(origvm.get_connection()) + dstconn = util.dup_conn(origdconn) - vminst = srcconn.vmm.lookupByName(origvm.get_name()) - vm = vmmDomain(srcconn, vminst, vminst.UUID()) + vminst = srcconn.vmm.lookupByName(origvm.get_name()) + vm = vmmDomain(srcconn, vminst, vminst.UUID()) - logging.debug("Migrating vm=%s from %s to %s", vm.get_name(), - srcconn.get_uri(), dstconn.get_uri()) - timer = None - if max_downtime != 0: - # 0 means that the spin box migrate-max-downtime does not - # be enabled. - current_thread = threading.currentThread() - timer = util.safe_timeout_add(100, - self._async_set_max_downtime, - vm, max_downtime, - current_thread) - vm.migrate(dstconn, migrate_uri, rate, live, secure) - if timer: - gobject.source_remove(timer) - except Exception, e: - if not (isinstance(e, libvirt.libvirtError) and - asyncjob.job_canceled): - # If job is cancelled, we should not report the error - # to user. - errinfo = (str(e), ("Unable to migrate guest:\n %s" % - "".join(traceback.format_exc()))) - finally: - if errinfo: - asyncjob.set_error(errinfo[0], errinfo[1]) + logging.debug("Migrating vm=%s from %s to %s", vm.get_name(), + srcconn.get_uri(), dstconn.get_uri()) + timer = None + if max_downtime != 0: + # 0 means that the spin box migrate-max-downtime does not + # be enabled. + current_thread = threading.currentThread() + timer = util.safe_timeout_add(100, + self._async_set_max_downtime, + vm, max_downtime, + current_thread) + vm.migrate(dstconn, migrate_uri, rate, live, secure) + if timer: + gobject.source_remove(timer) + except Exception, e: + # If job is cancelled, don't report error + if isinstance(e, libvirt.libvirtError) and asyncjob.job_canceled: + return + raise e vmmGObjectUI.type_register(vmmMigrateDialog) diff --git a/src/virtManager/storagepool.py b/src/virtManager/storagepool.py index 48f9f71a0..9a0d269dc 100644 --- a/src/virtManager/storagepool.py +++ b/src/virtManager/storagepool.py @@ -53,7 +53,7 @@ class vmmStoragePool(vmmLibvirtObject): def set_active(self, state): self.active = state - self._update_xml() + self.refresh_xml() def is_active(self): return self.active @@ -67,11 +67,11 @@ class vmmStoragePool(vmmLibvirtObject): def start(self): self.pool.create(0) - self._update_xml() + self.refresh_xml() def stop(self): self.pool.destroy() - self._update_xml() + self.refresh_xml() def delete(self, nodelete=True): if nodelete: diff --git a/src/virtManager/util.py b/src/virtManager/util.py index ebd7fafef..7905ae023 100644 --- a/src/virtManager/util.py +++ b/src/virtManager/util.py @@ -234,8 +234,10 @@ def browse_local(parent, dialog_name, conn, start_folder=None, return ret def dup_lib_conn(libconn): - vmmconn = _dup_all_conn(None, libconn) - return vmmconn.vmm + conn = _dup_all_conn(None, libconn) + if isinstance(conn, virtManager.connection.vmmConnection): + return conn.vmm + return conn def dup_conn(conn): return _dup_all_conn(conn, None)