[PATCH 0/1] Report guest reboot as shutdown detail
In oVirt for example, we have the concept of next-run config. This is a new config (memory/cpu/devices/etc) for the VM that cannot be applied live. When a next-run config exists, we set the VM to destroy on guest reboot, so we can boot it again with it's new settings on a reboot. But to be able to distinguish a reboot vs a shutdown (so we know if we need to boot the VM again or not), we need to know what has been triggered within the VM. But this is currently not passed via any event. Therefor this patch adds a new event, so we are able to distinguish a in-guest reboot vs shutdown. Jean-Louis Dupond (1): qemu: report guest reboot as shutdown detail for on_reboot=destroy 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(-) -- 2.55.0
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 <jean-louis@dupond.be> --- 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
participants (1)
-
Jean-Louis Dupond