[libvirt] [PATCH v3 4/7] qemu: Translate the iscsi pool/volume disk source

John Ferlan jferlan at redhat.com
Fri Jul 19 12:32:30 UTC 2013


The difference with already supported pool types (dir, fs, block)
is: there are two modes for iscsi pool (or network pools in future),
one can specify it either to use the volume target path (the path
showed up on host) with mode='host', or to use the remote URI qemu
supports (e.g. file=iscsi://example.org:6000/iqn.1992-01.com.example/1)
with mode='direct'.

For 'host' mode, it copies the volume target path into disk->src. For
'direct' mode, the corresponding info in the *one* pool source host def
is copied to disk->hosts[0].
---
 src/conf/domain_conf.c  |   8 ++++
 src/conf/domain_conf.h  |   1 +
 src/qemu/qemu_command.c |  15 ++++++-
 src/qemu/qemu_conf.c    | 101 +++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index dddd55d..231edb5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -18403,6 +18403,14 @@ virDomainDiskSourceIsBlockType(virDomainDiskDefPtr def)
      */
     if (def->type == VIR_DOMAIN_DISK_TYPE_VOLUME && def->srcpool &&
         def->srcpool->voltype == VIR_STORAGE_VOL_BLOCK) {
+        /* We don't think the volume accessed by remote URI is
+         * block type source, since we can't/shouldn't manage it
+         * (e.g. set sgio=filtered|unfiltered for it) in libvirt.
+         */
+         if (def->srcpool->pooltype == VIR_STORAGE_POOL_ISCSI &&
+             def->srcpool->mode == VIR_DOMAIN_DISK_SOURCE_POOL_MODE_DIRECT)
+             return false;
+
         return true;
     }
     return false;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4db981d..327f3f9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -677,6 +677,7 @@ struct _virDomainDiskSourcePoolDef {
     char *pool; /* pool name */
     char *volume; /* volume name */
     int voltype; /* enum virStorageVolType, internal only */
+    int pooltype; /* enum virStoragePoolType, internal only */
     int mode; /* enum virDomainDiskSourcePoolMode */
 };
 typedef virDomainDiskSourcePoolDef *virDomainDiskSourcePoolDefPtr;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 5265f77..4e4ee9e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3214,7 +3214,20 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
                                      "block type volume"));
                     goto error;
                 }
-                virBufferEscape(&opt, ',', ",", "file=%s,", disk->src);
+
+                if (disk->srcpool->pooltype == VIR_STORAGE_POOL_ISCSI) {
+                    if (disk->srcpool->mode ==
+                        VIR_DOMAIN_DISK_SOURCE_POOL_MODE_DIRECT) {
+                        if (qemuBuildISCSIString(conn, disk, &opt) < 0)
+                            goto error;
+                        virBufferAddChar(&opt, ',');
+                    } else if (disk->srcpool->mode ==
+                               VIR_DOMAIN_DISK_SOURCE_POOL_MODE_HOST) {
+                        virBufferEscape(&opt, ',', ",", "file=%s,", disk->src);
+                    }
+                } else {
+                    virBufferEscape(&opt, ',', ",", "file=%s,", disk->src);
+                }
                 break;
             case VIR_STORAGE_VOL_FILE:
                 virBufferEscape(&opt, ',', ",", "file=%s,", disk->src);
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 332b9f2..6e6163f 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1125,12 +1125,75 @@ int qemuDriverAllocateID(virQEMUDriverPtr driver)
     return virAtomicIntInc(&driver->nextvmid);
 }
 
+static int
+qemuAddISCSIPoolSourceHost(virDomainDiskDefPtr def,
+                           virStoragePoolDefPtr pooldef)
+{
+    int ret = -1;
+    char **tokens = NULL;
+
+    /* Only support one host */
+    if (pooldef->source.nhost != 1) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Expected exactly 1 host for the storage pool"));
+        goto cleanup;
+    }
+
+    /* iscsi pool only supports one host */
+    def->nhosts = 1;
+
+    if (VIR_ALLOC_N(def->hosts, def->nhosts) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(def->hosts[0].name, pooldef->source.hosts[0].name) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&def->hosts[0].port, "%d",
+                    pooldef->source.hosts[0].port ?
+                    pooldef->source.hosts[0].port :
+                    3260) < 0)
+        goto cleanup;
+
+    /* iscsi volume has name like "unit:0:0:1" */
+    if (!(tokens = virStringSplit(def->srcpool->volume, ":", 0)))
+        goto cleanup;
+
+    if (virStringListLength(tokens) != 4) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unexpected iscsi volume name '%s'"),
+                       def->srcpool->volume);
+        goto cleanup;
+    }
+
+    /* iscsi pool has only one source device path */
+    if (virAsprintf(&def->src, "%s/%s",
+                    pooldef->source.devices[0].path,
+                    tokens[3]) < 0)
+        goto cleanup;
+
+    /* Storage pool have not supported these 2 attributes yet,
+     * use the defaults.
+     */
+    def->hosts[0].transport = VIR_DOMAIN_DISK_PROTO_TRANS_TCP;
+    def->hosts[0].socket = NULL;
+
+    def->protocol = VIR_DOMAIN_DISK_PROTOCOL_ISCSI;
+
+    ret = 0;
+
+cleanup:
+    virStringFreeList(tokens);
+    return ret;
+}
+
 int
 qemuTranslateDiskSourcePool(virConnectPtr conn,
                             virDomainDiskDefPtr def)
 {
+    virStoragePoolDefPtr pooldef = NULL;
     virStoragePoolPtr pool = NULL;
     virStorageVolPtr vol = NULL;
+    char *poolxml = NULL;
     virStorageVolInfo info;
     int ret = -1;
 
@@ -1158,11 +1221,45 @@ qemuTranslateDiskSourcePool(virConnectPtr conn,
 
     switch (info.type) {
     case VIR_STORAGE_VOL_FILE:
-    case VIR_STORAGE_VOL_BLOCK:
     case VIR_STORAGE_VOL_DIR:
         if (!(def->src = virStorageVolGetPath(vol)))
             goto cleanup;
         break;
+    case VIR_STORAGE_VOL_BLOCK:
+        if (!(poolxml = virStoragePoolGetXMLDesc(pool, 0)))
+            goto cleanup;
+
+        if (!(pooldef = virStoragePoolDefParseString(poolxml)))
+            goto cleanup;
+
+        if (def->srcpool->mode && pooldef->type != VIR_STORAGE_POOL_ISCSI) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("disk source mode is only valid when "
+                             "storage pool is of iscsi type"));
+            goto cleanup;
+        }
+
+        def->srcpool->pooltype = pooldef->type;
+        if (pooldef->type == VIR_STORAGE_POOL_ISCSI) {
+            /* Default to use the LUN's path on host */
+            if (!def->srcpool->mode)
+                def->srcpool->mode = VIR_DOMAIN_DISK_SOURCE_POOL_MODE_HOST;
+
+            if (def->srcpool->mode ==
+                VIR_DOMAIN_DISK_SOURCE_POOL_MODE_DIRECT) {
+                if (qemuAddISCSIPoolSourceHost(def, pooldef) < 0)
+                    goto cleanup;
+            } else if (def->srcpool->mode ==
+                       VIR_DOMAIN_DISK_SOURCE_POOL_MODE_HOST) {
+                if (!(def->src = virStorageVolGetPath(vol)))
+                    goto cleanup;
+            }
+        } else {
+            if (!(def->src = virStorageVolGetPath(vol)))
+                goto cleanup;
+        }
+
+        break;
     case VIR_STORAGE_VOL_NETWORK:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("Using network volume as disk source is not supported"));
@@ -1174,5 +1271,7 @@ qemuTranslateDiskSourcePool(virConnectPtr conn,
 cleanup:
     virStoragePoolFree(pool);
     virStorageVolFree(vol);
+    VIR_FREE(poolxml);
+    virStoragePoolDefFree(pooldef);
     return ret;
 }
-- 
1.8.1.4




More information about the libvir-list mailing list