]> xenbits.xensource.com Git - libvirt.git/commitdiff
virISCSIScanTargets: Honour iSCSI interface
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 29 Jun 2018 14:05:50 +0000 (16:05 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 25 Jul 2018 05:11:13 +0000 (07:11 +0200)
When scanning for targets, iSCSI might give different results
depending on the interface used. This is basically just name of
config file under /etc/iscsi/ifaces to use. The file contains
initiator IQN thus different results claim.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
src/storage/storage_backend_iscsi.c
src/util/viriscsi.c
src/util/viriscsi.h
tests/viriscsitest.c

index 7871d1915b11c2549b927d6f57e0cebd98cbea37..3b9dddb4fdd4536b5b501084efd84319ca3c9990 100644 (file)
@@ -194,7 +194,9 @@ virStorageBackendISCSIFindPoolSources(const char *srcSpec,
     if (!(portal = virStorageBackendISCSIPortal(source)))
         goto cleanup;
 
-    if (virISCSIScanTargets(portal, &ntargets, &targets) < 0)
+    if (virISCSIScanTargets(portal,
+                            source->initiator.iqn,
+                            &ntargets, &targets) < 0)
         goto cleanup;
 
     if (VIR_ALLOC_N(list.sources, ntargets) < 0)
index 1ddf00aa4c4adbceee9862580c27cdd34dd4c6f9..549f75b4344984252ab7ef16ee2c5c9627c55539 100644 (file)
 VIR_LOG_INIT("util.iscsi");
 
 
+static int
+virISCSIScanTargetsInternal(const char *portal,
+                            const char *ifacename,
+                            size_t *ntargetsret,
+                            char ***targetsret);
+
+
 struct virISCSISessionData {
     char *session;
     const char *devpath;
@@ -286,9 +293,10 @@ virISCSIConnection(const char *portal,
              * iscsiadm doesn't let you send commands to the Interface IQN,
              * unless you've first issued a 'sendtargets' command to the
              * portal. Without the sendtargets all that is received is a
-             * "iscsiadm: No records found"
+             * "iscsiadm: No records found". However, we must ensure that
+             * the command is issued over interface name we invented above.
              */
-            if (virISCSIScanTargets(portal, NULL, NULL) < 0)
+            if (virISCSIScanTargetsInternal(portal, ifacename, NULL, NULL) < 0)
                 goto cleanup;
 
             break;
@@ -371,10 +379,11 @@ virISCSIGetTargets(char **const groups,
 }
 
 
-int
-virISCSIScanTargets(const char *portal,
-                    size_t *ntargetsret,
-                    char ***targetsret)
+static int
+virISCSIScanTargetsInternal(const char *portal,
+                            const char *ifacename,
+                            size_t *ntargetsret,
+                            char ***targetsret)
 {
     /**
      *
@@ -400,6 +409,12 @@ virISCSIScanTargets(const char *portal,
                                              "--op", "nonpersistent",
                                              NULL);
 
+    if (ifacename) {
+        virCommandAddArgList(cmd,
+                             "--interface", ifacename,
+                             NULL);
+    }
+
     memset(&list, 0, sizeof(list));
 
     if (virCommandRunRegex(cmd,
@@ -425,6 +440,58 @@ virISCSIScanTargets(const char *portal,
     return ret;
 }
 
+
+/**
+ * virISCSIScanTargets:
+ * @portal: iSCSI portal
+ * @initiatoriqn: Initiator IQN
+ * @ntargets: number of items in @targetsret array
+ * @targets: array of targets
+ *
+ * For given @portal issue sendtargets command. Optionally,
+ * @initiatoriqn can be set to override default configuration.
+ * The targets are stored into @targets array and the size of
+ * the array is stored into @ntargets.
+ *
+ * Returns: 0 on success,
+ *         -1 otherwise (with error reported)
+ */
+int
+virISCSIScanTargets(const char *portal,
+                    const char *initiatoriqn,
+                    size_t *ntargets,
+                    char ***targets)
+{
+    char *ifacename = NULL;
+    int ret = -1;
+
+    if (ntargets)
+        *ntargets = 0;
+    if (targets)
+        *targets = NULL;
+
+    if (initiatoriqn) {
+        switch ((virStorageBackendIQNFound(initiatoriqn, &ifacename))) {
+        case IQN_FOUND:
+            break;
+
+        case IQN_MISSING:
+            virReportError(VIR_ERR_OPERATION_FAILED,
+                           _("no iSCSI interface defined for IQN %s"),
+                           initiatoriqn);
+            ATTRIBUTE_FALLTHROUGH;
+        case IQN_ERROR:
+        default:
+            return -1;
+        }
+    }
+
+    ret = virISCSIScanTargetsInternal(portal, ifacename, ntargets, targets);
+    VIR_FREE(ifacename);
+    return ret;
+}
+
+
 /*
  * virISCSINodeNew:
  * @portal: address for iSCSI target
index a44beeaf67968fb6e8d1cdaf1f0b61e51603ccd1..31b589dbf9e9b4380d2951f089a497f533039315 100644 (file)
@@ -49,6 +49,7 @@ virISCSIRescanLUNs(const char *session)
 
 int
 virISCSIScanTargets(const char *portal,
+                    const char *initiatoriqn,
                     size_t *ntargetsret,
                     char ***targetsret)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
index aa4ba577076850f2dc4b6f97af032aa144dffd6e..4bdb782e3613ddc44401af0d292b315c3931a2cb 100644 (file)
@@ -145,7 +145,7 @@ testISCSIScanTargets(const void *data)
 
     virCommandSetDryRun(NULL, testIscsiadmCb, NULL);
 
-    if (virISCSIScanTargets(info->portal, &ntargets, &targets) < 0)
+    if (virISCSIScanTargets(info->portal, NULL, &ntargets, &targets) < 0)
         goto cleanup;
 
     if (info->nexpected != ntargets) {