]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
rbd: Utilize storage pool namespace to manage config options
authorJohn Ferlan <jferlan@redhat.com>
Tue, 8 Jan 2019 14:28:03 +0000 (09:28 -0500)
committerJohn Ferlan <jferlan@redhat.com>
Wed, 30 Jan 2019 00:16:25 +0000 (19:16 -0500)
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>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
docs/formatstorage.html.in
docs/schemas/storagepool.rng
src/storage/storage_backend_rbd.c
tests/storagepoolxml2xmlin/pool-rbd-ns-configopts.xml [new file with mode: 0644]
tests/storagepoolxml2xmlout/pool-rbd-ns-configopts.xml [new file with mode: 0644]
tests/storagepoolxml2xmltest.c

index 7a79ec82d80dce820b0d273e1af3cc1e1893054b..d19bc579a437b3e2219c9841c339e75529ed693d 100644 (file)
       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
 
       <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>
index 0b359669afd74f9cfa9fa3a5c3003d552c8c3fc9..e1944ff8e180b8b87151f0652107f47b7715debb 100644 (file)
       <ref name='sizing'/>
       <ref name='sourcerbd'/>
     </interleave>
+    <optional>
+      <ref name='rbd_config_opts'/>
+    </optional>
   </define>
 
   <define name='poolsheepdog'>
     </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>
index 24dd1349ae2baae08cbb2d2b2bf2c70cca29f8a2..2348f80146e7016b408f69c5c4fc8f31b4315066 100644 (file)
@@ -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 (file)
index 0000000..6b62aa6
--- /dev/null
@@ -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 (file)
index 0000000..342a0ff
--- /dev/null
@@ -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>
index aff9ff160cf407531e4b80b8acec117535f1e62d..90d00a8d9e490f845cf9949fa8a9b248120c2a30 100644 (file)
@@ -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");