mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-17 06:03:52 +03:00
qemu: Add support for job phase
Asynchronous jobs may take long time to finish and may consist of several phases which we need to now about to help with recovery/rollback after libvirtd restarts.
This commit is contained in:
parent
e6704af1fc
commit
5b2d0bbc4c
@ -65,6 +65,46 @@ VIR_ENUM_IMPL(qemuDomainAsyncJob, QEMU_ASYNC_JOB_LAST,
|
||||
);
|
||||
|
||||
|
||||
const char *
|
||||
qemuDomainAsyncJobPhaseToString(enum qemuDomainAsyncJob job,
|
||||
int phase ATTRIBUTE_UNUSED)
|
||||
{
|
||||
switch (job) {
|
||||
case QEMU_ASYNC_JOB_MIGRATION_OUT:
|
||||
case QEMU_ASYNC_JOB_MIGRATION_IN:
|
||||
case QEMU_ASYNC_JOB_SAVE:
|
||||
case QEMU_ASYNC_JOB_DUMP:
|
||||
case QEMU_ASYNC_JOB_NONE:
|
||||
case QEMU_ASYNC_JOB_LAST:
|
||||
; /* fall through */
|
||||
}
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
int
|
||||
qemuDomainAsyncJobPhaseFromString(enum qemuDomainAsyncJob job,
|
||||
const char *phase)
|
||||
{
|
||||
if (!phase)
|
||||
return 0;
|
||||
|
||||
switch (job) {
|
||||
case QEMU_ASYNC_JOB_MIGRATION_OUT:
|
||||
case QEMU_ASYNC_JOB_MIGRATION_IN:
|
||||
case QEMU_ASYNC_JOB_SAVE:
|
||||
case QEMU_ASYNC_JOB_DUMP:
|
||||
case QEMU_ASYNC_JOB_NONE:
|
||||
case QEMU_ASYNC_JOB_LAST:
|
||||
; /* fall through */
|
||||
}
|
||||
|
||||
if (STREQ(phase, "none"))
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
|
||||
virDomainEventPtr event,
|
||||
virConnectDomainEventGenericCallback cb,
|
||||
@ -135,6 +175,7 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
|
||||
struct qemuDomainJobObj *job = &priv->job;
|
||||
|
||||
job->asyncJob = QEMU_ASYNC_JOB_NONE;
|
||||
job->phase = 0;
|
||||
job->mask = DEFAULT_JOB_MASK;
|
||||
job->start = 0;
|
||||
memset(&job->info, 0, sizeof(job->info));
|
||||
@ -151,6 +192,7 @@ qemuDomainObjRestoreJob(virDomainObjPtr obj,
|
||||
memset(job, 0, sizeof(*job));
|
||||
job->active = priv->job.active;
|
||||
job->asyncJob = priv->job.asyncJob;
|
||||
job->phase = priv->job.phase;
|
||||
|
||||
qemuDomainObjResetJob(priv);
|
||||
qemuDomainObjResetAsyncJob(priv);
|
||||
@ -249,9 +291,15 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
|
||||
virBufferAsprintf(buf, " <lockstate>%s</lockstate>\n", priv->lockState);
|
||||
|
||||
if (priv->job.active || priv->job.asyncJob) {
|
||||
virBufferAsprintf(buf, " <job type='%s' async='%s'/>\n",
|
||||
virBufferAsprintf(buf, " <job type='%s' async='%s'",
|
||||
qemuDomainJobTypeToString(priv->job.active),
|
||||
qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
|
||||
if (priv->job.phase) {
|
||||
virBufferAsprintf(buf, " phase='%s'",
|
||||
qemuDomainAsyncJobPhaseToString(
|
||||
priv->job.asyncJob, priv->job.phase));
|
||||
}
|
||||
virBufferAddLit(buf, "/>\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -384,6 +432,17 @@ static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
|
||||
}
|
||||
VIR_FREE(tmp);
|
||||
priv->job.asyncJob = async;
|
||||
|
||||
if ((tmp = virXPathString("string(./job[1]/@phase)", ctxt))) {
|
||||
priv->job.phase = qemuDomainAsyncJobPhaseFromString(async, tmp);
|
||||
if (priv->job.phase < 0) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unknown job phase %s"), tmp);
|
||||
VIR_FREE(tmp);
|
||||
goto error;
|
||||
}
|
||||
VIR_FREE(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -594,6 +653,20 @@ qemuDomainObjSaveJob(struct qemud_driver *driver, virDomainObjPtr obj)
|
||||
VIR_WARN("Failed to save status on vm %s", obj->def->name);
|
||||
}
|
||||
|
||||
void
|
||||
qemuDomainObjSetJobPhase(struct qemud_driver *driver,
|
||||
virDomainObjPtr obj,
|
||||
int phase)
|
||||
{
|
||||
qemuDomainObjPrivatePtr priv = obj->privateData;
|
||||
|
||||
if (!priv->job.asyncJob)
|
||||
return;
|
||||
|
||||
priv->job.phase = phase;
|
||||
qemuDomainObjSaveJob(driver, obj);
|
||||
}
|
||||
|
||||
void
|
||||
qemuDomainObjSetAsyncJobMask(virDomainObjPtr obj,
|
||||
unsigned long long allowedJobs)
|
||||
|
@ -97,6 +97,7 @@ struct qemuDomainJobObj {
|
||||
|
||||
virCond asyncCond; /* Use to coordinate with async jobs */
|
||||
enum qemuDomainAsyncJob asyncJob; /* Currently active async job */
|
||||
int phase; /* Job phase (mainly for migrations) */
|
||||
unsigned long long mask; /* Jobs allowed during async job */
|
||||
unsigned long long start; /* When the async job started */
|
||||
virDomainJobInfo info; /* Async job progress data */
|
||||
@ -140,6 +141,11 @@ struct qemuDomainWatchdogEvent
|
||||
int action;
|
||||
};
|
||||
|
||||
const char *qemuDomainAsyncJobPhaseToString(enum qemuDomainAsyncJob job,
|
||||
int phase);
|
||||
int qemuDomainAsyncJobPhaseFromString(enum qemuDomainAsyncJob job,
|
||||
const char *phase);
|
||||
|
||||
void qemuDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque);
|
||||
|
||||
/* driver must be locked before calling */
|
||||
@ -182,6 +188,9 @@ void qemuDomainObjEndNestedJob(struct qemud_driver *driver,
|
||||
virDomainObjPtr obj);
|
||||
|
||||
void qemuDomainObjSaveJob(struct qemud_driver *driver, virDomainObjPtr obj);
|
||||
void qemuDomainObjSetJobPhase(struct qemud_driver *driver,
|
||||
virDomainObjPtr obj,
|
||||
int phase);
|
||||
void qemuDomainObjSetAsyncJobMask(virDomainObjPtr obj,
|
||||
unsigned long long allowedJobs);
|
||||
void qemuDomainObjRestoreJob(virDomainObjPtr obj,
|
||||
|
Loading…
x
Reference in New Issue
Block a user