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(a)redhat.com>
---
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