[libvirt] [PATCH v2 6/6] rbd: Utilize storage pool namespace to manage config options

John Ferlan posted 6 patches 5 years, 10 months ago
There is a newer version of this series
[libvirt] [PATCH v2 6/6] rbd: Utilize storage pool namespace to manage config options
Posted by John Ferlan 5 years, 10 months ago
Allow for adjustment of RBD configuration options via Storage
Pool XML Namespace adjustments.

Based off original patch/concept:

https://www.redhat.com/archives/libvir-list/2014-May/msg00940.html

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 docs/formatstorage.html.in                    |  45 +++++
 docs/schemas/storagepool.rng                  |  23 +++
 src/storage/storage_backend_rbd.c             | 159 +++++++++++++++++-
 .../pool-rbd-configopts.xml                   |  17 ++
 .../pool-rbd-configopts.xml                   |  20 +++
 tests/storagepoolxml2xmltest.c                |   1 +
 6 files changed, 264 insertions(+), 1 deletion(-)
 create mode 100644 tests/storagepoolxml2xmlin/pool-rbd-configopts.xml
 create mode 100644 tests/storagepoolxml2xmlout/pool-rbd-configopts.xml

diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index 308b94f5e5..4e0fe0a981 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -437,6 +437,51 @@
 
       <span class="since">Since 5.0.0.</span></dd>
 
+      <dt><code>rbd:config_opts</code></dt>
+      <dd>Provides an XML namespace mechanism to optionally utilize
+        specifically named options for the RBD configuration options
+        via the rados_conf_set API for the <code>rbd</code> type
+        storage pools. In order to designate that the Storage Pool
+        will be using the mechanism, the <code>pool</code> element
+        must be modified to provide the XML namespace attribute
+        syntax as follows:
+
+        <p>
+        xmlns:rbd='http://libvirt.org/schemas/storagepool/source/rbd/1.0'
+        </p>
+
+        <p>
+        The <code>rbd:config_opts</code> defines the configuration options
+        by specifying multiple <code>rbd:option</code> subelements with
+        the attribute <code>name</code> specifying the configuration option
+        to be added and <code>value</code> specifying the configuration
+        option value. The name and value for each option is only checked
+        to be not empty. The name and value provided are not checked since
+        it's possible options don't exist on all distributions. It is
+        expected that proper and valid options will be supplied for the
+        target host.
+        </p>
+
+        The following XML snippet shows the syntax required in order to
+        utilize
+      <pre>
+&lt;pool type="rbd" xmlns:rbd='http://libvirt.org/schemas/storagepool/source/rbd/1.0'&gt;
+  &lt;name&gt;myrbdpool&lt;/name&gt;
+...
+  &lt;source&gt;
+    &lt;name&gt;rbdpool&lt;/name&gt;
+    &lt;host name='1.2.3.4'/&gt;
+    &lt;host name='my.ceph.monitor'/&gt;
+    &lt;host name='third.ceph.monitor' port='6789'/&gt;
+    &lt;rbd:config_opts&gt;
+      &lt;rbd:option name='client_mount_timeout' value='45'/&gt;
+      &lt;rbd:option name='rados_mon_op_timeout' value='20'/&gt;
+      &lt;rbd:option name='rados_osd_op_timeout' value='10'/&gt;
+    &lt;/rbd:config_opts&gt;
+  &lt;/source&gt;
+...</pre>
+
+      <span class="since">Since 5.0.0.</span></dd>
     </dl>
 
     <h3><a id="StoragePoolTarget">Target elements</a></h3>
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 20c7ae5744..54fa584828 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -647,6 +647,9 @@
         <optional>
           <ref name='sourceinfoauth'/>
         </optional>
+        <optional>
+          <ref name='rbd_config_opts'/>
+        </optional>
       </interleave>
     </element>
   </define>
@@ -695,4 +698,24 @@
     </element>
   </define>
 
+  <!--
+       Optional storage pool extensions in their own namespace:
+         RBD
+    -->
+
+  <define name="rbd_config_opts">
+    <element name="config_opts" ns="http://libvirt.org/schemas/storagepool/source/rbd/1.0">
+      <zeroOrMore>
+        <element name="option">
+          <attribute name='name'>
+            <text/>
+          </attribute>
+          <attribute name='value'>
+            <text/>
+          </attribute>
+        </element>
+      </zeroOrMore>
+    </element>
+  </define>
+
 </grammar>
diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
index 24dd1349ae..c419b12e2d 100644
--- a/src/storage/storage_backend_rbd.c
+++ b/src/storage/storage_backend_rbd.c
@@ -36,6 +36,7 @@
 #include "rbd/librbd.h"
 #include "secret_util.h"
 #include "storage_util.h"
+#include <libxml/xpathInternals.h>
 
 #define VIR_FROM_THIS VIR_FROM_STORAGE
 
@@ -50,6 +51,138 @@ struct _virStorageBackendRBDState {
 typedef struct _virStorageBackendRBDState virStorageBackendRBDState;
 typedef virStorageBackendRBDState *virStorageBackendRBDStatePtr;
 
+/* NetFS Storage Pool Namespace options to share w/ storage_backend_fs.c and
+ * the virStorageBackendFileSystemMountCmd method */
+typedef struct _virStoragePoolRBDMountOptionsDef virStoragePoolRBDMountOptionsDef;
+typedef virStoragePoolRBDMountOptionsDef *virStoragePoolRBDMountOptionsDefPtr;
+struct _virStoragePoolRBDMountOptionsDef {
+    size_t noptions;
+    char **names;
+    char **values;
+};
+
+#define STORAGE_POOL_RBD_NAMESPACE_HREF "http://libvirt.org/schemas/storagepool/source/rbd/1.0"
+
+static void
+virStoragePoolDefRBDNamespaceFree(void *nsdata)
+{
+    virStoragePoolRBDMountOptionsDefPtr cmdopts = nsdata;
+    size_t i;
+
+    if (!cmdopts)
+        return;
+
+    for (i = 0; i < cmdopts->noptions; i++) {
+        VIR_FREE(cmdopts->names[i]);
+        VIR_FREE(cmdopts->values[i]);
+    }
+
+    VIR_FREE(cmdopts);
+}
+
+
+static int
+virStoragePoolDefRBDNamespaceParse(xmlXPathContextPtr ctxt,
+                                   void **data)
+{
+    virStoragePoolRBDMountOptionsDefPtr cmdopts = NULL;
+    xmlNodePtr *nodes = NULL;
+    int nnodes;
+    size_t i;
+    int ret = -1;
+
+    if (xmlXPathRegisterNs(ctxt, BAD_CAST "rbd",
+                           BAD_CAST STORAGE_POOL_RBD_NAMESPACE_HREF) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to register xml namespace '%s'"),
+                       STORAGE_POOL_RBD_NAMESPACE_HREF);
+        return -1;
+    }
+
+    nnodes = virXPathNodeSet("./rbd:config_opts/rbd:option", ctxt, &nodes);
+    if (nnodes < 0)
+        return -1;
+
+    if (nnodes == 0)
+        return 0;
+
+    if (VIR_ALLOC(cmdopts) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC_N(cmdopts->names, nnodes) < 0 ||
+        VIR_ALLOC_N(cmdopts->values, nnodes) < 0)
+        goto cleanup;
+
+    for (i = 0; i < nnodes; i++) {
+        if (!(cmdopts->names[cmdopts->noptions] =
+              virXMLPropString(nodes[i], "name"))) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("no rbd option name specified"));
+            goto cleanup;
+        }
+        if (*cmdopts->names[cmdopts->noptions] == '\0') {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("empty rbd option name specified"));
+            goto cleanup;
+        }
+        if (!(cmdopts->values[cmdopts->noptions] =
+              virXMLPropString(nodes[i], "value"))) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("no rbd option value specified for name '%s'"),
+                           cmdopts->names[cmdopts->noptions]);
+            goto cleanup;
+        }
+        if (*cmdopts->values[cmdopts->noptions] == '\0') {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("empty rbd option value specified for name '%s'"),
+                           cmdopts->names[cmdopts->noptions]);
+            goto cleanup;
+        }
+        cmdopts->noptions++;
+    }
+
+    VIR_STEAL_PTR(*data, cmdopts);
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(nodes);
+    virStoragePoolDefRBDNamespaceFree(cmdopts);
+    return ret;
+}
+
+
+static int
+virStoragePoolDefRBDNamespaceFormatXML(virBufferPtr buf,
+                                       void *nsdata)
+{
+    size_t i;
+    virStoragePoolRBDMountOptionsDefPtr def = nsdata;
+
+    if (!def)
+        return 0;
+
+    virBufferAddLit(buf, "<rbd:config_opts>\n");
+    virBufferAdjustIndent(buf, 2);
+
+    for (i = 0; i < def->noptions; i++) {
+        virBufferEscapeString(buf, "<rbd:option name='%s' ", def->names[i]);
+        virBufferEscapeString(buf, "value='%s'/>\n", def->values[i]);
+    }
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</rbd:config_opts>\n");
+
+    return 0;
+}
+
+
+static const char *
+virStoragePoolDefRBDNamespaceHref(void)
+{
+    return "xmlns:rbd='" STORAGE_POOL_RBD_NAMESPACE_HREF "'";
+}
+
+
 static int
 virStorageBackendRBDRADOSConfSet(rados_t cluster,
                                  const char *option,
@@ -183,6 +316,17 @@ virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr ptr,
                                          rbd_default_format) < 0)
         goto cleanup;
 
+    if (source->namespaceData) {
+        virStoragePoolRBDMountOptionsDefPtr cmdopts = source->namespaceData;
+
+        for (i = 0; i < cmdopts->noptions; i++) {
+            if (virStorageBackendRBDRADOSConfSet(ptr->cluster,
+                                                 cmdopts->names[i],
+                                                 cmdopts->values[i]) < 0)
+                goto cleanup;
+        }
+    }
+
     ptr->starttime = time(0);
     if ((r = rados_connect(ptr->cluster)) < 0) {
         virReportSystemError(-r, _("failed to connect to the RADOS monitor on: %s"),
@@ -1277,6 +1421,7 @@ virStorageBackendRBDVolWipe(virStoragePoolObjPtr pool,
     return ret;
 }
 
+
 virStorageBackend virStorageBackendRBD = {
     .type = VIR_STORAGE_POOL_RBD,
 
@@ -1291,8 +1436,20 @@ virStorageBackend virStorageBackendRBD = {
 };
 
 
+static virStoragePoolXMLNamespace virStoragePoolRBDXMLNamespace = {
+    .parse = virStoragePoolDefRBDNamespaceParse,
+    .free = virStoragePoolDefRBDNamespaceFree,
+    .format = virStoragePoolDefRBDNamespaceFormatXML,
+    .href = virStoragePoolDefRBDNamespaceHref,
+};
+
+
 int
 virStorageBackendRBDRegister(void)
 {
-    return virStorageBackendRegister(&virStorageBackendRBD);
+    if (virStorageBackendRegister(&virStorageBackendRBD) < 0)
+        return -1;
+
+    return virStorageBackendNamespaceInit(VIR_STORAGE_POOL_RBD,
+                                          &virStoragePoolRBDXMLNamespace);
 }
diff --git a/tests/storagepoolxml2xmlin/pool-rbd-configopts.xml b/tests/storagepoolxml2xmlin/pool-rbd-configopts.xml
new file mode 100644
index 0000000000..a23f559afb
--- /dev/null
+++ b/tests/storagepoolxml2xmlin/pool-rbd-configopts.xml
@@ -0,0 +1,17 @@
+<pool type='rbd' xmlns:rbd='http://libvirt.org/schemas/storagepool/source/rbd/1.0'>
+  <name>ceph</name>
+  <uuid>47c1faee-0207-e741-f5ae-d9b019b98fe2</uuid>
+  <source>
+    <name>rbd</name>
+    <host name='localhost' port='6789'/>
+    <host name='localhost' port='6790'/>
+    <auth username='admin' type='ceph'>
+      <secret uuid='2ec115d7-3a88-3ceb-bc12-0ac909a6fd87'/>
+    </auth>
+    <rbd:config_opts>
+      <rbd:option name='client_mount_timeout' value='45'/>
+      <rbd:option name='rados_mon_op_timeout' value='10'/>
+      <rbd:option name='rados_osd_op_timeout' value='20'/>
+    </rbd:config_opts>
+  </source>
+</pool>
diff --git a/tests/storagepoolxml2xmlout/pool-rbd-configopts.xml b/tests/storagepoolxml2xmlout/pool-rbd-configopts.xml
new file mode 100644
index 0000000000..121a69c0d7
--- /dev/null
+++ b/tests/storagepoolxml2xmlout/pool-rbd-configopts.xml
@@ -0,0 +1,20 @@
+<pool type='rbd' xmlns:rbd='http://libvirt.org/schemas/storagepool/source/rbd/1.0'>
+  <name>ceph</name>
+  <uuid>47c1faee-0207-e741-f5ae-d9b019b98fe2</uuid>
+  <capacity unit='bytes'>0</capacity>
+  <allocation unit='bytes'>0</allocation>
+  <available unit='bytes'>0</available>
+  <source>
+    <host name='localhost' port='6789'/>
+    <host name='localhost' port='6790'/>
+    <name>rbd</name>
+    <auth type='ceph' username='admin'>
+      <secret uuid='2ec115d7-3a88-3ceb-bc12-0ac909a6fd87'/>
+    </auth>
+    <rbd:config_opts>
+      <rbd:option name='client_mount_timeout' value='45'/>
+      <rbd:option name='rados_mon_op_timeout' value='10'/>
+      <rbd:option name='rados_osd_op_timeout' value='20'/>
+    </rbd:config_opts>
+  </source>
+</pool>
diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
index c08313d236..25f134fc23 100644
--- a/tests/storagepoolxml2xmltest.c
+++ b/tests/storagepoolxml2xmltest.c
@@ -105,6 +105,7 @@ mymain(void)
     DO_TEST("pool-zfs");
     DO_TEST("pool-zfs-sourcedev");
     DO_TEST("pool-rbd");
+    DO_TEST("pool-rbd-configopts");
     DO_TEST("pool-vstorage");
     DO_TEST("pool-iscsi-direct-auth");
     DO_TEST("pool-iscsi-direct");
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 6/6] rbd: Utilize storage pool namespace to manage config options
Posted by Michal Privoznik 5 years, 10 months ago
On 1/8/19 6:52 PM, John Ferlan wrote:
> Allow for adjustment of RBD configuration options via Storage
> Pool XML Namespace adjustments.
> 
> Based off original patch/concept:
> 
> https://www.redhat.com/archives/libvir-list/2014-May/msg00940.html
> 
> Signed-off-by: John Ferlan <jferlan@redhat.com>
> ---
>  docs/formatstorage.html.in                    |  45 +++++
>  docs/schemas/storagepool.rng                  |  23 +++
>  src/storage/storage_backend_rbd.c             | 159 +++++++++++++++++-
>  .../pool-rbd-configopts.xml                   |  17 ++
>  .../pool-rbd-configopts.xml                   |  20 +++
>  tests/storagepoolxml2xmltest.c                |   1 +
>  6 files changed, 264 insertions(+), 1 deletion(-)
>  create mode 100644 tests/storagepoolxml2xmlin/pool-rbd-configopts.xml
>  create mode 100644 tests/storagepoolxml2xmlout/pool-rbd-configopts.xml
> 
> diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
> index 308b94f5e5..4e0fe0a981 100644
> --- a/docs/formatstorage.html.in
> +++ b/docs/formatstorage.html.in
> @@ -437,6 +437,51 @@
>  
>        <span class="since">Since 5.0.0.</span></dd>
>  
> +      <dt><code>rbd:config_opts</code></dt>
> +      <dd>Provides an XML namespace mechanism to optionally utilize
> +        specifically named options for the RBD configuration options
> +        via the rados_conf_set API for the <code>rbd</code> type
> +        storage pools. In order to designate that the Storage Pool
> +        will be using the mechanism, the <code>pool</code> element
> +        must be modified to provide the XML namespace attribute
> +        syntax as follows:
> +
> +        <p>
> +        xmlns:rbd='http://libvirt.org/schemas/storagepool/source/rbd/1.0'
> +        </p>
> +
> +        <p>
> +        The <code>rbd:config_opts</code> defines the configuration options
> +        by specifying multiple <code>rbd:option</code> subelements with
> +        the attribute <code>name</code> specifying the configuration option
> +        to be added and <code>value</code> specifying the configuration
> +        option value. The name and value for each option is only checked
> +        to be not empty. The name and value provided are not checked since
> +        it's possible options don't exist on all distributions. It is
> +        expected that proper and valid options will be supplied for the
> +        target host.
> +        </p>
> +
> +        The following XML snippet shows the syntax required in order to
> +        utilize
> +      <pre>
> +&lt;pool type="rbd" xmlns:rbd='http://libvirt.org/schemas/storagepool/source/rbd/1.0'&gt;
> +  &lt;name&gt;myrbdpool&lt;/name&gt;
> +...
> +  &lt;source&gt;
> +    &lt;name&gt;rbdpool&lt;/name&gt;
> +    &lt;host name='1.2.3.4'/&gt;
> +    &lt;host name='my.ceph.monitor'/&gt;
> +    &lt;host name='third.ceph.monitor' port='6789'/&gt;
> +    &lt;rbd:config_opts&gt;
> +      &lt;rbd:option name='client_mount_timeout' value='45'/&gt;
> +      &lt;rbd:option name='rados_mon_op_timeout' value='20'/&gt;
> +      &lt;rbd:option name='rados_osd_op_timeout' value='10'/&gt;
> +    &lt;/rbd:config_opts&gt;
> +  &lt;/source&gt;
> +...</pre>
> +
> +      <span class="since">Since 5.0.0.</span></dd>
>      </dl>
>  
>      <h3><a id="StoragePoolTarget">Target elements</a></h3>
> diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
> index 20c7ae5744..54fa584828 100644
> --- a/docs/schemas/storagepool.rng
> +++ b/docs/schemas/storagepool.rng
> @@ -647,6 +647,9 @@
>          <optional>
>            <ref name='sourceinfoauth'/>
>          </optional>
> +        <optional>
> +          <ref name='rbd_config_opts'/>
> +        </optional>
>        </interleave>
>      </element>
>    </define>
> @@ -695,4 +698,24 @@
>      </element>
>    </define>
>  
> +  <!--
> +       Optional storage pool extensions in their own namespace:
> +         RBD
> +    -->
> +
> +  <define name="rbd_config_opts">
> +    <element name="config_opts" ns="http://libvirt.org/schemas/storagepool/source/rbd/1.0">
> +      <zeroOrMore>
> +        <element name="option">
> +          <attribute name='name'>
> +            <text/>
> +          </attribute>
> +          <attribute name='value'>
> +            <text/>
> +          </attribute>
> +        </element>
> +      </zeroOrMore>
> +    </element>
> +  </define>
> +
>  </grammar>
> diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
> index 24dd1349ae..c419b12e2d 100644
> --- a/src/storage/storage_backend_rbd.c
> +++ b/src/storage/storage_backend_rbd.c
> @@ -36,6 +36,7 @@
>  #include "rbd/librbd.h"
>  #include "secret_util.h"
>  #include "storage_util.h"
> +#include <libxml/xpathInternals.h>
>  
>  #define VIR_FROM_THIS VIR_FROM_STORAGE
>  
> @@ -50,6 +51,138 @@ struct _virStorageBackendRBDState {
>  typedef struct _virStorageBackendRBDState virStorageBackendRBDState;
>  typedef virStorageBackendRBDState *virStorageBackendRBDStatePtr;
>  
> +/* NetFS Storage Pool Namespace options to share w/ storage_backend_fs.c and
> + * the virStorageBackendFileSystemMountCmd method */
> +typedef struct _virStoragePoolRBDMountOptionsDef virStoragePoolRBDMountOptionsDef;
> +typedef virStoragePoolRBDMountOptionsDef *virStoragePoolRBDMountOptionsDefPtr;
> +struct _virStoragePoolRBDMountOptionsDef {
> +    size_t noptions;
> +    char **names;
> +    char **values;
> +};
> +
> +#define STORAGE_POOL_RBD_NAMESPACE_HREF "http://libvirt.org/schemas/storagepool/source/rbd/1.0"
> +
> +static void
> +virStoragePoolDefRBDNamespaceFree(void *nsdata)
> +{
> +    virStoragePoolRBDMountOptionsDefPtr cmdopts = nsdata;
> +    size_t i;
> +
> +    if (!cmdopts)
> +        return;
> +
> +    for (i = 0; i < cmdopts->noptions; i++) {
> +        VIR_FREE(cmdopts->names[i]);
> +        VIR_FREE(cmdopts->values[i]);
> +    }
> +

Again, VIR_FREE(cmdopts->names) and VIR_FREE(cmdopts->values);

> +    VIR_FREE(cmdopts);
> +}


Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list