);
+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,
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));
memset(job, 0, sizeof(*job));
job->active = priv->job.active;
job->asyncJob = priv->job.asyncJob;
+ job->phase = priv->job.phase;
qemuDomainObjResetJob(priv);
qemuDomainObjResetAsyncJob(priv);
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;
}
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;
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)
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 */
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 */
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,