mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +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
|
static int
|
||||||
qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt,
|
qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt,
|
||||||
virStorageSource *src)
|
virStorageSource *src)
|
||||||
@ -1971,6 +1998,7 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt,
|
|||||||
bool fdsetPresent = false;
|
bool fdsetPresent = false;
|
||||||
unsigned int fdSetID;
|
unsigned int fdSetID;
|
||||||
int enccount;
|
int enccount;
|
||||||
|
xmlNodePtr nbdkitnode = NULL;
|
||||||
|
|
||||||
src->nodestorage = virXPathString("string(./nodenames/nodename[@type='storage']/@name)", ctxt);
|
src->nodestorage = virXPathString("string(./nodenames/nodename[@type='storage']/@name)", ctxt);
|
||||||
src->nodeformat = virXPathString("string(./nodenames/nodename[@type='format']/@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)
|
virTristateBoolTypeFromString(thresholdEventWithIndex) == VIR_TRISTATE_BOOL_YES)
|
||||||
src->thresholdEventWithIndex = true;
|
src->thresholdEventWithIndex = true;
|
||||||
|
|
||||||
|
if ((nbdkitnode = virXPathNode("nbdkit", ctxt))) {
|
||||||
|
if (qemuStorageSourcePrivateDataParseNbdkit(nbdkitnode, ctxt, src) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
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
|
static int
|
||||||
qemuStorageSourcePrivateDataFormat(virStorageSource *src,
|
qemuStorageSourcePrivateDataFormat(virStorageSource *src,
|
||||||
virBuffer *buf)
|
virBuffer *buf)
|
||||||
@ -2102,6 +2151,9 @@ qemuStorageSourcePrivateDataFormat(virStorageSource *src,
|
|||||||
if (src->thresholdEventWithIndex)
|
if (src->thresholdEventWithIndex)
|
||||||
virBufferAddLit(buf, "<thresholdEvent indexUsed='yes'/>\n");
|
virBufferAddLit(buf, "<thresholdEvent indexUsed='yes'/>\n");
|
||||||
|
|
||||||
|
if (srcPriv)
|
||||||
|
qemuStorageSourcePrivateDataFormatNbdkit(srcPriv->nbdkitProcess, buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,6 +627,77 @@ qemuNbdkitProcessNew(virStorageSource *source,
|
|||||||
return nbdkit;
|
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
|
bool
|
||||||
qemuNbdkitInitStorageSource(qemuNbdkitCaps *caps,
|
qemuNbdkitInitStorageSource(qemuNbdkitCaps *caps,
|
||||||
|
@ -54,6 +54,14 @@ qemuNbdkitInitStorageSource(qemuNbdkitCaps *nbdkitCaps,
|
|||||||
uid_t user,
|
uid_t user,
|
||||||
gid_t group);
|
gid_t group);
|
||||||
|
|
||||||
|
void
|
||||||
|
qemuNbdkitReconnectStorageSource(virStorageSource *source,
|
||||||
|
const char *pidfile,
|
||||||
|
const char *socketfile);
|
||||||
|
|
||||||
|
void
|
||||||
|
qemuNbdkitStorageSourceManageProcess(virStorageSource *src);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
qemuNbdkitCapsGet(qemuNbdkitCaps *nbdkitCaps,
|
qemuNbdkitCapsGet(qemuNbdkitCaps *nbdkitCaps,
|
||||||
qemuNbdkitCapsFlags flag);
|
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 */
|
/* update domain state XML with possibly updated state in virDomainObj */
|
||||||
if (virDomainObjSave(obj, driver->xmlopt, cfg->stateDir) < 0)
|
if (virDomainObjSave(obj, driver->xmlopt, cfg->stateDir) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -345,6 +345,10 @@
|
|||||||
<fdset type='storage' id='1337'/>
|
<fdset type='storage' id='1337'/>
|
||||||
</fdsets>
|
</fdsets>
|
||||||
<thresholdEvent indexUsed='yes'/>
|
<thresholdEvent indexUsed='yes'/>
|
||||||
|
<nbdkit>
|
||||||
|
<pidfile>/path/to/nbdkit.pid</pidfile>
|
||||||
|
<socketfile>/path/to/nbdkit.socket</socketfile>
|
||||||
|
</nbdkit>
|
||||||
</privateData>
|
</privateData>
|
||||||
</source>
|
</source>
|
||||||
<backingStore/>
|
<backingStore/>
|
||||||
|
Loading…
Reference in New Issue
Block a user