An object for storing information about a nbdkit process that is serving
a specific virStorageSource. At the moment, this information is just
stored in the private data of virStorageSource and not used at all.
Future commits will use this data to actually start a nbdkit process.
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
Reviewed-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_conf.c | 22 ++++++++++++
src/qemu/qemu_conf.h | 2 ++
src/qemu/qemu_domain.c | 31 ++++++++++++++++
src/qemu/qemu_domain.h | 4 +++
src/qemu/qemu_nbdkit.c | 82 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_nbdkit.h | 26 ++++++++++++++
6 files changed, 167 insertions(+)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index bd984448a3..bf6c42f637 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1659,3 +1659,25 @@ qemuHugepageMakeBasedir(virQEMUDriver *driver,
return 0;
}
+
+
+/*
+ * qemuGetNbdkitCaps:
+ * @driver: the qemu driver
+ *
+ * Gets the capabilities for Nbdkit for the specified driver. These can be used
+ * to determine whether a particular disk source can be served by nbdkit or
+ * not.
+ *
+ * Returns: a reference to qemuNbdkitCaps or NULL
+ */
+qemuNbdkitCaps*
+qemuGetNbdkitCaps(virQEMUDriver *driver)
+{
+ char *nbdkitBinary = virFindFileInPath("nbdkit");
+
+ if (!nbdkitBinary)
+ return NULL;
+
+ return virFileCacheLookup(driver->nbdkitCapsCache, nbdkitBinary);
+}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index a44985fb8b..1a3ba3a0fb 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -377,3 +377,5 @@ int qemuGetMemoryBackingPath(virQEMUDriver *driver,
int qemuHugepageMakeBasedir(virQEMUDriver *driver,
virHugeTLBFS *hugepage);
+
+qemuNbdkitCaps* qemuGetNbdkitCaps(virQEMUDriver *driver);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 6eea8a9fa5..a12ebc7d3f 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -882,6 +882,7 @@ qemuDomainStorageSourcePrivateDispose(void *obj)
g_clear_pointer(&priv->httpcookie, qemuDomainSecretInfoFree);
g_clear_pointer(&priv->tlsKeySecret, qemuDomainSecretInfoFree);
g_clear_pointer(&priv->fdpass, qemuFDPassFree);
+ g_clear_pointer(&priv->nbdkitProcess, qemuNbdkitProcessFree);
}
@@ -10420,6 +10421,34 @@ qemuDomainPrepareStorageSourceNFS(virStorageSource *src)
}
+/* qemuPrepareStorageSourceNbdkit:
+ * @src: source for a disk
+ *
+ * If src is an network source that is managed by nbdkit, prepare data so that
+ * nbdkit can be launched before the domain is started
+ *
+ * Returns true if nbdkit will be used for this source,
+ */
+static bool
+qemuDomainPrepareStorageSourceNbdkit(virStorageSource *src,
+ virQEMUDriverConfig *cfg,
+ const char *alias,
+ qemuDomainObjPrivate *priv)
+{
+ g_autoptr(qemuNbdkitCaps) nbdkit = NULL;
+
+ if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK)
+ return false;
+
+ nbdkit = qemuGetNbdkitCaps(priv->driver);
+ if (!nbdkit)
+ return false;
+
+ return qemuNbdkitInitStorageSource(nbdkit, src, priv->libDir,
+ alias, cfg->user, cfg->group);
+}
+
+
/* qemuProcessPrepareStorageSourceTLS:
* @source: source for a disk
* @cfg: driver configuration
@@ -11249,6 +11278,8 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef
*disk,
if (qemuDomainPrepareStorageSourceFDs(src, priv) < 0)
return -1;
+ qemuDomainPrepareStorageSourceNbdkit(src, cfg, src->nodestorage, priv);
+
return 0;
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 999190e381..572cd67856 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -33,6 +33,7 @@
#include "qemu_conf.h"
#include "qemu_capabilities.h"
#include "qemu_migration_params.h"
+#include "qemu_nbdkit.h"
#include "qemu_slirp.h"
#include "qemu_fd.h"
#include "virchrdev.h"
@@ -308,6 +309,9 @@ struct _qemuDomainStorageSourcePrivate {
/* file descriptors if user asks for FDs to be passed */
qemuFDPass *fdpass;
+
+ /* an nbdkit process for serving network storage sources */
+ qemuNbdkitProcess *nbdkitProcess;
};
virObject *qemuDomainStorageSourcePrivateNew(void);
diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c
index 033a31ce32..2f9c5f19ef 100644
--- a/src/qemu/qemu_nbdkit.c
+++ b/src/qemu/qemu_nbdkit.c
@@ -550,3 +550,85 @@ qemuNbdkitCapsCacheNew(const char *cachedir)
g_autofree char *dir = g_build_filename(cachedir, "nbdkitcapabilities",
NULL);
return virFileCacheNew(dir, "xml", &nbdkitCapsCacheHandlers);
}
+
+
+static qemuNbdkitProcess *
+qemuNbdkitProcessNew(virStorageSource *source,
+ const char *pidfile,
+ const char *socketfile)
+{
+ qemuNbdkitProcess *nbdkit = g_new0(qemuNbdkitProcess, 1);
+ /* weak reference -- source owns this object, so it will always outlive us */
+ nbdkit->source = source;
+ nbdkit->user = -1;
+ nbdkit->group = -1;
+ nbdkit->pid = -1;
+ nbdkit->pidfile = g_strdup(pidfile);
+ nbdkit->socketfile = g_strdup(socketfile);
+
+ return nbdkit;
+}
+
+
+bool
+qemuNbdkitInitStorageSource(qemuNbdkitCaps *caps,
+ virStorageSource *source,
+ char *statedir,
+ const char *alias,
+ uid_t user,
+ gid_t group)
+{
+ qemuDomainStorageSourcePrivate *srcPriv =
qemuDomainStorageSourcePrivateFetch(source);
+ g_autofree char *pidname = g_strdup_printf("nbdkit-%s.pid", alias);
+ g_autofree char *socketname = g_strdup_printf("nbdkit-%s.socket", alias);
+ g_autofree char *pidfile = g_build_filename(statedir, pidname, NULL);
+ g_autofree char *socketfile = g_build_filename(statedir, socketname, NULL);
+ qemuNbdkitProcess *proc;
+
+ if (srcPriv->nbdkitProcess)
+ return false;
+
+ switch (source->protocol) {
+ case VIR_STORAGE_NET_PROTOCOL_HTTP:
+ case VIR_STORAGE_NET_PROTOCOL_HTTPS:
+ case VIR_STORAGE_NET_PROTOCOL_FTP:
+ case VIR_STORAGE_NET_PROTOCOL_FTPS:
+ case VIR_STORAGE_NET_PROTOCOL_TFTP:
+ if (!virBitmapIsBitSet(caps->flags, QEMU_NBDKIT_CAPS_PLUGIN_CURL))
+ return false;
+ break;
+ case VIR_STORAGE_NET_PROTOCOL_SSH:
+ if (!virBitmapIsBitSet(caps->flags, QEMU_NBDKIT_CAPS_PLUGIN_SSH))
+ return false;
+ break;
+ case VIR_STORAGE_NET_PROTOCOL_NONE:
+ case VIR_STORAGE_NET_PROTOCOL_NBD:
+ case VIR_STORAGE_NET_PROTOCOL_RBD:
+ case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
+ case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
+ case VIR_STORAGE_NET_PROTOCOL_ISCSI:
+ case VIR_STORAGE_NET_PROTOCOL_VXHS:
+ case VIR_STORAGE_NET_PROTOCOL_NFS:
+ case VIR_STORAGE_NET_PROTOCOL_LAST:
+ return false;
+ }
+
+ proc = qemuNbdkitProcessNew(source, pidfile, socketfile);
+ proc->caps = g_object_ref(caps);
+ proc->user = user;
+ proc->group = group;
+
+ srcPriv->nbdkitProcess = proc;
+
+ return true;
+}
+
+
+void
+qemuNbdkitProcessFree(qemuNbdkitProcess *proc)
+{
+ g_clear_pointer(&proc->pidfile, g_free);
+ g_clear_pointer(&proc->socketfile, g_free);
+ g_clear_object(&proc->caps);
+ g_free(proc);
+}
diff --git a/src/qemu/qemu_nbdkit.h b/src/qemu/qemu_nbdkit.h
index 4aba7c8455..8844bba13c 100644
--- a/src/qemu/qemu_nbdkit.h
+++ b/src/qemu/qemu_nbdkit.h
@@ -20,10 +20,12 @@
#pragma once
#include "internal.h"
+#include "storage_source_conf.h"
#include "virenum.h"
#include "virfilecache.h"
typedef struct _qemuNbdkitCaps qemuNbdkitCaps;
+typedef struct _qemuNbdkitProcess qemuNbdkitProcess;
typedef enum {
/* 0 */
@@ -42,6 +44,14 @@ qemuNbdkitCapsNew(const char *path);
virFileCache *
qemuNbdkitCapsCacheNew(const char *cachedir);
+bool
+qemuNbdkitInitStorageSource(qemuNbdkitCaps *nbdkitCaps,
+ virStorageSource *source,
+ char *statedir,
+ const char *alias,
+ uid_t user,
+ gid_t group);
+
bool
qemuNbdkitCapsGet(qemuNbdkitCaps *nbdkitCaps,
qemuNbdkitCapsFlags flag);
@@ -52,3 +62,19 @@ qemuNbdkitCapsSet(qemuNbdkitCaps *nbdkitCaps,
#define QEMU_TYPE_NBDKIT_CAPS qemu_nbdkit_caps_get_type()
G_DECLARE_FINAL_TYPE(qemuNbdkitCaps, qemu_nbdkit_caps, QEMU, NBDKIT_CAPS, GObject);
+
+struct _qemuNbdkitProcess {
+ qemuNbdkitCaps *caps;
+ virStorageSource *source;
+
+ char *pidfile;
+ char *socketfile;
+ uid_t user;
+ gid_t group;
+ pid_t pid;
+};
+
+void
+qemuNbdkitProcessFree(qemuNbdkitProcess *proc);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuNbdkitProcess, qemuNbdkitProcessFree);
--
2.41.0