From 7a227688a83880200e85dab02420aa94a72a7f9c Mon Sep 17 00:00:00 2001
From: John Ferlan
Date: Mon, 7 Jan 2019 17:14:57 -0500
Subject: [PATCH] storage: Add infrastructure to manage XML namespace options
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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
Reviewed-by: Daniel P. Berrangé
---
docs/formatstorage.html.in | 63 +++++++++
docs/schemas/storagepool.rng | 23 +++
src/storage/storage_backend_fs.c | 132 ++++++++++++++++++
src/storage/storage_util.c | 16 +++
src/storage/storage_util.h | 14 ++
tests/Makefile.am | 4 +-
.../pool-netfs-ns-mountopts.xml | 25 ++++
.../pool-netfs-ns-mountopts.xml | 25 ++++
tests/storagepoolxml2xmltest.c | 6 +
9 files changed, 307 insertions(+), 1 deletion(-)
create mode 100644 tests/storagepoolxml2xmlin/pool-netfs-ns-mountopts.xml
create mode 100644 tests/storagepoolxml2xmlout/pool-netfs-ns-mountopts.xml
diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in
index 85107c85ae..7a79ec82d8 100644
--- a/docs/formatstorage.html.in
+++ b/docs/formatstorage.html.in
@@ -508,6 +508,69 @@
device, measured in bytes. Since 0.4.1
+
+
+
+ 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.
+
+
+ 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.
+
+
+ fs:mount_opts
+ Provides an XML namespace mechanism to optionally utilize
+ specifically named options for the mount command via the "-o"
+ option for the fs
or netfs
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:fs='http://libvirt.org/schemas/storagepool/source/fs/1.0'
+
+
+
+ The fs:mount_opts
defines the mount options by
+ specifying multiple fs:option
subelements with
+ the attribute name
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.
+
+
+ The following XML snippet shows the syntax required in order to
+ utilize for a netfs pool:
+
+<pool type="netfs" xmlns:fs='http://libvirt.org/schemas/storagepool/source/fs/1.0'>
+ <name>nfsimages</name>
+...
+ <source>
+...
+ </source>
+...
+ <target>
+...
+ </target>
+ <fs:mount_opts>
+ <fs:option name='sync'/>
+ <fs:option name='lazytime'/>
+ </fs:mount_opts>
+</pool>
+...
+
+ Since 5.1.0.
+
+
+
A storage volume will generally be either a file or a device
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index f9a16422cc..0b359669af 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -52,6 +52,9 @@
+
+
+
@@ -64,6 +67,9 @@
+
+
+
@@ -682,4 +688,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index dc9869417e..0ec99c60ed 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -41,6 +41,7 @@ VIR_LOG_INIT("storage.storage_backend_fs");
#if WITH_STORAGE_FS
+# include
# include
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:
+ *
+ *
+ *
+ *
+ *
+ *
+ * and the or 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, "\n");
+ virBufferAdjustIndent(buf, 2);
+
+ for (i = 0; i < def->noptions; i++)
+ virBufferEscapeString(buf, " \n",
+ def->options[i]);
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, " \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;
diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
index a5cb47b4d0..4596cd4518 100644
--- a/src/storage/storage_util.c
+++ b/src/storage/storage_util.c
@@ -82,6 +82,22 @@
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)
diff --git a/src/storage/storage_util.h b/src/storage/storage_util.h
index c872468135..8b44b54a3b 100644
--- a/src/storage/storage_util.h
+++ b/src/storage/storage_util.h
@@ -26,6 +26,20 @@
# 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
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f74d8463b6..ab4c716529 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 0000000000..0434b16eb7
--- /dev/null
+++ b/tests/storagepoolxml2xmlin/pool-netfs-ns-mountopts.xml
@@ -0,0 +1,25 @@
+
+ nfsimages
+ 7641d5a8-af11-f730-a34e-0a7dfcede71f
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+ /mnt
+
+ 0700
+ 0
+ 0
+
+
+
+
+
+
+
diff --git a/tests/storagepoolxml2xmlout/pool-netfs-ns-mountopts.xml b/tests/storagepoolxml2xmlout/pool-netfs-ns-mountopts.xml
new file mode 100644
index 0000000000..4bd164f220
--- /dev/null
+++ b/tests/storagepoolxml2xmlout/pool-netfs-ns-mountopts.xml
@@ -0,0 +1,25 @@
+
+ nfsimages
+ 7641d5a8-af11-f730-a34e-0a7dfcede71f
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+ /mnt
+
+ 0700
+ 0
+ 0
+
+
+
+
+
+
+
diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
index d18390034f..aff9ff160c 100644
--- a/tests/storagepoolxml2xmltest.c
+++ b/tests/storagepoolxml2xmltest.c
@@ -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");