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(a)redhat.com>
---
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