]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Check whether pools are already active upon libvirtd startup
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 11 Nov 2010 20:09:20 +0000 (20:09 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 23 Nov 2010 15:00:35 +0000 (15:00 +0000)
When libvirt starts up all storage pools default to the inactive
state, even if the underlying storage is already active on the
host. This introduces a new API into the internal storage backend
drivers that checks whether a storage pool is already active. If
the pool is active at libvirtd startup, the volume list will be
immediately populated.

* src/storage/storage_backend.h: New internal API for checking
  storage pool state
* src/storage/storage_driver.c: Check whether a pool is active
  upon driver startup
* src/storage/storage_backend_fs.c, src/storage/storage_backend_iscsi.c,
  src/storage/storage_backend_logical.c, src/storage/storage_backend_mpath.c,
  src/storage/storage_backend_scsi.c: Add checks for pool state

src/storage/storage_backend.h
src/storage/storage_backend_fs.c
src/storage/storage_backend_iscsi.c
src/storage/storage_backend_logical.c
src/storage/storage_backend_mpath.c
src/storage/storage_backend_scsi.c
src/storage/storage_driver.c

index 1165a45f3935e2362b7949e72f192f37355cf3bc..6f395c767b3a8736962fe0789fe307e5ee73b68b 100644 (file)
 # define __VIR_STORAGE_BACKEND_H__
 
 # include <stdint.h>
+# include <stdbool.h>
 # include "internal.h"
 # include "storage_conf.h"
 
 typedef char * (*virStorageBackendFindPoolSources)(virConnectPtr conn, const char *srcSpec, unsigned int flags);
+typedef int (*virStorageBackendCheckPool)(virConnectPtr conn, virStoragePoolObjPtr pool, bool *active);
 typedef int (*virStorageBackendStartPool)(virConnectPtr conn, virStoragePoolObjPtr pool);
 typedef int (*virStorageBackendBuildPool)(virConnectPtr conn, virStoragePoolObjPtr pool, unsigned int flags);
 typedef int (*virStorageBackendRefreshPool)(virConnectPtr conn, virStoragePoolObjPtr pool);
@@ -65,6 +67,7 @@ struct _virStorageBackend {
     int type;
 
     virStorageBackendFindPoolSources findPoolSources;
+    virStorageBackendCheckPool checkPool;
     virStorageBackendStartPool startPool;
     virStorageBackendBuildPool buildPool;
     virStorageBackendRefreshPool refreshPool;
index 85bd4ab4d1d5e8879e6448345d0e038db52e46aa..d916d2d19efde40a7affe4dbbdface1fcdd372be 100644 (file)
@@ -479,6 +479,30 @@ virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
 #endif /* WITH_STORAGE_FS */
 
 
+static int
+virStorageBackendFileSystemCheck(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                 virStoragePoolObjPtr pool,
+                                 bool *isActive)
+{
+    *isActive = false;
+    if (pool->def->type == VIR_STORAGE_POOL_DIR) {
+        if (access(pool->def->target.path, F_OK) == 0)
+            *isActive = true;
+#if WITH_STORAGE_FS
+    } else {
+        int ret;
+        if ((ret = virStorageBackendFileSystemIsMounted(pool)) != 0) {
+            if (ret < 0)
+                return -1;
+            *isActive = true;
+        }
+#endif /* WITH_STORAGE_FS */
+    }
+
+    return 0;
+}
+
+#if WITH_STORAGE_FS
 /**
  * @conn connection to report errors against
  * @pool storage pool to start
@@ -489,7 +513,6 @@ virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
  *
  * Returns 0 on success, -1 on error
  */
-#if WITH_STORAGE_FS
 static int
 virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virStoragePoolObjPtr pool)
@@ -937,6 +960,7 @@ virStorageBackend virStorageBackendDirectory = {
     .type = VIR_STORAGE_POOL_DIR,
 
     .buildPool = virStorageBackendFileSystemBuild,
+    .checkPool = virStorageBackendFileSystemCheck,
     .refreshPool = virStorageBackendFileSystemRefresh,
     .deletePool = virStorageBackendFileSystemDelete,
     .buildVol = virStorageBackendFileSystemVolBuild,
@@ -951,6 +975,7 @@ virStorageBackend virStorageBackendFileSystem = {
     .type = VIR_STORAGE_POOL_FS,
 
     .buildPool = virStorageBackendFileSystemBuild,
+    .checkPool = virStorageBackendFileSystemCheck,
     .startPool = virStorageBackendFileSystemStart,
     .refreshPool = virStorageBackendFileSystemRefresh,
     .stopPool = virStorageBackendFileSystemStop,
@@ -965,6 +990,7 @@ virStorageBackend virStorageBackendNetFileSystem = {
     .type = VIR_STORAGE_POOL_NETFS,
 
     .buildPool = virStorageBackendFileSystemBuild,
+    .checkPool = virStorageBackendFileSystemCheck,
     .startPool = virStorageBackendFileSystemStart,
     .findPoolSources = virStorageBackendFileSystemNetFindPoolSources,
     .refreshPool = virStorageBackendFileSystemRefresh,
index b376de288ac820636ed45afe42bc940ec27d431e..6eff5f5ba045c8f1adf61fbf95396b80dbd5964c 100644 (file)
@@ -633,6 +633,39 @@ cleanup:
     return ret;
 }
 
+static int
+virStorageBackendISCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                virStoragePoolObjPtr pool,
+                                bool *isActive)
+{
+    char *session = NULL;
+    int ret = -1;
+
+    *isActive = false;
+
+    if (pool->def->source.host.name == NULL) {
+        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("missing source host"));
+        return -1;
+    }
+
+    if (pool->def->source.ndevice != 1 ||
+        pool->def->source.devices[0].path == NULL) {
+        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("missing source device"));
+        return -1;
+    }
+
+    if ((session = virStorageBackendISCSISession(pool, 1)) != NULL) {
+        *isActive = true;
+        VIR_FREE(session);
+    }
+    ret = 0;
+
+    return ret;
+}
+
+
 static int
 virStorageBackendISCSIStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 virStoragePoolObjPtr pool)
@@ -730,6 +763,7 @@ cleanup:
 virStorageBackend virStorageBackendISCSI = {
     .type = VIR_STORAGE_POOL_ISCSI,
 
+    .checkPool = virStorageBackendISCSICheckPool,
     .startPool = virStorageBackendISCSIStartPool,
     .refreshPool = virStorageBackendISCSIRefreshPool,
     .stopPool = virStorageBackendISCSIStopPool,
index e6c69385f8ed91a88538e6ed0918ff0609cdec9f..203fe5d8712b870b9558ccc960bd3f85aa89214d 100644 (file)
@@ -360,6 +360,27 @@ virStorageBackendLogicalFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
 }
 
 
+static int
+virStorageBackendLogicalCheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                  virStoragePoolObjPtr pool,
+                                  bool *isActive)
+{
+    char *path;
+
+    *isActive = false;
+    if (virAsprintf(&path, "/dev/%s", pool->def->source.name) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (access(path, F_OK) == 0)
+        *isActive = true;
+
+    VIR_FREE(path);
+
+    return 0;
+}
+
 static int
 virStorageBackendLogicalStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
                                   virStoragePoolObjPtr pool)
@@ -684,6 +705,7 @@ virStorageBackend virStorageBackendLogical = {
     .type = VIR_STORAGE_POOL_LOGICAL,
 
     .findPoolSources = virStorageBackendLogicalFindPoolSources,
+    .checkPool = virStorageBackendLogicalCheckPool,
     .startPool = virStorageBackendLogicalStartPool,
     .buildPool = virStorageBackendLogicalBuildPool,
     .refreshPool = virStorageBackendLogicalRefreshPool,
index 79ad4b8e1c9cfee2de48bbe2be416e213c753790..be4db787855f56ab6895453f5f29b3e59a6ac178 100644 (file)
@@ -291,6 +291,22 @@ out:
     return retval;
 }
 
+static int
+virStorageBackendMpathCheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+                                bool *isActive)
+{
+    const char *path = "/dev/mpath";
+
+    *isActive = false;
+
+    if (access(path, F_OK) == 0)
+        *isActive = true;
+
+    return 0;
+}
+
+
 
 static int
 virStorageBackendMpathRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -313,5 +329,6 @@ virStorageBackendMpathRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
 virStorageBackend virStorageBackendMpath = {
     .type = VIR_STORAGE_POOL_MPATH,
 
+    .checkPool = virStorageBackendMpathCheckPool,
     .refreshPool = virStorageBackendMpathRefreshPool,
 };
index d0af7de694724e14f970d1655c78f1562b5d5b44..8fa2f52463024c02ac7777a645a596417cc21156 100644 (file)
@@ -587,6 +587,26 @@ out:
     return retval;
 }
 
+static int
+virStorageBackendSCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+                               virStoragePoolObjPtr pool,
+                               bool *isActive)
+{
+    char *path;
+
+    *isActive = false;
+    if (virAsprintf(&path, "/sys/class/scsi_host/%s", pool->def->source.adapter) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (access(path, F_OK) == 0)
+        *isActive = true;
+
+    VIR_FREE(path);
+
+    return 0;
+}
 
 static int
 virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -621,5 +641,6 @@ out:
 virStorageBackend virStorageBackendSCSI = {
     .type = VIR_STORAGE_POOL_SCSI,
 
+    .checkPool = virStorageBackendSCSICheckPool,
     .refreshPool = virStorageBackendSCSIRefreshPool,
 };
index 6df706b325f8d3b92e0261c382a20fa9dc485db0..6a4ad6d782abeea2fa21ccdecbda5815cbd13cc4 100644 (file)
@@ -69,34 +69,49 @@ storageDriverAutostart(virStorageDriverStatePtr driver) {
 
     for (i = 0 ; i < driver->pools.count ; i++) {
         virStoragePoolObjPtr pool = driver->pools.objs[i];
+        virStorageBackendPtr backend;
+        bool started = false;
 
         virStoragePoolObjLock(pool);
-        if (pool->autostart &&
-            !virStoragePoolObjIsActive(pool)) {
-            virStorageBackendPtr backend;
-            if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
-                VIR_ERROR(_("Missing backend %d"), pool->def->type);
-                virStoragePoolObjUnlock(pool);
-                continue;
-            }
+        if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
+            VIR_ERROR(_("Missing backend %d"), pool->def->type);
+            virStoragePoolObjUnlock(pool);
+            continue;
+        }
 
+        if (backend->checkPool &&
+            backend->checkPool(NULL, 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 &&
+            !virStoragePoolObjIsActive(pool)) {
             if (backend->startPool &&
                 backend->startPool(NULL, pool) < 0) {
                 virErrorPtr err = virGetLastError();
                 VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
                           pool->def->name, err ? err->message :
-                          "no error message found");
+                          _("no error message found"));
                 virStoragePoolObjUnlock(pool);
                 continue;
             }
+            started = true;
+        }
 
+        if (started) {
             if (backend->refreshPool(NULL, pool) < 0) {
                 virErrorPtr err = virGetLastError();
                 if (backend->stopPool)
                     backend->stopPool(NULL, pool);
                 VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
                           pool->def->name, err ? err->message :
-                          "no error message found");
+                          _("no error message found"));
                 virStoragePoolObjUnlock(pool);
                 continue;
             }