[libvirt] [PATCH 0/3] iscsi-direct: first part

clem@lse.epita.fr posted 3 patches 5 years, 9 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/20180713220615.31054-1-clem@lse.epita.fr
Test syntax-check passed
There is a newer version of this series
configure.ac                               |   9 +-
m4/virt-libiscsi.m4                        |  30 ++
m4/virt-storage-iscsi-direct.m4            |  44 ++
src/conf/domain_conf.c                     |   1 +
src/conf/storage_conf.c                    |  31 +-
src/conf/storage_conf.h                    |   1 +
src/conf/virstorageobj.c                   |   2 +
src/storage/Makefile.inc.am                |  24 ++
src/storage/storage_backend.c              |   6 +
src/storage/storage_backend_iscsi_direct.c | 444 +++++++++++++++++++++
src/storage/storage_backend_iscsi_direct.h |   6 +
src/storage/storage_driver.c               |   1 +
tools/virsh-pool.c                         |   3 +
13 files changed, 597 insertions(+), 5 deletions(-)
create mode 100644 m4/virt-libiscsi.m4
create mode 100644 m4/virt-storage-iscsi-direct.m4
create mode 100644 src/storage/storage_backend_iscsi_direct.c
create mode 100644 src/storage/storage_backend_iscsi_direct.h
[libvirt] [PATCH 0/3] iscsi-direct: first part
Posted by clem@lse.epita.fr 5 years, 9 months ago
From: Clementine Hayat <clem@lse.epita.fr>

Hello,

This is the implementation of the iscsi-direct backend storage pool.
The documentation, some API calls and tests are still missing and will
be comming in a second part.

Best Regards,

-- 
Clementine Hayat


Clementine Hayat (3):
  configure: Introduce libiscsi in build system
  storage: Introduce iscsi_direct pool type
  storage: Implement iscsi_direct pool backend

 configure.ac                               |   9 +-
 m4/virt-libiscsi.m4                        |  30 ++
 m4/virt-storage-iscsi-direct.m4            |  44 ++
 src/conf/domain_conf.c                     |   1 +
 src/conf/storage_conf.c                    |  31 +-
 src/conf/storage_conf.h                    |   1 +
 src/conf/virstorageobj.c                   |   2 +
 src/storage/Makefile.inc.am                |  24 ++
 src/storage/storage_backend.c              |   6 +
 src/storage/storage_backend_iscsi_direct.c | 444 +++++++++++++++++++++
 src/storage/storage_backend_iscsi_direct.h |   6 +
 src/storage/storage_driver.c               |   1 +
 tools/virsh-pool.c                         |   3 +
 13 files changed, 597 insertions(+), 5 deletions(-)
 create mode 100644 m4/virt-libiscsi.m4
 create mode 100644 m4/virt-storage-iscsi-direct.m4
 create mode 100644 src/storage/storage_backend_iscsi_direct.c
 create mode 100644 src/storage/storage_backend_iscsi_direct.h

-- 
2.17.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 0/3] iscsi-direct: first part
Posted by clem@lse.epita.fr 5 years, 9 months ago
From: Clementine Hayat <clem@lse.epita.fr>

Hello,

This is the implementation of the iscsi-direct backend storage pool
version 2.
The documentation, some API calls and tests are still missing and will
be comming in a second part.

Best Regards,

-- 
Clementine Hayat

Clementine Hayat (3):
  configure: Introduce libiscsi in build system
  storage: Introduce iscsi_direct pool type
  storage: Implement iscsi_direct pool backend

 configure.ac                               |   9 +-
 m4/virt-libiscsi.m4                        |  30 ++
 m4/virt-storage-iscsi-direct.m4            |  44 ++
 src/conf/domain_conf.c                     |   4 +
 src/conf/storage_conf.c                    |  33 +-
 src/conf/storage_conf.h                    |   1 +
 src/conf/virstorageobj.c                   |   2 +
 src/storage/Makefile.inc.am                |  24 ++
 src/storage/storage_backend.c              |   6 +
 src/storage/storage_backend_iscsi_direct.c | 460 +++++++++++++++++++++
 src/storage/storage_backend_iscsi_direct.h |   6 +
 src/storage/storage_driver.c               |   1 +
 tools/virsh-pool.c                         |   3 +
 13 files changed, 618 insertions(+), 5 deletions(-)
 create mode 100644 m4/virt-libiscsi.m4
 create mode 100644 m4/virt-storage-iscsi-direct.m4
 create mode 100644 src/storage/storage_backend_iscsi_direct.c
 create mode 100644 src/storage/storage_backend_iscsi_direct.h

-- 
2.18.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 0/3] iscsi-direct: first part
Posted by Michal Privoznik 5 years, 9 months ago
On 07/23/2018 08:42 PM, clem@lse.epita.fr wrote:
> From: Clementine Hayat <clem@lse.epita.fr>
> 
> Hello,
> 
> This is the implementation of the iscsi-direct backend storage pool
> version 2.
> The documentation, some API calls and tests are still missing and will
> be comming in a second part.
> 
> Best Regards,
> 

When posting patches to the list, always make sure they are rebased onto
current HEAD. Fortunately, the merge conflict was small so I could
resolve it instantly.

Usually, the cover letter for any new version of patches looks like this:

There is a link to previous version (at least),
there is a diff to previous version.

A good example looks something like this:

https://www.redhat.com/archives/libvir-list/2018-July/msg01343.html

Also, no need to put extra -- at the end of the cover letter - MTAs
usually interpret it as end of git commit message.

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 1/3] configure: Introduce libiscsi in build system
Posted by clem@lse.epita.fr 5 years, 9 months ago
From: Clementine Hayat <clem@lse.epita.fr>

The minimal required version is 1.18.0 because the synchrounous function
needed were introduced here.

Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
---
 configure.ac        |  3 +++
 m4/virt-libiscsi.m4 | 30 ++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 m4/virt-libiscsi.m4

diff --git a/configure.ac b/configure.ac
index a87ca06854..c668630a79 100644
--- a/configure.ac
+++ b/configure.ac
@@ -250,6 +250,7 @@ LIBVIRT_ARG_FIREWALLD
 LIBVIRT_ARG_FUSE
 LIBVIRT_ARG_GLUSTER
 LIBVIRT_ARG_HAL
+LIBVIRT_ARG_LIBISCSI
 LIBVIRT_ARG_LIBPCAP
 LIBVIRT_ARG_LIBSSH
 LIBVIRT_ARG_LIBXML
@@ -290,6 +291,7 @@ LIBVIRT_CHECK_FUSE
 LIBVIRT_CHECK_GLUSTER
 LIBVIRT_CHECK_GNUTLS
 LIBVIRT_CHECK_HAL
+LIBVIRT_CHECK_LIBISCSI
 LIBVIRT_CHECK_LIBNL
 LIBVIRT_CHECK_LIBPARTED
 LIBVIRT_CHECK_LIBPCAP
@@ -970,6 +972,7 @@ LIBVIRT_RESULT_FUSE
 LIBVIRT_RESULT_GLUSTER
 LIBVIRT_RESULT_GNUTLS
 LIBVIRT_RESULT_HAL
+LIBVIRT_RESULT_LIBISCSI
 LIBVIRT_RESULT_LIBNL
 LIBVIRT_RESULT_LIBPCAP
 LIBVIRT_RESULT_LIBSSH
diff --git a/m4/virt-libiscsi.m4 b/m4/virt-libiscsi.m4
new file mode 100644
index 0000000000..2747f00ec4
--- /dev/null
+++ b/m4/virt-libiscsi.m4
@@ -0,0 +1,30 @@
+dnl Libiscsi library
+dnl
+dnl Copyright (C) 2018 Clementine Hayat.
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library.  If not, see
+dnl <http://www.gnu.org/licenses/>.
+dnl
+
+AC_DEFUN([LIBVIRT_ARG_LIBISCSI],[
+  LIBVIRT_ARG_WITH_FEATURE([LIBISCSI], [libiscsi], [check], [1.18.0])
+])
+
+AC_DEFUN([LIBVIRT_CHECK_LIBISCSI],[
+  LIBVIRT_CHECK_PKG([LIBISCSI], [libiscsi], [1.18.0])
+])
+
+AC_DEFUN([LIBVIRT_RESULT_LIBISCSI],[
+  LIBVIRT_RESULT_LIB(LIBISCSI)
+])
-- 
2.18.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 1/3] configure: Introduce libiscsi in build system
Posted by Michal Privoznik 5 years, 9 months ago
On 07/23/2018 08:42 PM, clem@lse.epita.fr wrote:
> From: Clementine Hayat <clem@lse.epita.fr>
> 
> The minimal required version is 1.18.0 because the synchrounous function
> needed were introduced here.
> 
> Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
> ---
>  configure.ac        |  3 +++
>  m4/virt-libiscsi.m4 | 30 ++++++++++++++++++++++++++++++
>  2 files changed, 33 insertions(+)
>  create mode 100644 m4/virt-libiscsi.m4

ACK

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 2/3] storage: Introduce iscsi_direct pool type
Posted by clem@lse.epita.fr 5 years, 9 months ago
From: Clementine Hayat <clem@lse.epita.fr>

Introducing the pool as a noop. Integration inside the build
system. Implementation will be in the following commits.

Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
---
 configure.ac                               |  6 ++-
 m4/virt-storage-iscsi-direct.m4            | 41 +++++++++++++++
 src/conf/domain_conf.c                     |  4 ++
 src/conf/storage_conf.c                    | 33 ++++++++++--
 src/conf/storage_conf.h                    |  1 +
 src/conf/virstorageobj.c                   |  2 +
 src/storage/Makefile.inc.am                | 22 ++++++++
 src/storage/storage_backend.c              |  6 +++
 src/storage/storage_backend_iscsi_direct.c | 58 ++++++++++++++++++++++
 src/storage/storage_backend_iscsi_direct.h |  6 +++
 src/storage/storage_driver.c               |  1 +
 tools/virsh-pool.c                         |  3 ++
 12 files changed, 178 insertions(+), 5 deletions(-)
 create mode 100644 m4/virt-storage-iscsi-direct.m4
 create mode 100644 src/storage/storage_backend_iscsi_direct.c
 create mode 100644 src/storage/storage_backend_iscsi_direct.h

diff --git a/configure.ac b/configure.ac
index c668630a79..87ac4dc2c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -564,6 +564,7 @@ LIBVIRT_STORAGE_ARG_DIR
 LIBVIRT_STORAGE_ARG_FS
 LIBVIRT_STORAGE_ARG_LVM
 LIBVIRT_STORAGE_ARG_ISCSI
+LIBVIRT_STORAGE_ARG_ISCSI_DIRECT
 LIBVIRT_STORAGE_ARG_SCSI
 LIBVIRT_STORAGE_ARG_MPATH
 LIBVIRT_STORAGE_ARG_DISK
@@ -578,6 +579,7 @@ if test "$with_libvirtd" = "no"; then
   with_storage_fs=no
   with_storage_lvm=no
   with_storage_iscsi=no
+  with_storage_iscsi_direct=no
   with_storage_scsi=no
   with_storage_mpath=no
   with_storage_disk=no
@@ -598,6 +600,7 @@ LIBVIRT_STORAGE_CHECK_DIR
 LIBVIRT_STORAGE_CHECK_FS
 LIBVIRT_STORAGE_CHECK_LVM
 LIBVIRT_STORAGE_CHECK_ISCSI
+LIBVIRT_STORAGE_CHECK_ISCSI_DIRECT
 LIBVIRT_STORAGE_CHECK_SCSI
 LIBVIRT_STORAGE_CHECK_MPATH
 LIBVIRT_STORAGE_CHECK_DISK
@@ -608,7 +611,7 @@ LIBVIRT_STORAGE_CHECK_ZFS
 LIBVIRT_STORAGE_CHECK_VSTORAGE
 
 with_storage=no
-for backend in dir fs lvm iscsi scsi mpath rbd disk; do
+for backend in dir fs lvm iscsi iscsi_direct scsi mpath rbd disk; do
     if eval test \$with_storage_$backend = yes; then
         with_storage=yes
         break
@@ -936,6 +939,7 @@ LIBVIRT_STORAGE_RESULT_DIR
 LIBVIRT_STORAGE_RESULT_FS
 LIBVIRT_STORAGE_RESULT_LVM
 LIBVIRT_STORAGE_RESULT_ISCSI
+LIBVIRT_STORAGE_RESULT_ISCSI_DIRECT
 LIBVIRT_STORAGE_RESULT_SCSI
 LIBVIRT_STORAGE_RESULT_MPATH
 LIBVIRT_STORAGE_RESULT_DISK
diff --git a/m4/virt-storage-iscsi-direct.m4 b/m4/virt-storage-iscsi-direct.m4
new file mode 100644
index 0000000000..cc2d490352
--- /dev/null
+++ b/m4/virt-storage-iscsi-direct.m4
@@ -0,0 +1,41 @@
+dnl Iscsi-direct storage
+dnl
+dnl Copyright (C) 2018 Clementine Hayat.
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library.  If not, see
+dnl <http://www.gnu.org/licenses/>.
+dnl
+
+AC_DEFUN([LIBVIRT_STORAGE_ARG_ISCSI_DIRECT], [
+  LIBVIRT_ARG_WITH_FEATURE([STORAGE_ISCSI_DIRECT],
+                           [iscsi-direct backend for the storage driver],
+                           [check])
+])
+
+AC_DEFUN([LIBVIRT_STORAGE_CHECK_ISCSI_DIRECT], [
+  AC_REQUIRE([LIBVIRT_CHECK_LIBISCSI])
+  if test "$with_storage_iscsi_direct" = "check"; then
+    with_storage_iscsi_direct=$with_libiscsi
+  fi
+  if test "$with_storage_iscsi_direct" = "yes"; then
+    AC_DEFINE_UNQUOTED([WITH_STORAGE_ISCSI_DIRECT], [1],
+                       [whether iSCSI backend for storage driver is enabled])
+  fi
+  AM_CONDITIONAL([WITH_STORAGE_ISCSI_DIRECT],
+                 [test "$with_storage_iscsi_direct" = "yes"])
+])
+
+AC_DEFUN([LIBVIRT_STORAGE_RESULT_ISCSI_DIRECT], [
+  LIBVIRT_RESULT([iscsi-direct], [$with_storage_iscsi_direct])
+])
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7396616eda..5af27a6ad2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30163,6 +30163,10 @@ virDomainDiskTranslateSourcePool(virDomainDiskDefPtr def)
 
         break;
 
+    case VIR_STORAGE_POOL_ISCSI_DIRECT:
+        def->src->srcpool->mode = VIR_STORAGE_SOURCE_POOL_MODE_DIRECT;
+        break;
+
     case VIR_STORAGE_POOL_ISCSI:
         if (def->startupPolicy) {
             virReportError(VIR_ERR_XML_ERROR, "%s",
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 5036ab9ef8..ee1586410b 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -62,9 +62,9 @@ VIR_ENUM_IMPL(virStoragePool,
               VIR_STORAGE_POOL_LAST,
               "dir", "fs", "netfs",
               "logical", "disk", "iscsi",
-              "scsi", "mpath", "rbd",
-              "sheepdog", "gluster", "zfs",
-              "vstorage")
+              "iscsi-direct", "scsi", "mpath",
+              "rbd", "sheepdog", "gluster",
+              "zfs", "vstorage")
 
 VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
               VIR_STORAGE_POOL_FS_LAST,
@@ -207,6 +207,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
          .formatToString = virStoragePoolFormatDiskTypeToString,
       }
     },
+    {.poolType = VIR_STORAGE_POOL_ISCSI_DIRECT,
+     .poolOptions = {
+         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
+                   VIR_STORAGE_POOL_SOURCE_DEVICE |
+                   VIR_STORAGE_POOL_SOURCE_NETWORK |
+                   VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
+      },
+      .volOptions = {
+         .formatToString = virStoragePoolFormatDiskTypeToString,
+      }
+    },
     {.poolType = VIR_STORAGE_POOL_SCSI,
      .poolOptions = {
          .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
@@ -803,6 +814,19 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
             goto error;
     }
 
+    if (ret->type == VIR_STORAGE_POOL_ISCSI_DIRECT) {
+        if (!ret->source.initiator.iqn) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("missing storage pool initiator iqn"));
+            goto error;
+        }
+        if (!ret->source.ndevice) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("missing storage pool device path"));
+            goto error;
+        }
+    }
+
  cleanup:
     VIR_FREE(uuid);
     VIR_FREE(type);
@@ -1004,7 +1028,8 @@ virStoragePoolDefFormatBuf(virBufferPtr buf,
      * files, so they don't have a target */
     if (def->type != VIR_STORAGE_POOL_RBD &&
         def->type != VIR_STORAGE_POOL_SHEEPDOG &&
-        def->type != VIR_STORAGE_POOL_GLUSTER) {
+        def->type != VIR_STORAGE_POOL_GLUSTER &&
+        def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
         virBufferAddLit(buf, "<target>\n");
         virBufferAdjustIndent(buf, 2);
 
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 15dfd8becf..858623783d 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -85,6 +85,7 @@ typedef enum {
     VIR_STORAGE_POOL_LOGICAL,  /* Logical volume groups / volumes */
     VIR_STORAGE_POOL_DISK,     /* Disk partitions */
     VIR_STORAGE_POOL_ISCSI,    /* iSCSI targets */
+    VIR_STORAGE_POOL_ISCSI_DIRECT, /* iSCSI targets using libiscsi */
     VIR_STORAGE_POOL_SCSI,     /* SCSI HBA */
     VIR_STORAGE_POOL_MPATH,    /* Multipath devices */
     VIR_STORAGE_POOL_RBD,      /* RADOS Block Device */
diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c
index e66b2ebfb2..1c45bb71b9 100644
--- a/src/conf/virstorageobj.c
+++ b/src/conf/virstorageobj.c
@@ -1838,11 +1838,13 @@ virStoragePoolObjSourceFindDuplicateCb(const void *payload,
         break;
 
     case VIR_STORAGE_POOL_ISCSI:
+    case VIR_STORAGE_POOL_ISCSI_DIRECT:
     case VIR_STORAGE_POOL_FS:
     case VIR_STORAGE_POOL_LOGICAL:
     case VIR_STORAGE_POOL_DISK:
     case VIR_STORAGE_POOL_ZFS:
         if ((data->def->type == VIR_STORAGE_POOL_ISCSI ||
+             data->def->type == VIR_STORAGE_POOL_ISCSI_DIRECT ||
              data->def->type == VIR_STORAGE_POOL_FS ||
              data->def->type == VIR_STORAGE_POOL_LOGICAL ||
              data->def->type == VIR_STORAGE_POOL_DISK ||
diff --git a/src/storage/Makefile.inc.am b/src/storage/Makefile.inc.am
index ea98c0ee52..b2714fd960 100644
--- a/src/storage/Makefile.inc.am
+++ b/src/storage/Makefile.inc.am
@@ -31,6 +31,11 @@ STORAGE_DRIVER_ISCSI_SOURCES = \
 	storage/storage_backend_iscsi.c \
 	$(NULL)
 
+STORAGE_DRIVER_ISCSI_DIRECT_SOURCES = \
+	storage/storage_backend_iscsi_direct.h \
+	storage/storage_backend_iscsi_direct.c \
+	$(NULL)
+
 STORAGE_DRIVER_SCSI_SOURCES = \
 	storage/storage_backend_scsi.h \
 	storage/storage_backend_scsi.c \
@@ -89,6 +94,7 @@ EXTRA_DIST += \
 	$(STORAGE_FILE_FS_SOURCES) \
 	$(STORAGE_DRIVER_LVM_SOURCES) \
 	$(STORAGE_DRIVER_ISCSI_SOURCES) \
+	$(STORAGE_DRIVER_ISCSI_DIRECT_SOURCES) \
 	$(STORAGE_DRIVER_SCSI_SOURCES) \
 	$(STORAGE_DRIVER_MPATH_SOURCES) \
 	$(STORAGE_DRIVER_DISK_SOURCES) \
@@ -193,6 +199,22 @@ libvirt_storage_backend_iscsi_la_LIBADD = \
 	$(NULL)
 endif WITH_STORAGE_ISCSI
 
+if WITH_STORAGE_ISCSI_DIRECT
+libvirt_storage_backend_iscsi_direct_la_SOURCES = $(STORAGE_DRIVER_ISCSI_DIRECT_SOURCES)
+libvirt_storage_backend_iscsi_direct_la_CFLAGS = \
+	-I$(srcdir)/conf \
+	$(LIBISCSI_CFLAGS) \
+	$(AM_CFLAGS) \
+	$(NULL)
+
+storagebackend_LTLIBRARIES += libvirt_storage_backend_iscsi-direct.la
+libvirt_storage_backend_iscsi_direct_la_LDFLAGS = $(AM_LDFLAGS_MOD)
+libvirt_storage_backend_iscsi_direct_la_LIBADD = \
+	libvirt.la \
+	../gnulib/lib/libgnu.la \
+	$(NULL)
+endif WITH_STORAGE_ISCSI_DIRECT
+
 if WITH_STORAGE_SCSI
 libvirt_storage_backend_scsi_la_SOURCES = $(STORAGE_DRIVER_SCSI_SOURCES)
 libvirt_storage_backend_scsi_la_CFLAGS = \
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 7d226f3d3a..e7fbc37eb1 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -43,6 +43,9 @@
 #if WITH_STORAGE_ISCSI
 # include "storage_backend_iscsi.h"
 #endif
+#if WITH_STORAGE_ISCSI_DIRECT
+# include "storage_backend_iscsi_direct.h"
+#endif
 #if WITH_STORAGE_SCSI
 # include "storage_backend_scsi.h"
 #endif
@@ -122,6 +125,9 @@ virStorageBackendDriversRegister(bool allbackends ATTRIBUTE_UNUSED)
 #if WITH_STORAGE_ISCSI
     VIR_STORAGE_BACKEND_REGISTER(virStorageBackendISCSIRegister, "iscsi");
 #endif
+#if WITH_STORAGE_ISCSI_DIRECT
+    VIR_STORAGE_BACKEND_REGISTER(virStorageBackendISCSIDirectRegister, "iscsi-direct");
+#endif
 #if WITH_STORAGE_SCSI
     VIR_STORAGE_BACKEND_REGISTER(virStorageBackendSCSIRegister, "scsi");
 #endif
diff --git a/src/storage/storage_backend_iscsi_direct.c b/src/storage/storage_backend_iscsi_direct.c
new file mode 100644
index 0000000000..94c4c989ff
--- /dev/null
+++ b/src/storage/storage_backend_iscsi_direct.c
@@ -0,0 +1,58 @@
+/*
+ * storage_backend_iscsi_direct.c: storage backend for iSCSI using libiscsi
+ *
+ * Copyright (C) 2018 Clementine Hayat.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Clementine Hayat <clem@lse.epita.fr>
+ */
+
+#include <config.h>
+
+#include "storage_backend_iscsi_direct.h"
+#include "storage_util.h"
+#include "virlog.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+VIR_LOG_INIT("storage.storage_backend_iscsi_direct");
+
+
+static int
+virStorageBackendISCSIDirectCheckPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+                                      bool *isActive ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+static int
+virStorageBackendISCSIDirectRefreshPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+virStorageBackend virStorageBackendISCSIDirect = {
+    .type = VIR_STORAGE_POOL_ISCSI_DIRECT,
+
+    .checkPool = virStorageBackendISCSIDirectCheckPool,
+    .refreshPool = virStorageBackendISCSIDirectRefreshPool,
+};
+
+int
+virStorageBackendISCSIDirectRegister(void)
+{
+    return virStorageBackendRegister(&virStorageBackendISCSIDirect);
+}
diff --git a/src/storage/storage_backend_iscsi_direct.h b/src/storage/storage_backend_iscsi_direct.h
new file mode 100644
index 0000000000..545579daf7
--- /dev/null
+++ b/src/storage/storage_backend_iscsi_direct.h
@@ -0,0 +1,6 @@
+#ifndef __VIR_STORAGE_BACKEND_ISCSI_H__
+# define __VIR_STORAGE_BACKEND_ISCSI_H__
+
+int virStorageBackendISCSIDirectRegister(void);
+
+#endif /* __VIR_STORAGE_BACKEND_ISCSI_H__ */
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 8070d159ea..c108f026ce 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1566,6 +1566,7 @@ storageVolLookupByPathCallback(virStoragePoolObjPtr obj,
         case VIR_STORAGE_POOL_LOGICAL:
         case VIR_STORAGE_POOL_DISK:
         case VIR_STORAGE_POOL_ISCSI:
+        case VIR_STORAGE_POOL_ISCSI_DIRECT:
         case VIR_STORAGE_POOL_SCSI:
         case VIR_STORAGE_POOL_MPATH:
         case VIR_STORAGE_POOL_VSTORAGE:
diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c
index cc49a5b96d..4604b05020 100644
--- a/tools/virsh-pool.c
+++ b/tools/virsh-pool.c
@@ -1203,6 +1203,9 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
             case VIR_STORAGE_POOL_ISCSI:
                 flags |= VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI;
                 break;
+            case VIR_STORAGE_POOL_ISCSI_DIRECT:
+                flags |= VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI;
+                break;
             case VIR_STORAGE_POOL_SCSI:
                 flags |= VIR_CONNECT_LIST_STORAGE_POOLS_SCSI;
                 break;
-- 
2.18.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 2/3] storage: Introduce iscsi_direct pool type
Posted by Michal Privoznik 5 years, 9 months ago
On 07/23/2018 08:43 PM, clem@lse.epita.fr wrote:
> From: Clementine Hayat <clem@lse.epita.fr>
> 
> Introducing the pool as a noop. Integration inside the build
> system. Implementation will be in the following commits.
> 
> Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
> ---
>  configure.ac                               |  6 ++-
>  m4/virt-storage-iscsi-direct.m4            | 41 +++++++++++++++
>  src/conf/domain_conf.c                     |  4 ++
>  src/conf/storage_conf.c                    | 33 ++++++++++--
>  src/conf/storage_conf.h                    |  1 +
>  src/conf/virstorageobj.c                   |  2 +
>  src/storage/Makefile.inc.am                | 22 ++++++++
>  src/storage/storage_backend.c              |  6 +++
>  src/storage/storage_backend_iscsi_direct.c | 58 ++++++++++++++++++++++
>  src/storage/storage_backend_iscsi_direct.h |  6 +++
>  src/storage/storage_driver.c               |  1 +
>  tools/virsh-pool.c                         |  3 ++
>  12 files changed, 178 insertions(+), 5 deletions(-)
>  create mode 100644 m4/virt-storage-iscsi-direct.m4
>  create mode 100644 src/storage/storage_backend_iscsi_direct.c
>  create mode 100644 src/storage/storage_backend_iscsi_direct.h

Missing documentation. I can not push these without any documentation.
You need to document what the new type is doing, what the XML should
look like. Also, might be worth putting some test cases into
storagepoolxml2xmltest.
Since you will be sending v3, can you add docs/news.xml entry (in a
separate patch) too please?

> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 7396616eda..5af27a6ad2 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -30163,6 +30163,10 @@ virDomainDiskTranslateSourcePool(virDomainDiskDefPtr def)
>  
>          break;
>  
> +    case VIR_STORAGE_POOL_ISCSI_DIRECT:
> +        def->src->srcpool->mode = VIR_STORAGE_SOURCE_POOL_MODE_DIRECT;
> +        break;
> +
>      case VIR_STORAGE_POOL_ISCSI:
>          if (def->startupPolicy) {
>              virReportError(VIR_ERR_XML_ERROR, "%s",
> diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
> index 5036ab9ef8..ee1586410b 100644
> --- a/src/conf/storage_conf.c
> +++ b/src/conf/storage_conf.c
> @@ -62,9 +62,9 @@ VIR_ENUM_IMPL(virStoragePool,
>                VIR_STORAGE_POOL_LAST,
>                "dir", "fs", "netfs",
>                "logical", "disk", "iscsi",
> -              "scsi", "mpath", "rbd",
> -              "sheepdog", "gluster", "zfs",
> -              "vstorage")
> +              "iscsi-direct", "scsi", "mpath",
> +              "rbd", "sheepdog", "gluster",
> +              "zfs", "vstorage")
>  
>  VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
>                VIR_STORAGE_POOL_FS_LAST,
> @@ -207,6 +207,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
>           .formatToString = virStoragePoolFormatDiskTypeToString,
>        }
>      },
> +    {.poolType = VIR_STORAGE_POOL_ISCSI_DIRECT,
> +     .poolOptions = {
> +         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
> +                   VIR_STORAGE_POOL_SOURCE_DEVICE |
> +                   VIR_STORAGE_POOL_SOURCE_NETWORK |
> +                   VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
> +      },
> +      .volOptions = {
> +         .formatToString = virStoragePoolFormatDiskTypeToString,
> +      }
> +    },
>      {.poolType = VIR_STORAGE_POOL_SCSI,
>       .poolOptions = {
>           .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
> @@ -803,6 +814,19 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
>              goto error;
>      }
>  
> +    if (ret->type == VIR_STORAGE_POOL_ISCSI_DIRECT) {
> +        if (!ret->source.initiator.iqn) {
> +            virReportError(VIR_ERR_XML_ERROR, "%s",
> +                           _("missing storage pool initiator iqn"));
> +            goto error;
> +        }
> +        if (!ret->source.ndevice) {
> +            virReportError(VIR_ERR_XML_ERROR, "%s",
> +                           _("missing storage pool device path"));
> +            goto error;
> +        }
> +    }

So the wole idea of poolOptions and volOptions is to specify which parts
of pool/volume XML are required so that we don't have to base checks
like this on ret->type rather than flags.
On the other hand, comment just above VIR_STORAGE_POOL_SOURCE_* enum
says it declares mandatory components which it clearly doesn't. So after
all I think we are safe here.

> +
>   cleanup:
>      VIR_FREE(uuid);
>      VIR_FREE(type);
> @@ -1004,7 +1028,8 @@ virStoragePoolDefFormatBuf(virBufferPtr buf,
>       * files, so they don't have a target */
>      if (def->type != VIR_STORAGE_POOL_RBD &&
>          def->type != VIR_STORAGE_POOL_SHEEPDOG &&
> -        def->type != VIR_STORAGE_POOL_GLUSTER) {
> +        def->type != VIR_STORAGE_POOL_GLUSTER &&
> +        def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
>          virBufferAddLit(buf, "<target>\n");
>          virBufferAdjustIndent(buf, 2);

Might be worth updating the comment just above this block ;-)


Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 2/3] storage: Introduce iscsi_direct pool type
Posted by Clementine Hayat 5 years, 9 months ago
2018-07-24 14:24 GMT+02:00 Michal Privoznik <mprivozn@redhat.com>:
> On 07/23/2018 08:43 PM, clem@lse.epita.fr wrote:
>> From: Clementine Hayat <clem@lse.epita.fr>
>>
>> Introducing the pool as a noop. Integration inside the build
>> system. Implementation will be in the following commits.
>>
>> Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
>> ---
>>  configure.ac                               |  6 ++-
>>  m4/virt-storage-iscsi-direct.m4            | 41 +++++++++++++++
>>  src/conf/domain_conf.c                     |  4 ++
>>  src/conf/storage_conf.c                    | 33 ++++++++++--
>>  src/conf/storage_conf.h                    |  1 +
>>  src/conf/virstorageobj.c                   |  2 +
>>  src/storage/Makefile.inc.am                | 22 ++++++++
>>  src/storage/storage_backend.c              |  6 +++
>>  src/storage/storage_backend_iscsi_direct.c | 58 ++++++++++++++++++++++
>>  src/storage/storage_backend_iscsi_direct.h |  6 +++
>>  src/storage/storage_driver.c               |  1 +
>>  tools/virsh-pool.c                         |  3 ++
>>  12 files changed, 178 insertions(+), 5 deletions(-)
>>  create mode 100644 m4/virt-storage-iscsi-direct.m4
>>  create mode 100644 src/storage/storage_backend_iscsi_direct.c
>>  create mode 100644 src/storage/storage_backend_iscsi_direct.h
>
> Missing documentation. I can not push these without any documentation.
> You need to document what the new type is doing, what the XML should
> look like. Also, might be worth putting some test cases into
> storagepoolxml2xmltest.
> Since you will be sending v3, can you add docs/news.xml entry (in a
> separate patch) too please?

Yes sure.

>> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>> index 7396616eda..5af27a6ad2 100644
>> --- a/src/conf/domain_conf.c
>> +++ b/src/conf/domain_conf.c
>> @@ -30163,6 +30163,10 @@ virDomainDiskTranslateSourcePool(virDomainDiskDefPtr def)
>>
>>          break;
>>
>> +    case VIR_STORAGE_POOL_ISCSI_DIRECT:
>> +        def->src->srcpool->mode = VIR_STORAGE_SOURCE_POOL_MODE_DIRECT;
>> +        break;
>> +
>>      case VIR_STORAGE_POOL_ISCSI:
>>          if (def->startupPolicy) {
>>              virReportError(VIR_ERR_XML_ERROR, "%s",
>> diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
>> index 5036ab9ef8..ee1586410b 100644
>> --- a/src/conf/storage_conf.c
>> +++ b/src/conf/storage_conf.c
>> @@ -62,9 +62,9 @@ VIR_ENUM_IMPL(virStoragePool,
>>                VIR_STORAGE_POOL_LAST,
>>                "dir", "fs", "netfs",
>>                "logical", "disk", "iscsi",
>> -              "scsi", "mpath", "rbd",
>> -              "sheepdog", "gluster", "zfs",
>> -              "vstorage")
>> +              "iscsi-direct", "scsi", "mpath",
>> +              "rbd", "sheepdog", "gluster",
>> +              "zfs", "vstorage")
>>
>>  VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
>>                VIR_STORAGE_POOL_FS_LAST,
>> @@ -207,6 +207,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
>>           .formatToString = virStoragePoolFormatDiskTypeToString,
>>        }
>>      },
>> +    {.poolType = VIR_STORAGE_POOL_ISCSI_DIRECT,
>> +     .poolOptions = {
>> +         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
>> +                   VIR_STORAGE_POOL_SOURCE_DEVICE |
>> +                   VIR_STORAGE_POOL_SOURCE_NETWORK |
>> +                   VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
>> +      },
>> +      .volOptions = {
>> +         .formatToString = virStoragePoolFormatDiskTypeToString,
>> +      }
>> +    },
>>      {.poolType = VIR_STORAGE_POOL_SCSI,
>>       .poolOptions = {
>>           .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
>> @@ -803,6 +814,19 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
>>              goto error;
>>      }
>>
>> +    if (ret->type == VIR_STORAGE_POOL_ISCSI_DIRECT) {
>> +        if (!ret->source.initiator.iqn) {
>> +            virReportError(VIR_ERR_XML_ERROR, "%s",
>> +                           _("missing storage pool initiator iqn"));
>> +            goto error;
>> +        }
>> +        if (!ret->source.ndevice) {
>> +            virReportError(VIR_ERR_XML_ERROR, "%s",
>> +                           _("missing storage pool device path"));
>> +            goto error;
>> +        }
>> +    }
>
> So the wole idea of poolOptions and volOptions is to specify which parts
> of pool/volume XML are required so that we don't have to base checks
> like this on ret->type rather than flags.
> On the other hand, comment just above VIR_STORAGE_POOL_SOURCE_* enum
> says it declares mandatory components which it clearly doesn't. So after
> all I think we are safe here.

That actually isn't the case for the initiator iqn flag.
Is it on purpose or should I patch it in another thread?

>> +
>>   cleanup:
>>      VIR_FREE(uuid);
>>      VIR_FREE(type);
>> @@ -1004,7 +1028,8 @@ virStoragePoolDefFormatBuf(virBufferPtr buf,
>>       * files, so they don't have a target */
>>      if (def->type != VIR_STORAGE_POOL_RBD &&
>>          def->type != VIR_STORAGE_POOL_SHEEPDOG &&
>> -        def->type != VIR_STORAGE_POOL_GLUSTER) {
>> +        def->type != VIR_STORAGE_POOL_GLUSTER &&
>> +        def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
>>          virBufferAddLit(buf, "<target>\n");
>>          virBufferAdjustIndent(buf, 2);
>
> Might be worth updating the comment just above this block ;-)
>

Sure!

-- 
Clementine Hayat

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 2/3] storage: Introduce iscsi_direct pool type
Posted by Michal Privoznik 5 years, 9 months ago
On 07/24/2018 06:19 PM, Clementine Hayat wrote:
> 2018-07-24 14:24 GMT+02:00 Michal Privoznik <mprivozn@redhat.com>:
>> On 07/23/2018 08:43 PM, clem@lse.epita.fr wrote:
>>> From: Clementine Hayat <clem@lse.epita.fr>
>>>
>>> Introducing the pool as a noop. Integration inside the build
>>> system. Implementation will be in the following commits.
>>>
>>> Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
>>> ---
>>>  configure.ac                               |  6 ++-
>>>  m4/virt-storage-iscsi-direct.m4            | 41 +++++++++++++++
>>>  src/conf/domain_conf.c                     |  4 ++
>>>  src/conf/storage_conf.c                    | 33 ++++++++++--
>>>  src/conf/storage_conf.h                    |  1 +
>>>  src/conf/virstorageobj.c                   |  2 +
>>>  src/storage/Makefile.inc.am                | 22 ++++++++
>>>  src/storage/storage_backend.c              |  6 +++
>>>  src/storage/storage_backend_iscsi_direct.c | 58 ++++++++++++++++++++++
>>>  src/storage/storage_backend_iscsi_direct.h |  6 +++
>>>  src/storage/storage_driver.c               |  1 +
>>>  tools/virsh-pool.c                         |  3 ++
>>>  12 files changed, 178 insertions(+), 5 deletions(-)
>>>  create mode 100644 m4/virt-storage-iscsi-direct.m4
>>>  create mode 100644 src/storage/storage_backend_iscsi_direct.c
>>>  create mode 100644 src/storage/storage_backend_iscsi_direct.h
>>


>>> @@ -803,6 +814,19 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
>>>              goto error;
>>>      }
>>>
>>> +    if (ret->type == VIR_STORAGE_POOL_ISCSI_DIRECT) {
>>> +        if (!ret->source.initiator.iqn) {
>>> +            virReportError(VIR_ERR_XML_ERROR, "%s",
>>> +                           _("missing storage pool initiator iqn"));
>>> +            goto error;
>>> +        }
>>> +        if (!ret->source.ndevice) {
>>> +            virReportError(VIR_ERR_XML_ERROR, "%s",
>>> +                           _("missing storage pool device path"));
>>> +            goto error;
>>> +        }
>>> +    }
>>
>> So the wole idea of poolOptions and volOptions is to specify which parts
>> of pool/volume XML are required so that we don't have to base checks
>> like this on ret->type rather than flags.
>> On the other hand, comment just above VIR_STORAGE_POOL_SOURCE_* enum
>> says it declares mandatory components which it clearly doesn't. So after
>> all I think we are safe here.
> 
> That actually isn't the case for the initiator iqn flag.
> Is it on purpose or should I patch it in another thread?

I think saving that for a separate patch is okay.
Speaking of threads, I forgot to mention, feel free to send v3 as a
completely new thread. We don't really thread versions under v1.

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 2/3] storage: Introduce iscsi_direct pool type
Posted by Pavel Hrdina 5 years, 9 months ago
On Mon, Jul 23, 2018 at 08:43:00PM +0200, clem@lse.epita.fr wrote:
> From: Clementine Hayat <clem@lse.epita.fr>
> 
> Introducing the pool as a noop. Integration inside the build
> system. Implementation will be in the following commits.
> 
> Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
> ---
>  configure.ac                               |  6 ++-
>  m4/virt-storage-iscsi-direct.m4            | 41 +++++++++++++++
>  src/conf/domain_conf.c                     |  4 ++
>  src/conf/storage_conf.c                    | 33 ++++++++++--
>  src/conf/storage_conf.h                    |  1 +
>  src/conf/virstorageobj.c                   |  2 +
>  src/storage/Makefile.inc.am                | 22 ++++++++
>  src/storage/storage_backend.c              |  6 +++
>  src/storage/storage_backend_iscsi_direct.c | 58 ++++++++++++++++++++++
>  src/storage/storage_backend_iscsi_direct.h |  6 +++
>  src/storage/storage_driver.c               |  1 +
>  tools/virsh-pool.c                         |  3 ++
>  12 files changed, 178 insertions(+), 5 deletions(-)
>  create mode 100644 m4/virt-storage-iscsi-direct.m4
>  create mode 100644 src/storage/storage_backend_iscsi_direct.c
>  create mode 100644 src/storage/storage_backend_iscsi_direct.h
> 
> diff --git a/configure.ac b/configure.ac
> index c668630a79..87ac4dc2c3 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -564,6 +564,7 @@ LIBVIRT_STORAGE_ARG_DIR
>  LIBVIRT_STORAGE_ARG_FS
>  LIBVIRT_STORAGE_ARG_LVM
>  LIBVIRT_STORAGE_ARG_ISCSI
> +LIBVIRT_STORAGE_ARG_ISCSI_DIRECT
>  LIBVIRT_STORAGE_ARG_SCSI
>  LIBVIRT_STORAGE_ARG_MPATH
>  LIBVIRT_STORAGE_ARG_DISK
> @@ -578,6 +579,7 @@ if test "$with_libvirtd" = "no"; then
>    with_storage_fs=no
>    with_storage_lvm=no
>    with_storage_iscsi=no
> +  with_storage_iscsi_direct=no
>    with_storage_scsi=no
>    with_storage_mpath=no
>    with_storage_disk=no
> @@ -598,6 +600,7 @@ LIBVIRT_STORAGE_CHECK_DIR
>  LIBVIRT_STORAGE_CHECK_FS
>  LIBVIRT_STORAGE_CHECK_LVM
>  LIBVIRT_STORAGE_CHECK_ISCSI
> +LIBVIRT_STORAGE_CHECK_ISCSI_DIRECT
>  LIBVIRT_STORAGE_CHECK_SCSI
>  LIBVIRT_STORAGE_CHECK_MPATH
>  LIBVIRT_STORAGE_CHECK_DISK
> @@ -608,7 +611,7 @@ LIBVIRT_STORAGE_CHECK_ZFS
>  LIBVIRT_STORAGE_CHECK_VSTORAGE
>  
>  with_storage=no
> -for backend in dir fs lvm iscsi scsi mpath rbd disk; do
> +for backend in dir fs lvm iscsi iscsi_direct scsi mpath rbd disk; do
>      if eval test \$with_storage_$backend = yes; then
>          with_storage=yes
>          break
> @@ -936,6 +939,7 @@ LIBVIRT_STORAGE_RESULT_DIR
>  LIBVIRT_STORAGE_RESULT_FS
>  LIBVIRT_STORAGE_RESULT_LVM
>  LIBVIRT_STORAGE_RESULT_ISCSI
> +LIBVIRT_STORAGE_RESULT_ISCSI_DIRECT
>  LIBVIRT_STORAGE_RESULT_SCSI
>  LIBVIRT_STORAGE_RESULT_MPATH
>  LIBVIRT_STORAGE_RESULT_DISK
> diff --git a/m4/virt-storage-iscsi-direct.m4 b/m4/virt-storage-iscsi-direct.m4
> new file mode 100644
> index 0000000000..cc2d490352
> --- /dev/null
> +++ b/m4/virt-storage-iscsi-direct.m4
> @@ -0,0 +1,41 @@
> +dnl Iscsi-direct storage
> +dnl
> +dnl Copyright (C) 2018 Clementine Hayat.
> +dnl
> +dnl This library is free software; you can redistribute it and/or
> +dnl modify it under the terms of the GNU Lesser General Public
> +dnl License as published by the Free Software Foundation; either
> +dnl version 2.1 of the License, or (at your option) any later version.
> +dnl
> +dnl This library is distributed in the hope that it will be useful,
> +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
> +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +dnl Lesser General Public License for more details.
> +dnl
> +dnl You should have received a copy of the GNU Lesser General Public
> +dnl License along with this library.  If not, see
> +dnl <http://www.gnu.org/licenses/>.
> +dnl
> +
> +AC_DEFUN([LIBVIRT_STORAGE_ARG_ISCSI_DIRECT], [
> +  LIBVIRT_ARG_WITH_FEATURE([STORAGE_ISCSI_DIRECT],
> +                           [iscsi-direct backend for the storage driver],
> +                           [check])
> +])
> +
> +AC_DEFUN([LIBVIRT_STORAGE_CHECK_ISCSI_DIRECT], [
> +  AC_REQUIRE([LIBVIRT_CHECK_LIBISCSI])
> +  if test "$with_storage_iscsi_direct" = "check"; then
> +    with_storage_iscsi_direct=$with_libiscsi
> +  fi
> +  if test "$with_storage_iscsi_direct" = "yes"; then
> +    AC_DEFINE_UNQUOTED([WITH_STORAGE_ISCSI_DIRECT], [1],
> +                       [whether iSCSI backend for storage driver is enabled])
> +  fi
> +  AM_CONDITIONAL([WITH_STORAGE_ISCSI_DIRECT],
> +                 [test "$with_storage_iscsi_direct" = "yes"])
> +])
> +
> +AC_DEFUN([LIBVIRT_STORAGE_RESULT_ISCSI_DIRECT], [
> +  LIBVIRT_RESULT([iscsi-direct], [$with_storage_iscsi_direct])
> +])
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 7396616eda..5af27a6ad2 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -30163,6 +30163,10 @@ virDomainDiskTranslateSourcePool(virDomainDiskDefPtr def)
>  
>          break;
>  
> +    case VIR_STORAGE_POOL_ISCSI_DIRECT:
> +        def->src->srcpool->mode = VIR_STORAGE_SOURCE_POOL_MODE_DIRECT;
> +        break;

This is not exactly what I meant, this will not work.

Firstly, we should error out if startupPolicy is set the same way as we
do for VIR_STORAGE_POOL_ISCSI.

We also need to call all this code to translate the storage pool into
domain disk definition:

       case VIR_STORAGE_SOURCE_POOL_MODE_DIRECT:
           def->src->srcpool->actualtype = VIR_STORAGE_TYPE_NETWORK;
           def->src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI;

           if (virDomainDiskTranslateSourcePoolAuth(def,
                                                    &pooldef->source) < 0)
               goto cleanup;

           /* Source pool may not fill in the secrettype field,
            * so we need to do so here
            */
           if (def->src->auth && !def->src->auth->secrettype) {
               const char *secrettype =
                   virSecretUsageTypeToString(VIR_SECRET_USAGE_TYPE_ISCSI);
               if (VIR_STRDUP(def->src->auth->secrettype, secrettype) < 0)
                   goto cleanup;
           }

           if (virDomainDiskAddISCSIPoolSourceHost(def, pooldef) < 0)
               goto cleanup;

So I would suggest moving that code into separate function and calling
that function for VIR_STORAGE_POOL_ISCSI_DIRECT and also in the original
place of that code.

You can test this part by creating domain with this disk definition:

    ...
    <disk type='volume' device='disk'>
      <driver name='qemu' type='raw'/>
      <source pool='storage-pool-name' volume='storage-volume-name'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    ...

Pavel
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 3/3] storage: Implement iscsi_direct pool backend
Posted by clem@lse.epita.fr 5 years, 9 months ago
From: Clementine Hayat <clem@lse.epita.fr>

We need here libiscsi for the storgae pool backend.
For the iscsi-direct storage pool, only checkPool and refreshPool should
be necessary.
The pool is state-less and just need the informations within the volume
to work.

Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
---
 m4/virt-storage-iscsi-direct.m4            |   3 +
 src/storage/Makefile.inc.am                |   2 +
 src/storage/storage_backend_iscsi_direct.c | 408 ++++++++++++++++++++-
 3 files changed, 410 insertions(+), 3 deletions(-)

diff --git a/m4/virt-storage-iscsi-direct.m4 b/m4/virt-storage-iscsi-direct.m4
index cc2d490352..dab4414169 100644
--- a/m4/virt-storage-iscsi-direct.m4
+++ b/m4/virt-storage-iscsi-direct.m4
@@ -29,6 +29,9 @@ AC_DEFUN([LIBVIRT_STORAGE_CHECK_ISCSI_DIRECT], [
     with_storage_iscsi_direct=$with_libiscsi
   fi
   if test "$with_storage_iscsi_direct" = "yes"; then
+    if test "$with_libiscsi" = "no"; then
+      AC_MSG_ERROR([Need libiscsi for iscsi-direct storage driver])
+    fi
     AC_DEFINE_UNQUOTED([WITH_STORAGE_ISCSI_DIRECT], [1],
                        [whether iSCSI backend for storage driver is enabled])
   fi
diff --git a/src/storage/Makefile.inc.am b/src/storage/Makefile.inc.am
index b2714fd960..bd5ea06f8b 100644
--- a/src/storage/Makefile.inc.am
+++ b/src/storage/Makefile.inc.am
@@ -203,6 +203,7 @@ if WITH_STORAGE_ISCSI_DIRECT
 libvirt_storage_backend_iscsi_direct_la_SOURCES = $(STORAGE_DRIVER_ISCSI_DIRECT_SOURCES)
 libvirt_storage_backend_iscsi_direct_la_CFLAGS = \
 	-I$(srcdir)/conf \
+	-I$(srcdir)/secret \
 	$(LIBISCSI_CFLAGS) \
 	$(AM_CFLAGS) \
 	$(NULL)
@@ -211,6 +212,7 @@ storagebackend_LTLIBRARIES += libvirt_storage_backend_iscsi-direct.la
 libvirt_storage_backend_iscsi_direct_la_LDFLAGS = $(AM_LDFLAGS_MOD)
 libvirt_storage_backend_iscsi_direct_la_LIBADD = \
 	libvirt.la \
+	$(LIBISCSI_LIBS) \
 	../gnulib/lib/libgnu.la \
 	$(NULL)
 endif WITH_STORAGE_ISCSI_DIRECT
diff --git a/src/storage/storage_backend_iscsi_direct.c b/src/storage/storage_backend_iscsi_direct.c
index 94c4c989ff..b9a9bb3eb0 100644
--- a/src/storage/storage_backend_iscsi_direct.c
+++ b/src/storage/storage_backend_iscsi_direct.c
@@ -22,28 +22,430 @@
 
 #include <config.h>
 
+#include <iscsi/iscsi.h>
+#include <iscsi/scsi-lowlevel.h>
+
+#include "datatypes.h"
+#include "secret_util.h"
 #include "storage_backend_iscsi_direct.h"
 #include "storage_util.h"
+#include "viralloc.h"
+#include "virerror.h"
 #include "virlog.h"
+#include "virobject.h"
+#include "virstring.h"
+#include "virtime.h"
+#include "viruuid.h"
 
 #define VIR_FROM_THIS VIR_FROM_STORAGE
 
+#define ISCSI_DEFAULT_TARGET_PORT 3260
+#define VIR_ISCSI_TEST_UNIT_TIMEOUT 30 * 1000
+
 VIR_LOG_INIT("storage.storage_backend_iscsi_direct");
 
+static struct iscsi_context *
+virISCSIDirectCreateContext(const char* initiator_iqn)
+{
+    struct iscsi_context *iscsi = NULL;
+
+    iscsi = iscsi_create_context(initiator_iqn);
+    if (!iscsi)
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to create iscsi context for %s"),
+                       initiator_iqn);
+    return iscsi;
+}
+
+static char *
+virStorageBackendISCSIDirectPortal(virStoragePoolSourcePtr source)
+{
+    char *portal = NULL;
+
+    if (source->nhost != 1) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Expected exactly 1 host for the storage pool"));
+        return NULL;
+    }
+    if (source->hosts[0].port == 0) {
+        ignore_value(virAsprintf(&portal, "%s:%d",
+                                 source->hosts[0].name,
+                                 ISCSI_DEFAULT_TARGET_PORT));
+    } else if (strchr(source->hosts[0].name, ':')) {
+        ignore_value(virAsprintf(&portal, "[%s]:%d",
+                                 source->hosts[0].name,
+                                 source->hosts[0].port));
+    } else {
+        ignore_value(virAsprintf(&portal, "%s:%d",
+                                 source->hosts[0].name,
+                                 source->hosts[0].port));
+    }
+    return portal;
+}
+
+static int
+virStorageBackendISCSIDirectSetAuth(struct iscsi_context *iscsi,
+                                    virStoragePoolSourcePtr source)
+{
+    unsigned char *secret_value = NULL;
+    size_t secret_size;
+    virStorageAuthDefPtr authdef = source->auth;
+    int ret = -1;
+    virConnectPtr conn = NULL;
+
+    if (!authdef || authdef->authType == VIR_STORAGE_AUTH_TYPE_NONE)
+        return 0;
+
+    VIR_DEBUG("username='%s' authType=%d seclookupdef.type=%d",
+              authdef->username, authdef->authType, authdef->seclookupdef.type);
+
+    if (authdef->authType != VIR_STORAGE_AUTH_TYPE_CHAP) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("iscsi-direct pool only supports 'chap' auth type"));
+        return ret;
+    }
+
+    if (!(conn = virGetConnectSecret()))
+        return ret;
+
+    if (virSecretGetSecretString(conn, &authdef->seclookupdef,
+                                 VIR_SECRET_USAGE_TYPE_ISCSI,
+                                 &secret_value, &secret_size) < 0)
+        goto cleanup;
+
+    if (iscsi_set_initiator_username_pwd(iscsi,
+                                         authdef->username,
+                                         (const char *)secret_value) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to set credential: %s"),
+                       iscsi_get_error(iscsi));
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_DISPOSE_N(secret_value, secret_size);
+    virObjectUnref(conn);
+    return ret;
+}
+
+static int
+virISCSIDirectSetContext(struct iscsi_context *iscsi,
+                         const char *target_name)
+{
+    if (iscsi_init_transport(iscsi, TCP_TRANSPORT) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to init transport: %s"),
+                       iscsi_get_error(iscsi));
+        return -1;
+    }
+    if (iscsi_set_targetname(iscsi, target_name) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to set target name: %s"),
+                       iscsi_get_error(iscsi));
+        return -1;
+    }
+    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to set session type: %s"),
+                       iscsi_get_error(iscsi));
+        return -1;
+    }
+    return 0;
+}
+
+static int
+virISCSIDirectConnect(struct iscsi_context *iscsi,
+                      const char *portal)
+{
+    if (iscsi_connect_sync(iscsi, portal) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to connect: %s"),
+                       iscsi_get_error(iscsi));
+        return -1;
+    }
+    if (iscsi_login_sync(iscsi) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to login: %s"),
+                       iscsi_get_error(iscsi));
+        return -1;
+    }
+    return 0;
+}
+
+static struct scsi_reportluns_list *
+virISCSIDirectReportLuns(struct iscsi_context *iscsi)
+{
+    struct scsi_task *task = NULL;
+    struct scsi_reportluns_list *list = NULL;
+    int full_size;
+
+    if (!(task = iscsi_reportluns_sync(iscsi, 0, 16))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to reportluns: %s"),
+                       iscsi_get_error(iscsi));
+        goto cleanup;
+    }
+
+    full_size = scsi_datain_getfullsize(task);
+
+    if (full_size > task->datain.size) {
+        scsi_free_scsi_task(task);
+        if (!(task = iscsi_reportluns_sync(iscsi, 0, full_size))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Failed to reportluns: %s"),
+                           iscsi_get_error(iscsi));
+            goto cleanup;
+        }
+    }
+
+    if (!(list = scsi_datain_unmarshall(task))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to unmarshall reportluns: %s"),
+                       iscsi_get_error(iscsi));
+        goto cleanup;
+    }
+
+ cleanup:
+    scsi_free_scsi_task(task);
+    return list;
+}
+
+static int
+virISCSIDirectTestUnitReady(struct iscsi_context *iscsi,
+                            int lun)
+{
+    struct scsi_task *task = NULL;
+    int ret = -1;
+    virTimeBackOffVar timebackoff;
+
+    if (virTimeBackOffStart(&timebackoff, 1,
+                            VIR_ISCSI_TEST_UNIT_TIMEOUT) < 0)
+        goto cleanup;
+
+    do {
+        if (!(task = iscsi_testunitready_sync(iscsi, lun))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Failed testunitready: %s"),
+                           iscsi_get_error(iscsi));
+            goto cleanup;
+        }
+
+        if (task->status != SCSI_STATUS_CHECK_CONDITION ||
+            task->sense.key != SCSI_SENSE_UNIT_ATTENTION ||
+            task->sense.ascq != SCSI_SENSE_ASCQ_BUS_RESET)
+            break;
+
+        scsi_free_scsi_task(task);
+    } while (virTimeBackOffWait(&timebackoff));
+
+    if (task->status != SCSI_STATUS_GOOD) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed testunitready: %s"),
+                       iscsi_get_error(iscsi));
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    scsi_free_scsi_task(task);
+    return ret;
+}
+
+static int
+virISCSIDirectSetVolumeAttributes(virStoragePoolObjPtr pool,
+                                  virStorageVolDefPtr vol,
+                                  int lun,
+                                  char *portal)
+{
+    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
+
+    if (virAsprintf(&vol->name, "%u", lun) < 0)
+        return -1;
+    if (virAsprintf(&vol->key, "ip-%s-iscsi-%s-lun-%u", portal,
+                    def->source.devices[0].path, lun) < 0)
+        return -1;
+    if (virAsprintf(&vol->target.path, "ip-%s-iscsi-%s-lun-%u", portal,
+                    def->source.devices[0].path, lun) < 0)
+        return -1;
+    return 0;
+}
+
+static int
+virISCSIDirectSetVolumeCapacity(struct iscsi_context *iscsi,
+                                virStorageVolDefPtr vol,
+                                int lun)
+{
+    struct scsi_task *task = NULL;
+    struct scsi_inquiry_standard *inq = NULL;
+    long long size = 0;
+    int ret = -1;
+
+    if (!(task = iscsi_inquiry_sync(iscsi, lun, 0, 0, 64)) ||
+        task->status != SCSI_STATUS_GOOD) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to send inquiry command: %s"),
+                       iscsi_get_error(iscsi));
+        goto cleanup;
+    }
+
+    if (!(inq = scsi_datain_unmarshall(task))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to unmarshall reply: %s"),
+                       iscsi_get_error(iscsi));
+        goto cleanup;
+    }
+
+    if (inq->device_type == SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
+        struct scsi_readcapacity10 *rc10 = NULL;
+
+        scsi_free_scsi_task(task);
+        task = NULL;
+
+        if (!(task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0)) ||
+            task->status != SCSI_STATUS_GOOD) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Failed to get capacity of lun: %s"),
+                           iscsi_get_error(iscsi));
+            goto cleanup;
+        }
+
+        if (!(rc10 = scsi_datain_unmarshall(task))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Failed to unmarshall reply: %s"),
+                           iscsi_get_error(iscsi));
+            goto cleanup;
+        }
+
+        size  = rc10->block_size;
+        size *= rc10->lba;
+        vol->target.capacity = size;
+        vol->target.allocation = size;
+
+    }
+
+    ret = 0;
+ cleanup:
+    scsi_free_scsi_task(task);
+    return ret;
+}
+
+static int
+virISCSIDirectRefreshVol(virStoragePoolObjPtr pool,
+                         struct iscsi_context *iscsi,
+                         int lun,
+                         char *portal)
+{
+    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
+    virStorageVolDefPtr vol = NULL;
+    int ret = -1;
+
+    virStoragePoolObjClearVols(pool);
+    if (virISCSIDirectTestUnitReady(iscsi, lun) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC(vol) < 0)
+        goto cleanup;
+
+    vol->type = VIR_STORAGE_VOL_NETWORK;
+
+    if (virISCSIDirectSetVolumeCapacity(iscsi, vol, lun) < 0)
+        goto cleanup;
+
+    def->capacity += vol->target.capacity;
+    def->allocation += vol->target.allocation;
+
+    if (virISCSIDirectSetVolumeAttributes(pool, vol, lun, portal) < 0)
+        goto cleanup;
+
+    if (virStoragePoolObjAddVol(pool, vol) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to create volume: %d"),
+                       lun);
+        goto cleanup;
+    }
+    vol = NULL;
+
+    ret = 0;
+ cleanup:
+    virStorageVolDefFree(vol);
+    return ret;
+}
 
 static int
-virStorageBackendISCSIDirectCheckPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
-                                      bool *isActive ATTRIBUTE_UNUSED)
+virStorageBackendISCSIDirectRefreshVols(virStoragePoolObjPtr pool,
+                                        struct iscsi_context *iscsi,
+                                        char *portal)
 {
+    struct scsi_reportluns_list *list = NULL;
+    size_t i;
+
+    if (!(list = virISCSIDirectReportLuns(iscsi)))
+        return -1;
+    for (i = 0; i < list->num; i++) {
+        if (virISCSIDirectRefreshVol(pool, iscsi, list->luns[i], portal) < 0)
+            return -1;
+    }
+
     return 0;
 }
 
 static int
-virStorageBackendISCSIDirectRefreshPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED)
+virISCSIDirectDisconnect(struct iscsi_context *iscsi)
 {
+    if (iscsi_logout_sync(iscsi) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to logout: %s"),
+                       iscsi_get_error(iscsi));
+        return -1;
+    }
+    if (iscsi_disconnect(iscsi) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to disconnect: %s"),
+                       iscsi_get_error(iscsi));
+        return -1;
+    }
     return 0;
 }
 
+static int
+virStorageBackendISCSIDirectCheckPool(virStoragePoolObjPtr pool,
+                                      bool *isActive)
+{
+    *isActive = virStoragePoolObjIsActive(pool);
+    return 0;
+}
+
+static int
+virStorageBackendISCSIDirectRefreshPool(virStoragePoolObjPtr pool)
+{
+    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
+    struct iscsi_context *iscsi = NULL;
+    char *portal = NULL;
+    int ret = -1;
+
+    if (!(iscsi = virISCSIDirectCreateContext(def->source.initiator.iqn)))
+        goto cleanup;
+    if (!(portal = virStorageBackendISCSIDirectPortal(&def->source)))
+        goto cleanup;
+    if (virStorageBackendISCSIDirectSetAuth(iscsi, &def->source) < 0)
+        goto cleanup;
+    if (virISCSIDirectSetContext(iscsi, def->source.devices[0].path) < 0)
+        goto cleanup;
+    if (virISCSIDirectConnect(iscsi, portal) < 0)
+        goto cleanup;
+    if (virStorageBackendISCSIDirectRefreshVols(pool, iscsi, portal) < 0)
+        goto disconect;
+
+    ret = 0;
+ disconect:
+    virISCSIDirectDisconnect(iscsi);
+ cleanup:
+    VIR_FREE(portal);
+    iscsi_destroy_context(iscsi);
+    return ret;
+}
+
 virStorageBackend virStorageBackendISCSIDirect = {
     .type = VIR_STORAGE_POOL_ISCSI_DIRECT,
 
-- 
2.18.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 3/3] storage: Implement iscsi_direct pool backend
Posted by Michal Privoznik 5 years, 9 months ago
On 07/23/2018 08:43 PM, clem@lse.epita.fr wrote:
> From: Clementine Hayat <clem@lse.epita.fr>
> 
> We need here libiscsi for the storgae pool backend.
> For the iscsi-direct storage pool, only checkPool and refreshPool should
> be necessary.

Well, they are necessary only for basic support. There is still couple
of APIs worth implementing ;-)

> The pool is state-less and just need the informations within the volume
> to work.
> 
> Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
> ---
>  m4/virt-storage-iscsi-direct.m4            |   3 +
>  src/storage/Makefile.inc.am                |   2 +
>  src/storage/storage_backend_iscsi_direct.c | 408 ++++++++++++++++++++-
>  3 files changed, 410 insertions(+), 3 deletions(-)

ACK

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 3/3] storage: Implement iscsi_direct pool backend
Posted by Pavel Hrdina 5 years, 9 months ago
On Mon, Jul 23, 2018 at 08:43:01PM +0200, clem@lse.epita.fr wrote:
> From: Clementine Hayat <clem@lse.epita.fr>
> 
> We need here libiscsi for the storgae pool backend.
> For the iscsi-direct storage pool, only checkPool and refreshPool should
> be necessary.
> The pool is state-less and just need the informations within the volume
> to work.
> 
> Signed-off-by: Clementine Hayat <clem@lse.epita.fr>
> ---
>  m4/virt-storage-iscsi-direct.m4            |   3 +
>  src/storage/Makefile.inc.am                |   2 +
>  src/storage/storage_backend_iscsi_direct.c | 408 ++++++++++++++++++++-
>  3 files changed, 410 insertions(+), 3 deletions(-)
> 
> diff --git a/m4/virt-storage-iscsi-direct.m4 b/m4/virt-storage-iscsi-direct.m4
> index cc2d490352..dab4414169 100644
> --- a/m4/virt-storage-iscsi-direct.m4
> +++ b/m4/virt-storage-iscsi-direct.m4
> @@ -29,6 +29,9 @@ AC_DEFUN([LIBVIRT_STORAGE_CHECK_ISCSI_DIRECT], [
>      with_storage_iscsi_direct=$with_libiscsi
>    fi
>    if test "$with_storage_iscsi_direct" = "yes"; then
> +    if test "$with_libiscsi" = "no"; then
> +      AC_MSG_ERROR([Need libiscsi for iscsi-direct storage driver])
> +    fi
>      AC_DEFINE_UNQUOTED([WITH_STORAGE_ISCSI_DIRECT], [1],
>                         [whether iSCSI backend for storage driver is enabled])
>    fi
> diff --git a/src/storage/Makefile.inc.am b/src/storage/Makefile.inc.am
> index b2714fd960..bd5ea06f8b 100644
> --- a/src/storage/Makefile.inc.am
> +++ b/src/storage/Makefile.inc.am
> @@ -203,6 +203,7 @@ if WITH_STORAGE_ISCSI_DIRECT
>  libvirt_storage_backend_iscsi_direct_la_SOURCES = $(STORAGE_DRIVER_ISCSI_DIRECT_SOURCES)
>  libvirt_storage_backend_iscsi_direct_la_CFLAGS = \
>  	-I$(srcdir)/conf \
> +	-I$(srcdir)/secret \
>  	$(LIBISCSI_CFLAGS) \
>  	$(AM_CFLAGS) \
>  	$(NULL)
> @@ -211,6 +212,7 @@ storagebackend_LTLIBRARIES += libvirt_storage_backend_iscsi-direct.la
>  libvirt_storage_backend_iscsi_direct_la_LDFLAGS = $(AM_LDFLAGS_MOD)
>  libvirt_storage_backend_iscsi_direct_la_LIBADD = \
>  	libvirt.la \
> +	$(LIBISCSI_LIBS) \
>  	../gnulib/lib/libgnu.la \
>  	$(NULL)
>  endif WITH_STORAGE_ISCSI_DIRECT
> diff --git a/src/storage/storage_backend_iscsi_direct.c b/src/storage/storage_backend_iscsi_direct.c
> index 94c4c989ff..b9a9bb3eb0 100644
> --- a/src/storage/storage_backend_iscsi_direct.c
> +++ b/src/storage/storage_backend_iscsi_direct.c
> @@ -22,28 +22,430 @@
>  
>  #include <config.h>
>  
> +#include <iscsi/iscsi.h>
> +#include <iscsi/scsi-lowlevel.h>
> +
> +#include "datatypes.h"
> +#include "secret_util.h"
>  #include "storage_backend_iscsi_direct.h"
>  #include "storage_util.h"
> +#include "viralloc.h"
> +#include "virerror.h"
>  #include "virlog.h"
> +#include "virobject.h"
> +#include "virstring.h"
> +#include "virtime.h"
> +#include "viruuid.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_STORAGE
>  
> +#define ISCSI_DEFAULT_TARGET_PORT 3260
> +#define VIR_ISCSI_TEST_UNIT_TIMEOUT 30 * 1000
> +
>  VIR_LOG_INIT("storage.storage_backend_iscsi_direct");
>  
> +static struct iscsi_context *
> +virISCSIDirectCreateContext(const char* initiator_iqn)
> +{
> +    struct iscsi_context *iscsi = NULL;
> +
> +    iscsi = iscsi_create_context(initiator_iqn);
> +    if (!iscsi)
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to create iscsi context for %s"),
> +                       initiator_iqn);
> +    return iscsi;
> +}
> +
> +static char *
> +virStorageBackendISCSIDirectPortal(virStoragePoolSourcePtr source)
> +{
> +    char *portal = NULL;
> +
> +    if (source->nhost != 1) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("Expected exactly 1 host for the storage pool"));
> +        return NULL;
> +    }
> +    if (source->hosts[0].port == 0) {
> +        ignore_value(virAsprintf(&portal, "%s:%d",
> +                                 source->hosts[0].name,
> +                                 ISCSI_DEFAULT_TARGET_PORT));
> +    } else if (strchr(source->hosts[0].name, ':')) {
> +        ignore_value(virAsprintf(&portal, "[%s]:%d",
> +                                 source->hosts[0].name,
> +                                 source->hosts[0].port));
> +    } else {
> +        ignore_value(virAsprintf(&portal, "%s:%d",
> +                                 source->hosts[0].name,
> +                                 source->hosts[0].port));
> +    }
> +    return portal;
> +}
> +
> +static int
> +virStorageBackendISCSIDirectSetAuth(struct iscsi_context *iscsi,
> +                                    virStoragePoolSourcePtr source)
> +{
> +    unsigned char *secret_value = NULL;
> +    size_t secret_size;
> +    virStorageAuthDefPtr authdef = source->auth;
> +    int ret = -1;
> +    virConnectPtr conn = NULL;
> +
> +    if (!authdef || authdef->authType == VIR_STORAGE_AUTH_TYPE_NONE)
> +        return 0;
> +
> +    VIR_DEBUG("username='%s' authType=%d seclookupdef.type=%d",
> +              authdef->username, authdef->authType, authdef->seclookupdef.type);
> +
> +    if (authdef->authType != VIR_STORAGE_AUTH_TYPE_CHAP) {
> +        virReportError(VIR_ERR_XML_ERROR, "%s",
> +                       _("iscsi-direct pool only supports 'chap' auth type"));
> +        return ret;
> +    }
> +
> +    if (!(conn = virGetConnectSecret()))
> +        return ret;
> +
> +    if (virSecretGetSecretString(conn, &authdef->seclookupdef,
> +                                 VIR_SECRET_USAGE_TYPE_ISCSI,
> +                                 &secret_value, &secret_size) < 0)
> +        goto cleanup;
> +
> +    if (iscsi_set_initiator_username_pwd(iscsi,
> +                                         authdef->username,
> +                                         (const char *)secret_value) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to set credential: %s"),
> +                       iscsi_get_error(iscsi));
> +        goto cleanup;
> +    }
> +
> +    ret = 0;
> + cleanup:
> +    VIR_DISPOSE_N(secret_value, secret_size);
> +    virObjectUnref(conn);
> +    return ret;
> +}
> +
> +static int
> +virISCSIDirectSetContext(struct iscsi_context *iscsi,
> +                         const char *target_name)
> +{
> +    if (iscsi_init_transport(iscsi, TCP_TRANSPORT) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to init transport: %s"),
> +                       iscsi_get_error(iscsi));
> +        return -1;
> +    }
> +    if (iscsi_set_targetname(iscsi, target_name) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to set target name: %s"),
> +                       iscsi_get_error(iscsi));
> +        return -1;
> +    }
> +    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to set session type: %s"),
> +                       iscsi_get_error(iscsi));
> +        return -1;
> +    }
> +    return 0;
> +}
> +
> +static int
> +virISCSIDirectConnect(struct iscsi_context *iscsi,
> +                      const char *portal)
> +{
> +    if (iscsi_connect_sync(iscsi, portal) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to connect: %s"),
> +                       iscsi_get_error(iscsi));
> +        return -1;
> +    }
> +    if (iscsi_login_sync(iscsi) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to login: %s"),
> +                       iscsi_get_error(iscsi));
> +        return -1;
> +    }
> +    return 0;
> +}
> +
> +static struct scsi_reportluns_list *
> +virISCSIDirectReportLuns(struct iscsi_context *iscsi)
> +{
> +    struct scsi_task *task = NULL;
> +    struct scsi_reportluns_list *list = NULL;
> +    int full_size;
> +
> +    if (!(task = iscsi_reportluns_sync(iscsi, 0, 16))) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to reportluns: %s"),
> +                       iscsi_get_error(iscsi));
> +        goto cleanup;
> +    }

Here we create new task.

> +
> +    full_size = scsi_datain_getfullsize(task);
> +
> +    if (full_size > task->datain.size) {
> +        scsi_free_scsi_task(task);
> +        if (!(task = iscsi_reportluns_sync(iscsi, 0, full_size))) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Failed to reportluns: %s"),
> +                           iscsi_get_error(iscsi));
> +            goto cleanup;
> +        }
> +    }

Here we get all the available LUNs.

> +
> +    if (!(list = scsi_datain_unmarshall(task))) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to unmarshall reportluns: %s"),
> +                       iscsi_get_error(iscsi));
> +        goto cleanup;
> +    }

And here we get the list of the available LUNs, so far so good.  But
there is a hidden issue, the memory returned here and stored into @list
is not newly allocated memory but it's part of the @task data structure.

> +
> + cleanup:
> +    scsi_free_scsi_task(task);

Here we free all the memory allocated by the @task together with the
@list and then we return pointer to freed memory.

> +    return list;
> +}
> +
> +static int
> +virISCSIDirectTestUnitReady(struct iscsi_context *iscsi,
> +                            int lun)
> +{
> +    struct scsi_task *task = NULL;
> +    int ret = -1;
> +    virTimeBackOffVar timebackoff;
> +
> +    if (virTimeBackOffStart(&timebackoff, 1,
> +                            VIR_ISCSI_TEST_UNIT_TIMEOUT) < 0)
> +        goto cleanup;
> +
> +    do {
> +        if (!(task = iscsi_testunitready_sync(iscsi, lun))) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Failed testunitready: %s"),
> +                           iscsi_get_error(iscsi));
> +            goto cleanup;
> +        }
> +
> +        if (task->status != SCSI_STATUS_CHECK_CONDITION ||
> +            task->sense.key != SCSI_SENSE_UNIT_ATTENTION ||
> +            task->sense.ascq != SCSI_SENSE_ASCQ_BUS_RESET)
> +            break;
> +
> +        scsi_free_scsi_task(task);
> +    } while (virTimeBackOffWait(&timebackoff));
> +
> +    if (task->status != SCSI_STATUS_GOOD) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed testunitready: %s"),
> +                       iscsi_get_error(iscsi));
> +        goto cleanup;
> +    }
> +
> +    ret = 0;
> + cleanup:
> +    scsi_free_scsi_task(task);
> +    return ret;
> +}
> +
> +static int
> +virISCSIDirectSetVolumeAttributes(virStoragePoolObjPtr pool,
> +                                  virStorageVolDefPtr vol,
> +                                  int lun,
> +                                  char *portal)
> +{
> +    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
> +
> +    if (virAsprintf(&vol->name, "%u", lun) < 0)
> +        return -1;
> +    if (virAsprintf(&vol->key, "ip-%s-iscsi-%s-lun-%u", portal,
> +                    def->source.devices[0].path, lun) < 0)
> +        return -1;
> +    if (virAsprintf(&vol->target.path, "ip-%s-iscsi-%s-lun-%u", portal,
> +                    def->source.devices[0].path, lun) < 0)
> +        return -1;

Now that I'm testing the code I'm not sure about these values.  For
example the name cannot be only the number of the LUN, that will not
work in domain XML if we use virDomainDiskAddISCSIPoolSourceHost() in
order to translate storage volume into domain disk definition.

I thing we should use these values:

    name            unit:0:0:$LUN
    path            $poolName/$volName

key can remain as it is.


> +    return 0;
> +}
> +
> +static int
> +virISCSIDirectSetVolumeCapacity(struct iscsi_context *iscsi,
> +                                virStorageVolDefPtr vol,
> +                                int lun)
> +{
> +    struct scsi_task *task = NULL;
> +    struct scsi_inquiry_standard *inq = NULL;
> +    long long size = 0;
> +    int ret = -1;
> +
> +    if (!(task = iscsi_inquiry_sync(iscsi, lun, 0, 0, 64)) ||
> +        task->status != SCSI_STATUS_GOOD) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to send inquiry command: %s"),
> +                       iscsi_get_error(iscsi));
> +        goto cleanup;
> +    }
> +
> +    if (!(inq = scsi_datain_unmarshall(task))) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to unmarshall reply: %s"),
> +                       iscsi_get_error(iscsi));
> +        goto cleanup;
> +    }
> +
> +    if (inq->device_type == SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
> +        struct scsi_readcapacity10 *rc10 = NULL;
> +
> +        scsi_free_scsi_task(task);
> +        task = NULL;
> +
> +        if (!(task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0)) ||
> +            task->status != SCSI_STATUS_GOOD) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Failed to get capacity of lun: %s"),
> +                           iscsi_get_error(iscsi));
> +            goto cleanup;
> +        }
> +
> +        if (!(rc10 = scsi_datain_unmarshall(task))) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("Failed to unmarshall reply: %s"),
> +                           iscsi_get_error(iscsi));
> +            goto cleanup;
> +        }
> +
> +        size  = rc10->block_size;
> +        size *= rc10->lba;
> +        vol->target.capacity = size;
> +        vol->target.allocation = size;
> +
> +    }
> +
> +    ret = 0;
> + cleanup:
> +    scsi_free_scsi_task(task);
> +    return ret;
> +}
> +
> +static int
> +virISCSIDirectRefreshVol(virStoragePoolObjPtr pool,
> +                         struct iscsi_context *iscsi,
> +                         int lun,
> +                         char *portal)
> +{
> +    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
> +    virStorageVolDefPtr vol = NULL;
> +    int ret = -1;
> +
> +    virStoragePoolObjClearVols(pool);
> +    if (virISCSIDirectTestUnitReady(iscsi, lun) < 0)
> +        goto cleanup;
> +
> +    if (VIR_ALLOC(vol) < 0)
> +        goto cleanup;
> +
> +    vol->type = VIR_STORAGE_VOL_NETWORK;
> +
> +    if (virISCSIDirectSetVolumeCapacity(iscsi, vol, lun) < 0)
> +        goto cleanup;
> +
> +    def->capacity += vol->target.capacity;
> +    def->allocation += vol->target.allocation;
> +
> +    if (virISCSIDirectSetVolumeAttributes(pool, vol, lun, portal) < 0)
> +        goto cleanup;
> +
> +    if (virStoragePoolObjAddVol(pool, vol) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to create volume: %d"),
> +                       lun);
> +        goto cleanup;
> +    }
> +    vol = NULL;
> +
> +    ret = 0;
> + cleanup:
> +    virStorageVolDefFree(vol);
> +    return ret;
> +}
>  
>  static int
> -virStorageBackendISCSIDirectCheckPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
> -                                      bool *isActive ATTRIBUTE_UNUSED)
> +virStorageBackendISCSIDirectRefreshVols(virStoragePoolObjPtr pool,
> +                                        struct iscsi_context *iscsi,
> +                                        char *portal)
>  {
> +    struct scsi_reportluns_list *list = NULL;
> +    size_t i;
> +
> +    if (!(list = virISCSIDirectReportLuns(iscsi)))
> +        return -1;

Unfortunately this will not work :/.  Documentation of libiscsi really
sucks, sigh.

> +    for (i = 0; i < list->num; i++) {
> +        if (virISCSIDirectRefreshVol(pool, iscsi, list->luns[i], portal) < 0)
> +            return -1;
> +    }

This for loop needs to be moved into virISCSIDirectReportLuns(), witch
means that we can remove expand content of that function here and remove
it completely.  The result would be only having
virStorageBackendISCSIDirectRefreshVols() with code from
virISCSIDirectReportLuns() as well.

Pavel

> +
>      return 0;
>  }
>  
>  static int
> -virStorageBackendISCSIDirectRefreshPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED)
> +virISCSIDirectDisconnect(struct iscsi_context *iscsi)
>  {
> +    if (iscsi_logout_sync(iscsi) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to logout: %s"),
> +                       iscsi_get_error(iscsi));
> +        return -1;
> +    }
> +    if (iscsi_disconnect(iscsi) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to disconnect: %s"),
> +                       iscsi_get_error(iscsi));
> +        return -1;
> +    }
>      return 0;
>  }
>  
> +static int
> +virStorageBackendISCSIDirectCheckPool(virStoragePoolObjPtr pool,
> +                                      bool *isActive)
> +{
> +    *isActive = virStoragePoolObjIsActive(pool);
> +    return 0;
> +}
> +
> +static int
> +virStorageBackendISCSIDirectRefreshPool(virStoragePoolObjPtr pool)
> +{
> +    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
> +    struct iscsi_context *iscsi = NULL;
> +    char *portal = NULL;
> +    int ret = -1;
> +
> +    if (!(iscsi = virISCSIDirectCreateContext(def->source.initiator.iqn)))
> +        goto cleanup;
> +    if (!(portal = virStorageBackendISCSIDirectPortal(&def->source)))
> +        goto cleanup;
> +    if (virStorageBackendISCSIDirectSetAuth(iscsi, &def->source) < 0)
> +        goto cleanup;
> +    if (virISCSIDirectSetContext(iscsi, def->source.devices[0].path) < 0)
> +        goto cleanup;
> +    if (virISCSIDirectConnect(iscsi, portal) < 0)
> +        goto cleanup;
> +    if (virStorageBackendISCSIDirectRefreshVols(pool, iscsi, portal) < 0)
> +        goto disconect;
> +
> +    ret = 0;
> + disconect:
> +    virISCSIDirectDisconnect(iscsi);
> + cleanup:
> +    VIR_FREE(portal);
> +    iscsi_destroy_context(iscsi);
> +    return ret;
> +}
> +
>  virStorageBackend virStorageBackendISCSIDirect = {
>      .type = VIR_STORAGE_POOL_ISCSI_DIRECT,
>  
> -- 
> 2.18.0
> 
> --
> libvir-list mailing list
> libvir-list@redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list