This patch set realizes the multi-IQN concept discussed in an earlier thread 
http://www.mail-archive.com/libvir-list@redhat.com/msg16706.html

And here .. http://www.mail-archive.com/libvir-list@redhat.com/msg17499.html

The patch realizes an XML schema like the one below and allows libvirt to read 
through it to create storage pools.
These XMLs when created using a virtualization manager realize unique VM to 
storage LUN mappings through a single console and thus opening up possibilities 
for the following scenarios -

* possibility of multiple IQNs for a single Guest
* option for hypervisor's initiator to use these IQNs on behalf of the guest

Change Log from v0.4:
1) Set default tab space to 4(Hopefully this is corrected this time ;) )
2) Review comments from Dave Allan
    a) Use output of "iscsiadm -m iface" to search for existing iqn names in 
the iface files.
3) Create new unique iface file names for user provided iqn names if the iqns 
are not present in the existing iface files.

Change Log from v0.3:
1) Set default tab space to 4
2) Use Case Description for Commit Log
3) Review comments from Dave Allan
    a) No initiator iqn in the xml would mean use of the default initiator iqn 
name
    b) Initiator iqn provided would mean a unique session to be created using 
the provided iqn name.
    c) Single iSCSI session per pool
4) Added syntax in doc/schemas/storagepool.rng

There are no new errors introduced by this patch with "make check" and "make 
syntax-check" tests.

Signed-off-by: Sudhir Bellad <sudhir_bel...@dell.com>
Signed-off-by: Shyam Iyer <shyam_i...@dell.com>
commit f9cf55ebe516e285f9552b6e9106458b1129c121
Author: shyam_i...@dell.com <shyam_i...@dell.com>
Date:   Mon Dec 28 03:13:23 2009 -0600

    [Patch v0.5] iSCSI Multi-IQN (Libvirt Support)
    
    The following patch set realizes the multi-IQN concept discussed in an 
earlier thread http://www.mail-archive.com/libvir-list@redhat.com/msg16706.html
    
    And here .. http://www.mail-archive.com/libvir-list@redhat.com/msg17499.html
    
    The patch realizes an XML schema like the one below and allows libvirt to 
read through it to create storage pools.
    These XMLs when created using a virtualization manager realize unique VM to 
storage LUN mappings through a single console and thus opening up possibilities 
for the following scenarios -
    
    * possibility of multiple IQNs for a single Guest
    * option for hypervisor's initiator to use these IQNs on behalf of the guest
    
    Change Log from v0.4:
    1) Set default tab space to 4(Hopefully this is corrected this time ;) )
    2) Review comments from Dave Allan
        a) Use output of "iscsiadm -m iface" to search for existing iqn names 
in the iface files.
    3) Create new unique iface file names for user provided iqn names if the 
iqns are not present in the existing iface files.
    
    Change Log from v0.3:
    1) Set default tab space to 4
    2) Use Case Description for Commit Log
    3) Review comments from Dave Allan
        a) No initiator iqn in the xml would mean use of the default initiator 
iqn name
        b) Initiator iqn provided would mean a unique session to be created 
using the provided iqn name.
        c) Single iSCSI session per pool
    4) Added syntax in doc/schemas/storagepool.rng
    
    There are no new errors introduced by this patch with "make check" and 
"make syntax-check" tests.
    
    Signed-off-by: Sudhir Bellad <sudhir_bel...@dell.com>
    Signed-off-by: shyam_i...@dell.com <shyam_i...@dell.com>

diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 249bf9c..90d16a8 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -188,6 +188,15 @@
     </element>
   </define>
 
+  <define name='initiatorinfoiqnname'>
+    <element name='iqn'>
+      <attribute name='name'>
+       <text/>
+      </attribute>
+      <empty/>
+    </element>
+  </define>
+
   <define name='devextents'>
     <oneOrMore>
       <element name='freeExtent'>
@@ -362,6 +371,7 @@
     <element name='source'>
       <ref name='sourceinfohost'/>
       <ref name='sourceinfodev'/>
+      <ref name='initiatorinfoiqnname'/>
       <optional>
         <ref name='sourceinfoauth'/>
       </optional>
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 0aefa06..0830cce 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -106,11 +106,12 @@ struct _virStorageVolOptions {
 
 /* Flags to indicate mandatory components in the pool source */
 enum {
-    VIR_STORAGE_POOL_SOURCE_HOST    = (1<<0),
-    VIR_STORAGE_POOL_SOURCE_DEVICE  = (1<<1),
-    VIR_STORAGE_POOL_SOURCE_DIR     = (1<<2),
-    VIR_STORAGE_POOL_SOURCE_ADAPTER = (1<<3),
-    VIR_STORAGE_POOL_SOURCE_NAME    = (1<<4),
+    VIR_STORAGE_POOL_SOURCE_HOST            = (1<<0),
+    VIR_STORAGE_POOL_SOURCE_DEVICE          = (1<<1),
+    VIR_STORAGE_POOL_SOURCE_DIR             = (1<<2),
+    VIR_STORAGE_POOL_SOURCE_ADAPTER         = (1<<3),
+    VIR_STORAGE_POOL_SOURCE_NAME            = (1<<4),
+    VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN   = (1<<5),
 };
 
 
@@ -179,7 +180,8 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
     { .poolType = VIR_STORAGE_POOL_ISCSI,
       .poolOptions = {
             .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
-                      VIR_STORAGE_POOL_SOURCE_DEVICE),
+                      VIR_STORAGE_POOL_SOURCE_DEVICE |
+                        VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
         },
       .volOptions = {
             .formatToString = virStoragePoolFormatDiskTypeToString,
@@ -283,6 +285,7 @@ virStoragePoolSourceFree(virStoragePoolSourcePtr source) {
     VIR_FREE(source->dir);
     VIR_FREE(source->name);
     VIR_FREE(source->adapter);
+    VIR_FREE(source->initiator.iqn);
 
     if (source->authType == VIR_STORAGE_POOL_AUTH_CHAP) {
         VIR_FREE(source->auth.chap.login);
@@ -666,6 +669,10 @@ virStoragePoolDefParseXML(virConnectPtr conn,
             goto cleanup;
         }
     }
+    
+    if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN) {
+        ret->source.initiator.iqn = virXPathString(conn, 
"string(./initiator/iqn/@name)", ctxt);
+    }
 
     if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
         if (!ret->source.dir) {
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index a795981..afa7984 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -182,6 +182,12 @@ struct _virStoragePoolSourceDeviceExtent {
     int type;  /* free space type */
 };
 
+typedef struct _virStoragePoolSourceInitiatorAttr 
virStoragePoolSourceInitiatorAttr;
+struct _virStoragePoolSourceInitiatorAttr {
+    /* Initiator iqn name */
+    char *iqn;
+};
+
 /*
  * Pools can be backed by one or more devices, and some
  * allow us to track free space on underlying devices.
@@ -223,6 +229,9 @@ struct _virStoragePoolSource {
     /* Or a name */
     char *name;
 
+       /* initiator iqn name */
+    virStoragePoolSourceInitiatorAttr initiator;
+
     int authType;       /* virStoragePoolAuthType */
     union {
         virStoragePoolAuthChap chap;
diff --git a/src/storage/storage_backend_iscsi.c 
b/src/storage/storage_backend_iscsi.c
index b516add..d53f6fe 100644
--- a/src/storage/storage_backend_iscsi.c
+++ b/src/storage/storage_backend_iscsi.c
@@ -33,6 +33,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <dirent.h>
+#include <sys/stat.h>
 
 #include "virterror_internal.h"
 #include "storage_backend_scsi.h"
@@ -159,13 +160,126 @@ virStorageBackendISCSIConnection(virConnectPtr conn,
                                  const char *portal,
                                  const char *action)
 {
-    const char *const cmdargv[] = {
+
+    if (pool->def->source.initiator.iqn != NULL) {
+        int fd = -1;
+        FILE *fp = NULL;
+        pid_t child = 0;
+        char line[1024];
+        char ifacename[256];
+        bool found = false;
+        const char *const prog[] = {
+        ISCSIADM, "--mode", "iface", NULL
+        };
+
+        /* Run the program and capture its output */
+        if (virExec(conn, prog, NULL, NULL,
+                       &child, -1, &fd, NULL, VIR_EXEC_NONE) < 0) {
+            return -1;
+        }
+
+        if ((fp = fdopen(fd, "r")) == NULL) {
+               virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("cannot read fd"));
+            return -1;
+        }
+
+        memset(line,'\0',1024);
+        memset(ifacename,'\0',256);
+
+        while (fgets(line, sizeof(line), fp) != NULL) {
+            int len = strlen(line);
+
+            if (len && line[len-1] == '\n')
+                line[len-1] = '\0';
+
+            if((strstr(line,pool->def->source.initiator.iqn) != NULL)){
+                char *token;
+                token = strtok(line," ");
+                strcpy(ifacename,token);
+                found=true;
+                break;
+            }
+        }
+
+        if (!found) {
+            int exitstatus = -1;
+
+            strcpy(ifacename, IFACE_PATH"iface-iqn-XXXXXX");
+            if (mktemp(ifacename) == NULL) {
+                virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                "%s", _("cannot generate iface file name"));
+                return -1;
+            }
+
+            const char *const cmdargv1[] = {
+            ISCSIADM, "--mode", "iface", "--interface", ifacename + 
IFACE_PATH_LENGTH,
+            "--op", "new", NULL
+            };
+
+            /* Note that we ignore the exitstatus.  Older versions of iscsiadm 
tools
+            * returned an exit status of > 0, even if they succeeded.  We will 
just
+            * rely on whether iface file got created properly.
+            */
+            if (virRun(conn, cmdargv1, &exitstatus) < 0)
+                return -1;
+
+            const char *const cmdargv2[] = {
+            ISCSIADM, "--mode", "iface", "--interface", ifacename + 
IFACE_PATH_LENGTH,
+            "--op", "update", "--name", "iface.initiatorname", "--value",
+            pool->def->source.initiator.iqn, NULL
+            };
+
+            /* Note that we ignore the exitstatus.  Older versions of iscsiadm 
tools
+            * returned an exit status of > 0, even if they succeeded.  We will 
just
+            * rely on whether iface file got updated properly.
+            */
+
+            if (virRun(conn, cmdargv2, &exitstatus) < 0)
+               return -1;
+
+            const char *const cmdsendtarget[] = {
+            ISCSIADM, "--mode", "discovery", "--type", "sendtargets",
+            "--portal", portal, NULL
+            };
+
+            if (virRun(conn, cmdsendtarget, NULL) < 0)
+                return -1;
+
+            const char *const cmdargv[] = {
+            ISCSIADM, "--mode", "node", "--portal", portal,
+            "--targetname", pool->def->source.devices[0].path, "--interface",
+            ifacename + IFACE_PATH_LENGTH, action, NULL
+            };
+
+            if (virRun(conn, cmdargv, NULL) < 0)
+                return -1;
+        }
+        else {
+            const char *const cmdargv[] = {
+            ISCSIADM, "--mode", "node", "--portal", portal,
+            "--targetname", pool->def->source.devices[0].path, "--interface",
+            ifacename, action, NULL
+            };
+
+            if (virRun(conn, cmdargv, NULL) < 0)
+                return -1;
+        }
+
+        if (fp)
+            fclose(fp);
+        else
+            close(fd);
+
+    }
+    else{
+        const char *const cmdargv[] = {
         ISCSIADM, "--mode", "node", "--portal", portal,
         "--targetname", pool->def->source.devices[0].path, action, NULL
-    };
-
-    if (virRun(conn, cmdargv, NULL) < 0)
-        return -1;
+        };
+        if (virRun(conn, cmdargv, NULL) < 0)
+            return -1;
+    }
 
     return 0;
 }
diff --git a/src/storage/storage_backend_iscsi.h 
b/src/storage/storage_backend_iscsi.h
index 665ed13..e44de7b 100644
--- a/src/storage/storage_backend_iscsi.h
+++ b/src/storage/storage_backend_iscsi.h
@@ -28,4 +28,7 @@
 
 extern virStorageBackend virStorageBackendISCSI;
 
+#define IFACE_PATH "/var/lib/iscsi/ifaces"
+#define IFACE_PATH_LENGTH 21
+
 #endif /* __VIR_STORAGE_BACKEND_ISCSI_H__ */
--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to