qemu: Do not poll for spice migration status

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@redhat.com>
This commit is contained in:
Jiri Denemark 2015-05-25 16:57:49 +02:00
parent bfbbb78ca3
commit 2ad46e5b0e
8 changed files with 41 additions and 128 deletions

View File

@ -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);
}

View File

@ -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,

View File

@ -2416,45 +2416,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;
}
@ -3680,7 +3664,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);

View File

@ -2123,16 +2123,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,

View File

@ -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,

View File

@ -2684,55 +2684,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)

View File

@ -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

View File

@ -1705,45 +1705,6 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStatus(const void *data)
return ret;
}
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)
{
@ -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);