6d3351
From f0747aa9c94a5a79c9766959fcd479e04a56da3e Mon Sep 17 00:00:00 2001
6d3351
Message-Id: <f0747aa9c94a5a79c9766959fcd479e04a56da3e@dist-git>
6d3351
From: Martin Kletzander <mkletzan@redhat.com>
6d3351
Date: Wed, 31 May 2017 08:21:33 +0200
6d3351
Subject: [PATCH] qemu: Report shutdown event details
6d3351
6d3351
QEMU will likely report the details of it shutting down, particularly
6d3351
whether the shutdown was initiated by the guest or host.  We should
6d3351
forward that information along, at least for shutdown events.  Reset
6d3351
has that as well, however that is not a lifecycle event and would add
6d3351
extra constants that might not be used.  It can be added later on.
6d3351
6d3351
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1384007
6d3351
6d3351
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
6d3351
(cherry picked from commit a8eba5036cb4b0e2ec827e9e6e019ce70e451377)
6d3351
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
---
6d3351
 examples/object-events/event-test.c |  6 ++++++
6d3351
 include/libvirt/libvirt-domain.h    | 11 ++++++++++-
6d3351
 src/qemu/qemu_monitor.c             |  6 +++---
6d3351
 src/qemu/qemu_monitor.h             |  3 ++-
6d3351
 src/qemu/qemu_monitor_json.c        | 10 ++++++++--
6d3351
 src/qemu/qemu_process.c             | 21 +++++++++++++++++++--
6d3351
 tools/virsh-domain.c                |  4 +++-
6d3351
 7 files changed, 51 insertions(+), 10 deletions(-)
6d3351
6d3351
diff --git a/examples/object-events/event-test.c b/examples/object-events/event-test.c
6d3351
index 12690cac0..78d200806 100644
6d3351
--- a/examples/object-events/event-test.c
6d3351
+++ b/examples/object-events/event-test.c
6d3351
@@ -240,6 +240,12 @@ eventDetailToString(int event,
6d3351
             case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
6d3351
                 return "Finished";
6d3351
 
6d3351
+            case VIR_DOMAIN_EVENT_SHUTDOWN_GUEST:
6d3351
+                return "Guest request";
6d3351
+
6d3351
+            case VIR_DOMAIN_EVENT_SHUTDOWN_HOST:
6d3351
+                return "Host request";
6d3351
+
6d3351
             case VIR_DOMAIN_EVENT_SHUTDOWN_LAST:
6d3351
                 break;
6d3351
             }
6d3351
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
6d3351
index c9e96a6c9..720db32f7 100644
6d3351
--- a/include/libvirt/libvirt-domain.h
6d3351
+++ b/include/libvirt/libvirt-domain.h
6d3351
@@ -2983,7 +2983,16 @@ typedef enum {
6d3351
  * Details on the cause of a 'shutdown' lifecycle event
6d3351
  */
6d3351
 typedef enum {
6d3351
-    VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0, /* Guest finished shutdown sequence */
6d3351
+    /* Guest finished shutdown sequence */
6d3351
+    VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = 0,
6d3351
+
6d3351
+    /* Domain finished shutting down after request from the guest itself
6d3351
+     * (e.g. hardware-specific action) */
6d3351
+    VIR_DOMAIN_EVENT_SHUTDOWN_GUEST = 1,
6d3351
+
6d3351
+    /* Domain finished shutting down after request from the host (e.g. killed by
6d3351
+     * a signal) */
6d3351
+    VIR_DOMAIN_EVENT_SHUTDOWN_HOST = 2,
6d3351
 
6d3351
 # ifdef VIR_ENUM_SENTINELS
6d3351
     VIR_DOMAIN_EVENT_SHUTDOWN_LAST
6d3351
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
6d3351
index 488d761fb..b5e890607 100644
6d3351
--- a/src/qemu/qemu_monitor.c
6d3351
+++ b/src/qemu/qemu_monitor.c
6d3351
@@ -1303,12 +1303,12 @@ qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
6d3351
 
6d3351
 
6d3351
 int
6d3351
-qemuMonitorEmitShutdown(qemuMonitorPtr mon)
6d3351
+qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest)
6d3351
 {
6d3351
     int ret = -1;
6d3351
-    VIR_DEBUG("mon=%p", mon);
6d3351
+    VIR_DEBUG("mon=%p guest=%u", mon, guest);
6d3351
 
6d3351
-    QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm);
6d3351
+    QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm, guest);
6d3351
     return ret;
6d3351
 }
6d3351
 
6d3351
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
6d3351
index c1506b0fc..9901203b1 100644
6d3351
--- a/src/qemu/qemu_monitor.h
6d3351
+++ b/src/qemu/qemu_monitor.h
6d3351
@@ -130,6 +130,7 @@ typedef int (*qemuMonitorDomainEventCallback)(qemuMonitorPtr mon,
6d3351
                                               void *opaque);
6d3351
 typedef int (*qemuMonitorDomainShutdownCallback)(qemuMonitorPtr mon,
6d3351
                                                  virDomainObjPtr vm,
6d3351
+                                                 virTristateBool guest,
6d3351
                                                  void *opaque);
6d3351
 typedef int (*qemuMonitorDomainResetCallback)(qemuMonitorPtr mon,
6d3351
                                               virDomainObjPtr vm,
6d3351
@@ -342,7 +343,7 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
6d3351
 int qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
6d3351
                          long long seconds, unsigned int micros,
6d3351
                          const char *details);
6d3351
-int qemuMonitorEmitShutdown(qemuMonitorPtr mon);
6d3351
+int qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest);
6d3351
 int qemuMonitorEmitReset(qemuMonitorPtr mon);
6d3351
 int qemuMonitorEmitPowerdown(qemuMonitorPtr mon);
6d3351
 int qemuMonitorEmitStop(qemuMonitorPtr mon);
6d3351
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
6d3351
index 601aa3e74..f22df3007 100644
6d3351
--- a/src/qemu/qemu_monitor_json.c
6d3351
+++ b/src/qemu/qemu_monitor_json.c
6d3351
@@ -523,9 +523,15 @@ qemuMonitorJSONKeywordStringToJSON(const char *str, const char *firstkeyword)
6d3351
 }
6d3351
 
6d3351
 
6d3351
-static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
6d3351
+static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data)
6d3351
 {
6d3351
-    qemuMonitorEmitShutdown(mon);
6d3351
+    bool guest = false;
6d3351
+    virTristateBool guest_initiated = VIR_TRISTATE_BOOL_ABSENT;
6d3351
+
6d3351
+    if (virJSONValueObjectGetBoolean(data, "guest", &guest) == 0)
6d3351
+        guest_initiated = guest ? VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
6d3351
+
6d3351
+    qemuMonitorEmitShutdown(mon, guest_initiated);
6d3351
 }
6d3351
 
6d3351
 static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
6d3351
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
6d3351
index 6f0d07242..998dbeb6b 100644
6d3351
--- a/src/qemu/qemu_process.c
6d3351
+++ b/src/qemu/qemu_process.c
6d3351
@@ -634,12 +634,14 @@ qemuProcessHandleEvent(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
6d3351
 static int
6d3351
 qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
6d3351
                           virDomainObjPtr vm,
6d3351
+                          virTristateBool guest_initiated,
6d3351
                           void *opaque)
6d3351
 {
6d3351
     virQEMUDriverPtr driver = opaque;
6d3351
     qemuDomainObjPrivatePtr priv;
6d3351
     virObjectEventPtr event = NULL;
6d3351
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
6d3351
+    int detail = 0;
6d3351
 
6d3351
     VIR_DEBUG("vm=%p", vm);
6d3351
 
6d3351
@@ -662,9 +664,24 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
6d3351
     virDomainObjSetState(vm,
6d3351
                          VIR_DOMAIN_SHUTDOWN,
6d3351
                          VIR_DOMAIN_SHUTDOWN_UNKNOWN);
6d3351
+
6d3351
+    switch (guest_initiated) {
6d3351
+    case VIR_TRISTATE_BOOL_YES:
6d3351
+        detail = VIR_DOMAIN_EVENT_SHUTDOWN_GUEST;
6d3351
+        break;
6d3351
+
6d3351
+    case VIR_TRISTATE_BOOL_NO:
6d3351
+        detail = VIR_DOMAIN_EVENT_SHUTDOWN_HOST;
6d3351
+        break;
6d3351
+
6d3351
+    default:
6d3351
+        detail = VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED;
6d3351
+        break;
6d3351
+    }
6d3351
+
6d3351
     event = virDomainEventLifecycleNewFromObj(vm,
6d3351
-                                     VIR_DOMAIN_EVENT_SHUTDOWN,
6d3351
-                                     VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED);
6d3351
+                                              VIR_DOMAIN_EVENT_SHUTDOWN,
6d3351
+                                              detail);
6d3351
 
6d3351
     if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
6d3351
         VIR_WARN("Unable to save status on vm %s after state change",
6d3351
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
6d3351
index bc0ded686..3374f2c8b 100644
6d3351
--- a/tools/virsh-domain.c
6d3351
+++ b/tools/virsh-domain.c
6d3351
@@ -12385,7 +12385,9 @@ VIR_ENUM_IMPL(virshDomainEventStopped,
6d3351
 VIR_ENUM_DECL(virshDomainEventShutdown)
6d3351
 VIR_ENUM_IMPL(virshDomainEventShutdown,
6d3351
               VIR_DOMAIN_EVENT_SHUTDOWN_LAST,
6d3351
-              N_("Finished"))
6d3351
+              N_("Finished"),
6d3351
+              N_("Finished after guest request"),
6d3351
+              N_("Finished after host request"))
6d3351
 
6d3351
 VIR_ENUM_DECL(virshDomainEventPMSuspended)
6d3351
 VIR_ENUM_IMPL(virshDomainEventPMSuspended,
6d3351
-- 
6d3351
2.13.0
6d3351