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@xxxxxxxxx> Signed-off-by: Vasiliy Tolstov <v.tolstov@xxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list