mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
qemu: include nbdkit state in private xml
Add xml to the private data for a disk source to represent the nbdkit process so that the state can be re-created if the libvirt daemon is restarted. Format: <nbdkit> <pidfile>/path/to/nbdkit.pid</pidfile> <socketfile>/path/to/nbdkit.socket</socketfile> </nbdkit> Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
d20a6eda44
commit
dfa657aa27
@ -1958,6 +1958,33 @@ qemuStorageSourcePrivateDataAssignSecinfo(qemuDomainSecretInfo **secinfo,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuStorageSourcePrivateDataParseNbdkit(xmlNodePtr node,
|
||||
xmlXPathContextPtr ctxt,
|
||||
virStorageSource *src)
|
||||
{
|
||||
g_autofree char *pidfile = NULL;
|
||||
g_autofree char *socketfile = NULL;
|
||||
VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
||||
|
||||
ctxt->node = node;
|
||||
|
||||
if (!(pidfile = virXPathString("string(./pidfile)", ctxt))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing nbdkit pidfile"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(socketfile = virXPathString("string(./socketfile)", ctxt))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing nbdkit socketfile"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
qemuNbdkitReconnectStorageSource(src, pidfile, socketfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt,
|
||||
virStorageSource *src)
|
||||
@ -1971,6 +1998,7 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt,
|
||||
bool fdsetPresent = false;
|
||||
unsigned int fdSetID;
|
||||
int enccount;
|
||||
xmlNodePtr nbdkitnode = NULL;
|
||||
|
||||
src->nodestorage = virXPathString("string(./nodenames/nodename[@type='storage']/@name)", ctxt);
|
||||
src->nodeformat = virXPathString("string(./nodenames/nodename[@type='format']/@name)", ctxt);
|
||||
@ -2036,6 +2064,10 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt,
|
||||
virTristateBoolTypeFromString(thresholdEventWithIndex) == VIR_TRISTATE_BOOL_YES)
|
||||
src->thresholdEventWithIndex = true;
|
||||
|
||||
if ((nbdkitnode = virXPathNode("nbdkit", ctxt))) {
|
||||
if (qemuStorageSourcePrivateDataParseNbdkit(nbdkitnode, ctxt, src) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2053,6 +2085,23 @@ qemuStorageSourcePrivateDataFormatSecinfo(virBuffer *buf,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuStorageSourcePrivateDataFormatNbdkit(qemuNbdkitProcess *nbdkit,
|
||||
virBuffer *buf)
|
||||
{
|
||||
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
|
||||
|
||||
if (!nbdkit)
|
||||
return;
|
||||
|
||||
virBufferEscapeString(&childBuf, "<pidfile>%s</pidfile>\n",
|
||||
nbdkit->pidfile);
|
||||
virBufferEscapeString(&childBuf, "<socketfile>%s</socketfile>\n",
|
||||
nbdkit->socketfile);
|
||||
virXMLFormatElement(buf, "nbdkit", NULL, &childBuf);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuStorageSourcePrivateDataFormat(virStorageSource *src,
|
||||
virBuffer *buf)
|
||||
@ -2102,6 +2151,9 @@ qemuStorageSourcePrivateDataFormat(virStorageSource *src,
|
||||
if (src->thresholdEventWithIndex)
|
||||
virBufferAddLit(buf, "<thresholdEvent indexUsed='yes'/>\n");
|
||||
|
||||
if (srcPriv)
|
||||
qemuStorageSourcePrivateDataFormatNbdkit(srcPriv->nbdkitProcess, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -627,6 +627,77 @@ qemuNbdkitProcessNew(virStorageSource *source,
|
||||
return nbdkit;
|
||||
}
|
||||
|
||||
/**
|
||||
* qemuNbdkitReconnectStorageSource:
|
||||
* @source: a storage source
|
||||
* @pidfile: a pidfile for an nbdkit process
|
||||
* @socketfile: the socket file associated with the nbdkit process
|
||||
*
|
||||
* This function constructs a new qemuNbdkitProcess object with the given values for @pidfile and
|
||||
* @socketfile and stores it in @source. This is intended to be called when the libvirt daemon is
|
||||
* restarted and tries to reconnect to all currently-running domains. Since this function is called
|
||||
* from the code that parses the current daemon state, it should not perform any filesystem
|
||||
* operations, or anything else that might fail. Additional initialization will be done later by
|
||||
* calling qemuNbdkitStorageSourceManageProcess().
|
||||
*/
|
||||
void
|
||||
qemuNbdkitReconnectStorageSource(virStorageSource *source,
|
||||
const char *pidfile,
|
||||
const char *socketfile)
|
||||
{
|
||||
qemuDomainStorageSourcePrivate *srcpriv = qemuDomainStorageSourcePrivateFetch(source);
|
||||
|
||||
if (srcpriv->nbdkitProcess) {
|
||||
VIR_WARN("source already has an nbdkit process");
|
||||
return;
|
||||
}
|
||||
|
||||
srcpriv->nbdkitProcess = qemuNbdkitProcessNew(source, pidfile, socketfile);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuNbdkitStorageSourceManageProcessOne(virStorageSource *source)
|
||||
{
|
||||
qemuDomainStorageSourcePrivate *srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(source);
|
||||
qemuNbdkitProcess *proc;
|
||||
|
||||
if (!srcpriv)
|
||||
return;
|
||||
|
||||
proc = srcpriv->nbdkitProcess;
|
||||
|
||||
if (!proc)
|
||||
return;
|
||||
|
||||
if (proc->pid <= 0) {
|
||||
if (virPidFileReadPath(proc->pidfile, &proc->pid) < 0) {
|
||||
VIR_WARN("Unable to read pidfile '%s'", proc->pidfile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (virProcessKill(proc->pid, 0) < 0)
|
||||
VIR_WARN("nbdkit process %i is not alive", proc->pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* qemuNbdkitStorageSourceManageProcess:
|
||||
* @source: a storage source
|
||||
* @vm: the vm that owns this storage source
|
||||
*
|
||||
* This function re-enables monitoring of any nbdkit processes associated with the backing chain of
|
||||
* @source. It is intended to be called after libvirt restarts and has loaded its current state from
|
||||
* disk and is attempting to re-connect to active domains.
|
||||
*/
|
||||
void
|
||||
qemuNbdkitStorageSourceManageProcess(virStorageSource *source)
|
||||
{
|
||||
virStorageSource *backing;
|
||||
for (backing = source; backing != NULL; backing = backing->backingStore)
|
||||
qemuNbdkitStorageSourceManageProcessOne(backing);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
qemuNbdkitInitStorageSource(qemuNbdkitCaps *caps,
|
||||
|
@ -54,6 +54,14 @@ qemuNbdkitInitStorageSource(qemuNbdkitCaps *nbdkitCaps,
|
||||
uid_t user,
|
||||
gid_t group);
|
||||
|
||||
void
|
||||
qemuNbdkitReconnectStorageSource(virStorageSource *source,
|
||||
const char *pidfile,
|
||||
const char *socketfile);
|
||||
|
||||
void
|
||||
qemuNbdkitStorageSourceManageProcess(virStorageSource *src);
|
||||
|
||||
bool
|
||||
qemuNbdkitCapsGet(qemuNbdkitCaps *nbdkitCaps,
|
||||
qemuNbdkitCapsFlags flag);
|
||||
|
@ -9054,6 +9054,12 @@ qemuProcessReconnect(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < obj->def->ndisks; i++)
|
||||
qemuNbdkitStorageSourceManageProcess(obj->def->disks[i]->src);
|
||||
|
||||
if (obj->def->os.loader && obj->def->os.loader->nvram)
|
||||
qemuNbdkitStorageSourceManageProcess(obj->def->os.loader->nvram);
|
||||
|
||||
/* update domain state XML with possibly updated state in virDomainObj */
|
||||
if (virDomainObjSave(obj, driver->xmlopt, cfg->stateDir) < 0)
|
||||
goto error;
|
||||
|
@ -345,6 +345,10 @@
|
||||
<fdset type='storage' id='1337'/>
|
||||
</fdsets>
|
||||
<thresholdEvent indexUsed='yes'/>
|
||||
<nbdkit>
|
||||
<pidfile>/path/to/nbdkit.pid</pidfile>
|
||||
<socketfile>/path/to/nbdkit.socket</socketfile>
|
||||
</nbdkit>
|
||||
</privateData>
|
||||
</source>
|
||||
<backingStore/>
|
||||
|
Loading…
Reference in New Issue
Block a user