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

From: Clementine Hayat <clem@lse.epita.fr> Hello, This is the implementation of the iscsi-direct backend storage pool version 4. v1: https://www.redhat.com/archives/libvir-list/2018-July/msg00918.html v2: https://www.redhat.com/archives/libvir-list/2018-July/msg01528.html v3: https://www.redhat.com/archives/libvir-list/2018-July/msg02076.html Best Regards, -- Clementine Hayat Clementine Hayat (4): configure: Introduce libiscsi in build system storage: Introduce iscsi_direct pool type storage: Implement iscsi_direct pool backend news: add storage pool iscsi-direct configure.ac | 9 +- docs/news.xml | 9 + docs/schemas/storagepool.rng | 35 ++ docs/storage.html.in | 30 ++ m4/virt-libiscsi.m4 | 30 ++ m4/virt-storage-iscsi-direct.m4 | 44 ++ src/conf/domain_conf.c | 1 + src/conf/storage_conf.c | 22 +- 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 | 452 ++++++++++++++++++ src/storage/storage_backend_iscsi_direct.h | 6 + src/storage/storage_driver.c | 1 + .../pool-iscsi-direct-auth.xml | 14 + .../pool-iscsi-direct.xml | 11 + .../pool-iscsi-direct-auth.xml | 17 + .../pool-iscsi-direct.xml | 14 + tests/storagepoolxml2xmltest.c | 2 + tools/virsh-pool.c | 3 + 21 files changed, 727 insertions(+), 6 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 create mode 100644 tests/storagepoolxml2xmlin/pool-iscsi-direct-auth.xml create mode 100644 tests/storagepoolxml2xmlin/pool-iscsi-direct.xml create mode 100644 tests/storagepoolxml2xmlout/pool-iscsi-direct-auth.xml create mode 100644 tests/storagepoolxml2xmlout/pool-iscsi-direct.xml -- 2.18.0

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 c6287f656a..0b682349f6 100644 --- a/configure.ac +++ b/configure.ac @@ -251,6 +251,7 @@ LIBVIRT_ARG_FUSE LIBVIRT_ARG_GLUSTER LIBVIRT_ARG_HAL LIBVIRT_ARG_JANSSON +LIBVIRT_ARG_LIBISCSI LIBVIRT_ARG_LIBPCAP LIBVIRT_ARG_LIBSSH LIBVIRT_ARG_LIBXML @@ -292,6 +293,7 @@ LIBVIRT_CHECK_GLUSTER LIBVIRT_CHECK_GNUTLS LIBVIRT_CHECK_HAL LIBVIRT_CHECK_JANSSON +LIBVIRT_CHECK_LIBISCSI LIBVIRT_CHECK_LIBNL LIBVIRT_CHECK_LIBPARTED LIBVIRT_CHECK_LIBPCAP @@ -973,6 +975,7 @@ LIBVIRT_RESULT_GLUSTER LIBVIRT_RESULT_GNUTLS LIBVIRT_RESULT_HAL LIBVIRT_RESULT_JANSSON +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

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 +- docs/schemas/storagepool.rng | 35 +++++++++++ docs/storage.html.in | 30 ++++++++++ m4/virt-storage-iscsi-direct.m4 | 41 +++++++++++++ src/conf/domain_conf.c | 1 + src/conf/storage_conf.c | 22 +++++-- 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 + .../pool-iscsi-direct-auth.xml | 14 +++++ .../pool-iscsi-direct.xml | 11 ++++ .../pool-iscsi-direct-auth.xml | 17 ++++++ .../pool-iscsi-direct.xml | 14 +++++ tests/storagepoolxml2xmltest.c | 2 + tools/virsh-pool.c | 3 + 19 files changed, 286 insertions(+), 6 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 create mode 100644 tests/storagepoolxml2xmlin/pool-iscsi-direct-auth.xml create mode 100644 tests/storagepoolxml2xmlin/pool-iscsi-direct.xml create mode 100644 tests/storagepoolxml2xmlout/pool-iscsi-direct-auth.xml create mode 100644 tests/storagepoolxml2xmlout/pool-iscsi-direct.xml diff --git a/configure.ac b/configure.ac index 0b682349f6..bd7de04a44 100644 --- a/configure.ac +++ b/configure.ac @@ -566,6 +566,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 @@ -580,6 +581,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 @@ -600,6 +602,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 @@ -610,7 +613,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 @@ -938,6 +941,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/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng index 52b2044bef..11ac55d06f 100644 --- a/docs/schemas/storagepool.rng +++ b/docs/schemas/storagepool.rng @@ -18,6 +18,7 @@ <ref name='poollogical'/> <ref name='pooldisk'/> <ref name='pooliscsi'/> + <ref name='pooliscsidirect'/> <ref name='poolscsi'/> <ref name='poolmpath'/> <ref name='poolrbd'/> @@ -101,6 +102,19 @@ </interleave> </define> + <define name='pooliscsidirect'> + <attribute name='type'> + <value>iscsi-direct</value> + </attribute> + <interleave> + <ref name='commonmetadata'/> + <optional> + <ref name='sizing'/> + </optional> + <ref name='sourceiscsidirect'/> + </interleave> + </define> + <define name='poolscsi'> <attribute name='type'> <value>scsi</value> @@ -314,6 +328,14 @@ </element> </define> + <define name='sourceinfodeviscsidirect'> + <element name='device'> + <attribute name='path'> + <ref name='IscsiQualifiedName'/> + </attribute> + </element> + </define> + <define name='initiatorinfo'> <element name='initiator'> <element name='iqn'> @@ -595,6 +617,19 @@ </element> </define> + <define name='sourceiscsidirect'> + <element name='source'> + <interleave> + <ref name='sourceinfohost'/> + <ref name='sourceinfodeviscsidirect'/> + <ref name='initiatorinfo'/> + <optional> + <ref name='sourceinfoauth'/> + </optional> + </interleave> + </element> + </define> + <define name='sourcescsi'> <element name='source'> <interleave> diff --git a/docs/storage.html.in b/docs/storage.html.in index 1906aa6cd4..744819d99d 100644 --- a/docs/storage.html.in +++ b/docs/storage.html.in @@ -433,6 +433,36 @@ The iSCSI volume pool does not use the volume format type element. </p> + <h2><a id="StorageBackendISCSIDirect">iSCSI direct pool</a></h2> + <p> + This is a variant of the iSCSI pool. Instead of unsing iscsiadm, it uses + libiscsi. + It require a host, a path which is the target iqn and an initiator iqn. + </p> + + <h3>Example pool input</h3> + <pre> +<pool type="iscsi-direct"> + <name>virtimages</name> + <source> + <host name="iscsi.example.com"/> + <device path="iqn.2013-06.com.example:iscsi-pool"/> + </source> + <initiator> + <iqn name="iqn.2013-06.com.example:iscsi-initiator"/> + </initiator> +</pool></pre> + + <h3>Valid pool format types</h3> + <p> + The iSCSI volume pool does not use the pool format type element. + </p> + + <h3>Valid volume format types</h3> + <p> + The iSCSI volume pool does not use the volume format type element. + </p> + <h2><a id="StorageBackendSCSI">SCSI pool</a></h2> <p> This provides a pool based on a SCSI HBA. Volumes are preexisting SCSI 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 eff8af20e7..7dcbe8a20b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -30252,6 +30252,7 @@ virDomainDiskTranslateSourcePool(virDomainDiskDefPtr def) break; + case VIR_STORAGE_POOL_ISCSI_DIRECT: 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..f967ea0f66 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), @@ -1000,11 +1011,12 @@ virStoragePoolDefFormatBuf(virBufferPtr buf, if (virStoragePoolSourceFormat(buf, options, &def->source) < 0) return -1; - /* RBD, Sheepdog, and Gluster devices are not local block devs nor + /* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor * 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/tests/storagepoolxml2xmlin/pool-iscsi-direct-auth.xml b/tests/storagepoolxml2xmlin/pool-iscsi-direct-auth.xml new file mode 100644 index 0000000000..96c82e161f --- /dev/null +++ b/tests/storagepoolxml2xmlin/pool-iscsi-direct-auth.xml @@ -0,0 +1,14 @@ +<pool type="iscsi-direct"> + <name>iscsi-direct-auth</name> + <uuid>034d66fc-f507-437a-b552-c479ffd63820</uuid> + <source> + <host name="iscsi.example.com"/> + <device path="iqn.2013-06.com.example:iscsi-pool"/> + <initiator> + <iqn name='iqn.2013-06.com.example:iscsi-initiator'/> + </initiator> + <auth type='chap' username='user'> + <secret uuid='10ed4ad4-c7b0-4696-b574-b40e04fea84b'/> + </auth> + </source> +</pool> diff --git a/tests/storagepoolxml2xmlin/pool-iscsi-direct.xml b/tests/storagepoolxml2xmlin/pool-iscsi-direct.xml new file mode 100644 index 0000000000..9369a3cc43 --- /dev/null +++ b/tests/storagepoolxml2xmlin/pool-iscsi-direct.xml @@ -0,0 +1,11 @@ +<pool type="iscsi-direct"> + <name>iscsi-direct</name> + <uuid>034d66fc-f507-437a-b552-c479ffd63819</uuid> + <source> + <host name="iscsi.example.com"/> + <device path="iqn.2013-06.com.example:iscsi-pool"/> + <initiator> + <iqn name='iqn.2013-06.com.example:iscsi-initiator'/> + </initiator> + </source> +</pool> diff --git a/tests/storagepoolxml2xmlout/pool-iscsi-direct-auth.xml b/tests/storagepoolxml2xmlout/pool-iscsi-direct-auth.xml new file mode 100644 index 0000000000..63b9105cbf --- /dev/null +++ b/tests/storagepoolxml2xmlout/pool-iscsi-direct-auth.xml @@ -0,0 +1,17 @@ +<pool type='iscsi-direct'> + <name>iscsi-direct-auth</name> + <uuid>034d66fc-f507-437a-b552-c479ffd63820</uuid> + <capacity unit='bytes'>0</capacity> + <allocation unit='bytes'>0</allocation> + <available unit='bytes'>0</available> + <source> + <host name='iscsi.example.com'/> + <device path='iqn.2013-06.com.example:iscsi-pool'/> + <initiator> + <iqn name='iqn.2013-06.com.example:iscsi-initiator'/> + </initiator> + <auth type='chap' username='user'> + <secret uuid='10ed4ad4-c7b0-4696-b574-b40e04fea84b'/> + </auth> + </source> +</pool> diff --git a/tests/storagepoolxml2xmlout/pool-iscsi-direct.xml b/tests/storagepoolxml2xmlout/pool-iscsi-direct.xml new file mode 100644 index 0000000000..84717dd152 --- /dev/null +++ b/tests/storagepoolxml2xmlout/pool-iscsi-direct.xml @@ -0,0 +1,14 @@ +<pool type='iscsi-direct'> + <name>iscsi-direct</name> + <uuid>034d66fc-f507-437a-b552-c479ffd63819</uuid> + <capacity unit='bytes'>0</capacity> + <allocation unit='bytes'>0</allocation> + <available unit='bytes'>0</available> + <source> + <host name='iscsi.example.com'/> + <device path='iqn.2013-06.com.example:iscsi-pool'/> + <initiator> + <iqn name='iqn.2013-06.com.example:iscsi-initiator'/> + </initiator> + </source> +</pool> diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c index 974f0afe39..28421235bf 100644 --- a/tests/storagepoolxml2xmltest.c +++ b/tests/storagepoolxml2xmltest.c @@ -102,6 +102,8 @@ mymain(void) DO_TEST("pool-zfs-sourcedev"); DO_TEST("pool-rbd"); DO_TEST("pool-vstorage"); + DO_TEST("pool-iscsi-direct-auth"); + DO_TEST("pool-iscsi-direct"); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index 6faff781b2..89206a48f5 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

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 for basic support. 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 | 400 ++++++++++++++++++++- 3 files changed, 402 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..ab192730fb 100644 --- a/src/storage/storage_backend_iscsi_direct.c +++ b/src/storage/storage_backend_iscsi_direct.c @@ -22,28 +22,422 @@ #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 -virStorageBackendISCSIDirectCheckPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, - bool *isActive ATTRIBUTE_UNUSED) +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 int -virStorageBackendISCSIDirectRefreshPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED) +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, "unit:0:0:%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 +virISCSIDirectReportLuns(virStoragePoolObjPtr pool, + struct iscsi_context *iscsi, + char *portal) +{ + struct scsi_task *task = NULL; + struct scsi_reportluns_list *list = NULL; + int full_size; + size_t i; + int ret = -1; + + 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; + } + + for (i = 0; i < list->num; i++) { + if (virISCSIDirectRefreshVol(pool, iscsi, list->luns[i], portal) < 0) + goto cleanup; + } + + ret = 0; + cleanup: + scsi_free_scsi_task(task); + return ret; +} + +static int +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 (virISCSIDirectReportLuns(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

From: Clementine Hayat <clem@lse.epita.fr> Signed-off-by: Clementine Hayat <clem@lse.epita.fr> --- docs/news.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index a68ef2dc1c..73e79dff0f 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -35,6 +35,15 @@ <libvirt> <release version="v4.6.0" date="unreleased"> <section title="New features"> + <change> + <summary> + storage: add storage pool iscsi-direct + </summary> + <description> + Introduce a new storage pool backend that uses libiscsi instead of + iscsiadm. It support basic pool operations: checkPool and refreshPool. + </description> + </change> <change> <summary> qemu: Implement the HTM pSeries feature -- 2.18.0
participants (1)
-
clem@lse.epita.fr