]> xenbits.xensource.com Git - libvirt.git/commitdiff
storage: Add infrastructure to manage XML namespace options
authorJohn Ferlan <jferlan@redhat.com>
Mon, 7 Jan 2019 22:14:57 +0000 (17:14 -0500)
committerJohn Ferlan <jferlan@redhat.com>
Wed, 30 Jan 2019 00:16:13 +0000 (19:16 -0500)
Introduce the virStoragePoolFSMountOptionsDef to be used to
manage the Storage Pool XML Namespace for mount options.

Using a new virStorageBackendNamespaceInit function, set the
virStoragePoolXMLNamespace into the _virStoragePoolOptions when
the storage backend is loaded.

Modify the storagepool.rng to allow for the usage of a different
XML namespace to parse the fs_mount_opts to be included with
the fs and netfs storage pool definitions.

Modify the storagepoolxml2xmltest to utilize a properly modified
XML file to parse and format the namespace for a netfs storage pool.

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_fs.c
src/storage/storage_util.c
src/storage/storage_util.h
tests/Makefile.am
tests/storagepoolxml2xmlin/pool-netfs-ns-mountopts.xml [new file with mode: 0644]
tests/storagepoolxml2xmlout/pool-netfs-ns-mountopts.xml [new file with mode: 0644]
tests/storagepoolxml2xmltest.c

index 85107c85ae6030679737ce539c8de41e3bc6d1f9..7a79ec82d80dce820b0d273e1af3cc1e1893054b 100644 (file)
       device, measured in bytes.  <span class="since">Since 0.4.1</span>
     </p>
 
+    <h3><a id="StoragePoolNamespaces">Storage Pool Namespaces</a></h3>
+
+    <p>
+      Usage of Storage Pool Namespaces provides a mechanism to provide
+      pool type specific data in a free form or arbitrary manner via
+      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.
+    </p>
+    <p>
+      Usage of namespaces comes with no support guarantees. It is intended
+      for developers testing out a concept prior to requesting an explicitly
+      supported XML option in libvirt, and thus should never be used in
+      production.
+    </p>
+    <dl>
+      <dt><code>fs:mount_opts</code></dt>
+      <dd>Provides an XML namespace mechanism to optionally utilize
+        specifically named options for the mount command via the "-o"
+        option for the <code>fs</code> or <code>netfs</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:fs='http://libvirt.org/schemas/storagepool/source/fs/1.0'
+        </p>
+
+        <p>
+        The <code>fs:mount_opts</code> defines the mount options by
+        specifying multiple <code>fs:option</code> subelements with
+        the attribute <code>name</code> specifying the mount option to
+        be added. The value of the named option is 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 for a netfs pool:
+      <pre>
+&lt;pool type="netfs" xmlns:fs='http://libvirt.org/schemas/storagepool/source/fs/1.0'&gt;
+  &lt;name&gt;nfsimages&lt;/name&gt;
+...
+  &lt;source&gt;
+...
+  &lt;/source&gt;
+...
+  &lt;target&gt;
+...
+  &lt;/target&gt;
+  &lt;fs:mount_opts&gt;
+    &lt;fs:option name='sync'/&gt;
+    &lt;fs:option name='lazytime'/&gt;
+  &lt;/fs:mount_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>
     <p>
       A storage volume will generally be either a file or a device
index f9a16422cc89af725fec1c0b1ed0c53b51562f08..0b359669afd74f9cfa9fa3a5c3003d552c8c3fc9 100644 (file)
@@ -52,6 +52,9 @@
       <ref name='sourcefs'/>
       <ref name='target'/>
     </interleave>
+    <optional>
+      <ref name='fs_mount_opts'/>
+    </optional>
   </define>
 
   <define name='poolnetfs'>
@@ -64,6 +67,9 @@
       <ref name='sourcenetfs'/>
       <ref name='target'/>
     </interleave>
+    <optional>
+      <ref name='fs_mount_opts'/>
+    </optional>
   </define>
 
   <define name='poollogical'>
     </data>
   </define>
 
+  <!--
+       Optional storage pool extensions in their own namespace:
+         "fs" or "netfs"
+    -->
+
+  <define name="fs_mount_opts">
+    <element name="mount_opts" ns="http://libvirt.org/schemas/storagepool/source/fs/1.0">
+      <zeroOrMore>
+        <element name="option">
+          <attribute name='name'>
+            <text/>
+          </attribute>
+        </element>
+      </zeroOrMore>
+    </element>
+  </define>
+
 </grammar>
index dc9869417e1aed9e536c6664e888be4be8f40807..0ec99c60ed766ec30e21e277576215881904d1ec 100644 (file)
@@ -41,6 +41,7 @@ VIR_LOG_INIT("storage.storage_backend_fs");
 
 #if WITH_STORAGE_FS
 
+# include <libxml/xpathInternals.h>
 # include <mntent.h>
 
 struct _virNetfsDiscoverState {
@@ -559,6 +560,122 @@ virStorageBackendFileSystemBuild(virStoragePoolObjPtr pool,
 }
 
 
+#if WITH_STORAGE_FS
+
+# define STORAGE_POOL_FS_NAMESPACE_HREF "http://libvirt.org/schemas/storagepool/source/fs/1.0"
+
+/* Backend XML Namespace handling for fs or netfs specific mount options to
+ * be added to the mount -o {options_list} command line that are not otherwise
+ * supplied by supported XML. The XML will use the format, such as:
+ *
+ *     <fs:mount_opts>
+ *       <fs:option name='sync'/>
+ *       <fs:option name='lazytime'/>
+ *     </fs:mount_opts>
+ *
+ * and the <pool type='fs'> or <pool type='netfs'> is required to have a
+ * "xmlns:fs='%s'" attribute using the STORAGE_POOL_FS_NAMESPACE_HREF
+ */
+
+static void
+virStoragePoolDefFSNamespaceFree(void *nsdata)
+{
+    virStoragePoolFSMountOptionsDefPtr cmdopts = nsdata;
+    size_t i;
+
+    if (!cmdopts)
+        return;
+
+    for (i = 0; i < cmdopts->noptions; i++)
+        VIR_FREE(cmdopts->options[i]);
+    VIR_FREE(cmdopts->options);
+
+    VIR_FREE(cmdopts);
+}
+
+
+static int
+virStoragePoolDefFSNamespaceParse(xmlXPathContextPtr ctxt,
+                                  void **data)
+{
+    virStoragePoolFSMountOptionsDefPtr cmdopts = NULL;
+    xmlNodePtr *nodes = NULL;
+    int nnodes;
+    size_t i;
+    int ret = -1;
+
+    if (xmlXPathRegisterNs(ctxt, BAD_CAST "fs",
+                           BAD_CAST STORAGE_POOL_FS_NAMESPACE_HREF) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to register xml namespace '%s'"),
+                       STORAGE_POOL_FS_NAMESPACE_HREF);
+        return -1;
+    }
+
+    nnodes = virXPathNodeSet("./fs:mount_opts/fs:option", ctxt, &nodes);
+    if (nnodes < 0)
+        return -1;
+
+    if (nnodes == 0)
+        return 0;
+
+    if (VIR_ALLOC(cmdopts) < 0 ||
+        VIR_ALLOC_N(cmdopts->options, nnodes) < 0)
+        goto cleanup;
+
+    for (i = 0; i < nnodes; i++) {
+        if (!(cmdopts->options[cmdopts->noptions] =
+              virXMLPropString(nodes[i], "name"))) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("no fs mount option name specified"));
+            goto cleanup;
+        }
+        cmdopts->noptions++;
+    }
+
+    VIR_STEAL_PTR(*data, cmdopts);
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(nodes);
+    virStoragePoolDefFSNamespaceFree(cmdopts);
+    return ret;
+}
+
+
+static int
+virStoragePoolDefFSNamespaceFormatXML(virBufferPtr buf,
+                                      void *nsdata)
+{
+    size_t i;
+    virStoragePoolFSMountOptionsDefPtr def = nsdata;
+
+    if (!def)
+        return 0;
+
+    virBufferAddLit(buf, "<fs:mount_opts>\n");
+    virBufferAdjustIndent(buf, 2);
+
+    for (i = 0; i < def->noptions; i++)
+        virBufferEscapeString(buf, "<fs:option name='%s'/>\n",
+                              def->options[i]);
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</fs:mount_opts>\n");
+
+    return 0;
+}
+
+
+static const char *
+virStoragePoolDefFSNamespaceHref(void)
+{
+    return "xmlns:fs='" STORAGE_POOL_FS_NAMESPACE_HREF "'";
+}
+
+#endif /* WITH_STORAGE_FS */
+
+
 virStorageBackend virStorageBackendDirectory = {
     .type = VIR_STORAGE_POOL_DIR,
 
@@ -617,6 +734,13 @@ virStorageBackend virStorageBackendNetFileSystem = {
     .downloadVol = virStorageBackendVolDownloadLocal,
     .wipeVol = virStorageBackendVolWipeLocal,
 };
+
+static virStoragePoolXMLNamespace virStoragePoolFSXMLNamespace = {
+    .parse = virStoragePoolDefFSNamespaceParse,
+    .free = virStoragePoolDefFSNamespaceFree,
+    .format = virStoragePoolDefFSNamespaceFormatXML,
+    .href = virStoragePoolDefFSNamespaceHref,
+};
 #endif /* WITH_STORAGE_FS */
 
 
@@ -630,8 +754,16 @@ virStorageBackendFsRegister(void)
     if (virStorageBackendRegister(&virStorageBackendFileSystem) < 0)
         return -1;
 
+    if (virStorageBackendNamespaceInit(VIR_STORAGE_POOL_FS,
+                                       &virStoragePoolFSXMLNamespace) < 0)
+        return -1;
+
     if (virStorageBackendRegister(&virStorageBackendNetFileSystem) < 0)
         return -1;
+
+    if (virStorageBackendNamespaceInit(VIR_STORAGE_POOL_NETFS,
+                                       &virStoragePoolFSXMLNamespace) < 0)
+        return -1;
 #endif /* WITH_STORAGE_FS */
 
     return 0;
index a5cb47b4d0b6c5a864a7827b13e85ea889b7875f..4596cd451839f69372ab7432fcb0e1999bb8f1aa 100644 (file)
 
 VIR_LOG_INIT("storage.storage_util");
 
+
+/* virStorageBackendNamespaceInit:
+ * @poolType: virStoragePoolType
+ * @xmlns: Storage Pool specific namespace callback methods
+ *
+ * To be called during storage backend registration to configure the
+ * Storage Pool XML Namespace based on the backend's needs.
+ */
+int
+virStorageBackendNamespaceInit(int poolType,
+                               virStoragePoolXMLNamespacePtr xmlns)
+{
+    return virStoragePoolOptionsPoolTypeSetXMLNamespace(poolType, xmlns);
+}
+
+
 #define READ_BLOCK_SIZE_DEFAULT  (1024 * 1024)
 #define WRITE_BLOCK_SIZE_DEFAULT (4 * 1024)
 
index c872468135f8693dd0e7181b935c369b5cc8ac32..8b44b54a3b0181a5a38b1ab280a816ff5d9bed7c 100644 (file)
 # include "storage_driver.h"
 # include "storage_backend.h"
 
+/* Storage Pool Namespace options to share w/ storage_backend_fs.c and
+ * the virStorageBackendFileSystemMountCmd method */
+typedef struct _virStoragePoolFSMountOptionsDef virStoragePoolFSMountOptionsDef;
+typedef virStoragePoolFSMountOptionsDef *virStoragePoolFSMountOptionsDefPtr;
+struct _virStoragePoolFSMountOptionsDef {
+    size_t noptions;
+    char **options;
+};
+
+int
+virStorageBackendNamespaceInit(int poolType,
+                               virStoragePoolXMLNamespacePtr xmlns);
+
+
 /* File creation/cloning functions used for cloning between backends */
 
 int
index f74d8463b655f38613fda435f2fe3115aa2f8d74..ab4c71652901cc91d00277ba83cfb9d76bfbadd7 100644 (file)
@@ -937,7 +937,9 @@ storagevolxml2xmltest_LDADD = $(LDADDS)
 storagepoolxml2xmltest_SOURCES = \
        storagepoolxml2xmltest.c \
        testutils.c testutils.h
-storagepoolxml2xmltest_LDADD = $(LDADDS)
+storagepoolxml2xmltest_LDADD = $(LDADDS) \
+       ../src/libvirt_driver_storage_impl.la \
+       $(GNULIB_LIBS)
 
 nodedevxml2xmltest_SOURCES = \
        nodedevxml2xmltest.c \
diff --git a/tests/storagepoolxml2xmlin/pool-netfs-ns-mountopts.xml b/tests/storagepoolxml2xmlin/pool-netfs-ns-mountopts.xml
new file mode 100644 (file)
index 0000000..0434b16
--- /dev/null
@@ -0,0 +1,25 @@
+<pool type='netfs' xmlns:fs='http://libvirt.org/schemas/storagepool/source/fs/1.0'>
+  <name>nfsimages</name>
+  <uuid>7641d5a8-af11-f730-a34e-0a7dfcede71f</uuid>
+  <capacity>0</capacity>
+  <allocation>0</allocation>
+  <available>0</available>
+  <source>
+    <host name='localhost'/>
+    <dir path='/var/lib/libvirt/images'/>
+    <format type='nfs'/>
+    <protocol ver='3'/>
+  </source>
+  <target>
+    <path>/mnt</path>
+    <permissions>
+      <mode>0700</mode>
+      <owner>0</owner>
+      <group>0</group>
+    </permissions>
+  </target>
+  <fs:mount_opts>
+    <fs:option name='sync'/>
+    <fs:option name='lazytime'/>
+  </fs:mount_opts>
+</pool>
diff --git a/tests/storagepoolxml2xmlout/pool-netfs-ns-mountopts.xml b/tests/storagepoolxml2xmlout/pool-netfs-ns-mountopts.xml
new file mode 100644 (file)
index 0000000..4bd164f
--- /dev/null
@@ -0,0 +1,25 @@
+<pool type='netfs' xmlns:fs='http://libvirt.org/schemas/storagepool/source/fs/1.0'>
+  <name>nfsimages</name>
+  <uuid>7641d5a8-af11-f730-a34e-0a7dfcede71f</uuid>
+  <capacity unit='bytes'>0</capacity>
+  <allocation unit='bytes'>0</allocation>
+  <available unit='bytes'>0</available>
+  <source>
+    <host name='localhost'/>
+    <dir path='/var/lib/libvirt/images'/>
+    <format type='nfs'/>
+    <protocol ver='3'/>
+  </source>
+  <target>
+    <path>/mnt</path>
+    <permissions>
+      <mode>0700</mode>
+      <owner>0</owner>
+      <group>0</group>
+    </permissions>
+  </target>
+  <fs:mount_opts>
+    <fs:option name='sync'/>
+    <fs:option name='lazytime'/>
+  </fs:mount_opts>
+</pool>
index d18390034fc3fef62b5ebc97d172c2f070a184ad..aff9ff160cf407531e4b80b8acec117535f1e62d 100644 (file)
@@ -11,6 +11,8 @@
 #include "testutilsqemu.h"
 #include "virstring.h"
 
+#include "storage/storage_util.h"
+
 #define VIR_FROM_THIS VIR_FROM_NONE
 
 static int
@@ -70,6 +72,9 @@ mymain(void)
                    testCompareXMLToXMLHelper, (name)) < 0) \
         ret = -1
 
+    if (storageRegisterAll() < 0)
+       return EXIT_FAILURE;
+
     DO_TEST("pool-dir");
     DO_TEST("pool-dir-naming");
     DO_TEST("pool-fs");
@@ -86,6 +91,7 @@ mymain(void)
     DO_TEST("pool-netfs-protocol-ver");
     DO_TEST("pool-netfs-gluster");
     DO_TEST("pool-netfs-cifs");
+    DO_TEST("pool-netfs-ns-mountopts");
     DO_TEST("pool-scsi");
     DO_TEST("pool-scsi-type-scsi-host");
     DO_TEST("pool-scsi-type-fc-host");