diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cbc408f784..1c170b6ded 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2364,6 +2364,7 @@ virStorageSourceIsBlockLocal; virStorageSourceIsEmpty; virStorageSourceIsLocalStorage; virStorageSourceNewFromBacking; +virStorageSourceNewFromBackingAbsolute; virStorageSourceParseRBDColonString; virStorageSourcePoolDefFree; virStorageSourcePoolModeTypeFromString; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 16de603588..0fa96815b6 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -2514,7 +2514,7 @@ virStorageSourceParseBackingColon(virStorageSourcePtr src, } -static virStorageSourcePtr +virStorageSourcePtr virStorageSourceNewFromBackingAbsolute(const char *path) { virStorageSourcePtr ret; diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 78beaf4def..1a76fad0f6 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -380,4 +380,7 @@ int virStorageFileGetRelativeBackingPath(virStorageSourcePtr from, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); int virStorageFileCheckCompat(const char *compat); + +virStorageSourcePtr virStorageSourceNewFromBackingAbsolute(const char *path); + #endif /* __VIR_STORAGE_FILE_H__ */ diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index 580065e04d..6016a3beb8 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -665,6 +665,58 @@ testPathRelative(const void *args) } +struct testBackingParseData { + const char *backing; + const char *expect; +}; + +static int +testBackingParse(const void *args) +{ + const struct testBackingParseData *data = args; + virBuffer buf = VIR_BUFFER_INITIALIZER; + virStorageSourcePtr src = NULL; + char *xml = NULL; + int ret = -1; + + if (!(src = virStorageSourceNewFromBackingAbsolute(data->backing))) { + if (!data->expect) + ret = 0; + + goto cleanup; + } + + if (src && !data->expect) { + fprintf(stderr, "parsing of backing store string '%s' should " + "have failed\n", data->backing); + goto cleanup; + } + + if (virDomainDiskSourceFormat(&buf, src, 0, 0) < 0 || + !(xml = virBufferContentAndReset(&buf))) { + fprintf(stderr, "failed to format disk source xml\n"); + goto cleanup; + } + + if (!STREQ(xml, data->expect)) { + fprintf(stderr, "\n backing store string '%s'\n" + "expected storage source xml:\n%s\n" + "actual storage source xml:\n%s\n", + data->backing, data->expect, xml); + goto cleanup; + } + + ret = 0; + + cleanup: + virStorageSourceFree(src); + virBufferFreeAndReset(&buf); + VIR_FREE(xml); + + return ret; +} + + static int mymain(void) { @@ -674,6 +726,7 @@ mymain(void) struct testLookupData data2; struct testPathCanonicalizeData data3; struct testPathRelativeBacking data4; + struct testBackingParseData data5; virStorageSourcePtr chain = NULL; virStorageSourcePtr chain2; /* short for chain->backingStore */ virStorageSourcePtr chain3; /* short for chain2->backingStore */ @@ -1276,6 +1329,33 @@ mymain(void) TEST_RELATIVE_BACKING(21, backingchain[10], backingchain[11], "../../../../blah/image4"); TEST_RELATIVE_BACKING(22, backingchain[11], backingchain[11], "../blah/image4"); + + virTestCounterReset("Backing store parse "); + +#define TEST_BACKING_PARSE(bck, xml) \ + do { \ + data5.backing = bck; \ + data5.expect = xml; \ + if (virTestRun(virTestCounterNext(), \ + testBackingParse, &data5) < 0) \ + ret = -1; \ + } while (0) + + TEST_BACKING_PARSE("path", "\n"); + TEST_BACKING_PARSE("://", NULL); + TEST_BACKING_PARSE("http://example.com/file", + "\n" + " \n" + "\n"); + TEST_BACKING_PARSE("rbd:testshare:id=asdf:mon_host=example.com", + "\n" + " \n" + "\n"); + TEST_BACKING_PARSE("nbd:example.org:6000:exportname=blah", + "\n" + " \n" + "\n"); + cleanup: /* Final cleanup */ virStorageSourceFree(chain);