]> xenbits.xensource.com Git - libvirt.git/commitdiff
storage: Add mixed fc_host/scsi_host duplicate adapter source checks
authorJohn Ferlan <jferlan@redhat.com>
Fri, 14 Nov 2014 14:50:59 +0000 (09:50 -0500)
committerJohn Ferlan <jferlan@redhat.com>
Mon, 1 Dec 2014 15:04:25 +0000 (10:04 -0500)
https://bugzilla.redhat.com/show_bug.cgi?id=1159180

The virStoragePoolSourceFindDuplicate only checks the incoming definition
against the same type of pool as the def; however, for "scsi_host" and
"fc_host" adapter pools, it's possible that either some pool "scsi_host"
adapter definition is already using the scsi_hostN that the "fc_host"
adapter definition wants to use or some "fc_host" pool adapter definition
is using a vHBA scsi_hostN or parent scsi_hostN that an incoming "scsi_host"
definition is trying to use.

This patch adds the mismatched type checks and adds extraneous comments
to describe what each check is determining.

This patch also modifies the documentation to be describe what scsi_hostN
devices a "scsi_host" source adapter should use and which to avoid. It also
updates the parent definition to specifically call out that for mixed
environments it's better to define which parent to use so that the duplicate
pool checks can be done properly.

docs/formatstorage.html.in
src/conf/storage_conf.c
src/conf/storage_conf.h
src/parallels/parallels_storage.c
src/storage/storage_driver.c

index 29c193108f407bdb50ede47d489b371797b31ae2..de786b874cdc59f1ee3f28fd7413bed8d17c45bb 100644 (file)
             compatibility, this attribute is optional <b>only</b> for the
             "scsi_host" adapter, but is mandatory for the "fc_host" adapter.
             <span class="since">Since 1.0.5</span>
+            A "fc_host" capable scsi_hostN can be determined by using
+            <code>virsh nodedev-list --cap fc_host</code>.
+            <span class="since">Since 1.2.8</span>
+            <p>
+            Note: Regardless of whether a "scsi_host" adapter type is defined
+            using a <code>name</code> or a <code>parentaddr</code>, it
+            should refer to a real scsi_host adapter as found through a
+            <code>virsh nodedev-list scsi_host</code> and <code>virsh
+            nodedev-dumpxml scsi_hostN</code> on one of the scsi_host's
+            displayed. It should not refer to a "fc_host" capable scsi_hostN
+            nor should it refer to the vHBA created for some "fc_host"
+            adapter. For a vHBA the <code>nodedev-dumpxml</code>
+            output parent setting will be the "fc_host" capable scsi_hostN
+            value. Additionally, do not refer to an iSCSI scsi_hostN for the
+            "scsi_host" source. An iSCSI scsi_hostN's
+            <code>nodedev-dumpxml</code> output parent field is generally
+            "computer". This is a libvirt created parent value indicating
+            no parent was defined for the node device.
+            </p>
             </dd>
         </dl>
         <dl>
             the vHBA created by 'virsh nodedev-create', rather it is
             the parent of that vHBA. If the value is not provided, libvirt
             will determine the parent based either finding the wwnn,wwpn
-            defined for an existing scsi_host or by creating a vHBA.
+            defined for an existing scsi_host or by creating a vHBA. Providing
+            the parent attribute is also useful for the duplicate pool
+            definition checks. This is more important in environments where
+            both the "fc_host" and "scsi_host" source adapter pools are being
+            used in order to ensure a new definition doesn't duplicate using
+            the scsi_hostN of some existing storage pool.
             <span class="since">Since 1.0.4</span>
           </dd>
           <dt><code>managed</code></dt>
index a76d48a26cae434d1aefc8ca1b04b418b3122414..f75e862e0d7d550eeb5c987befab9564a1d51e0f 100644 (file)
@@ -2169,6 +2169,83 @@ getSCSIHostNumber(virStoragePoolSourceAdapter adapter,
     VIR_FREE(name);
     return ret;
 }
+
+/*
+ * matchFCHostToSCSIHost:
+ *
+ * @conn: Connection pointer
+ * @fc_adapter: fc_host adapter (either def or pool->def)
+ * @scsi_hostnum: Already determined "scsi_pool" hostnum
+ *
+ * Returns true/false whether there is a match between the incoming
+ *         fc_adapter host# and the scsi_host host#
+ */
+static bool
+matchFCHostToSCSIHost(virConnectPtr conn,
+                      virStoragePoolSourceAdapter fc_adapter,
+                      unsigned int scsi_hostnum)
+{
+    char *name = NULL;
+    char *parent_name = NULL;
+    unsigned int fc_hostnum;
+
+    /* If we have a parent defined, get it's hostnum, and compare to the
+     * scsi_hostnum. If they are the same, then we have a match
+     */
+    if (fc_adapter.data.fchost.parent &&
+        virGetSCSIHostNumber(fc_adapter.data.fchost.parent, &fc_hostnum) == 0 &&
+        scsi_hostnum == fc_hostnum)
+        return true;
+
+    /* If we find an fc_adapter name, then either libvirt created a vHBA
+     * for this fc_host or a 'virsh nodedev-create' generated a vHBA.
+     */
+    if ((name = virGetFCHostNameByWWN(NULL, fc_adapter.data.fchost.wwnn,
+                                      fc_adapter.data.fchost.wwpn))) {
+
+        /* Get the scsi_hostN for the vHBA in order to see if it
+         * matches our scsi_hostnum
+         */
+        if (virGetSCSIHostNumber(name, &fc_hostnum) == 0 &&
+            scsi_hostnum == fc_hostnum) {
+            VIR_FREE(name);
+            return true;
+        }
+
+        /* We weren't provided a parent, so we have to query the node
+         * device driver in order to ascertain the parent of the vHBA.
+         * If the parent fc_hostnum is the same as the scsi_hostnum, we
+         * have a match.
+         */
+        if (conn && !fc_adapter.data.fchost.parent) {
+            parent_name = virStoragePoolGetVhbaSCSIHostParent(conn, name);
+            if (parent_name) {
+                if (virGetSCSIHostNumber(parent_name, &fc_hostnum) == 0 &&
+                    scsi_hostnum == fc_hostnum) {
+                    VIR_FREE(parent_name);
+                    VIR_FREE(name);
+                    return true;
+                }
+                VIR_FREE(parent_name);
+            } else {
+                /* Throw away the error and fall through */
+                virResetLastError();
+                VIR_DEBUG("Could not determine parent vHBA");
+            }
+        }
+        VIR_FREE(name);
+    }
+
+    /* NB: Lack of a name means that this vHBA hasn't yet been created,
+     *     which means our scsi_host cannot be using the vHBA. Furthermore,
+     *     lack of a provided parent means libvirt is going to choose the
+     *     "best" fc_host capable adapter based on availabilty. That could
+     *     conflict with an existing scsi_host definition, but there's no
+     *     way to know that now.
+     */
+    return false;
+}
+
 static bool
 matchSCSIAdapterParent(virStoragePoolObjPtr pool,
                        virStoragePoolDefPtr def)
@@ -2193,7 +2270,8 @@ matchSCSIAdapterParent(virStoragePoolObjPtr pool,
 
 
 int
-virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools,
+virStoragePoolSourceFindDuplicate(virConnectPtr conn,
+                                  virStoragePoolObjListPtr pools,
                                   virStoragePoolDefPtr def)
 {
     size_t i;
@@ -2253,6 +2331,38 @@ virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools,
                     break;
                 if (pool_hostnum == def_hostnum)
                     matchpool = pool;
+            } else if (pool->def->source.adapter.type ==
+                       VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST &&
+                       def->source.adapter.type ==
+                       VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
+                unsigned int scsi_hostnum;
+
+                /* Get the scsi_hostN for the scsi_host source adapter def */
+                if (getSCSIHostNumber(def->source.adapter,
+                                      &scsi_hostnum) < 0)
+                    break;
+
+                if (matchFCHostToSCSIHost(conn, pool->def->source.adapter,
+                                          scsi_hostnum)) {
+                    matchpool = pool;
+                    break;
+                }
+
+            } else if (pool->def->source.adapter.type ==
+                       VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST &&
+                       def->source.adapter.type ==
+                       VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
+                unsigned int scsi_hostnum;
+
+                if (getSCSIHostNumber(pool->def->source.adapter,
+                                      &scsi_hostnum) < 0)
+                    break;
+
+                if (matchFCHostToSCSIHost(conn, def->source.adapter,
+                                          scsi_hostnum)) {
+                    matchpool = pool;
+                    break;
+                }
             }
             break;
         case VIR_STORAGE_POOL_ISCSI:
index 228bb1c39e2bc445c5b6b6c2488fe83ebc2766bf..2c9eaedebc4e6893de93bc4e1d9e8abb83d8850a 100644 (file)
@@ -394,7 +394,8 @@ char *virStoragePoolGetVhbaSCSIHostParent(virConnectPtr conn,
                                           const char *name)
     ATTRIBUTE_NONNULL(1);
 
-int virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools,
+int virStoragePoolSourceFindDuplicate(virConnectPtr conn,
+                                      virStoragePoolObjListPtr pools,
                                       virStoragePoolDefPtr def);
 
 void virStoragePoolObjLock(virStoragePoolObjPtr obj);
index e1b6ea89eec276adca3c529fc6792c5942201b30..4a16325dc087422f046b778188204d4a432da6d1 100644 (file)
@@ -719,7 +719,7 @@ parallelsStoragePoolDefineXML(virConnectPtr conn,
     if (virStoragePoolObjIsDuplicate(&privconn->pools, def, 0) < 0)
         goto cleanup;
 
-    if (virStoragePoolSourceFindDuplicate(&privconn->pools, def) < 0)
+    if (virStoragePoolSourceFindDuplicate(conn, &privconn->pools, def) < 0)
         goto cleanup;
 
     if (parallelsStoragePoolGetAlloc(def))
index 23b63f540e13e79d5f7f7e20956c311c8c3526db..88dea3457a7b85f28fc76fc33cfaae251f1d553d 100644 (file)
@@ -610,7 +610,7 @@ storagePoolCreateXML(virConnectPtr conn,
     if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
         goto cleanup;
 
-    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
+    if (virStoragePoolSourceFindDuplicate(conn, &driver->pools, def) < 0)
         goto cleanup;
 
     if ((backend = virStorageBackendForType(def->type)) == NULL)
@@ -669,7 +669,7 @@ storagePoolDefineXML(virConnectPtr conn,
     if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
         goto cleanup;
 
-    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
+    if (virStoragePoolSourceFindDuplicate(conn, &driver->pools, def) < 0)
         goto cleanup;
 
     if (virStorageBackendForType(def->type) == NULL)