[libvirt] [PATCHv2 6/9] storage: Implement ephemeral storage APIs in the generic storage driver

Peter Krempa pkrempa at redhat.com
Thu Jan 16 13:14:35 UTC 2014


This patch implements the APIs for creating temporary storage pools for
the generic storage driver.
---
 src/check-aclrules.pl        |   3 +
 src/storage/storage_driver.c | 253 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 256 insertions(+)

diff --git a/src/check-aclrules.pl b/src/check-aclrules.pl
index 057517e..7174868 100755
--- a/src/check-aclrules.pl
+++ b/src/check-aclrules.pl
@@ -73,6 +73,9 @@ my %implwhitelist = (
     "xenUnifiedDomainIsPersistent" => 1,
     "xenUnifiedDomainIsUpdated" => 1,
     "xenUnifiedDomainOpenConsole" => 1,
+    "storageEphemeralFree" => 1,                # internal API, no RPC
+    "storageEphemeralFromDiskDef" => 1,         # internal API, no RPC
+    "storageEphemeralFromSnapshotDiskDef" => 1, # internal API, no RPC
     );
 my %filterimplwhitelist = (
     "xenUnifiedConnectListDomains" => 1,
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index a6bc801..c82c620 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -50,6 +50,8 @@
 #include "virstring.h"
 #include "viraccessapicheck.h"

+#include "dirname.h"
+
 #define VIR_FROM_THIS VIR_FROM_STORAGE

 static virStorageDriverStatePtr driverState;
@@ -2586,6 +2588,253 @@ cleanup:
     return ret;
 }

+
+static void
+storageEphemeralFree(virStorageEphemeralPtr def)
+{
+    virConnectPtr conn;
+    virStorageDriverStatePtr driver;
+    virStoragePoolObjPtr pool;
+
+    if (!def)
+        return;
+
+    if (!def->existing &&
+        def->pool) {
+        conn = def->pool->conn;
+        driver = conn->storagePrivateData;
+
+        if ((pool = virStoragePoolObjFindByUUID(&driver->pools,
+                                                def->pool->uuid))) {
+            virStoragePoolObjRemove(&driver->pools, pool);
+        }
+    }
+
+    if (def->vol)
+        virStorageVolFree(def->vol);
+
+    if (def->pool)
+        virStoragePoolFree(def->pool);
+}
+
+
+static void
+storageEphemeralGenerateUniquePoolID(virStoragePoolDefPtr def)
+{
+    virUUIDGenerate(def->uuid);
+    virUUIDFormat(def->uuid, def->name);
+}
+
+
+static virStoragePoolPtr
+storageEphemeralCreateDirPool(virConnectPtr conn,
+                              const char *source)
+{
+    virStorageDriverStatePtr driver = conn->storagePrivateData;
+    virStoragePoolDefPtr def = NULL;
+    virStoragePoolObjPtr pool = NULL;
+    virStorageBackendPtr backend;
+    virStoragePoolPtr ret = NULL;
+
+    if (VIR_ALLOC(def) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC_N(def->name, VIR_UUID_STRING_BUFLEN) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(def->target.path, source) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(def->source.dir, def->target.path) < 0)
+        goto cleanup;
+
+    def->type = VIR_STORAGE_POOL_DIR;
+
+    storageDriverLock(driver);
+
+    /* generate a unique name */
+    do {
+        if (pool) {
+            virStoragePoolObjUnlock(pool);
+            pool = NULL;
+        }
+
+        storageEphemeralGenerateUniquePoolID(def);
+
+        if ((pool = virStoragePoolObjFindByUUID(&driver->pools, def->uuid)))
+            continue;
+
+        pool = virStoragePoolObjFindByName(&driver->pools, def->name);
+    } while (pool);
+
+    if (!(backend = virStorageBackendForType(def->type)))
+        goto cleanup;
+
+    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
+        goto cleanup;
+    def = NULL;
+
+    if (backend->startPool &&
+        backend->startPool(conn, pool) < 0) {
+        virStoragePoolObjRemove(&driver->pools, pool);
+        pool = NULL;
+        goto cleanup;
+    }
+
+    pool->active = 1;
+    pool->internal = true;
+
+    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
+                            NULL, NULL);
+
+cleanup:
+    virStoragePoolDefFree(def);
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    storageDriverUnlock(driver);
+    return ret;
+}
+
+
+static virStorageVolPtr
+storageEphemeralCreateVol(virStoragePoolPtr obj,
+                          const char *source)
+{
+
+    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
+    virStoragePoolObjPtr pool;
+    virStorageBackendPtr backend;
+    virStorageVolDefPtr vol = NULL;
+    virStorageVolPtr ret = NULL;
+
+    storageDriverLock(driver);
+    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
+    storageDriverUnlock(driver);
+
+    if (!pool) {
+        virReportError(VIR_ERR_NO_STORAGE_POOL,
+                       _("no storage pool with matching uuid %s"), obj->uuid);
+        goto cleanup;
+    }
+
+    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
+        goto cleanup;
+
+    if (VIR_ALLOC(vol) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(vol->name, source) < 0)
+        goto cleanup;
+
+    if (backend->createVol(obj->conn, pool, vol, true) < 0)
+        goto cleanup;
+
+    if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
+        goto cleanup;
+
+    if (!(ret = virGetStorageVol(obj->conn, pool->def->name,
+                                 pool->volumes.objs[pool->volumes.count - 1]->name,
+                                 pool->volumes.objs[pool->volumes.count - 1]->key,
+                                 NULL, NULL))) {
+        vol = pool->volumes.objs[pool->volumes.count--];
+        goto cleanup;
+    }
+
+cleanup:
+    virStorageVolDefFree(vol);
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    return ret;
+}
+
+
+static virStorageEphemeralPtr
+storageEphemeralCreate(virConnectPtr conn,
+                       int type,
+                       const char *source,
+                       virDomainDiskSourcePoolDefPtr srcpool)
+{
+    virStorageEphemeralPtr ret = NULL;
+    char *dirname = NULL;
+    char *filename = NULL;
+
+    if (VIR_ALLOC(ret) < 0)
+        goto error;
+
+    switch ((enum virDomainDiskType) type) {
+    case VIR_DOMAIN_DISK_TYPE_LAST:
+    case VIR_DOMAIN_DISK_TYPE_BLOCK:
+    case VIR_DOMAIN_DISK_TYPE_FILE:
+    case VIR_DOMAIN_DISK_TYPE_DIR:
+        if (!(dirname = mdir_name(source))) {
+            virReportOOMError();
+            goto error;
+        }
+
+        if (VIR_STRDUP(filename, last_component(source)) < 1)
+            goto error;
+
+        if (!(ret->pool = storageEphemeralCreateDirPool(conn, dirname)))
+            goto error;
+
+        if (!(ret->vol = storageEphemeralCreateVol(ret->pool, filename)))
+            goto error;
+
+        break;
+
+    case VIR_DOMAIN_DISK_TYPE_NETWORK:
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("ephemeral network based volumes are not yet supported"));
+        goto error;
+        break;
+
+    case VIR_DOMAIN_DISK_TYPE_VOLUME:
+        ret->existing = true;
+
+        if (!(ret->pool = virStoragePoolLookupByName(conn, srcpool->pool)))
+            goto error;
+
+        if (!(ret->vol = virStorageVolLookupByName(ret->pool, srcpool->volume)))
+            goto error;
+
+        break;
+    }
+
+cleanup:
+    VIR_FREE(dirname);
+    VIR_FREE(filename);
+
+    return ret;
+
+error:
+    storageEphemeralFree(ret);
+    ret = NULL;
+    goto cleanup;
+}
+
+
+static virStorageEphemeralPtr
+storageEphemeralFromDiskDef(virConnectPtr conn,
+                            virDomainDiskDefPtr def)
+{
+    return storageEphemeralCreate(conn,
+                                  def->type,
+                                  def->src,
+                                  def->srcpool);
+
+}
+
+
+static virStorageEphemeralPtr
+storageEphemeralFromSnapshotDiskDef(virConnectPtr conn,
+                                    virDomainSnapshotDiskDefPtr def)
+{
+    return storageEphemeralCreate(conn,
+                                  def->type,
+                                  def->file,
+                                  NULL);
+}
+
 static virStorageDriver storageDriver = {
     .name = "storage",
     .storageOpen = storageOpen, /* 0.4.0 */
@@ -2632,6 +2881,10 @@ static virStorageDriver storageDriver = {

     .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
     .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
+
+    .storageEphemeralFree = storageEphemeralFree, /* 1.2.2 */
+    .storageEphemeralFromDiskDef = storageEphemeralFromDiskDef, /* 1.2.2 */
+    .storageEphemeralFromSnapshotDiskDef = storageEphemeralFromSnapshotDiskDef, /* 1.2.2 */
 };


-- 
1.8.5.2




More information about the libvir-list mailing list