This patch adds support for gluster specific JSON parser functionality This will help in parsing the backing store which uses JSON syntax and update the meta-data in the domain specific objects while taking snapshots which inturn helps in successful creation/updation of backing store information in domain xml Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@xxxxxxxxxx> --- src/util/virstoragefile.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 16de603..033d6a2 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -41,10 +41,12 @@ #include "virstring.h" #include "virutil.h" #include "viruri.h" +#include "virjson.h" #include "dirname.h" #include "virbuffer.h" #define VIR_FROM_THIS VIR_FROM_STORAGE +#define DEFAULT_GLUSTER_PORT 24007 VIR_LOG_INIT("util.storagefile"); @@ -2126,6 +2128,209 @@ virStorageSourceNewFromBackingRelative(virStorageSourcePtr parent, goto cleanup; } +#if WITH_STORAGE_GLUSTER +static int +virStorageSourceParseBackingJSON(virStorageSourcePtr src, + const char *path) +{ + virJSONValuePtr json = NULL; + virJSONValuePtr file = NULL; + virJSONValuePtr server = NULL; + virJSONValuePtr object = NULL; + const char *str = NULL; + int port = 0; + size_t i = 0; + int ret = -1; + + /* An example of gluster json formatted string containing two servers: + * + * json:{ file: { driver:"gluster", volume:"testvol", path:"/a.img", + * server :[ {type:"tcp", host:"1.2.3.4", port:24007}, + * {type:"unix", socket:"/tmp/glusterd.socket"}, + * ] }, driver:"qcow2" } + */ + + /* Get 'json:' object */ + json = virJSONValueFromString(path+strlen("json:")); + + /* Get Image file format */ + if (virJSONValueObjectHasKey(json, "driver")) { + if (!(str = virJSONValueObjectGetString(json, "driver"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get String from key 'driver'")); + goto error; + } + if ((src->format = virStorageFileFormatTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get Format type of key 'driver'")); + goto error; + } + } else { + src->format = 1; /* default to raw */ + } + + /* Get 'file:' object */ + if (virJSONValueObjectHasKey(json, "file")) { + if (!(file = virJSONValueObjectGet(json, "file"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get Object from key 'file'")); + goto error; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("No Key 'file'")); + goto error; + } + + /* Get 'protocol' Info */ + if (virJSONValueObjectHasKey(file, "driver")) { + if (!(str = virJSONValueObjectGetString(file, "driver"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get String from key 'driver'")); + goto error; + } + if ((src->protocol = virStorageNetProtocolTypeFromString(str)) <= 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get Protocol type of key 'driver'")); + goto error; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No protocol Key 'driver'")); + goto error; + } + + /* Get 'volume' name Info */ + if (virJSONValueObjectHasKey(file, "volume")) { + if (!(str = virJSONValueObjectGetString(file, "volume"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get String from key 'volume'")); + goto error; + } + if (VIR_STRDUP(src->volume, str) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Falied to duplicate value of key 'volume'")); + goto error; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("No Key 'volume'")); + goto error; + } + + /* Get 'path' info of Image*/ + if (virJSONValueObjectHasKey(file, "path")) { + if (!(str = virJSONValueObjectGetString(file, "path"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get String from key 'path'")); + goto error; + } + if (VIR_STRDUP(src->path, str) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Falied to duplicate value of key 'path'")); + goto error; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("No Key 'path'")); + goto error; + } + + /* Get 'server:' object */ + if (virJSONValueObjectHasKey(file, "server")) { + if (!(server = virJSONValueObjectGetArray(file, "server"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get Array Object from key 'file'")); + goto error; + } + if (!(src->nhosts = virJSONValueArraySize(server))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get Size of Array from key 'server'")); + goto error; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("No Key 'server'")); + goto error; + } + + /* null-terminated list */ + if (VIR_ALLOC_N(src->hosts, src->nhosts + 1) < 0) + goto error; + + /* Parse 'server' object for { type, host, port, socket} */ + for (i = 0; i < src->nhosts; i++) { + object = virJSONValueArrayGet(server, i); + if (virJSONValueObjectHasKey(object, "type")) { + if (!(str = virJSONValueObjectGetString(object, "type"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get String from key 'type'")); + goto error; + } + if ((src->hosts[i].transport = virStorageNetHostTransportTypeFromString(str)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get Transport from key 'type'")); + } + } else { + src->hosts[i].transport = VIR_STORAGE_NET_HOST_TRANS_TCP; + } + + if (src->hosts[i].transport == VIR_STORAGE_NET_HOST_TRANS_UNIX) { + if (virJSONValueObjectHasKey(object, "socket")) { + if (!(str = virJSONValueObjectGetString(object, "socket"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get String from key 'socket'")); + goto error; + } + if (VIR_STRDUP(src->hosts[i].socket, str) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Falied to duplicate value of key 'socket'")); + goto error; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("No Key 'socket'")); + goto error; + } + } else { /* tcp */ + if (virJSONValueObjectHasKey(object, "host")) { + if (!(str = virJSONValueObjectGetString(object, "host"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get String from key 'host'")); + goto error; + } + if (VIR_STRDUP(src->hosts[i].name, str) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Falied to duplicate value of key 'host'")); + goto error; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("No Key 'host'")); + goto error; + } + + if (virJSONValueObjectHasKey(object, "port")) { + if (virJSONValueObjectGetNumberInt(object, "port", &port) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get NumberInt from key 'port'")); + goto error; + } + if (virAsprintf(&src->hosts[i].port, "%d", port) < 0) + goto error; + } else { + if (virAsprintf(&src->hosts[i].port, "%d", DEFAULT_GLUSTER_PORT) < 0) + goto error; + } + } + } + + ret = 0; + + error: + virJSONValueFree(object); + virJSONValueFree(server); + virJSONValueFree(file); + virJSONValueFree(json); + + return ret; +} + +#endif /* WITH_STORAGE_GLUSTER */ static int virStorageSourceParseBackingURI(virStorageSourcePtr src, @@ -2534,6 +2739,9 @@ virStorageSourceNewFromBackingAbsolute(const char *path) if (strstr(path, "://")) { if (virStorageSourceParseBackingURI(ret, path) < 0) goto error; + } else if (strstr(path, "json:")) { + if (virStorageSourceParseBackingJSON(ret, path) < 0) + goto error; } else { if (virStorageSourceParseBackingColon(ret, path) < 0) goto error; -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list