c401cc
From 3ab4cf9a2038e1093495ed380cff1c074f702de6 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <3ab4cf9a2038e1093495ed380cff1c074f702de6@dist-git>
c401cc
From: Peter Krempa <pkrempa@redhat.com>
c401cc
Date: Wed, 26 Feb 2014 14:54:54 +0100
c401cc
Subject: [PATCH] qemu: Refactor qemuTranslateDiskSourcePool
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
c401cc
c401cc
Before this patch, the translation function still needs a second ugly
c401cc
helper function to actually format the command line for qemu. But if we
c401cc
do the right stuff in the translation function, we don't have to bother
c401cc
with the second function any more.
c401cc
c401cc
This patch removes the messy qemuBuildVolumeString function and changes
c401cc
qemuTranslateDiskSourcePool to set stuff up correctly so that the
c401cc
regular code paths meant for volumes can be used to format the command
c401cc
line correctly.
c401cc
c401cc
For this purpose a new helper "qemuDiskGetActualType()" is introduced to
c401cc
return the type of the volume in a pool.
c401cc
c401cc
As a part of the refactor the qemuTranslateDiskSourcePool function is
c401cc
fixed to do decisions based on the pool type instead of the volume type.
c401cc
This allows to separate pool-type-specific stuff more clearly and will
c401cc
ease addition of other pool types that will require certain other
c401cc
operations to get the correct pool source.
c401cc
c401cc
The previously fixed tests should make sure that we don't break stuff
c401cc
that was working before.
c401cc
c401cc
(cherry picked from commit e1a4d08baf9a8cc86c8b5ca27da9aeedb34b5908)
c401cc
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/conf/domain_conf.h   |   1 +
c401cc
 src/libvirt_private.syms |   1 +
c401cc
 src/qemu/qemu_command.c  |  81 ++++------------------------
c401cc
 src/qemu/qemu_conf.c     | 136 ++++++++++++++++++++++++++++++++++-------------
c401cc
 src/qemu/qemu_conf.h     |   2 +
c401cc
 5 files changed, 112 insertions(+), 109 deletions(-)
c401cc
c401cc
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
c401cc
index ff44a5d..4e6d4e7 100644
c401cc
--- a/src/conf/domain_conf.h
c401cc
+++ b/src/conf/domain_conf.h
c401cc
@@ -691,6 +691,7 @@ struct _virDomainDiskSourcePoolDef {
c401cc
     char *volume; /* volume name */
c401cc
     int voltype; /* enum virStorageVolType, internal only */
c401cc
     int pooltype; /* enum virStoragePoolType, internal only */
c401cc
+    int actualtype; /* enum virDomainDiskType, internal only */
c401cc
     int mode; /* enum virDomainDiskSourcePoolMode */
c401cc
 };
c401cc
 typedef virDomainDiskSourcePoolDef *virDomainDiskSourcePoolDefPtr;
c401cc
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
c401cc
index 0650a61..7df7e73 100644
c401cc
--- a/src/libvirt_private.syms
c401cc
+++ b/src/libvirt_private.syms
c401cc
@@ -691,6 +691,7 @@ virStoragePoolSourceFree;
c401cc
 virStoragePoolSourceListFormat;
c401cc
 virStoragePoolSourceListNewSource;
c401cc
 virStoragePoolTypeFromString;
c401cc
+virStoragePoolTypeToString;
c401cc
 virStorageVolDefFindByKey;
c401cc
 virStorageVolDefFindByName;
c401cc
 virStorageVolDefFindByPath;
c401cc
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
c401cc
index 4305052..2338b12 100644
c401cc
--- a/src/qemu/qemu_command.c
c401cc
+++ b/src/qemu/qemu_command.c
c401cc
@@ -3696,69 +3696,6 @@ qemuBuildNBDString(virConnectPtr conn, virDomainDiskDefPtr disk, virBufferPtr op
c401cc
     return 0;
c401cc
 }
c401cc
 
c401cc
-static int
c401cc
-qemuBuildVolumeString(virConnectPtr conn,
c401cc
-                      virDomainDiskDefPtr disk,
c401cc
-                      virBufferPtr opt)
c401cc
-{
c401cc
-    int ret = -1;
c401cc
-
c401cc
-    switch ((virStorageVolType) disk->srcpool->voltype) {
c401cc
-    case VIR_STORAGE_VOL_DIR:
c401cc
-        if (!disk->readonly) {
c401cc
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c401cc
-                           _("cannot create virtual FAT disks in read-write mode"));
c401cc
-            goto cleanup;
c401cc
-        }
c401cc
-        if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
c401cc
-            virBufferEscape(opt, ',', ",", "file=fat:floppy:%s,", disk->src);
c401cc
-        else
c401cc
-            virBufferEscape(opt, ',', ",", "file=fat:%s,", disk->src);
c401cc
-        break;
c401cc
-    case VIR_STORAGE_VOL_BLOCK:
c401cc
-        if (disk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN) {
c401cc
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
c401cc
-                           _("tray status 'open' is invalid for "
c401cc
-                             "block type volume"));
c401cc
-            goto cleanup;
c401cc
-        }
c401cc
-        if (disk->srcpool->pooltype == VIR_STORAGE_POOL_ISCSI) {
c401cc
-            if (disk->srcpool->mode ==
c401cc
-                VIR_DOMAIN_DISK_SOURCE_POOL_MODE_DIRECT) {
c401cc
-                if (qemuBuildISCSIString(conn, disk, opt) < 0)
c401cc
-                    goto cleanup;
c401cc
-                virBufferAddChar(opt, ',');
c401cc
-            } else if (disk->srcpool->mode ==
c401cc
-                       VIR_DOMAIN_DISK_SOURCE_POOL_MODE_HOST) {
c401cc
-                virBufferEscape(opt, ',', ",", "file=%s,", disk->src);
c401cc
-            }
c401cc
-        } else {
c401cc
-            virBufferEscape(opt, ',', ",", "file=%s,", disk->src);
c401cc
-        }
c401cc
-        break;
c401cc
-    case VIR_STORAGE_VOL_FILE:
c401cc
-        if (disk->auth.username) {
c401cc
-            if (qemuBuildISCSIString(conn, disk, opt) < 0)
c401cc
-                goto cleanup;
c401cc
-            virBufferAddChar(opt, ',');
c401cc
-        } else {
c401cc
-            virBufferEscape(opt, ',', ",", "file=%s,", disk->src);
c401cc
-        }
c401cc
-        break;
c401cc
-    case VIR_STORAGE_VOL_NETWORK:
c401cc
-    case VIR_STORAGE_VOL_NETDIR:
c401cc
-    case VIR_STORAGE_VOL_LAST:
c401cc
-        /* Keep the compiler quiet, qemuTranslateDiskSourcePool already
c401cc
-         * reported the unsupported error.
c401cc
-         */
c401cc
-        goto cleanup;
c401cc
-    }
c401cc
-
c401cc
-    ret = 0;
c401cc
-
c401cc
-cleanup:
c401cc
-    return ret;
c401cc
-}
c401cc
 
c401cc
 char *
c401cc
 qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
c401cc
@@ -3772,6 +3709,7 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
c401cc
         virDomainDiskGeometryTransTypeToString(disk->geometry.trans);
c401cc
     int idx = virDiskNameToIndex(disk->dst);
c401cc
     int busid = -1, unitid = -1;
c401cc
+    int actualType = qemuDiskGetActualType(disk);
c401cc
 
c401cc
     if (idx < 0) {
c401cc
         virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
@@ -3853,12 +3791,13 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
c401cc
 
c401cc
     /* disk->src is NULL when we use nbd disks */
c401cc
     if ((disk->src ||
c401cc
-        (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
c401cc
+        (actualType == VIR_DOMAIN_DISK_TYPE_NETWORK &&
c401cc
          disk->protocol == VIR_DOMAIN_DISK_PROTOCOL_NBD)) &&
c401cc
         !((disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY ||
c401cc
            disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
c401cc
           disk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN)) {
c401cc
-        if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
c401cc
+
c401cc
+        if (actualType == VIR_DOMAIN_DISK_TYPE_DIR) {
c401cc
             /* QEMU only supports magic FAT format for now */
c401cc
             if (disk->format > 0 && disk->format != VIR_STORAGE_FILE_FAT) {
c401cc
                 virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
@@ -3876,7 +3815,7 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
c401cc
                                 disk->src);
c401cc
             else
c401cc
                 virBufferEscape(&opt, ',', ",", "file=fat:%s,", disk->src);
c401cc
-        } else if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
c401cc
+        } else if (actualType == VIR_DOMAIN_DISK_TYPE_NETWORK) {
c401cc
             switch (disk->protocol) {
c401cc
             case VIR_DOMAIN_DISK_PROTOCOL_NBD:
c401cc
                 if (qemuBuildNBDString(conn, disk, &opt) < 0)
c401cc
@@ -3913,15 +3852,13 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
c401cc
                 }
c401cc
                 break;
c401cc
             }
c401cc
-        } else if (disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME) {
c401cc
-            if (qemuBuildVolumeString(conn, disk, &opt) < 0)
c401cc
-                goto error;
c401cc
         } else {
c401cc
-            if ((disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK) &&
c401cc
+            if ((actualType == VIR_DOMAIN_DISK_TYPE_BLOCK) &&
c401cc
                 (disk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN)) {
c401cc
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
c401cc
-                               _("tray status 'open' is invalid for "
c401cc
-                                 "block type disk"));
c401cc
+                               disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME ?
c401cc
+                               _("tray status 'open' is invalid for block type volume") :
c401cc
+                               _("tray status 'open' is invalid for block type disk"));
c401cc
                 goto error;
c401cc
             }
c401cc
             virBufferEscape(&opt, ',', ",", "file=%s,", disk->src);
c401cc
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
c401cc
index eb20228..0908547 100644
c401cc
--- a/src/qemu/qemu_conf.c
c401cc
+++ b/src/qemu/qemu_conf.c
c401cc
@@ -1267,6 +1267,17 @@ cleanup:
c401cc
     return ret;
c401cc
 }
c401cc
 
c401cc
+
c401cc
+int
c401cc
+qemuDiskGetActualType(virDomainDiskDefPtr def)
c401cc
+{
c401cc
+    if (def->type == VIR_DOMAIN_DISK_TYPE_VOLUME)
c401cc
+        return def->srcpool->actualtype;
c401cc
+
c401cc
+    return def->type;
c401cc
+}
c401cc
+
c401cc
+
c401cc
 int
c401cc
 qemuTranslateDiskSourcePool(virConnectPtr conn,
c401cc
                             virDomainDiskDefPtr def)
c401cc
@@ -1288,72 +1299,123 @@ qemuTranslateDiskSourcePool(virConnectPtr conn,
c401cc
     if (!(pool = virStoragePoolLookupByName(conn, def->srcpool->pool)))
c401cc
         return -1;
c401cc
 
c401cc
+    if (virStoragePoolIsActive(pool) != 1) {
c401cc
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
c401cc
+                       _("storage pool '%s' containing volume '%s' "
c401cc
+                         "is not active"),
c401cc
+                       def->srcpool->pool, def->srcpool->volume);
c401cc
+        goto cleanup;
c401cc
+    }
c401cc
+
c401cc
     if (!(vol = virStorageVolLookupByName(pool, def->srcpool->volume)))
c401cc
         goto cleanup;
c401cc
 
c401cc
     if (virStorageVolGetInfo(vol, &info) < 0)
c401cc
         goto cleanup;
c401cc
 
c401cc
-    if (def->startupPolicy &&
c401cc
-        info.type != VIR_STORAGE_VOL_FILE) {
c401cc
+    if (!(poolxml = virStoragePoolGetXMLDesc(pool, 0)))
c401cc
+        goto cleanup;
c401cc
+
c401cc
+    if (!(pooldef = virStoragePoolDefParseString(poolxml)))
c401cc
+        goto cleanup;
c401cc
+
c401cc
+    def->srcpool->pooltype = pooldef->type;
c401cc
+    def->srcpool->voltype = info.type;
c401cc
+
c401cc
+    if (def->srcpool->mode && pooldef->type != VIR_STORAGE_POOL_ISCSI) {
c401cc
         virReportError(VIR_ERR_XML_ERROR, "%s",
c401cc
-                       _("'startupPolicy' is only valid for 'file' type volume"));
c401cc
+                       _("disk source mode is only valid when "
c401cc
+                         "storage pool is of iscsi type"));
c401cc
         goto cleanup;
c401cc
     }
c401cc
 
c401cc
-    switch ((virStorageVolType) info.type) {
c401cc
-    case VIR_STORAGE_VOL_FILE:
c401cc
-    case VIR_STORAGE_VOL_DIR:
c401cc
+    switch ((enum virStoragePoolType) pooldef->type) {
c401cc
+    case VIR_STORAGE_POOL_DIR:
c401cc
+    case VIR_STORAGE_POOL_FS:
c401cc
+    case VIR_STORAGE_POOL_NETFS:
c401cc
+    case VIR_STORAGE_POOL_LOGICAL:
c401cc
+    case VIR_STORAGE_POOL_DISK:
c401cc
+    case VIR_STORAGE_POOL_SCSI:
c401cc
         if (!(def->src = virStorageVolGetPath(vol)))
c401cc
             goto cleanup;
c401cc
-        break;
c401cc
-    case VIR_STORAGE_VOL_BLOCK:
c401cc
-        if (!(poolxml = virStoragePoolGetXMLDesc(pool, 0)))
c401cc
+
c401cc
+        if (def->startupPolicy && info.type != VIR_STORAGE_VOL_FILE) {
c401cc
+            virReportError(VIR_ERR_XML_ERROR, "%s",
c401cc
+                           _("'startupPolicy' is only valid for "
c401cc
+                             "'file' type volume"));
c401cc
             goto cleanup;
c401cc
+        }
c401cc
+
c401cc
+
c401cc
+        switch (info.type) {
c401cc
+        case VIR_STORAGE_VOL_FILE:
c401cc
+            def->srcpool->actualtype = VIR_DOMAIN_DISK_TYPE_FILE;
c401cc
+            break;
c401cc
+
c401cc
+        case VIR_STORAGE_VOL_DIR:
c401cc
+            def->srcpool->actualtype = VIR_DOMAIN_DISK_TYPE_DIR;
c401cc
+            break;
c401cc
+
c401cc
+        case VIR_STORAGE_VOL_BLOCK:
c401cc
+            def->srcpool->actualtype = VIR_DOMAIN_DISK_TYPE_BLOCK;
c401cc
+            break;
c401cc
 
c401cc
-        if (!(pooldef = virStoragePoolDefParseString(poolxml)))
c401cc
+        case VIR_STORAGE_VOL_NETWORK:
c401cc
+        case VIR_STORAGE_VOL_NETDIR:
c401cc
+            virReportError(VIR_ERR_INTERNAL_ERROR,
c401cc
+                           _("unexpected storage volume type '%s' "
c401cc
+                             "for storage pool type '%s'"),
c401cc
+                           virStorageVolTypeToString(info.type),
c401cc
+                           virStoragePoolTypeToString(pooldef->type));
c401cc
             goto cleanup;
c401cc
+        }
c401cc
+
c401cc
+        break;
c401cc
 
c401cc
-        if (def->srcpool->mode && pooldef->type != VIR_STORAGE_POOL_ISCSI) {
c401cc
+    case VIR_STORAGE_POOL_ISCSI:
c401cc
+        if (def->startupPolicy) {
c401cc
             virReportError(VIR_ERR_XML_ERROR, "%s",
c401cc
-                           _("disk source mode is only valid when "
c401cc
-                             "storage pool is of iscsi type"));
c401cc
+                           _("'startupPolicy' is only valid for "
c401cc
+                             "'file' type volume"));
c401cc
             goto cleanup;
c401cc
         }
c401cc
 
c401cc
-        def->srcpool->pooltype = pooldef->type;
c401cc
-        if (pooldef->type == VIR_STORAGE_POOL_ISCSI) {
c401cc
-            /* Default to use the LUN's path on host */
c401cc
-            if (!def->srcpool->mode)
c401cc
-                def->srcpool->mode = VIR_DOMAIN_DISK_SOURCE_POOL_MODE_HOST;
c401cc
-
c401cc
-            if (def->srcpool->mode ==
c401cc
-                VIR_DOMAIN_DISK_SOURCE_POOL_MODE_DIRECT) {
c401cc
-                if (qemuAddISCSIPoolSourceHost(def, pooldef) < 0)
c401cc
-                    goto cleanup;
c401cc
-            } else if (def->srcpool->mode ==
c401cc
-                       VIR_DOMAIN_DISK_SOURCE_POOL_MODE_HOST) {
c401cc
-                if (!(def->src = virStorageVolGetPath(vol)))
c401cc
-                    goto cleanup;
c401cc
-            }
c401cc
+       switch (def->srcpool->mode) {
c401cc
+        case VIR_DOMAIN_DISK_SOURCE_POOL_MODE_DEFAULT:
c401cc
+        case VIR_DOMAIN_DISK_SOURCE_POOL_MODE_LAST:
c401cc
+            def->srcpool->mode = VIR_DOMAIN_DISK_SOURCE_POOL_MODE_HOST;
c401cc
+            /* fallthrough */
c401cc
+        case VIR_DOMAIN_DISK_SOURCE_POOL_MODE_HOST:
c401cc
+            def->srcpool->actualtype = VIR_DOMAIN_DISK_TYPE_BLOCK;
c401cc
+            if (!(def->src = virStorageVolGetPath(vol)))
c401cc
+                goto cleanup;
c401cc
+            break;
c401cc
+
c401cc
+        case VIR_DOMAIN_DISK_SOURCE_POOL_MODE_DIRECT:
c401cc
+            def->srcpool->actualtype = VIR_DOMAIN_DISK_TYPE_NETWORK;
c401cc
+            def->protocol = VIR_DOMAIN_DISK_PROTOCOL_ISCSI;
c401cc
 
c401cc
             if (qemuTranslateDiskSourcePoolAuth(def, pooldef) < 0)
c401cc
                 goto cleanup;
c401cc
-        } else {
c401cc
-            if (!(def->src = virStorageVolGetPath(vol)))
c401cc
+
c401cc
+            if (qemuAddISCSIPoolSourceHost(def, pooldef) < 0)
c401cc
                 goto cleanup;
c401cc
+            break;
c401cc
         }
c401cc
-
c401cc
         break;
c401cc
-    case VIR_STORAGE_VOL_NETWORK:
c401cc
-    case VIR_STORAGE_VOL_NETDIR:
c401cc
-    case VIR_STORAGE_VOL_LAST:
c401cc
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
c401cc
-                       _("Using network volume as disk source is not supported"));
c401cc
+
c401cc
+    case VIR_STORAGE_POOL_MPATH:
c401cc
+    case VIR_STORAGE_POOL_RBD:
c401cc
+    case VIR_STORAGE_POOL_SHEEPDOG:
c401cc
+    case VIR_STORAGE_POOL_GLUSTER:
c401cc
+    case VIR_STORAGE_POOL_LAST:
c401cc
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
c401cc
+                       _("using '%s' pools for backing 'volume' disks "
c401cc
+                         "isn't yet supported"),
c401cc
+                       virStoragePoolTypeToString(pooldef->type));
c401cc
         goto cleanup;
c401cc
     }
c401cc
 
c401cc
-    def->srcpool->voltype = info.type;
c401cc
     ret = 0;
c401cc
 cleanup:
c401cc
     if (ret < 0)
c401cc
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
c401cc
index e03be95..b90c563 100644
c401cc
--- a/src/qemu/qemu_conf.h
c401cc
+++ b/src/qemu/qemu_conf.h
c401cc
@@ -300,6 +300,8 @@ int qemuSetUnprivSGIO(virDomainDeviceDefPtr dev);
c401cc
 int qemuDriverAllocateID(virQEMUDriverPtr driver);
c401cc
 virDomainXMLOptionPtr virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver);
c401cc
 
c401cc
+int qemuDiskGetActualType(virDomainDiskDefPtr def);
c401cc
+
c401cc
 int qemuTranslateDiskSourcePool(virConnectPtr conn,
c401cc
                                 virDomainDiskDefPtr def);
c401cc
 
c401cc
-- 
c401cc
1.9.0
c401cc