[libvirt] [PATCH 1/3] storage conf: Add support for key-value pair options for pools

Wido den Hollander wido at widodh.nl
Wed May 28 09:38:38 UTC 2014


From: Wido den Hollander <wido at 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(&regex, "^[A-Za-z0-9][A-Za-z0-9_-]*[A-Za-z0-9]$", 0);
+    if (reti)
+        goto cleanup;
+
+    reti = regexec(&regex, msg, 0, NULL, 0);
+    if (!reti) {
+        ret = 0;
+    } else if (reti == REG_NOMATCH) {
+        ret = -1;
+    } else {
+        regerror(reti, &regex, msgbuf, sizeof(msgbuf));
+        ret = -2;
+    }
+
+cleanup:
+    regfree(&regex);
+    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




More information about the libvir-list mailing list