diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b26308e2ae..d0dd764743 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, " %s\n", priv->lockState); if (priv->job.active || priv->job.asyncJob) { - virBufferAsprintf(buf, " \n", + virBufferAsprintf(buf, " 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) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index d721e247ef..627d61aca2 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -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,