[libvirt] [PATCH v3] storage sheepdog: allow to specify redundancy level

Vasiliy Tolstov v.tolstov at selfip.ru
Thu Nov 19 08:44:23 UTC 2015


Some storage backends allows to specify per volume redundancy options.
Sheepdog use x format for specify copies, and x:y format to specify
data and parity block count.

Signed-off-by: Alexey Tyabin <aleksey.tyabin at gmail.com>
Signed-off-by: Vasiliy Tolstov <v.tolstov at selfip.ru>
---
 docs/schemas/storagevol.rng                 |   3 +
 src/conf/storage_conf.c                     |   2 +
 src/storage/storage_backend_sheepdog.c      | 143 +++++++++++++++++-----------
 src/util/virstoragefile.c                   |   4 +-
 src/util/virstoragefile.h                   |   2 +
 tests/storagebackendsheepdogtest.c          | 104 ++++++++++----------
 tests/storagevolxml2xmlin/vol-sheepdog.xml  |   1 +
 tests/storagevolxml2xmlout/vol-sheepdog.xml |   1 +
 8 files changed, 153 insertions(+), 107 deletions(-)

diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng
index 7450547..068993f 100644
--- a/docs/schemas/storagevol.rng
+++ b/docs/schemas/storagevol.rng
@@ -55,6 +55,9 @@
         <element name='allocation'>
           <ref name='scaledInteger'/>
         </element>
+        <element name='redundancy'>
+          <ref name='string'/>
+        </element>
       </optional>
     </interleave>
   </define>
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 9b8abea..d37c93a 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1345,6 +1345,8 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
         ret->target.allocation = ret->target.capacity;
     }

+    ret->target.redundancy = virXPathString("string(./redundancy)", ctxt);
+
     ret->target.path = virXPathString("string(./target/path)", ctxt);
     if (options->formatFromString) {
         char *format = virXPathString("string(./target/format/@type)", ctxt);
diff --git a/src/storage/storage_backend_sheepdog.c b/src/storage/storage_backend_sheepdog.c
index 1200813..d8356a1 100644
--- a/src/storage/storage_backend_sheepdog.c
+++ b/src/storage/storage_backend_sheepdog.c
@@ -51,43 +51,52 @@ virStorageBackendSheepdogParseNodeInfo(virStoragePoolDefPtr pool,
      * node id/total, size, used, use%, [total vdi size]
      *
      * example output:
-     * 0 15245667872 117571104 0%
-     * Total 15245667872 117571104 0% 20972341
+     * 0 425814278144 4871131136 420943147008 1%
+     * Total 2671562256384 32160083968 2639402172416 1% 75161927680
      */
-
-    const char *p, *next;
+    char **lines = NULL;
+    char **cells = NULL;
+    size_t i;
+    int ret = -1;

     pool->allocation = pool->capacity = pool->available = 0;

-    p = output;
-    do {
-        char *end;
+    lines = virStringSplit(output, "\n", 0);
+    if (lines == NULL)
+        goto cleanup;

-        if ((next = strchr(p, '\n')))
-            ++next;
-        else
-            break;
+    for (i = 0; lines[i]; i++) {
+        char *line = lines[i];
+        if (line == NULL)
+            goto cleanup;

-        if (!STRPREFIX(p, "Total "))
+        if (!STRPREFIX(line, "Total "))
             continue;

-        p = p + 6;
+        virStringStripControlChars(line);
+        virTrimSpaces(line, NULL);
+        if ((cells = virStringSplit(line, " ", 0)) == NULL)
+            continue;

-        if (virStrToLong_ull(p, &end, 10, &pool->capacity) < 0)
-            break;
+        if (virStringListLength(cells) < 3) {
+            goto cleanup;
+        }

-        if ((p = end + 1) > next)
-            break;
+        if (virStrToLong_ull(cells[1], NULL, 10, &pool->capacity) < 0)
+            goto cleanup;

-        if (virStrToLong_ull(p, &end, 10, &pool->allocation) < 0)
-            break;
+        if (virStrToLong_ull(cells[2], NULL, 10, &pool->allocation) < 0)
+            goto cleanup;

         pool->available = pool->capacity - pool->allocation;
-        return 0;
-
-    } while ((p = next));
+        ret = 0;
+        break;
+    }

-    return -1;
+ cleanup:
+    virStringFreeList(lines);
+    virStringFreeList(cells);
+    return ret;
 }

 void
@@ -275,6 +284,10 @@ virStorageBackendSheepdogBuildVol(virConnectPtr conn ATTRIBUTE_UNUSED,

     cmd = virCommandNewArgList(SHEEPDOGCLI, "vdi", "create", vol->name, NULL);
     virCommandAddArgFormat(cmd, "%llu", vol->target.capacity);
+
+    if(NULL != vol->target.redundancy)
+        virCommandAddArgList(cmd, "-c", vol->target.redundancy, NULL);
+
     virStorageBackendSheepdogAddHostArg(cmd, pool);
     if (virCommandRun(cmd, NULL) < 0)
         goto cleanup;
@@ -291,60 +304,78 @@ virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
                                       char *output)
 {
     /* fields:
-     * current/clone/snapshot, name, id, size, used, shared, creation time, vdi id, [tag]
+     * current/clone/snapshot, name, id, size, used, shared, creation time, vdi id, redundancy, [tag], size shift
      *
      * example output:
-     * s test 1 10 0 0 1336556634 7c2b25
-     * s test 2 10 0 0 1336557203 7c2b26
-     * = test 3 10 0 0 1336557216 7c2b27
+     * s test 1 10 0 0 1336556634 7c2b25 1 tt 22
+     * s test 2 10 0 0 1336557203 7c2b26 2 zz 22
+     * = 39865 0 21474836480 247463936 1337982976 1447516646 47d187 2  22
+     * = test 3 10 0 0 1336557216 7c2b27 3 xx 22
      */
-
-    int id;
-    const char *p, *next;
+    char **lines = NULL;
+    char **cells = NULL;
+    size_t i;
+    int ret = -1;

     vol->target.allocation = vol->target.capacity = 0;
+    vol->target.redundancy = NULL;

-    p = output;
-    do {
-        char *end;
+    lines = virStringSplit(output, "\n", 0);
+    if (lines == NULL)
+        goto cleanup;

-        if ((next = strchr(p, '\n')))
-            ++next;
+    for (i = 0; lines[i]; i++) {
+        char *line = lines[i];
+        if (line == NULL)
+            break;

-        /* ignore snapshots */
-        if (*p != '=')
+        if (!STRPREFIX(line, "= "))
             continue;

-        /* skip space */
-        if (p + 2 < next)
-            p += 2;
+        /* skip = and space */
+        if (*(line + 2) != '\0')
+            line += 2;
         else
-            return -1;
+            continue;

         /* skip name */
-        while (*p != '\0' && *p != ' ') {
-            if (*p == '\\')
-                ++p;
-            ++p;
+        while (*line != '\0' && *line != ' ') {
+            if (*line == '\\')
+                ++line;
+            ++line;
         }

-        if (virStrToLong_i(p, &end, 10, &id) < 0)
-            return -1;
+        /* skip space */
+        if (*(line + 1) != '\0')
+            line += 1;
+        else
+            continue;

-        p = end + 1;
+        virStringStripControlChars(line);
+        virTrimSpaces(line, NULL);
+        if ((cells = virStringSplit(line, " ", 0)) == NULL)
+            continue;

-        if (virStrToLong_ull(p, &end, 10, &vol->target.capacity) < 0)
-            return -1;
+        if (virStringListLength(cells) < 5)
+            continue;

-        p = end + 1;
+        if ((ret = virStrToLong_ull(cells[1], NULL, 10, &vol->target.capacity)) < 0)
+            goto cleanup;

-        if (virStrToLong_ull(p, &end, 10, &vol->target.allocation) < 0)
-            return -1;
+        if ((ret = virStrToLong_ull(cells[2], NULL, 10, &vol->target.allocation)) < 0)
+            goto cleanup;

-        return 0;
-    } while ((p = next));
+        if ((ret = VIR_STRDUP(vol->target.redundancy, cells[6])) < 0)
+            goto cleanup;

-    return -1;
+        ret = 0;
+        break;
+    }
+
+ cleanup:
+    virStringFreeList(lines);
+    virStringFreeList(cells);
+    return ret;
 }

 static int
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 2aa1d90..9cdc90d 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -1846,7 +1846,8 @@ virStorageSourceCopy(const virStorageSource *src,
         VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 ||
         VIR_STRDUP(ret->snapshot, src->snapshot) < 0 ||
         VIR_STRDUP(ret->configFile, src->configFile) < 0 ||
-        VIR_STRDUP(ret->compat, src->compat) < 0)
+        VIR_STRDUP(ret->compat, src->compat) < 0 ||
+        VIR_STRDUP(ret->redundancy, src->redundancy) < 0)
         goto error;

     if (src->nhosts) {
@@ -2040,6 +2041,7 @@ virStorageSourceClear(virStorageSourcePtr def)
     VIR_FREE(def->volume);
     VIR_FREE(def->snapshot);
     VIR_FREE(def->configFile);
+    VIR_FREE(def->redundancy);
     virStorageSourcePoolDefFree(def->srcpool);
     VIR_FREE(def->driverName);
     virBitmapFree(def->features);
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index b98fe25..c37cfc2 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -282,6 +282,8 @@ struct _virStorageSource {
     /* Name of the child backing store recorded in metadata of the
      * current file.  */
     char *backingStoreRaw;
+    /* redundancy level, may be used by sheepdog or ceph */
+    char *redundancy;
 };


diff --git a/tests/storagebackendsheepdogtest.c b/tests/storagebackendsheepdogtest.c
index 2b0f4db..d110bde 100644
--- a/tests/storagebackendsheepdogtest.c
+++ b/tests/storagebackendsheepdogtest.c
@@ -42,15 +42,23 @@ typedef struct {
     int expected_return;
     uint64_t expected_capacity;
     uint64_t expected_allocation;
-} collie_test;
+} collie_test1;
+
+typedef struct {
+    const char *output;
+    int expected_return;
+    uint64_t expected_capacity;
+    uint64_t expected_allocation;
+    const char *expected_redundancy;
+} collie_test2;

 struct testNodeInfoParserData {
-    collie_test data;
+    collie_test1 data;
     const char *poolxml;
 };

 struct testVDIListParserData {
-    collie_test data;
+    collie_test2 data;
     const char *poolxml;
     const char *volxml;
 };
@@ -60,7 +68,7 @@ static int
 test_node_info_parser(const void *opaque)
 {
     const struct testNodeInfoParserData *data = opaque;
-    collie_test test = data->data;
+    collie_test1 test = data->data;
     int ret = -1;
     char *output = NULL;
     virStoragePoolDefPtr pool = NULL;
@@ -75,11 +83,6 @@ test_node_info_parser(const void *opaque)
         test.expected_return)
         goto cleanup;

-    if (test.expected_return) {
-        ret = 0;
-        goto cleanup;
-    }
-
     if (pool->capacity == test.expected_capacity &&
         pool->allocation == test.expected_allocation)
         ret = 0;
@@ -94,7 +97,7 @@ static int
 test_vdi_list_parser(const void *opaque)
 {
     const struct testVDIListParserData *data = opaque;
-    collie_test test = data->data;
+    collie_test2 test = data->data;
     int ret = -1;
     char *output = NULL;
     virStoragePoolDefPtr pool = NULL;
@@ -113,14 +116,15 @@ test_vdi_list_parser(const void *opaque)
         test.expected_return)
         goto cleanup;

-    if (test.expected_return) {
-        ret = 0;
-        goto cleanup;
-    }

     if (vol->target.capacity == test.expected_capacity &&
-        vol->target.allocation == test.expected_allocation)
-        ret = 0;
+        vol->target.allocation == test.expected_allocation) {
+        if (test.expected_redundancy != NULL && vol->target.redundancy != NULL &&
+            !strcmp(vol->target.redundancy, test.expected_redundancy))
+            ret = 0;
+        if (test.expected_redundancy == NULL && vol->target.redundancy == NULL)
+            ret = 0;
+    }

  cleanup:
     VIR_FREE(output);
@@ -137,45 +141,47 @@ mymain(void)
     char *poolxml = NULL;
     char *volxml = NULL;

-    collie_test node_info_tests[] = {
+    collie_test1 node_info_tests[] = {
         {"", -1, 0, 0},
-        {"Total 15245667872 117571104 0% 20972341\n", 0, 15245667872, 117571104},
+        {"Total 2671562256384 32160083968 2639402172416 1% 75161927680\n", 0, 2671562256384, 32160083968},
+        {"Total 15245667872 117571104 20972341 0%\n", 0, 15245667872, 117571104},
         {"To", -1, 0, 0},
         {"asdf\nasdf", -1, 0, 0},
         {"Total ", -1, 0, 0},
         {"Total 1", -1, 0, 0},
         {"Total 1\n", -1, 0, 0},
         {"Total 1 ", -1, 0, 0},
-        {"Total 1 2", -1, 0, 0},
-        {"Total 1 2 ", -1, 0, 0},
+        {"Total 1 2 ", 0, 1, 2},
         {"Total 1 2\n", 0, 1, 2},
         {"Total 1 2 \n", 0, 1, 2},
+        {"Total 1 2 \n", 0, 1, 2},
         {"Total a 2 \n", -1, 0, 0},
-        {"Total 1 b \n", -1, 0, 0},
+        {"Total 1 b \n", -1, 1, 0},
         {"Total a b \n", -1, 0, 0},
         {"stuff\nTotal 1 2 \n", 0, 1, 2},
-        {"0 1 2 3\nTotal 1 2 \n", 0, 1, 2},
+        {"0 1 2\nTotal 1 2 \n", 0, 1, 2},
         {NULL, 0, 0, 0}
     };

-    collie_test vdi_list_tests[] = {
-        {"", -1, 0, 0},
-        {"= test 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
-        {"= test\\ with\\ spaces 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
-        {"= backslashattheend\\\\ 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
-        {"s test 1 10 20 0 1336556634 7c2b25\n= test 3 50 60 0 1336557216 7c2b27\n", 0, 50, 60},
-        {"=", -1, 0, 0},
-        {"= test", -1, 0, 0},
-        {"= test ", -1, 0, 0},
-        {"= test 1", -1, 0, 0},
-        {"= test 1 ", -1, 0, 0},
-        {"= test 1 2", -1, 0, 0},
-        {"= test 1 2 ", -1, 0, 0},
-        {"= test 1 2 3", -1, 0, 0},
-        {NULL, 0, 0, 0}
+    collie_test2 vdi_list_tests[] = {
+        {"", -1, 0, 0,NULL},
+        {"= test 3 10 20 1 1336557216 7c2b27 1 22\n", 0, 10, 20, "1"},
+        {"= test\\ with\\ spaces 3 10 20 0 1336557216 7c2b27 3:4 22\n", 0, 10, 20, "3:4"},
+        {"= backslashattheend\\\\ 3 10 20 0 1336557216 7c2b27 1 22\n", 0, 10, 20, "1"},
+        {"s test 1 10 20 0 1336556634 7c2b25 2\n= test 3 50 60 0 1336557216 7c2b27 2:3 22\n", 0, 50, 60, "2:3"},
+        {"=", -1, 0, 0, NULL},
+        {"= test", -1, 0, 0, NULL},
+        {"= test ", -1, 0, 0,NULL},
+        {"= test 1", -1, 0, 0,NULL},
+        {"= test 1 ", -1, 0, 0,NULL},
+        {"= test 1 2", -1, 0, 0,NULL},
+        {"= test 1 2 ", -1, 0, 0,NULL},
+        {"= test 1 2 3", -1, 0, 0,NULL},
+        {NULL, 0, 0, 0,NULL}
     };

-    collie_test *test = node_info_tests;
+    collie_test1 *test1 = node_info_tests;
+    collie_test2 *test2 = vdi_list_tests;

     if (virAsprintf(&poolxml, "%s/storagepoolxml2xmlin/pool-sheepdog.xml",
                     abs_srcdir) < 0)
@@ -185,10 +191,10 @@ mymain(void)
                     abs_srcdir) < 0)
         goto cleanup;

-#define DO_TEST_NODE(collie)                                            \
+#define DO_TEST_NODE(collie1)                                            \
     do {                                                                \
         struct testNodeInfoParserData data = {                          \
-            .data = collie,                                             \
+            .data = collie1,                                             \
             .poolxml = poolxml,                                         \
         };                                                              \
         if (virtTestRun("node_info_parser", test_node_info_parser,      \
@@ -196,16 +202,16 @@ mymain(void)
             ret = -1;                                                   \
     } while (0)

-    while (test->output != NULL) {
-        DO_TEST_NODE(*test);
-        ++test;
+    while (test1->output != NULL) {
+        DO_TEST_NODE(*test1);
+        ++test1;
     }


-#define DO_TEST_VDI(collie)                                             \
+#define DO_TEST_VDI(collie2)                                             \
     do {                                                                \
         struct testVDIListParserData data = {                           \
-            .data = collie,                                             \
+            .data = collie2,                                             \
             .poolxml = poolxml,                                         \
             .volxml = volxml,                                           \
         };                                                              \
@@ -214,11 +220,9 @@ mymain(void)
             ret = -1;                                                   \
     } while (0)

-    test = vdi_list_tests;
-
-    while (test->output != NULL) {
-        DO_TEST_VDI(*test);
-        ++test;
+    while (test2->output != NULL) {
+        DO_TEST_VDI(*test2);
+        ++test2;
     }

  cleanup:
diff --git a/tests/storagevolxml2xmlin/vol-sheepdog.xml b/tests/storagevolxml2xmlin/vol-sheepdog.xml
index d6e920b..f88e6db 100644
--- a/tests/storagevolxml2xmlin/vol-sheepdog.xml
+++ b/tests/storagevolxml2xmlin/vol-sheepdog.xml
@@ -4,6 +4,7 @@
   </source>
   <capacity unit='bytes'>1024</capacity>
   <allocation unit='bytes'>0</allocation>
+  <redundancy unit='string'>3</redundancy>
   <target>
     <path>sheepdog:test2</path>
   </target>
diff --git a/tests/storagevolxml2xmlout/vol-sheepdog.xml b/tests/storagevolxml2xmlout/vol-sheepdog.xml
index e1d6a9e..207f5fb 100644
--- a/tests/storagevolxml2xmlout/vol-sheepdog.xml
+++ b/tests/storagevolxml2xmlout/vol-sheepdog.xml
@@ -4,6 +4,7 @@
   </source>
   <capacity unit='bytes'>1024</capacity>
   <allocation unit='bytes'>0</allocation>
+  <redundancy unit='string'>3</redundancy>
   <target>
     <path>sheepdog:test2</path>
     <format type='unknown'/>
--
2.5.0




More information about the libvir-list mailing list