mirror of https://gitee.com/openkylin/libvirt.git
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:
parent
bfbbb78ca3
commit
2ad46e5b0e
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue