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(a)gmail.com>
Signed-off-by: Vasiliy Tolstov <v.tolstov(a)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