Add a modular parser that will allow to parse 'json' backing definitions that are supported by qemu. The initial implementation adds support for the 'file' driver. --- src/util/virstoragefile.c | 87 +++++++++++++++++++++++++++++++++++++++++++---- tests/virstoragetest.c | 8 +++++ 2 files changed, 88 insertions(+), 7 deletions(-) diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 0fa9681..826e4ba 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -43,6 +43,7 @@ #include "viruri.h" #include "dirname.h" #include "virbuffer.h" +#include "virjson.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -2514,10 +2515,80 @@ virStorageSourceParseBackingColon(virStorageSourcePtr src, } +static int +virStorageSourceParseBackingJSONPath(virStorageSourcePtr src, + virJSONValuePtr json, + int type) +{ + const char *path; + + if (!(path = virJSONValueObjectGetString(json, "file.filename"))) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing 'filename' field in JSON backing volume " + "definition")); + return -1; + } + + if (VIR_STRDUP(src->path, path) < 0) + return -1; + + src->type = type; + return 0; +} + + +struct virStorageSourceJSONDriverParser { + const char *drvname; + int (*func)(virStorageSourcePtr src, virJSONValuePtr json, int opaque); + int opaque; +}; + +static const struct virStorageSourceJSONDriverParser jsonParsers[] = { + {"file", virStorageSourceParseBackingJSONPath, VIR_STORAGE_TYPE_FILE}, +}; + + +static int +virStorageSourceParseBackingJSON(virStorageSourcePtr src, + const char *json) +{ + virJSONValuePtr root; + const char *drvname; + size_t i; + int ret = -1; + + if (!(root = virJSONValueFromString(json))) + return -1; + + if (!(drvname = virJSONValueObjectGetString(root, "file.driver"))) { + virReportError(VIR_ERR_INVALID_ARG, _("JSON backing volume defintion " + "'%s' lacks driver name"), json); + goto cleanup; + } + + for (i = 0; i < ARRAY_CARDINALITY(jsonParsers); i++) { + if (STREQ(drvname, jsonParsers[i].drvname)) { + ret = jsonParsers[i].func(src, root, jsonParsers[i].opaque); + goto cleanup; + } + } + + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing parser implementation for JSON backing volume " + "driver '%s'"), drvname); + + cleanup: + virJSONValueFree(root); + return ret; +} + + virStorageSourcePtr virStorageSourceNewFromBackingAbsolute(const char *path) { + const char *json; virStorageSourcePtr ret; + int rc; if (VIR_ALLOC(ret) < 0) return NULL; @@ -2531,13 +2602,15 @@ virStorageSourceNewFromBackingAbsolute(const char *path) ret->type = VIR_STORAGE_TYPE_NETWORK; /* handle URI formatted backing stores */ - if (strstr(path, "://")) { - if (virStorageSourceParseBackingURI(ret, path) < 0) - goto error; - } else { - if (virStorageSourceParseBackingColon(ret, path) < 0) - goto error; - } + if ((json = STRSKIP(path, "json:"))) + rc = virStorageSourceParseBackingJSON(ret, json); + else if (strstr(path, "://")) + rc = virStorageSourceParseBackingURI(ret, path); + else + rc = virStorageSourceParseBackingColon(ret, path); + + if (rc < 0) + goto error; } return ret; diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index 6016a3b..46bbfb5 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -1355,6 +1355,14 @@ mymain(void) "<source protocol='nbd' name='blah'>\n" " <host name='example.org' port='6000'/>\n" "</source>\n"); + TEST_BACKING_PARSE("json:", NULL); + TEST_BACKING_PARSE("json:asdgsdfg", NULL); + TEST_BACKING_PARSE("json:{}", NULL); + TEST_BACKING_PARSE("json: { \"file.driver\":\"blah\"}", NULL); + TEST_BACKING_PARSE("json:{\"file.driver\":\"file\"}", NULL); + TEST_BACKING_PARSE("json:{\"file.driver\":\"file\", " + "\"file.filename\":\"/path/to/file\"}", + "<source file='/path/to/file'/>\n"); cleanup: /* Final cleanup */ -- 2.9.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list