From ab6ca812763b539e5380d8d6c4fa9da939125814 Mon Sep 17 00:00:00 2001
From: John Ferlan
Date: Tue, 8 Jan 2019 09:28:03 -0500
Subject: [PATCH] rbd: Utilize storage pool namespace to manage config options
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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
Reviewed-by: Daniel P. Berrangé
---
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.
Usage of namespaces comes with no support guarantees. It is intended
@@ -569,6 +570,55 @@
Since 5.1.0.
+
rbd:config_opts
+ Provides an XML namespace mechanism to optionally utilize
+ specifically named options for the RBD configuration options
+ via the rados_conf_set API for the rbd
type
+ storage pools. In order to designate that the Storage Pool
+ will be using the mechanism, the pool
element
+ must be modified to provide the XML namespace attribute
+ syntax as follows:
+
+
+ xmlns:rbd='http://libvirt.org/schemas/storagepool/source/rbd/1.0'
+
+
+
+ The rbd:config_opts
defines the configuration options
+ by specifying multiple rbd:option
subelements with
+ the attribute name
specifying the configuration option
+ to be added and value
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.
+
+
+ The following XML snippet shows the syntax required in order to
+ utilize
+
+<pool type="rbd" xmlns:rbd='http://libvirt.org/schemas/storagepool/source/rbd/1.0'>
+ <name>myrbdpool</name>
+...
+ <source>
+...
+ </source>
+...
+ <target>
+...
+ </target>
+...
+ <rbd:config_opts>
+ <rbd:option name='client_mount_timeout' value='45'/>
+ <rbd:option name='rados_mon_op_timeout' value='20'/>
+ <rbd:option name='rados_osd_op_timeout' value='10'/>
+ </rbd:config_opts>
+</pool>
+
+
+ Since 5.1.0.
+
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 @@
+
+
+
@@ -705,4 +708,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
#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, "\n");
+ virBufferAdjustIndent(buf, 2);
+
+ for (i = 0; i < def->noptions; i++) {
+ virBufferEscapeString(buf, "names[i]);
+ virBufferEscapeString(buf, "value='%s'/>\n", def->values[i]);
+ }
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, " \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 @@
+
+ ceph
+ 47c1faee-0207-e741-f5ae-d9b019b98fe2
+
+ rbd
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+ ceph
+ 47c1faee-0207-e741-f5ae-d9b019b98fe2
+ 0
+ 0
+ 0
+
+
+
+ rbd
+
+
+
+
+
+
+
+
+
+
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");