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