The update was originally part of the storageDriverAutostart function,
but the pools have to be checked earlier during initialization phase, so
the 'checkPool' block has been moved to storagePoolUpdateAllState.
Prior to this update virStoragePoolLoadAllConfigs and
virStoragePoolLoadAllState functions gather all existing pool in the
system, so first it is necessary to filter out the ones that are
inactive (only config XML found), then determine storage backends for
the rest of the pools and run checkPool on each one of them to update
their 'active' property.
After update, pools have to be refreshed, otherwise the list of volumes
stays empty. Once again we need the connection, but all the
storage backends ignore this argument except for RBD, however RBD
doesn't support 'checkPool' callback, therefore it is safe to pass
connection as NULL pointer.
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1177733
---
src/storage/storage_driver.c | 73 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 61 insertions(+), 12 deletions(-)
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index d09acce..2899521 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -75,6 +75,64 @@ static void storageDriverUnlock(void)
}
static void
+storagePoolUpdateAllState(void)
+{
+ size_t i;
+ bool active = false;
+
+ for (i = 0; i < driver->pools.count; i++) {
+ virStoragePoolObjPtr pool = driver->pools.objs[i];
+ virStorageBackendPtr backend;
+
+ virStoragePoolObjLock(pool);
+ if (!virStoragePoolObjIsActive(pool)) {
+ virStoragePoolObjUnlock(pool);
+ continue;
+ }
+
+ if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
+ VIR_ERROR(_("Missing backend %d"), pool->def->type);
+ virStoragePoolObjUnlock(pool);
+ continue;
+ }
+
+ /* Backends which do not support 'checkPool' are considered
+ * inactive by default.
+ */
+ if (backend->checkPool &&
+ backend->checkPool(pool, &active) < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to initialize storage pool '%s': %s"),
+ pool->def->name, err ? err->message :
+ _("no error message found"));
+ virStoragePoolObjUnlock(pool);
+ continue;
+ }
+
+ /* We can pass NULL as connection, most backends do not use
+ * it anyway, but if they do and fail, we want to log error and
+ * continue with other pools.
+ */
+ if (active) {
+ virStoragePoolObjClearVols(pool);
+ if (backend->refreshPool(NULL, pool) < 0) {
+ virErrorPtr err = virGetLastError();
+ if (backend->stopPool)
+ backend->stopPool(NULL, pool);
+ VIR_ERROR(_("Failed to restart storage pool '%s':
%s"),
+ pool->def->name, err ? err->message :
+ _("no error message found"));
+ virStoragePoolObjUnlock(pool);
+ continue;
+ }
+ }
+
+ pool->active = active;
+ virStoragePoolObjUnlock(pool);
+ }
+}
+
+static void
storageDriverAutostart(void)
{
size_t i;
@@ -99,18 +157,7 @@ storageDriverAutostart(void)
continue;
}
- if (backend->checkPool &&
- backend->checkPool(pool, &started) < 0) {
- virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to initialize storage pool '%s': %s"),
- pool->def->name, err ? err->message :
- _("no error message found"));
- virStoragePoolObjUnlock(pool);
- continue;
- }
-
- if (!started &&
- pool->autostart &&
+ if (pool->autostart &&
!virStoragePoolObjIsActive(pool)) {
if (backend->startPool &&
backend->startPool(conn, pool) < 0) {
@@ -207,6 +254,8 @@ storageStateInitialize(bool privileged,
driver->autostartDir) < 0)
goto error;
+ storagePoolUpdateAllState();
+
storageDriverUnlock();
ret = 0;
--
1.9.3