[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v5 9/9] rbd: Utilize storage pool namespace to manage config options



Allow for adjustment of RBD configuration options via Storage
Pool XML Namespace adjustments. When namespace arguments are
used to start the pool, add a VIR_WARN to indicate that the
startup was tainted by custom config_opts.

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                    |  52 +++++-
 docs/schemas/storagepool.rng                  |  23 +++
 src/storage/storage_backend_rbd.c             | 169 +++++++++++++++++-
 .../pool-rbd-ns-configopts.xml                |  17 ++
 .../pool-rbd-ns-configopts.xml                |  20 +++
 tests/storagepoolxml2xmltest.c                |   1 +
 6 files changed, 278 insertions(+), 4 deletions(-)
 create mode 100644 tests/storagepoolxml2xmlin/pool-rbd-ns-configopts.xml
 create mode 100644 tests/storagepoolxml2xmlout/pool-rbd-ns-configopts.xml

diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index 7a79ec82d8..d19bc579a4 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -516,7 +516,8 @@
       XML syntax targeted solely for the needs of the specific pool type
       which is not otherwise supported in standard XML. For the "fs" and
       "netfs" pool types this provides a mechanism to provide additional
-      mount options on the command line.
+      mount options on the command line. For the "rbd" pool this provides
+      a mechanism to override default settings for RBD configuration options.
     </p>
     <p>
       Usage of namespaces comes with no support guarantees. It is intended
@@ -569,6 +570,55 @@
 
       <span class="since">Since 5.1.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;/source&gt;
+...
+  &lt;target&gt;
+...
+  &lt;/target&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;/pool&gt;
+</pre>
+
+      <span class="since">Since 5.1.0.</span></dd>
+
     </dl>
 
     <h2><a id="StorageVol">Storage volume XML</a></h2>
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 0b359669af..e1944ff8e1 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -156,6 +156,9 @@
       <ref name='sizing'/>
       <ref name='sourcerbd'/>
     </interleave>
+    <optional>
+      <ref name='rbd_config_opts'/>
+    </optional>
   </define>
 
   <define name='poolsheepdog'>
@@ -705,4 +708,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..2348f80146 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;
 
+typedef struct _virStoragePoolRBDConfigOptionsDef virStoragePoolRBDConfigOptionsDef;
+typedef virStoragePoolRBDConfigOptionsDef *virStoragePoolRBDConfigOptionsDefPtr;
+struct _virStoragePoolRBDConfigOptionsDef {
+    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)
+{
+    virStoragePoolRBDConfigOptionsDefPtr 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->names);
+    VIR_FREE(cmdopts->values);
+
+    VIR_FREE(cmdopts);
+}
+
+
+static int
+virStoragePoolDefRBDNamespaceParse(xmlXPathContextPtr ctxt,
+                                   void **data)
+{
+    virStoragePoolRBDConfigOptionsDefPtr 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;
+    virStoragePoolRBDConfigOptionsDefPtr 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,
@@ -69,10 +202,11 @@ virStorageBackendRBDRADOSConfSet(rados_t cluster,
 
 static int
 virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr ptr,
-                                  virStoragePoolSourcePtr source)
+                                  virStoragePoolDefPtr def)
 {
     int ret = -1;
     int r = 0;
+    virStoragePoolSourcePtr source = &def->source;
     virStorageAuthDefPtr authdef = source->auth;
     unsigned char *secret_value = NULL;
     size_t secret_value_size = 0;
@@ -183,6 +317,22 @@ virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr ptr,
                                          rbd_default_format) < 0)
         goto cleanup;
 
+    if (def->namespaceData) {
+        virStoragePoolRBDConfigOptionsDefPtr cmdopts = def->namespaceData;
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+        for (i = 0; i < cmdopts->noptions; i++) {
+            if (virStorageBackendRBDRADOSConfSet(ptr->cluster,
+                                                 cmdopts->names[i],
+                                                 cmdopts->values[i]) < 0)
+                goto cleanup;
+        }
+
+        virUUIDFormat(def->uuid, uuidstr);
+        VIR_WARN("Storage Pool name='%s' uuid='%s' is tainted by custom "
+                 "config_opts from XML", def->name, uuidstr);
+    }
+
     ptr->starttime = time(0);
     if ((r = rados_connect(ptr->cluster)) < 0) {
         virReportSystemError(-r, _("failed to connect to the RADOS monitor on: %s"),
@@ -256,7 +406,7 @@ virStorageBackendRBDNewState(virStoragePoolObjPtr pool)
     if (VIR_ALLOC(ptr) < 0)
         return NULL;
 
-    if (virStorageBackendRBDOpenRADOSConn(ptr, &def->source) < 0)
+    if (virStorageBackendRBDOpenRADOSConn(ptr, def) < 0)
         goto error;
 
     if (virStorageBackendRBDOpenIoCTX(ptr, pool) < 0)
@@ -1277,6 +1427,7 @@ virStorageBackendRBDVolWipe(virStoragePoolObjPtr pool,
     return ret;
 }
 
+
 virStorageBackend virStorageBackendRBD = {
     .type = VIR_STORAGE_POOL_RBD,
 
@@ -1291,8 +1442,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-ns-configopts.xml b/tests/storagepoolxml2xmlin/pool-rbd-ns-configopts.xml
new file mode 100644
index 0000000000..6b62aa6f7e
--- /dev/null
+++ b/tests/storagepoolxml2xmlin/pool-rbd-ns-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>
+  </source>
+  <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>
+</pool>
diff --git a/tests/storagepoolxml2xmlout/pool-rbd-ns-configopts.xml b/tests/storagepoolxml2xmlout/pool-rbd-ns-configopts.xml
new file mode 100644
index 0000000000..342a0ff74a
--- /dev/null
+++ b/tests/storagepoolxml2xmlout/pool-rbd-ns-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>
+  </source>
+  <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>
+</pool>
diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
index aff9ff160c..90d00a8d9e 100644
--- a/tests/storagepoolxml2xmltest.c
+++ b/tests/storagepoolxml2xmltest.c
@@ -106,6 +106,7 @@ mymain(void)
     DO_TEST("pool-zfs");
     DO_TEST("pool-zfs-sourcedev");
     DO_TEST("pool-rbd");
+    DO_TEST("pool-rbd-ns-configopts");
     DO_TEST("pool-vstorage");
     DO_TEST("pool-iscsi-direct-auth");
     DO_TEST("pool-iscsi-direct");
-- 
2.20.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]