From 766e0c91d7b3ae9c483a1962946a16a09a3a0661 Mon Sep 17 00:00:00 2001 From: Dmitry Guryanov Date: Tue, 4 Dec 2012 17:43:05 +0400 Subject: [PATCH] parallels: create storage pools by VM list There are no storage pools in Parallels Cloud Server - All VM data stored in a single directory: config, snapshots, memory dump together with disk images. Let's look through list of VMs and create a storage pool for each directory, containing VMs. So if you have 3 vms: /var/parallels/vm-1.pvm, /var/parallels/vm-2.pvm and /root/test.pvm - 2 storage pools appear: -var-parallels and -root. xml descriptions of the pools will be saved in /etc/libvirt/parallels-storage, so UUIDs will not change netween connections to libvirt. Signed-off-by: Dmitry Guryanov --- src/parallels/parallels_driver.c | 9 ++ src/parallels/parallels_storage.c | 155 ++++++++++++++++++++++++++++++ src/parallels/parallels_utils.h | 1 + 3 files changed, 165 insertions(+) diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index 8af729e979..b50026bd67 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -104,6 +104,7 @@ parallelsDomObjFreePrivate(void *p) return; VIR_FREE(pdom->uuid); + VIR_FREE(pdom->home); VIR_FREE(p); }; @@ -666,6 +667,14 @@ parallelsLoadDomain(parallelsConnPtr privconn, virJSONValuePtr jobj) if (!(pdom->uuid = strdup(tmp))) goto no_memory; + if (!(tmp = virJSONValueObjectGetString(jobj, "Home"))) { + parallelsParseError(); + goto cleanup; + } + + if (!(pdom->home = strdup(tmp))) + goto no_memory; + if (!(tmp = virJSONValueObjectGetString(jobj, "OS"))) goto cleanup; diff --git a/src/parallels/parallels_storage.c b/src/parallels/parallels_storage.c index 90c425a228..148d870d3f 100644 --- a/src/parallels/parallels_storage.c +++ b/src/parallels/parallels_storage.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "datatypes.h" #include "memory.h" @@ -114,12 +115,159 @@ cleanup: } +struct parallelsPoolsAddData { + virConnectPtr conn; + bool failed; +}; + +/* + * Generate unique pool name by path + */ +static char *parallelsMakePoolName(virConnectPtr conn, const char *path) +{ + parallelsConnPtr privconn = conn->privateData; + char *name; + + for (unsigned int i = 0; i < UINT_MAX; i++) { + bool found = false; + + if (!(name = strdup(path))) { + virReportOOMError(); + return NULL; + } + + if (i == 0) + name = strdup(path); + else + virAsprintf(&name, "%s-%u", path, i); + + if (!name) { + virReportOOMError(); + return 0; + } + + for (int j = 0; j < strlen(name); j++) + if (name[j] == '/') + name[j] = '-'; + + for (int j = 0; j < privconn->pools.count; j++) { + if (STREQ(name, privconn->pools.objs[j]->def->name)) { + found = true; + break; + } + } + + if (!found) + return name; + + VIR_FREE(name); + } + + return NULL; +} + +static virStoragePoolObjPtr +parallelsPoolCreateByPath(virConnectPtr conn, const char *path) +{ + parallelsConnPtr privconn = conn->privateData; + virStoragePoolObjListPtr pools = &privconn->pools; + virStoragePoolDefPtr def; + virStoragePoolObjPtr pool = NULL; + + if (VIR_ALLOC(def) < 0) + goto no_memory; + + if (!(def->name = parallelsMakePoolName(conn, path))) + goto error; + + if (VIR_ALLOC_N(def->uuid, VIR_UUID_BUFLEN)) + goto no_memory; + + if (virUUIDGenerate(def->uuid)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Can't generate UUID")); + goto error; + } + + def->type = VIR_STORAGE_POOL_DIR; + def->target.path = strdup(path); + + if (!(pool = virStoragePoolObjAssignDef(pools, def))) + goto error; + + if (virStoragePoolObjSaveDef(conn->storagePrivateData, pool, def) < 0) { + virStoragePoolObjRemove(pools, pool); + goto error; + } + + virStoragePoolObjUnlock(pool); + + return pool; +no_memory: + virReportOOMError(); +error: + virStoragePoolDefFree(def); + if (pool) + virStoragePoolObjUnlock(pool); + return NULL; +} + +/* + * Create pool of type VIR_STORAGE_POOL_DIR with + * path to the VM, if it's not exists. + */ +static virStoragePoolObjPtr +parallelsPoolAddByDomain(virConnectPtr conn, virDomainObjPtr dom) +{ + parallelsConnPtr privconn = conn->privateData; + parallelsDomObjPtr pdom = dom->privateData; + virStoragePoolObjListPtr pools = &privconn->pools; + char *poolPath; + virStoragePoolObjPtr pool = NULL; + + if (!(poolPath = strdup(pdom->home))) { + virReportOOMError(); + return NULL; + } + + poolPath = dirname(poolPath); + + for (int j = 0; j < pools->count; j++) { + if (STREQ(poolPath, pools->objs[j]->def->target.path)) { + pool = pools->objs[j]; + break; + } + } + + if (!pool) + pool = parallelsPoolCreateByPath(conn, poolPath); + + VIR_FREE(poolPath); + return pool; +} + +static void +parallelsPoolsAdd(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *opaque) +{ + struct parallelsPoolsAddData *data = (struct parallelsPoolsAddData *)opaque; + virDomainObjPtr dom = payload; + virStoragePoolObjPtr pool; + + if (!(pool = parallelsPoolAddByDomain(data->conn, dom))) + data->failed = true; + + return; +} + static int parallelsLoadPools(virConnectPtr conn) { parallelsConnPtr privconn = conn->privateData; virStorageDriverStatePtr storageState = conn->storagePrivateData; char *base = NULL; size_t i; + struct parallelsPoolsAddData data; if ((base = strdup(SYSCONFDIR "/libvirt")) == NULL) goto out_of_memory; @@ -143,6 +291,13 @@ static int parallelsLoadPools(virConnectPtr conn) goto error; } + data.conn = conn; + data.failed = false; + virHashForEach(privconn->domains.objs, parallelsPoolsAdd, &data); + + if (data.failed) + goto error; + for (i = 0; i < privconn->pools.count; i++) { virStoragePoolObjLock(privconn->pools.objs[i]); virStoragePoolObjPtr pool; diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h index 6a27003a0b..fb759cfb66 100644 --- a/src/parallels/parallels_utils.h +++ b/src/parallels/parallels_utils.h @@ -44,6 +44,7 @@ typedef struct _parallelsConn *parallelsConnPtr; struct parallelsDomObj { int id; char *uuid; + char *home; }; typedef struct parallelsDomObj *parallelsDomObjPtr; -- GitLab