From a03e2d3a9927eb2d207dc83e3e45c2e403732330 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Fri, 24 Apr 2015 16:48:26 +0200 Subject: [PATCH] qemu: Connect to guest agent after channel hotplug If a user hot-attaches the guest agent channel libvirt would ignore it until the restart of libvirtd or shutdown/destroy and start of the VM itself. This patch adds code that opens or closes the guest agent connection according to the state of the guest agent channel according to connect/disconnect events. To allow opening the channel from the event handler qemuConnectAgent needed to be exported. --- src/qemu/qemu_driver.c | 35 +++++++++++++++++++++++++++++++---- src/qemu/qemu_process.c | 2 +- src/qemu/qemu_process.h | 2 ++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6b16441907..70bf7aa1d6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4468,6 +4468,8 @@ processSerialChangedEvent(virQEMUDriverPtr driver, virDomainChrDeviceState newstate; virObjectEventPtr event = NULL; virDomainDeviceDef dev; + qemuDomainObjPrivatePtr priv = vm->privateData; + int rc; if (connected) newstate = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED; @@ -4494,10 +4496,35 @@ processSerialChangedEvent(virQEMUDriverPtr driver, dev.data.chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) goto endjob; - if (STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0") && - (event = virDomainEventAgentLifecycleNewFromObj(vm, newstate, - VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL))) - qemuDomainEventQueue(driver, event); + if (STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0")) { + switch (newstate) { + case VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED: + if (!priv->agent) { + if ((rc = qemuConnectAgent(driver, vm)) == -2) + goto endjob; + + if (rc < 0) + priv->agentError = true; + } + break; + + case VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED: + if (priv->agent) { + qemuAgentClose(priv->agent); + priv->agent = NULL; + priv->agentError = false; + } + break; + + case VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT: + case VIR_DOMAIN_CHR_DEVICE_STATE_LAST: + break; + }; + + if ((event = virDomainEventAgentLifecycleNewFromObj(vm, newstate, + VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL))) + qemuDomainEventQueue(driver, event); + } dev.data.chr->state = newstate; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 75ccb66ff5..7eeee47255 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -202,7 +202,7 @@ static qemuAgentCallbacks agentCallbacks = { }; -static int +int qemuConnectAgent(virQEMUDriverPtr driver, virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index c67b0cb677..d40f68d3a9 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -113,4 +113,6 @@ int qemuProcessSPICEAllocatePorts(virQEMUDriverPtr driver, virDomainDiskDefPtr qemuProcessFindDomainDiskByAlias(virDomainObjPtr vm, const char *alias); +int qemuConnectAgent(virQEMUDriverPtr driver, virDomainObjPtr vm); + #endif /* __QEMU_PROCESS_H__ */