qemu: Add qemuNbdkitProcess

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@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
Jonathon Jongsma 2022-07-05 17:00:11 -05:00
parent 0c00059a72
commit 1475c8c0d7
6 changed files with 167 additions and 0 deletions

View File

@ -1655,3 +1655,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)
{
g_autofree char *nbdkitBinary = virFindFileInPath("nbdkit");
if (!nbdkitBinary)
return NULL;
return virFileCacheLookup(driver->nbdkitCapsCache, nbdkitBinary);
}

View File

@ -377,3 +377,5 @@ int qemuGetMemoryBackingPath(virQEMUDriver *driver,
int qemuHugepageMakeBasedir(virQEMUDriver *driver,
virHugeTLBFS *hugepage);
qemuNbdkitCaps* qemuGetNbdkitCaps(virQEMUDriver *driver);

View File

@ -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);
}
@ -10459,6 +10460,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
@ -11288,6 +11317,8 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
if (qemuDomainPrepareStorageSourceFDs(src, priv) < 0)
return -1;
qemuDomainPrepareStorageSourceNbdkit(src, cfg, src->nodestorage, priv);
return 0;
}

View File

@ -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);

View File

@ -549,3 +549,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);
}

View File

@ -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);