]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: emit channel lifecycle event
authorLucas Kornicki <lucas.kornicki@nutanix.com>
Tue, 19 May 2026 13:11:36 +0000 (15:11 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 21 May 2026 13:32:54 +0000 (15:32 +0200)
Emit the channel lifecycle event on VSERPORT_CHANGE
and when refreshing virtio state.

On "org.qemu.guest_agent.0" channel state change both
agent and channel lifecycle events are emitted in that order.

Signed-off-by: Lucas Kornicki <lucas.kornicki@nutanix.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_driver.c
src/qemu/qemu_process.c

index eda1f42054af7c6d00f303569d3a27c9bcc878c2..bcafacfb60e57892688a96752684c9936122b24e 100644 (file)
@@ -3891,6 +3891,7 @@ processSerialChangedEvent(virQEMUDriver *driver,
     qemuDomainSaveStatus(vm);
 
     if (STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0")) {
+        virObjectEvent *agentEvent = NULL;
         if (newstate == VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED) {
             if (qemuConnectAgent(driver, vm) < 0)
                 goto endjob;
@@ -3901,11 +3902,19 @@ processSerialChangedEvent(virQEMUDriver *driver,
             priv->agentError = false;
         }
 
-        event = virDomainEventAgentLifecycleNewFromObj(vm, newstate,
-                                                       VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL);
-        virObjectEventStateQueue(driver->domainEventState, event);
+        agentEvent = virDomainEventAgentLifecycleNewFromObj(vm, newstate,
+                                                            VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL);
+        virObjectEventStateQueue(driver->domainEventState, agentEvent);
     }
 
+    /* we deliberately allow for goto endjob to skip generic event emission
+     * to ensure identical semantics for "org.qemu.guest_agent.0" */
+    event = virDomainEventChannelLifecycleNewFromObj(vm,
+                                                     dev.data.chr->target.name,
+                                                     newstate,
+                                                     VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_CHANNEL);
+    virObjectEventStateQueue(driver->domainEventState, event);
+
  endjob:
     virDomainObjEndJob(vm);
 }
index 83f5ebb19cb0e52d4a53955dc7c61340cc134e50..3561b6d17d5634b827b059af7251cb41c7d2ac1f 100644 (file)
@@ -2253,7 +2253,6 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriver *driver,
     size_t i;
     int agentReason = VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL;
     qemuMonitorChardevInfo *entry;
-    virObjectEvent *event = NULL;
     g_autofree char *id = NULL;
 
     if (booted)
@@ -2261,6 +2260,8 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriver *driver,
 
     for (i = 0; i < vm->def->nchannels; i++) {
         virDomainChrDef *chr = vm->def->channels[i];
+        virObjectEvent *events[2] = { 0 };
+
         if (chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
 
             VIR_FREE(id);
@@ -2271,11 +2272,21 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriver *driver,
                 !entry->state)
                 continue;
 
-            if (entry->state != VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT &&
-                STREQ_NULLABLE(chr->target.name, "org.qemu.guest_agent.0") &&
-                (event = virDomainEventAgentLifecycleNewFromObj(vm, entry->state,
-                                                                agentReason)))
-                virObjectEventStateQueue(driver->domainEventState, event);
+            if (entry->state != VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT) {
+                events[0] = virDomainEventChannelLifecycleNewFromObj(vm,
+                                                                     chr->target.name,
+                                                                     entry->state,
+                                                                     agentReason);
+                if (STREQ_NULLABLE(chr->target.name, "org.qemu.guest_agent.0")) {
+                    events[1] = virDomainEventAgentLifecycleNewFromObj(vm,
+                                                                       entry->state,
+                                                                       agentReason);
+                }
+
+                /* emit agent then channel when emitting both events */
+                virObjectEventStateQueue(driver->domainEventState, events[1]);
+                virObjectEventStateQueue(driver->domainEventState, events[0]);
+            }
 
             chr->state = entry->state;
         }