From: Wido den Hollander <wido(a)42on.com>
This allows the end-user to pass down options to the storage pool
backend.
For example NFS could get mount options or Ceph librados options
passed down.
---
docs/schemas/storagepool.rng | 16 +++++++++
docs/storage.html.in | 48 +++++++++++++++++++++++++
src/conf/storage_conf.c | 82 +++++++++++++++++++++++++++++++++++++++++-
src/conf/storage_conf.h | 15 ++++++++
4 files changed, 160 insertions(+), 1 deletion(-)
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 8d7a94d..7b38dce 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -294,6 +294,22 @@
</element>
</define>
+ <define name='sourceinfooptions'>
+ <oneOrMore>
+ <element name='option'>
+ <attribute name='name'>
+ <text/>
+ </attribute>
+ <optional>
+ <attribute name='value'>
+ <text/>
+ </attribute>
+ </optional>
+ <empty/>
+ </element>
+ </oneOrMore>
+ </define>
+
<define name='initiatorinfo'>
<element name='initiator'>
<element name='iqn'>
diff --git a/docs/storage.html.in b/docs/storage.html.in
index eb38b16..3acbd53 100644
--- a/docs/storage.html.in
+++ b/docs/storage.html.in
@@ -270,6 +270,30 @@
</target>
</pool></pre>
+ <h3>Mount options</h3>
+ <p>
+ It is also possible to influence the mount options used for NFS by
+ adding extra options in the pool's XML definition.
+ </p>
+ <pre>
+ <pool type="netfs">
+ <name>virtimages</name>
+ <source>
+ <host name="nfs.example.com"/>
+ <dir path="/var/lib/virt/images"/>
+ <format type='nfs'/>
+ <option name='noatime'/>
+ <option name='rsize' value='8k'/>
+ </source>
+ <target>
+ <path>/var/lib/virt/images</path>
+ </target>
+ </pool></pre>
+ <p>
+ Storage pool options are support since <strong>1.2.6</strong>
+ </p>
+
+
<h3>Valid pool format types</h3>
<p>
The network filesystem pool supports the following formats:
@@ -561,6 +585,30 @@
</source>
</pool></pre>
+ <h3>RADOS cluster options</h3>
+ <p>
+ It is also possible to influence the RADOS cluster options used by librados
+ by adding extra options in the pool's XML definition.
+ </p>
+ <pre>
+ <pool type="rbd">
+ <name>myrbdpool</name>
+ <source>
+ <name>rbdpool</name>
+ <host name='1.2.3.4' port='6789'/>
+ <host name='my.ceph.monitor' port='6789'/>
+ <host name='third.ceph.monitor' port='6789'/>
+ <auth username='admin' type='ceph'>
+ <secret
uuid='2ec115d7-3a88-3ceb-bc12-0ac909a6fd87'/>
+ </auth>
+ <option name='rados_mon_op_timeout' value='10'/>
+ <option name='rados_osd_op_timeout' value='10'/>
+ </source>
+ </pool></pre>
+ <p>
+ Storage pool options are support since <strong>1.2.6</strong>
+ </p>
+
<h3>Example volume output</h3>
<pre>
<volume>
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 8b6fd79..777e12d 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -32,6 +32,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
+#include <regex.h>
#include "virerror.h"
#include "datatypes.h"
@@ -370,6 +371,11 @@ virStoragePoolSourceClear(virStoragePoolSourcePtr source)
for (i = 0; i < source->ndevice; i++)
virStoragePoolSourceDeviceClear(&source->devices[i]);
VIR_FREE(source->devices);
+ for (i = 0; i < source->noptions; i++) {
+ VIR_FREE(source->options[i].name);
+ VIR_FREE(source->options[i].value);
+ }
+ VIR_FREE(source->options);
VIR_FREE(source->dir);
VIR_FREE(source->name);
virStoragePoolSourceAdapterClear(source->adapter);
@@ -551,6 +557,32 @@ virStoragePoolDefParseAuth(xmlXPathContextPtr ctxt,
return ret;
}
+static int virStoragePoolDefVerifyOption(char *msg)
+{
+ regex_t regex;
+ int reti;
+ char msgbuf[100];
+ int ret = -1;
+
+ reti = regcomp(®ex, "^[A-Za-z0-9][A-Za-z0-9_-]*[A-Za-z0-9]$", 0);
+ if (reti)
+ goto cleanup;
+
+ reti = regexec(®ex, msg, 0, NULL, 0);
+ if (!reti) {
+ ret = 0;
+ } else if (reti == REG_NOMATCH) {
+ ret = -1;
+ } else {
+ regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
+ ret = -2;
+ }
+
+cleanup:
+ regfree(®ex);
+ return ret;
+}
+
static int
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
virStoragePoolSourcePtr source,
@@ -559,7 +591,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
{
int ret = -1;
xmlNodePtr relnode, *nodeset = NULL;
- int nsource;
+ int nsource, noptions;
size_t i;
virStoragePoolOptionsPtr options;
char *name = NULL;
@@ -649,6 +681,44 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
}
}
+ noptions = virXPathNodeSet("./option", ctxt, &nodeset);
+ if (noptions > 0) {
+ if (VIR_ALLOC_N(source->options, noptions) < 0) {
+ VIR_FREE(nodeset);
+ goto cleanup;
+ }
+
+ source->noptions = noptions;
+
+ for (i = 0; i < noptions; i++) {
+ char *option = virXMLPropString(nodeset[i], "name");
+ if (option == NULL) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing storage pool option attribute
'name'"));
+ goto cleanup;
+ } else if (virStoragePoolDefVerifyOption(option) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s: %s",
+ _("invalid storage pool option"), option);
+ goto cleanup;
+ }
+ source->options[i].name = option;
+
+ /*
+ * We allow values to be NULL.
+ * E.g. for a NFS mount: <option name='soft'/> or <option
name='intr'/>
+ */
+ char *value = virXMLPropString(nodeset[i], "value");
+ if (value != NULL) {
+ if (virStoragePoolDefVerifyOption(value) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s: %s",
+ _("invalid storage pool option value"),
value);
+ goto cleanup;
+ }
+ source->options[i].value = value;
+ }
+ }
+ }
+
source->dir = virXPathString("string(./dir/@path)", ctxt);
/* In gluster, a missing dir defaults to "/" */
if (!source->dir && pool_type == VIR_STORAGE_POOL_GLUSTER &&
@@ -1166,6 +1236,16 @@ virStoragePoolSourceFormat(virBufferPtr buf,
virBufferEscapeString(buf, "<vendor name='%s'/>\n",
src->vendor);
virBufferEscapeString(buf, "<product name='%s'/>\n",
src->product);
+ if (src->noptions) {
+ for (i = 0; i < src->noptions; i++) {
+ virBufferAsprintf(buf, " <option name='%s'",
src->options[i].name);
+ if (src->options[i].value != NULL) {
+ virBufferAsprintf(buf, " value='%s'",
src->options[i].value);
+ }
+ virBufferAddLit(buf, "/>\n");
+ }
+ }
+
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</source>\n");
return 0;
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 04d99eb..715f129 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -147,6 +147,17 @@ struct _virStoragePoolSourceHost {
int port;
};
+/*
+ * Key-value pairs for passing down options to storage pools.
+ * Eg NFS mount options or Ceph RBD options
+ */
+typedef struct _virStoragePoolSourceOptions virStoragePoolSourceOptions;
+typedef virStoragePoolSourceOptions *virStoragePoolSourceOptionsPtr;
+struct _virStoragePoolSourceOptions {
+ char *name;
+ char *value;
+};
+
/*
* For MSDOS partitions, the free area is important when
@@ -259,6 +270,10 @@ struct _virStoragePoolSource {
* or lvm version, etc.
*/
int format;
+
+ /* Key-value pairs with options for the pool */
+ int noptions;
+ virStoragePoolSourceOptionsPtr options;
};
typedef struct _virStoragePoolTarget virStoragePoolTarget;
--
1.7.9.5