storagepool: Don't double invoke 'refresh' when events are present

We need to tweak refresh() handling to work similar to the shared
XML and status caching in libvirtobject.py: when the user manually
invokes the refresh() operation, and storage events are set up,
we just invoke the refresh() but let the event loop handle
refreshing the cache.

This fixes a backtrace when invoking a manual refresh via the
host details dialog
This commit is contained in:
Cole Robinson 2016-06-22 15:58:07 -04:00
parent cdf5d32434
commit 9a67fc4d6e
2 changed files with 24 additions and 10 deletions

View File

@ -778,9 +778,10 @@ class vmmConnection(vmmGObject):
name = pool.name()
logging.debug("storage pool lifecycle event: storage=%s event=%s "
"reason=%s", name, event, reason)
is_event_refreshed = (event == getattr(
libvirt, "VIR_STORAGE_POOL_EVENT_REFRESHED", 4))
if (not self.is_active() and
event == getattr(libvirt, "VIR_STORAGE_POOL_EVENT_REFRESHED", 4)):
if is_event_refreshed and not self.is_active():
# We refresh() pools during connection startup, and this spams
# the logs, so skip it.
return
@ -788,7 +789,10 @@ class vmmConnection(vmmGObject):
obj = self.get_pool(name)
if obj:
self.idle_add(obj.recache_from_event_loop)
if is_event_refreshed:
self.idle_add(obj.refresh_pool_cache_from_event_loop)
else:
self.idle_add(obj.recache_from_event_loop)
else:
self.schedule_priority_tick(pollpool=True, force=True)

View File

@ -153,7 +153,7 @@ class vmmStoragePool(vmmLibvirtObject):
# since the pools may be out of date. But if a storage pool
# shows up while the conn is connected, this means it was
# just 'defined' recently and doesn't need to be refreshed.
self.refresh(_do_refresh_xml=False)
self.refresh(_from_object_init=True)
for vol in self.get_volumes():
vol.init_libvirt_state()
@ -180,16 +180,27 @@ class vmmStoragePool(vmmLibvirtObject):
self._backend.undefine()
self._backend = None
def refresh(self, _do_refresh_xml=True):
def refresh(self, _from_object_init=False):
"""
:param _do_refresh_xml: We want this by default. It's only skipped
to avoid double updating XML via init_libvirt_state
:param _from_object_init: Only used for the refresh() call from
_init_libvirt_state. Tells us to not refresh the XML, since
we just updated it.
"""
if not self.is_active():
return
self._backend.refresh(0)
if _do_refresh_xml:
if self._using_events() and not _from_object_init:
# If we are using events, we let the event loop trigger
# the cache update for us. Except if from init_libvirt_state,
# we want the update to be done immediately
return
self.refresh_pool_cache_from_event_loop(
_from_object_init=_from_object_init)
def refresh_pool_cache_from_event_loop(self, _from_object_init=False):
if not _from_object_init:
self.ensure_latest_xml()
self._update_volumes(force=True)
self.idle_emit("refreshed")
@ -220,8 +231,7 @@ class vmmStoragePool(vmmLibvirtObject):
if not force and self._volumes is not None:
return
self._volumes = []
keymap = dict((o.get_connkey(), o) for o in self._volumes)
keymap = dict((o.get_connkey(), o) for o in self._volumes or [])
(ignore, ignore, allvols) = pollhelpers.fetch_volumes(
self.conn.get_backend(), self.get_backend(), keymap,
lambda obj, key: vmmStorageVolume(self.conn, obj, key))