QEMU_CAPS_SEAMLESS_MIGRATION capability says QEMU supports
SPICE_MIGRATE_COMPLETED event. Thus we can just drop all code which
polls query-spice and replace it with waiting for the event.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
Notes:
Version 2:
- new patch
src/qemu/qemu_domain.c | 1 +
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_migration.c | 38 ++++++++++------------------------
src/qemu/qemu_monitor.c | 10 ---------
src/qemu/qemu_monitor.h | 2 --
src/qemu/qemu_monitor_json.c | 49 --------------------------------------------
src/qemu/qemu_process.c | 28 +++++++++++++++++++++++++
tests/qemumonitorjsontest.c | 40 ------------------------------------
8 files changed, 41 insertions(+), 128 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index a1ce988..fe92a17 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -170,6 +170,7 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
job->mask = QEMU_JOB_DEFAULT_MASK;
job->dump_memory_only = false;
job->abortJob = false;
+ job->spiceMigrated = false;
VIR_FREE(job->current);
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 7479f70..55831a5 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -136,6 +136,7 @@ struct qemuDomainJobObj {
qemuDomainJobInfoPtr current; /* async job progress data */
qemuDomainJobInfoPtr completed; /* statistics data of a recently completed job
*/
bool abortJob; /* abort of the job requested */
+ bool spiceMigrated; /* spice migration completed */
};
typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver,
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 74c2657..84a66d6 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2375,45 +2375,29 @@ qemuMigrationSetPinAll(virQEMUDriverPtr driver,
}
static int
-qemuMigrationWaitForSpice(virQEMUDriverPtr driver,
- virDomainObjPtr vm)
+qemuMigrationWaitForSpice(virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
bool wait_for_spice = false;
- bool spice_migrated = false;
size_t i = 0;
- int rc;
- if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION)) {
- for (i = 0; i < vm->def->ngraphics; i++) {
- if (vm->def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
- wait_for_spice = true;
- break;
- }
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SEAMLESS_MIGRATION))
+ return 0;
+
+ for (i = 0; i < vm->def->ngraphics; i++) {
+ if (vm->def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ wait_for_spice = true;
+ break;
}
}
if (!wait_for_spice)
return 0;
- while (!spice_migrated) {
- /* Poll every 50ms for progress & to allow cancellation */
- struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
-
- if (qemuDomainObjEnterMonitorAsync(driver, vm,
- QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
+ while (!priv->job.spiceMigrated && !priv->job.abortJob) {
+ if (virDomainObjWait(vm) < 0)
return -1;
-
- rc = qemuMonitorGetSpiceMigrationStatus(priv->mon, &spice_migrated);
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- return -1;
- if (rc < 0)
- return -1;
- virObjectUnlock(vm);
- nanosleep(&ts, NULL);
- virObjectLock(vm);
}
-
return 0;
}
@@ -3587,7 +3571,7 @@ qemuMigrationConfirmPhase(virQEMUDriverPtr driver,
if (retcode == 0) {
/* If guest uses SPICE and supports seamless migration we have to hold
* up domain shutdown until SPICE server transfers its data */
- qemuMigrationWaitForSpice(driver, vm);
+ qemuMigrationWaitForSpice(vm);
qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED,
VIR_QEMU_PROCESS_STOP_MIGRATED);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 15f7852..a2a8f0d 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2201,16 +2201,6 @@ qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
int
-qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon,
- bool *spice_migrated)
-{
- QEMU_CHECK_MONITOR_JSON(mon);
-
- return qemuMonitorJSONGetSpiceMigrationStatus(mon, spice_migrated);
-}
-
-
-int
qemuMonitorMigrateToFd(qemuMonitorPtr mon,
unsigned int flags,
int fd)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 86da7ad..17b7003 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -498,8 +498,6 @@ struct _qemuMonitorMigrationStatus {
int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
qemuMonitorMigrationStatusPtr status);
-int qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon,
- bool *spice_migrated);
typedef enum {
QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 32e4100..a138f1f 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2689,55 +2689,6 @@ int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
}
-static int
-qemuMonitorJSONSpiceGetMigrationStatusReply(virJSONValuePtr reply,
- bool *spice_migrated)
-{
- virJSONValuePtr ret;
-
- if (!(ret = virJSONValueObjectGet(reply, "return"))) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("query-spice reply was missing return data"));
- return -1;
- }
-
- if (virJSONValueObjectGetBoolean(ret, "migrated", spice_migrated) < 0)
{
- /* Deliberately don't report error here as we are
- * probably dealing with older qemu which doesn't
- * report this yet. Pretend spice is migrated. */
- *spice_migrated = true;
- }
-
- return 0;
-}
-
-
-int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorPtr mon,
- bool *spice_migrated)
-{
- int ret;
- virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-spice",
- NULL);
- virJSONValuePtr reply = NULL;
-
- if (!cmd)
- return -1;
-
- ret = qemuMonitorJSONCommand(mon, cmd, &reply);
-
- if (ret == 0)
- ret = qemuMonitorJSONCheckError(cmd, reply);
-
- if (ret == 0)
- ret = qemuMonitorJSONSpiceGetMigrationStatusReply(reply,
- spice_migrated);
-
- virJSONValueFree(cmd);
- virJSONValueFree(reply);
- return ret;
-}
-
-
int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
unsigned int flags,
const char *uri)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 24d20e8..6d1ed28 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1481,6 +1481,33 @@ qemuProcessHandleSerialChanged(qemuMonitorPtr mon
ATTRIBUTE_UNUSED,
}
+static int
+qemuProcessHandleSpiceMigrated(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ qemuDomainObjPrivatePtr priv;
+
+ virObjectLock(vm);
+
+ VIR_DEBUG("Spice migration completed for domain %p %s",
+ vm, vm->def->name);
+
+ priv = vm->privateData;
+ if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) {
+ VIR_DEBUG("got SPICE_MIGRATE_COMPLETED event without a migration
job");
+ goto cleanup;
+ }
+
+ priv->job.spiceMigrated = true;
+ virDomainObjSignal(vm);
+
+ cleanup:
+ virObjectUnlock(vm);
+ return 0;
+}
+
+
static qemuMonitorCallbacks monitorCallbacks = {
.eofNotify = qemuProcessHandleMonitorEOF,
.errorNotify = qemuProcessHandleMonitorError,
@@ -1504,6 +1531,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
.domainDeviceDeleted = qemuProcessHandleDeviceDeleted,
.domainNicRxFilterChanged = qemuProcessHandleNicRxFilterChanged,
.domainSerialChange = qemuProcessHandleSerialChanged,
+ .domainSpiceMigrated = qemuProcessHandleSpiceMigrated,
};
static int
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index 0f82fd8..0623275 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -1706,45 +1706,6 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStatus(const void
*data)
}
static int
-testQemuMonitorJSONqemuMonitorJSONGetSpiceMigrationStatus(const void *data)
-{
- virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
- qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
- int ret = -1;
- bool spiceMigrated;
-
- if (!test)
- return -1;
-
- if (qemuMonitorTestAddItem(test, "query-spice",
- "{"
- " \"return\": {"
- " \"migrated\": true,"
- " \"enabled\": false,"
- " \"mouse-mode\":
\"client\""
- " },"
- " \"id\":
\"libvirt-14\""
- "}") < 0)
- goto cleanup;
-
- if (qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorTestGetMonitor(test),
- &spiceMigrated) < 0)
- goto cleanup;
-
- if (!spiceMigrated) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "Invalid spice migration status: %d, expecting 1",
- spiceMigrated);
- goto cleanup;
- }
-
- ret = 0;
- cleanup:
- qemuMonitorTestFree(test);
- return ret;
-}
-
-static int
testHashEqualChardevInfo(const void *value1, const void *value2)
{
const qemuMonitorChardevInfo *info1 = value1;
@@ -2400,7 +2361,6 @@ mymain(void)
DO_TEST(qemuMonitorJSONGetBlockStatsInfo);
DO_TEST(qemuMonitorJSONGetMigrationCacheSize);
DO_TEST(qemuMonitorJSONGetMigrationStatus);
- DO_TEST(qemuMonitorJSONGetSpiceMigrationStatus);
DO_TEST(qemuMonitorJSONGetChardevInfo);
DO_TEST(qemuMonitorJSONSetBlockIoThrottle);
DO_TEST(qemuMonitorJSONGetTargetArch);
--
2.4.1