https://bugzilla.redhat.com/show_bug.cgi?id=1293351 Since we already have virtio channel events, we know when guest agent within guest has (dis-)connected. Instead of us blindly connecting to a socket that no one is listening to, we can just follow what qemu-ga does. This has a nice benefit that we don't need to 'guest-ping' the agent just to timeout and find out nobody is listening. The way that this commit is implemented: - don't connect in qemuProcessLaunch directly, defer that to event callback (which already follows the agent) - processSerialChangedEvent - after migration is settled, before we resume vCPUs, ask qemu whether somebody is listening on the socket and if so, connect to it. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- diff to v4: - drop asking qemu in qemuConnectAgent; in most cases we were asking twice. Rather put explicit virtio channel querying into places that were missing it anyway. - Move qemuConnectAgent in qemuProcessReconnect() *after* we have refreshed channel states. src/qemu/qemu_migration.c | 15 +++++++++++++++ src/qemu/qemu_process.c | 39 ++++++++++++++++++++++++--------------- src/qemu/qemu_process.h | 2 ++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 51e7125..3493d0b 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -5795,6 +5795,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver, unsigned short port; unsigned long long timeReceived = 0; virObjectEventPtr event; + int rc; VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, " "cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d", @@ -5863,6 +5864,20 @@ qemuMigrationFinish(virQEMUDriverPtr driver, if (qemuMigrationStopNBDServer(driver, vm, mig) < 0) goto endjob; + if (qemuRefreshVirtioChannelState(driver, vm) < 0) + goto endjob; + + if ((rc = qemuConnectAgent(driver, vm)) < 0) { + if (rc == -2) + goto endjob; + + VIR_WARN("Cannot connect to QEMU guest agent for %s", + vm->def->name); + virResetLastError(); + priv->agentError = true; + } + + if (flags & VIR_MIGRATE_PERSIST_DEST) { if (qemuMigrationPersist(driver, vm, mig, !v3proto) < 0) { /* Hmpf. Migration was successful, but making it persistent diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index ee94d3f..b063035 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -208,6 +208,15 @@ qemuConnectAgent(virQEMUDriverPtr driver, virDomainObjPtr vm) if (!config) return 0; + if (priv->agent) + return 0; + + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VSERPORT_CHANGE) && + config->state != VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED) { + VIR_DEBUG("Deferring connecting to guest agent"); + return 0; + } + if (virSecurityManagerSetDaemonSocketLabel(driver->securityManager, vm->def) < 0) { VIR_ERROR(_("Failed to set security context for agent for %s"), @@ -1887,9 +1896,9 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriverPtr driver, } -static int -qemuProcessReconnectRefreshChannelVirtioState(virQEMUDriverPtr driver, - virDomainObjPtr vm) +int +qemuRefreshVirtioChannelState(virQEMUDriverPtr driver, + virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; virHashTablePtr info = NULL; @@ -3567,17 +3576,6 @@ qemuProcessReconnect(void *opaque) if (qemuConnectMonitor(driver, obj, QEMU_ASYNC_JOB_NONE, NULL) < 0) goto error; - /* Failure to connect to agent shouldn't be fatal */ - if ((ret = qemuConnectAgent(driver, obj)) < 0) { - if (ret == -2) - goto error; - - VIR_WARN("Cannot connect to QEMU guest agent for %s", - obj->def->name); - virResetLastError(); - priv->agentError = true; - } - if (qemuHostdevUpdateActiveDomainDevices(driver, obj->def) < 0) goto error; @@ -3664,7 +3662,7 @@ qemuProcessReconnect(void *opaque) if (qemuDomainCheckEjectableMedia(driver, obj, QEMU_ASYNC_JOB_NONE) < 0) goto error; - if (qemuProcessReconnectRefreshChannelVirtioState(driver, obj) < 0) + if (qemuRefreshVirtioChannelState(driver, obj) < 0) goto error; if (qemuProcessRefreshBalloonState(driver, obj, QEMU_ASYNC_JOB_NONE) < 0) @@ -3676,6 +3674,17 @@ qemuProcessReconnect(void *opaque) if (qemuProcessUpdateDevices(driver, obj) < 0) goto error; + /* Failure to connect to agent shouldn't be fatal */ + if ((ret = qemuConnectAgent(driver, obj)) < 0) { + if (ret == -2) + goto error; + + VIR_WARN("Cannot connect to QEMU guest agent for %s", + obj->def->name); + virResetLastError(); + priv->agentError = true; + } + /* update domain state XML with possibly updated state in virDomainObj */ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, obj) < 0) goto error; diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index cb5cee1..48e5632 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -153,4 +153,6 @@ virDomainDiskDefPtr qemuProcessFindDomainDiskByAlias(virDomainObjPtr vm, int qemuConnectAgent(virQEMUDriverPtr driver, virDomainObjPtr vm); +int qemuRefreshVirtioChannelState(virQEMUDriverPtr driver, + virDomainObjPtr vm); #endif /* __QEMU_PROCESS_H__ */ -- 2.4.10 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list