With the 'on_reboot' lifecycle action set to 'destroy' (QEMU
-action reboot=shutdown), a guest-initiated reboot is converted
into a shutdown. The QMP SHUTDOWN event carries a 'reason' field
distinguishing 'guest-reset' (guest requested a reboot) from
'guest-shutdown' (guest powered off), but libvirt discarded it.

Thread the reason through the monitor shutdown callback and map
'guest-reset' to a new VIR_DOMAIN_EVENT_SHUTDOWN_GUEST_RESET
lifecycle detail so that management applications can tell a
reboot apart from a poweroff when handling the SHUTDOWN event.

Signed-off-by: Jean-Louis Dupond <[email protected]>
---
 examples/c/misc/event-test.c     |  3 +++
 include/libvirt/libvirt-domain.h |  5 +++++
 src/qemu/qemu_monitor.c          |  2 +-
 src/qemu/qemu_monitor.h          |  3 ++-
 src/qemu/qemu_process.c          | 35 +++++++++++++++++++-------------
 tools/virsh-domain-event.c       |  3 ++-
 6 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c
index 601f5eafcf..f43f73fa6f 100644
--- a/examples/c/misc/event-test.c
+++ b/examples/c/misc/event-test.c
@@ -252,6 +252,9 @@ eventDetailToString(int event,
             case VIR_DOMAIN_EVENT_SHUTDOWN_HOST:
                 return "Host request";
 
+            case VIR_DOMAIN_EVENT_SHUTDOWN_GUEST_RESET:
+                return "Guest reboot request";
+
             case VIR_DOMAIN_EVENT_SHUTDOWN_LAST:
                 break;
             }
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 99208137c3..0c68755ec4 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -5806,6 +5806,11 @@ typedef enum {
      */
     VIR_DOMAIN_EVENT_SHUTDOWN_HOST = 2,
 
+    /* Domain finished shutting down because the guest requested a reboot
+     * while the 'on_reboot' lifecycle action was set to 'destroy' (Since: 
13.0.0)
+     */
+    VIR_DOMAIN_EVENT_SHUTDOWN_GUEST_RESET = 3,
+
 # ifdef VIR_ENUM_SENTINELS
     VIR_DOMAIN_EVENT_SHUTDOWN_LAST /* (Since: 0.9.10) */
 # endif
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 21df06ebd8..2763a5fb4c 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1082,7 +1082,7 @@ qemuMonitorEmitShutdown(qemuMonitor *mon, virTristateBool 
guest,
             qemuDomainSetFakeReboot(vm, true);
     }
 
-    QEMU_MONITOR_CALLBACK(mon, domainShutdown, mon->vm, guest);
+    QEMU_MONITOR_CALLBACK(mon, domainShutdown, mon->vm, guest, reason);
 }
 
 
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index e560618bf4..17d1018cd0 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -208,7 +208,8 @@ typedef void (*qemuMonitorDomainEventCallback)(qemuMonitor 
*mon,
                                                const char *details);
 typedef void (*qemuMonitorDomainShutdownCallback)(qemuMonitor *mon,
                                                   virDomainObj *vm,
-                                                  virTristateBool guest);
+                                                  virTristateBool guest,
+                                                  const char *reason);
 typedef void (*qemuMonitorDomainResetCallback)(qemuMonitor *mon,
                                                virDomainObj *vm);
 typedef void (*qemuMonitorDomainStopCallback)(qemuMonitor *mon,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index aaa9046146..d28cede5e8 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -746,14 +746,16 @@ qemuProcessHandleEvent(qemuMonitor *mon G_GNUC_UNUSED,
 static void
 qemuProcessHandleShutdown(qemuMonitor *mon G_GNUC_UNUSED,
                           virDomainObj *vm,
-                          virTristateBool guest_initiated)
+                          virTristateBool guest_initiated,
+                          const char *reason)
 {
     virQEMUDriver *driver;
     qemuDomainObjPrivate *priv;
     virObjectEvent *event = NULL;
     int detail = 0;
 
-    VIR_DEBUG("vm=%p", vm);
+    VIR_DEBUG("vm=%p guest=%u reason=%s", vm, guest_initiated,
+              NULLSTR(reason));
 
     virObjectLock(vm);
 
@@ -780,20 +782,25 @@ qemuProcessHandleShutdown(qemuMonitor *mon G_GNUC_UNUSED,
                              VIR_DOMAIN_SHUTDOWN,
                              VIR_DOMAIN_SHUTDOWN_UNKNOWN);
 
-        switch (guest_initiated) {
-        case VIR_TRISTATE_BOOL_YES:
-            detail = VIR_DOMAIN_EVENT_SHUTDOWN_GUEST;
-            break;
+        if (guest_initiated == VIR_TRISTATE_BOOL_YES &&
+            STREQ_NULLABLE(reason, "guest-reset")) {
+            detail = VIR_DOMAIN_EVENT_SHUTDOWN_GUEST_RESET;
+        } else {
+            switch (guest_initiated) {
+            case VIR_TRISTATE_BOOL_YES:
+                detail = VIR_DOMAIN_EVENT_SHUTDOWN_GUEST;
+                break;
 
-        case VIR_TRISTATE_BOOL_NO:
-            detail = VIR_DOMAIN_EVENT_SHUTDOWN_HOST;
-            break;
+            case VIR_TRISTATE_BOOL_NO:
+                detail = VIR_DOMAIN_EVENT_SHUTDOWN_HOST;
+                break;
 
-        case VIR_TRISTATE_BOOL_ABSENT:
-        case VIR_TRISTATE_BOOL_LAST:
-        default:
-            detail = VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED;
-            break;
+            case VIR_TRISTATE_BOOL_ABSENT:
+            case VIR_TRISTATE_BOOL_LAST:
+            default:
+                detail = VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED;
+                break;
+            }
         }
 
         event = virDomainEventLifecycleNewFromObj(vm,
diff --git a/tools/virsh-domain-event.c b/tools/virsh-domain-event.c
index a541b155f4..6e6d0de93e 100644
--- a/tools/virsh-domain-event.c
+++ b/tools/virsh-domain-event.c
@@ -114,7 +114,8 @@ VIR_ENUM_IMPL(virshDomainEventShutdown,
               VIR_DOMAIN_EVENT_SHUTDOWN_LAST,
               N_("Finished"),
               N_("Finished after guest request"),
-              N_("Finished after host request"));
+              N_("Finished after host request"),
+              N_("Finished after guest reboot request"));
 
 VIR_ENUM_DECL(virshDomainEventPMSuspended);
 VIR_ENUM_IMPL(virshDomainEventPMSuspended,
-- 
2.55.0

Reply via email to