mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
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> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
ab995c1fe9
commit
ab6ca81276
@ -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>
|
||||
<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>
|
||||
</pre>
|
||||
|
||||
<span class="since">Since 5.1.0.</span></dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<h2><a id="StorageVol">Storage volume XML</a></h2>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
17
tests/storagepoolxml2xmlin/pool-rbd-ns-configopts.xml
Normal file
17
tests/storagepoolxml2xmlin/pool-rbd-ns-configopts.xml
Normal file
@ -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>
|
20
tests/storagepoolxml2xmlout/pool-rbd-ns-configopts.xml
Normal file
20
tests/storagepoolxml2xmlout/pool-rbd-ns-configopts.xml
Normal file
@ -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>
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user