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 <dguryanov(a)parallels.com>
---
src/parallels/parallels_driver.c | 9 ++
src/parallels/parallels_storage.c | 155 +++++++++++++++++++++++++++++++++++++
src/parallels/parallels_utils.h | 1 +
3 files changed, 165 insertions(+), 0 deletions(-)
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index d10d7a2..21850d3 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -103,6 +103,7 @@ parallelsDomObjFreePrivate(void *p)
return;
VIR_FREE(pdom->uuid);
+ VIR_FREE(pdom->home);
VIR_FREE(p);
};
@@ -665,6 +666,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 bb6327f..c3daee0 100644
--- a/src/parallels/parallels_storage.c
+++ b/src/parallels/parallels_storage.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <dirent.h>
#include <sys/statvfs.h>
+#include <libgen.h>
#include "datatypes.h"
#include "memory.h"
@@ -114,11 +115,158 @@ 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;
+ struct parallelsPoolsAddData data;
if ((base = strdup(SYSCONFDIR "/libvirt")) == NULL)
goto out_of_memory;
@@ -142,6 +290,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 (size_t 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 6a27003..fb759cf 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;
--
1.7.1