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. --- src/qemu/qemu_domain.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_domain.h | 9 ++++++ 2 files changed, 83 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b26308e..d0dd764 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -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; @@ -595,6 +654,20 @@ qemuDomainObjSaveJob(struct qemud_driver *driver, virDomainObjPtr obj) } 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) { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 49be3d2..7245e67 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -91,6 +91,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 */ @@ -133,6 +134,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 */ @@ -175,6 +181,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, -- 1.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list