Blob Blame History Raw
From 0d64aa3d8573b36ae85b77138dc463ca05e7bae1 Mon Sep 17 00:00:00 2001
Message-Id: <0d64aa3d8573b36ae85b77138dc463ca05e7bae1@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 20 Jun 2017 10:22:41 +0200
Subject: [PATCH] util: storage: Add JSON parser for new options in iSCSI
 protocol

Starting from qemu 2.9, more granular options are supported. Add parser
for the relevant bits.

With this patch libvirt is able to parse the host and target IQN of from
the JSON pseudo-protocol specification.

This corresponds to BlockdevOptionsIscsi in qemu qapi.

(cherry picked from commit b24bc54080b4bc444e60560c0db00c5867e74000)

https://bugzilla.redhat.com/show_bug.cgi?id=1461638

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
---
 src/util/virstoragefile.c | 63 ++++++++++++++++++++++++++++++++++++++++++++---
 tests/virstoragetest.c    | 19 ++++++++++++++
 2 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 3f8bc43928..945c3e4198 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -2940,18 +2940,73 @@ virStorageSourceParseBackingJSONiSCSI(virStorageSourcePtr src,
                                       virJSONValuePtr json,
                                       int opaque ATTRIBUTE_UNUSED)
 {
+    const char *transport = virJSONValueObjectGetString(json, "transport");
+    const char *portal = virJSONValueObjectGetString(json, "portal");
+    const char *target = virJSONValueObjectGetString(json, "target");
     const char *uri;
+    char *port;
+    unsigned int lun = 0;
+    char *fulltarget = NULL;
+    int ret = -1;
 
     /* legacy URI based syntax passed via 'filename' option */
     if ((uri = virJSONValueObjectGetString(json, "filename")))
         return virStorageSourceParseBackingJSONUriStr(src, uri,
                                                       VIR_STORAGE_NET_PROTOCOL_ISCSI);
 
-    /* iSCSI currently supports only URI syntax passed in as filename */
-    virReportError(VIR_ERR_INVALID_ARG, "%s",
-                   _("missing iSCSI URI in JSON backing volume definition"));
+    src->type = VIR_STORAGE_TYPE_NETWORK;
+    src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI;
 
-    return -1;
+    if (VIR_ALLOC(src->hosts) < 0)
+        goto cleanup;
+
+    src->nhosts = 1;
+
+    if (STRNEQ_NULLABLE(transport, "tcp")) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("only TCP transport is supported for iSCSI volumes"));
+        goto cleanup;
+    }
+
+    src->hosts->transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
+
+    if (!portal) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("missing 'portal' address in iSCSI backing definition"));
+        goto cleanup;
+    }
+
+    if (!target) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("missing 'target' in iSCSI backing definition"));
+        goto cleanup;
+    }
+
+    if (VIR_STRDUP(src->hosts->name, portal) < 0)
+        goto cleanup;
+
+    if ((port = strchr(src->hosts->name, ':'))) {
+        if (VIR_STRDUP(src->hosts->port, port + 1) < 0)
+            goto cleanup;
+
+        if (strlen(src->hosts->port) == 0)
+            VIR_FREE(src->hosts->port);
+
+        *port = '\0';
+    }
+
+    ignore_value(virJSONValueObjectGetNumberUint(json, "lun", &lun));
+
+    if (virAsprintf(&fulltarget, "%s/%u", target, lun) < 0)
+        goto cleanup;
+
+    VIR_STEAL_PTR(src->path, fulltarget);
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(fulltarget);
+    return ret;
 }
 
 
diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c
index 4a1d4d0923..294e1f6ffb 100644
--- a/tests/virstoragetest.c
+++ b/tests/virstoragetest.c
@@ -1502,6 +1502,25 @@ mymain(void)
                                     "\"driver\": \"file\","
                                     "\"filename\": \"/path/to/file\" } } }",
                        "<source file='/path/to/file'/>\n");
+    TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"iscsi\","
+                                       "\"transport\":\"tcp\","
+                                       "\"portal\":\"test.org\","
+                                       "\"target\":\"iqn.2016-12.com.virttest:emulated-iscsi-noauth.target\""
+                                      "}"
+                            "}",
+                       "<source protocol='iscsi' name='iqn.2016-12.com.virttest:emulated-iscsi-noauth.target/0'>\n"
+                       "  <host name='test.org'/>\n"
+                       "</source>\n");
+    TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"iscsi\","
+                                       "\"transport\":\"tcp\","
+                                       "\"portal\":\"test.org:1234\","
+                                       "\"target\":\"iqn.2016-12.com.virttest:emulated-iscsi-noauth.target\","
+                                       "\"lun\":6"
+                                      "}"
+                            "}",
+                       "<source protocol='iscsi' name='iqn.2016-12.com.virttest:emulated-iscsi-noauth.target/6'>\n"
+                       "  <host name='test.org' port='1234'/>\n"
+                       "</source>\n");
 
  cleanup:
     /* Final cleanup */
-- 
2.13.1