Once we start waiting for migration events instead of polling
query-migrate, priv->job.current will not be regularly updated anymore
because we will get the current status directly from the events. Thus
virDomainGetJob{Info,Stats} will have to query QEMU, but they can't just
blindly update priv->job.current structure. This patch introduces
qemuMigrationFetchJobStatus which just fills in a caller supplied
structure and makes qemuMigrationUpdateJobStatus a tiny wrapper around
it.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
Notes:
Version 2:
- new patch
src/qemu/qemu_migration.c | 133 ++++++++++++++++++++++++++++++----------------
src/qemu/qemu_migration.h | 5 ++
2 files changed, 93 insertions(+), 45 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 84a66d6..08ea706 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2401,67 +2401,110 @@ qemuMigrationWaitForSpice(virDomainObjPtr vm)
return 0;
}
-static int
-qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- const char *job,
- qemuDomainAsyncJob asyncJob)
+
+static void
+qemuMigrationUpdateJobType(qemuDomainJobInfoPtr jobInfo)
{
- qemuDomainObjPrivatePtr priv = vm->privateData;
- qemuMonitorMigrationStatus status;
- qemuDomainJobInfoPtr jobInfo;
- int ret;
-
- memset(&status, 0, sizeof(status));
-
- ret = qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob);
- if (ret < 0) {
- /* Guest already exited or waiting for the job timed out; nothing
- * further to update. */
- return ret;
- }
- ret = qemuMonitorGetMigrationStatus(priv->mon, &status);
-
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- return -1;
-
- if (ret < 0 ||
- qemuDomainJobInfoUpdateTime(priv->job.current) < 0)
- return -1;
-
- ret = -1;
- jobInfo = priv->job.current;
- switch (status.status) {
+ switch (jobInfo->status.status) {
case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
jobInfo->type = VIR_DOMAIN_JOB_COMPLETED;
- /* fall through */
- case QEMU_MONITOR_MIGRATION_STATUS_SETUP:
- case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
- case QEMU_MONITOR_MIGRATION_STATUS_CANCELLING:
- ret = 0;
break;
case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
jobInfo->type = VIR_DOMAIN_JOB_NONE;
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("%s: %s"), job, _("is not active"));
break;
case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
jobInfo->type = VIR_DOMAIN_JOB_FAILED;
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("%s: %s"), job, _("unexpectedly failed"));
break;
case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED:
jobInfo->type = VIR_DOMAIN_JOB_CANCELLED;
+ break;
+
+ case QEMU_MONITOR_MIGRATION_STATUS_SETUP:
+ case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
+ case QEMU_MONITOR_MIGRATION_STATUS_CANCELLING:
+ break;
+ }
+}
+
+
+int
+qemuMigrationFetchJobStatus(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob asyncJob,
+ qemuDomainJobInfoPtr jobInfo)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int rv;
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ memset(&jobInfo->status, 0, sizeof(jobInfo->status));
+ rv = qemuMonitorGetMigrationStatus(priv->mon, &jobInfo->status);
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
+ return -1;
+
+ qemuMigrationUpdateJobType(jobInfo);
+ return qemuDomainJobInfoUpdateTime(jobInfo);
+}
+
+
+static int
+qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob asyncJob)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ qemuDomainJobInfoPtr jobInfo = priv->job.current;
+ qemuDomainJobInfo newInfo = *jobInfo;
+
+ if (qemuMigrationFetchJobStatus(driver, vm, asyncJob, &newInfo) < 0)
+ return -1;
+
+ *jobInfo = newInfo;
+ return 0;
+}
+
+
+static int
+qemuMigrationCheckJobStatus(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ const char *job,
+ qemuDomainAsyncJob asyncJob)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ qemuDomainJobInfoPtr jobInfo = priv->job.current;
+
+ if (qemuMigrationUpdateJobStatus(driver, vm, asyncJob) < 0)
+ return -1;
+
+ switch (jobInfo->type) {
+ case VIR_DOMAIN_JOB_NONE:
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("%s: %s"), job, _("is not active"));
+ return -1;
+
+ case VIR_DOMAIN_JOB_FAILED:
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("%s: %s"), job, _("unexpectedly failed"));
+ return -1;
+
+ case VIR_DOMAIN_JOB_CANCELLED:
virReportError(VIR_ERR_OPERATION_ABORTED,
_("%s: %s"), job, _("canceled by client"));
+ return -1;
+
+ case VIR_DOMAIN_JOB_BOUNDED:
+ case VIR_DOMAIN_JOB_UNBOUNDED:
+ case VIR_DOMAIN_JOB_COMPLETED:
+ case VIR_DOMAIN_JOB_LAST:
break;
}
- jobInfo->status = status;
-
- return ret;
+ return 0;
}
@@ -2502,7 +2545,7 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver,
/* Poll every 50ms for progress & to allow cancellation */
struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
- if (qemuMigrationUpdateJobStatus(driver, vm, job, asyncJob) == -1)
+ if (qemuMigrationCheckJobStatus(driver, vm, job, asyncJob) < 0)
goto error;
if (storage &&
@@ -4108,8 +4151,8 @@ qemuMigrationRun(virQEMUDriverPtr driver,
* rather failed later on. Check its status before waiting for a
* connection from qemu which may never be initiated.
*/
- if (qemuMigrationUpdateJobStatus(driver, vm, _("migration job"),
- QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
+ if (qemuMigrationCheckJobStatus(driver, vm, _("migration job"),
+ QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
goto cancel;
while ((fd = accept(spec->dest.unix_socket.sock, NULL, NULL)) < 0) {
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index e47bde5..65dfdec 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -180,4 +180,9 @@ int qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
int qemuMigrationCancel(virQEMUDriverPtr driver,
virDomainObjPtr vm);
+int qemuMigrationFetchJobStatus(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob asyncJob,
+ qemuDomainJobInfoPtr jobInfo);
+
#endif /* __QEMU_MIGRATION_H__ */
--
2.4.1