[libvirt] [PATCH v3 05/13] parallels: create storage pools by VM list

Dmitry Guryanov dguryanov at parallels.com
Wed Nov 28 09:30:27 UTC 2012


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 at 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 11c5b83..fe91968 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 90c425a..148d870 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,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 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.7.6




More information about the libvir-list mailing list