render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
9119d9
From fc7567b997f6cee3cce2ce291992706ede61b9c3 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <fc7567b997f6cee3cce2ce291992706ede61b9c3@dist-git>
9119d9
From: John Ferlan <jferlan@redhat.com>
9119d9
Date: Wed, 12 Nov 2014 13:34:50 -0500
9119d9
Subject: [PATCH] storage: Introduce 'managed' for the fchost parent
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1160926
9119d9
9119d9
Introduce a 'managed' attribute to allow libvirt to decide whether to
9119d9
delete a vHBA vport created via external means such as nodedev-create.
9119d9
The code currently decides whether to delete the vHBA based solely on
9119d9
whether the parent was provided at creation time. However, that may not
9119d9
be the desired action, so rather than delete and force someone to create
9119d9
another vHBA via an additional nodedev-create allow the configuration of
9119d9
the storage pool to decide the desired action.
9119d9
9119d9
During createVport when libvirt does the VPORT_CREATE, set the managed
9119d9
value to YES if not already set to indicate to the deleteVport code that
9119d9
it should delete the vHBA when the pool is destroyed.
9119d9
9119d9
If libvirtd is restarted all the memory only state was lost, so for a
9119d9
persistent storage pool, use the virStoragePoolSaveConfig in order to
9119d9
write out the managed value.
9119d9
9119d9
Because we're now saving the current configuration, we need to be sure
9119d9
to not save the parent in the output XML if it was undefined at start.
9119d9
Saving the name would cause future starts to always use the same parent
9119d9
which is not the expected result when not providing a parent. By not
9119d9
providing a parent, libvirt is expected to find the best available
9119d9
vHBA port for each subsequent (re)start.
9119d9
9119d9
At deleteVport, use the new managed value to decide whether to execute
9119d9
the VPORT_DELETE.  Since we no longer save the parent in memory or in
9119d9
XML when provided, if it was not provided, then we have to look it up.
9119d9
9119d9
(cherry picked from commit 5530f248db4974379f584eab5ad73dd20cf05de7)
9119d9
Signed-off-by: John Ferlan <jferlan@redhat.com>
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 docs/formatstorage.html.in                         | 13 ++++
9119d9
 docs/schemas/basictypes.rng                        |  5 ++
9119d9
 src/conf/storage_conf.c                            | 17 +++++
9119d9
 src/conf/storage_conf.h                            |  1 +
9119d9
 src/storage/storage_backend_scsi.c                 | 88 ++++++++++++++++++----
9119d9
 .../pool-scsi-type-fc-host-managed.xml             | 15 ++++
9119d9
 .../pool-scsi-type-fc-host-managed.xml             | 18 +++++
9119d9
 tests/storagepoolxml2xmltest.c                     |  1 +
9119d9
 8 files changed, 142 insertions(+), 16 deletions(-)
9119d9
 create mode 100644 tests/storagepoolxml2xmlin/pool-scsi-type-fc-host-managed.xml
9119d9
 create mode 100644 tests/storagepoolxml2xmlout/pool-scsi-type-fc-host-managed.xml
9119d9
9119d9
diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
9119d9
index 7872112..cb6393c 100644
9119d9
--- a/docs/formatstorage.html.in
9119d9
+++ b/docs/formatstorage.html.in
9119d9
@@ -189,6 +189,19 @@
9119d9
             defined for an existing scsi_host or by creating a vHBA.
9119d9
             Since 1.0.4
9119d9
           
9119d9
+          
managed
9119d9
+          
An optional attribute to instruct the SCSI storage backend to
9119d9
+            manage destroying the vHBA when the pool is destroyed. For
9119d9
+            configurations that do not provide an already created vHBA
9119d9
+            from a 'virsh nodedev-create', libvirt will set this property
9119d9
+            to "yes". For configurations that have already created a vHBA
9119d9
+            via 'virsh nodedev-create' and are using the wwnn/wwpn from
9119d9
+            that vHBA and optionally the scsi_host parent, setting this
9119d9
+            attribute to "yes" will allow libvirt to destroy the node device
9119d9
+            when the pool is destroyed. If this attribute is set to "no" or
9119d9
+            not defined in the XML, then libvirt will not destroy the vHBA.
9119d9
+            Since 1.2.11
9119d9
+          
9119d9
         
9119d9
         
9119d9
           
parentaddr
9119d9
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
9119d9
index 14245c9..9ddd92b 100644
9119d9
--- a/docs/schemas/basictypes.rng
9119d9
+++ b/docs/schemas/basictypes.rng
9119d9
@@ -389,6 +389,11 @@
9119d9
               <text/>
9119d9
             </attribute>
9119d9
           </optional>
9119d9
+          <optional>
9119d9
+            <attribute name='managed'>
9119d9
+              <ref name="virYesNo"/>
9119d9
+            </attribute>
9119d9
+          </optional>
9119d9
           <attribute name='wwnn'>
9119d9
             <ref name='wwn'/>
9119d9
           </attribute>
9119d9
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
9119d9
index 71e152f..9fd4601 100644
9119d9
--- a/src/conf/storage_conf.c
9119d9
+++ b/src/conf/storage_conf.c
9119d9
@@ -474,6 +474,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
9119d9
     char *name = NULL;
9119d9
     char *port = NULL;
9119d9
     char *adapter_type = NULL;
9119d9
+    char *managed = NULL;
9119d9
     int n;
9119d9
 
9119d9
     relnode = ctxt->node;
9119d9
@@ -577,6 +578,18 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
9119d9
             VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
9119d9
             source->adapter.data.fchost.parent =
9119d9
                 virXPathString("string(./adapter/@parent)", ctxt);
9119d9
+            managed = virXPathString("string(./adapter/@managed)", ctxt);
9119d9
+            if (managed) {
9119d9
+                source->adapter.data.fchost.managed =
9119d9
+                    virTristateBoolTypeFromString(managed);
9119d9
+                if (source->adapter.data.fchost.managed < 0) {
9119d9
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9119d9
+                                   _("unknown fc_host managed setting '%s'"),
9119d9
+                                   managed);
9119d9
+                    goto cleanup;
9119d9
+                }
9119d9
+            }
9119d9
+
9119d9
             source->adapter.data.fchost.wwnn =
9119d9
                 virXPathString("string(./adapter/@wwnn)", ctxt);
9119d9
             source->adapter.data.fchost.wwpn =
9119d9
@@ -674,6 +687,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
9119d9
     VIR_FREE(port);
9119d9
     VIR_FREE(nodeset);
9119d9
     VIR_FREE(adapter_type);
9119d9
+    VIR_FREE(managed);
9119d9
     virStorageAuthDefFree(authdef);
9119d9
     return ret;
9119d9
 }
9119d9
@@ -1075,6 +1089,9 @@ virStoragePoolSourceFormat(virBufferPtr buf,
9119d9
         if (src->adapter.type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
9119d9
             virBufferEscapeString(buf, " parent='%s'",
9119d9
                                   src->adapter.data.fchost.parent);
9119d9
+            if (src->adapter.data.fchost.managed)
9119d9
+                virBufferAsprintf(buf, " managed='%s'",
9119d9
+                                  virTristateBoolTypeToString(src->adapter.data.fchost.managed));
9119d9
             virBufferAsprintf(buf, " wwnn='%s' wwpn='%s'/>\n",
9119d9
                               src->adapter.data.fchost.wwnn,
9119d9
                               src->adapter.data.fchost.wwpn);
9119d9
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
9119d9
index 67145a0..765f681 100644
9119d9
--- a/src/conf/storage_conf.h
9119d9
+++ b/src/conf/storage_conf.h
9119d9
@@ -192,6 +192,7 @@ struct _virStoragePoolSourceAdapter {
9119d9
             char *parent;
9119d9
             char *wwnn;
9119d9
             char *wwpn;
9119d9
+            int managed;        /* enum virTristateSwitch */
9119d9
         } fchost;
9119d9
     } data;
9119d9
 };
9119d9
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
9119d9
index a5bb85f..3f61610 100644
9119d9
--- a/src/storage/storage_backend_scsi.c
9119d9
+++ b/src/storage/storage_backend_scsi.c
9119d9
@@ -590,6 +590,9 @@ getVhbaSCSIHostParent(virConnectPtr conn,
9119d9
     if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
9119d9
         goto cleanup;
9119d9
 
9119d9
+    /* The caller checks whether the returned value is NULL or not
9119d9
+     * before continuing
9119d9
+     */
9119d9
     ignore_value(VIR_STRDUP(vhba_parent, def->parent));
9119d9
 
9119d9
  cleanup:
9119d9
@@ -644,15 +647,21 @@ checkVhbaSCSIHostParent(virConnectPtr conn,
9119d9
 
9119d9
 static int
9119d9
 createVport(virConnectPtr conn,
9119d9
+            const char *configFile,
9119d9
             virStoragePoolDefPtr def)
9119d9
 {
9119d9
     virStoragePoolSourceAdapterPtr adapter = &def->source.adapter;
9119d9
     unsigned int parent_host;
9119d9
     char *name = NULL;
9119d9
+    char *parent_hoststr = NULL;
9119d9
 
9119d9
     if (adapter->type != VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST)
9119d9
         return 0;
9119d9
 
9119d9
+    VIR_DEBUG("conn=%p, configFile='%s' parent='%s', wwnn='%s' wwpn='%s'",
9119d9
+              conn, NULLSTR(configFile), NULLSTR(adapter->data.fchost.parent),
9119d9
+              adapter->data.fchost.wwnn, adapter->data.fchost.wwpn);
9119d9
+
9119d9
     /* If a parent was provided, then let's make sure it's vhost capable */
9119d9
     if (adapter->data.fchost.parent) {
9119d9
         if (virGetSCSIHostNumber(adapter->data.fchost.parent, &parent_host) < 0)
9119d9
@@ -687,15 +696,40 @@ createVport(virConnectPtr conn,
9119d9
     }
9119d9
 
9119d9
     if (!adapter->data.fchost.parent) {
9119d9
-        if (!(adapter->data.fchost.parent = virFindFCHostCapableVport(NULL))) {
9119d9
+        if (!(parent_hoststr = virFindFCHostCapableVport(NULL))) {
9119d9
             virReportError(VIR_ERR_XML_ERROR, "%s",
9119d9
                            _("'parent' for vHBA not specified, and "
9119d9
                              "cannot find one on this host"));
9119d9
             return -1;
9119d9
         }
9119d9
 
9119d9
-        if (virGetSCSIHostNumber(adapter->data.fchost.parent, &parent_host) < 0)
9119d9
+        if (virGetSCSIHostNumber(parent_hoststr, &parent_host) < 0) {
9119d9
+            VIR_FREE(parent_hoststr);
9119d9
             return -1;
9119d9
+        }
9119d9
+
9119d9
+        /* NOTE:
9119d9
+         * We do not save the parent_hoststr in adapter->data.fchost.parent
9119d9
+         * since we could be writing out the 'def' to the saved XML config.
9119d9
+         * If we wrote out the name in the XML, then future starts would
9119d9
+         * always use the same parent rather than finding the "best available"
9119d9
+         * parent. Besides we have a way to determine the parent based on
9119d9
+         * the 'name' field.
9119d9
+         */
9119d9
+        VIR_FREE(parent_hoststr);
9119d9
+    }
9119d9
+
9119d9
+    /* Since we're creating the vHBA, then we need to manage removing it
9119d9
+     * as well. Since we need this setting to "live" through a libvirtd
9119d9
+     * restart, we need to save the persistent configuration. So if not
9119d9
+     * already defined as YES, then force the issue.
9119d9
+     */
9119d9
+    if (adapter->data.fchost.managed != VIR_TRISTATE_BOOL_YES) {
9119d9
+        adapter->data.fchost.managed = VIR_TRISTATE_BOOL_YES;
9119d9
+        if (configFile) {
9119d9
+            if (virStoragePoolSaveConfig(configFile, def) < 0)
9119d9
+                return -1;
9119d9
+        }
9119d9
     }
9119d9
 
9119d9
     if (virManageVport(parent_host, adapter->data.fchost.wwpn,
9119d9
@@ -707,29 +741,50 @@ createVport(virConnectPtr conn,
9119d9
 }
9119d9
 
9119d9
 static int
9119d9
-deleteVport(virStoragePoolSourceAdapter adapter)
9119d9
+deleteVport(virConnectPtr conn,
9119d9
+            virStoragePoolSourceAdapter adapter)
9119d9
 {
9119d9
     unsigned int parent_host;
9119d9
     char *name = NULL;
9119d9
+    char *vhba_parent = NULL;
9119d9
     int ret = -1;
9119d9
 
9119d9
     if (adapter.type != VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST)
9119d9
         return 0;
9119d9
 
9119d9
-    /* It must be a HBA instead of a vHBA as long as "parent"
9119d9
-     * is NULL. "createVport" guaranteed "parent" for a vHBA
9119d9
-     * cannot be NULL, it's either specified in XML, or detected
9119d9
-     * automatically.
9119d9
-     */
9119d9
-    if (!adapter.data.fchost.parent)
9119d9
+    VIR_DEBUG("conn=%p parent='%s', managed='%d' wwnn='%s' wwpn='%s'",
9119d9
+              conn, NULLSTR(adapter.data.fchost.parent),
9119d9
+              adapter.data.fchost.managed,
9119d9
+              adapter.data.fchost.wwnn,
9119d9
+              adapter.data.fchost.wwpn);
9119d9
+
9119d9
+    /* If we're not managing the deletion of the vHBA, then just return */
9119d9
+    if (adapter.data.fchost.managed != VIR_TRISTATE_BOOL_YES)
9119d9
         return 0;
9119d9
 
9119d9
+    /* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn */
9119d9
     if (!(name = virGetFCHostNameByWWN(NULL, adapter.data.fchost.wwnn,
9119d9
-                                       adapter.data.fchost.wwpn)))
9119d9
-        return -1;
9119d9
-
9119d9
-    if (virGetSCSIHostNumber(adapter.data.fchost.parent, &parent_host) < 0)
9119d9
+                                       adapter.data.fchost.wwpn))) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("Failed to find fc_host for wwnn='%s' and wwpn='%s'"),
9119d9
+                       adapter.data.fchost.wwnn, adapter.data.fchost.wwpn);
9119d9
         goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    /* If at startup time we provided a parent, then use that to
9119d9
+     * get the parent_host value; otherwise, we have to determine
9119d9
+     * the parent scsi_host which we did not save at startup time
9119d9
+     */
9119d9
+    if (adapter.data.fchost.parent) {
9119d9
+        if (virGetSCSIHostNumber(adapter.data.fchost.parent, &parent_host) < 0)
9119d9
+            goto cleanup;
9119d9
+    } else {
9119d9
+        if (!(vhba_parent = getVhbaSCSIHostParent(conn, name)))
9119d9
+            goto cleanup;
9119d9
+
9119d9
+        if (virGetSCSIHostNumber(vhba_parent, &parent_host) < 0)
9119d9
+            goto cleanup;
9119d9
+    }
9119d9
 
9119d9
     if (virManageVport(parent_host, adapter.data.fchost.wwpn,
9119d9
                        adapter.data.fchost.wwnn, VPORT_DELETE) < 0)
9119d9
@@ -738,6 +793,7 @@ deleteVport(virStoragePoolSourceAdapter adapter)
9119d9
     ret = 0;
9119d9
  cleanup:
9119d9
     VIR_FREE(name);
9119d9
+    VIR_FREE(vhba_parent);
9119d9
     return ret;
9119d9
 }
9119d9
 
9119d9
@@ -817,15 +873,15 @@ static int
9119d9
 virStorageBackendSCSIStartPool(virConnectPtr conn,
9119d9
                                virStoragePoolObjPtr pool)
9119d9
 {
9119d9
-    return createVport(conn, pool->def);
9119d9
+    return createVport(conn, pool->configFile, pool->def);
9119d9
 }
9119d9
 
9119d9
 static int
9119d9
-virStorageBackendSCSIStopPool(virConnectPtr conn ATTRIBUTE_UNUSED,
9119d9
+virStorageBackendSCSIStopPool(virConnectPtr conn,
9119d9
                               virStoragePoolObjPtr pool)
9119d9
 {
9119d9
     virStoragePoolSourceAdapter adapter = pool->def->source.adapter;
9119d9
-    return deleteVport(adapter);
9119d9
+    return deleteVport(conn, adapter);
9119d9
 }
9119d9
 
9119d9
 virStorageBackend virStorageBackendSCSI = {
9119d9
diff --git a/tests/storagepoolxml2xmlin/pool-scsi-type-fc-host-managed.xml b/tests/storagepoolxml2xmlin/pool-scsi-type-fc-host-managed.xml
9119d9
new file mode 100644
9119d9
index 0000000..43611ee
9119d9
--- /dev/null
9119d9
+++ b/tests/storagepoolxml2xmlin/pool-scsi-type-fc-host-managed.xml
9119d9
@@ -0,0 +1,15 @@
9119d9
+<pool type='scsi'>
9119d9
+  <name>hba0</name>
9119d9
+  <uuid>e9392370-2917-565e-692b-d057f46512d6</uuid>
9119d9
+  <source>
9119d9
+    <adapter type='fc_host' parent='scsi_host5' managed='yes' wwnn='20000000c9831b4b' wwpn='10000000c9831b4b'/>
9119d9
+  </source>
9119d9
+  <target>
9119d9
+    <path>/dev/disk/by-path</path>
9119d9
+    <permissions>
9119d9
+      <mode>0700</mode>
9119d9
+      <owner>0</owner>
9119d9
+      <group>0</group>
9119d9
+    </permissions>
9119d9
+  </target>
9119d9
+</pool>
9119d9
diff --git a/tests/storagepoolxml2xmlout/pool-scsi-type-fc-host-managed.xml b/tests/storagepoolxml2xmlout/pool-scsi-type-fc-host-managed.xml
9119d9
new file mode 100644
9119d9
index 0000000..c8bb0db
9119d9
--- /dev/null
9119d9
+++ b/tests/storagepoolxml2xmlout/pool-scsi-type-fc-host-managed.xml
9119d9
@@ -0,0 +1,18 @@
9119d9
+<pool type='scsi'>
9119d9
+  <name>hba0</name>
9119d9
+  <uuid>e9392370-2917-565e-692b-d057f46512d6</uuid>
9119d9
+  <capacity unit='bytes'>0</capacity>
9119d9
+  <allocation unit='bytes'>0</allocation>
9119d9
+  <available unit='bytes'>0</available>
9119d9
+  <source>
9119d9
+    <adapter type='fc_host' parent='scsi_host5' managed='yes' wwnn='20000000c9831b4b' wwpn='10000000c9831b4b'/>
9119d9
+  </source>
9119d9
+  <target>
9119d9
+    <path>/dev/disk/by-path</path>
9119d9
+    <permissions>
9119d9
+      <mode>0700</mode>
9119d9
+      <owner>0</owner>
9119d9
+      <group>0</group>
9119d9
+    </permissions>
9119d9
+  </target>
9119d9
+</pool>
9119d9
diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
9119d9
index d7ae10b..b692bf2 100644
9119d9
--- a/tests/storagepoolxml2xmltest.c
9119d9
+++ b/tests/storagepoolxml2xmltest.c
9119d9
@@ -98,6 +98,7 @@ mymain(void)
9119d9
     DO_TEST("pool-scsi");
9119d9
     DO_TEST("pool-scsi-type-scsi-host");
9119d9
     DO_TEST("pool-scsi-type-fc-host");
9119d9
+    DO_TEST("pool-scsi-type-fc-host-managed");
9119d9
     DO_TEST("pool-mpath");
9119d9
     DO_TEST("pool-iscsi-multiiqn");
9119d9
     DO_TEST("pool-iscsi-vendor-product");
9119d9
-- 
9119d9
2.1.3
9119d9