aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2017-05-15 16:41:14 -0500
committerMarkus Armbruster <armbru@redhat.com>2017-05-23 13:28:17 +0200
commit08fba7ac9b618516a5f1d096f78a7e2837fe0594 (patch)
tree2d6a4ee0fff497b8f1515acbf903c8c818d99959
parentcf83f140059f21d4629ae4b61d468c3baef2bb4c (diff)
shutdown: Expose bool cause in SHUTDOWN and RESET events
Libvirt would like to be able to distinguish between a SHUTDOWN event triggered solely by guest request and one triggered by a SIGTERM or other action on the host. While qemu_kill_report() was already able to give different output to stderr based on whether a shutdown was triggered by a host signal (but NOT by a host UI event, such as clicking the X on the window), that information was then lost to management. The previous patches improved things to use an enum throughout all callsites, so now we have something ready to expose through QMP. Note that for now, the decision was to expose ONLY a boolean, rather than promoting ShutdownCause to a QAPI enum; this is because libvirt has not expressed an interest in anything finer-grained. We can still add additional details, in a backwards-compatible manner, if a need later arises (if the addition happens before 2.10, we can replace the bool with an enum; otherwise, the enum will have to be in addition to the bool); this patch merely adds a helper shutdown_caused_by_guest() to map the internal enum into the external boolean. Update expected iotest outputs to match the new data (complete coverage of the affected tests is obtained by -raw, -qcow2, and -nbd). Here is output from 'virsh qemu-monitor-event --loop' with the patch installed: event SHUTDOWN at 1492639680.731251 for domain fedora_13: {"guest":true} event STOP at 1492639680.732116 for domain fedora_13: <null> event SHUTDOWN at 1492639680.732830 for domain fedora_13: {"guest":false} Note that libvirt runs qemu with -no-shutdown: the first SHUTDOWN event was triggered by an action I took directly in the guest (shutdown -h), at which point qemu stops the vcpus and waits for libvirt to do any final cleanups; the second SHUTDOWN event is the result of libvirt sending SIGTERM now that it has completed cleanup. Libvirt is already smart enough to only feed the first qemu SHUTDOWN event to the end user (remember, virsh qemu-monitor-event is a low-level debugging interface that is explicitly unsupported by libvirt, so it sees things that normal end users do not); changing qemu to emit SHUTDOWN only once is outside the scope of this series. See also https://bugzilla.redhat.com/1384007 Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20170515214114.15442-6-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
-rw-r--r--include/sysemu/sysemu.h5
-rw-r--r--qapi/event.json17
-rw-r--r--tests/qemu-iotests/071.out4
-rw-r--r--tests/qemu-iotests/081.out2
-rw-r--r--tests/qemu-iotests/087.out12
-rw-r--r--tests/qemu-iotests/094.out2
-rw-r--r--tests/qemu-iotests/117.out2
-rw-r--r--tests/qemu-iotests/119.out2
-rw-r--r--tests/qemu-iotests/120.out2
-rw-r--r--tests/qemu-iotests/140.out2
-rw-r--r--tests/qemu-iotests/143.out2
-rw-r--r--tests/qemu-iotests/156.out2
-rw-r--r--vl.c8
13 files changed, 38 insertions, 24 deletions
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 58e54ee1ff..a86b8cfad7 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -49,6 +49,11 @@ typedef enum ShutdownCause {
SHUTDOWN_CAUSE__MAX,
} ShutdownCause;
+static inline bool shutdown_caused_by_guest(ShutdownCause cause)
+{
+ return cause >= SHUTDOWN_CAUSE_GUEST_SHUTDOWN;
+}
+
void vm_start(void);
int vm_prepare_start(void);
int vm_stop(RunState state);
diff --git a/qapi/event.json b/qapi/event.json
index e80f3f4446..6d22b025cc 100644
--- a/qapi/event.json
+++ b/qapi/event.json
@@ -10,6 +10,10 @@
# Emitted when the virtual machine has shut down, indicating that qemu is
# about to exit.
#
+# @guest: If true, the shutdown was triggered by a guest request (such as
+# a guest-initiated ACPI shutdown request or other hardware-specific action)
+# rather than a host request (such as sending qemu a SIGINT). (since 2.10)
+#
# Note: If the command-line option "-no-shutdown" has been specified, qemu will
# not exit, and a STOP event will eventually follow the SHUTDOWN event
#
@@ -17,11 +21,11 @@
#
# Example:
#
-# <- { "event": "SHUTDOWN",
+# <- { "event": "SHUTDOWN", "data": { "guest": true },
# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
#
##
-{ 'event': 'SHUTDOWN' }
+{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool' } }
##
# @POWERDOWN:
@@ -44,15 +48,20 @@
#
# Emitted when the virtual machine is reset
#
+# @guest: If true, the reset was triggered by a guest request (such as
+# a guest-initiated ACPI reboot request or other hardware-specific action)
+# rather than a host request (such as the QMP command system_reset).
+# (since 2.10)
+#
# Since: 0.12.0
#
# Example:
#
-# <- { "event": "RESET",
+# <- { "event": "RESET", "data": { "guest": false },
# "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
#
##
-{ 'event': 'RESET' }
+{ 'event': 'RESET', 'data': { 'guest': 'bool' } }
##
# @STOP:
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index dd879f1212..1d5e28d730 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -46,7 +46,7 @@ QMP_VERSION
read failed: Input/output error
{"return": ""}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Testing blkverify on existing block device ===
@@ -85,7 +85,7 @@ wrote 512/512 bytes at offset 0
read failed: Input/output error
{"return": ""}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
QEMU_PROG: Failed to flush the L2 table cache: Input/output error
QEMU_PROG: Failed to flush the refcount block cache: Input/output error
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
index 97df69d71c..2533c31c78 100644
--- a/tests/qemu-iotests/081.out
+++ b/tests/qemu-iotests/081.out
@@ -36,7 +36,7 @@ read 10485760/10485760 bytes at offset 0
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
== using quorum rewrite corrupted mode ==
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index dc6baf9366..59c5208272 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -8,7 +8,7 @@ QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Duplicate ID ===
@@ -19,7 +19,7 @@ QMP_VERSION
{"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}}
{"error": {"class": "GenericError", "desc": "Duplicate node name"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== aio=native without O_DIRECT ===
@@ -29,7 +29,7 @@ QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Encrypted image ===
@@ -40,14 +40,14 @@ QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
Testing:
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Missing driver ===
@@ -58,6 +58,6 @@ QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
*** done
diff --git a/tests/qemu-iotests/094.out b/tests/qemu-iotests/094.out
index b66dc0787d..f52baffe70 100644
--- a/tests/qemu-iotests/094.out
+++ b/tests/qemu-iotests/094.out
@@ -7,5 +7,5 @@ Formatting 'TEST_DIR/source.IMGFMT', fmt=IMGFMT size=67108864
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
*** done
diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
index f52dc1a357..851e214144 100644
--- a/tests/qemu-iotests/117.out
+++ b/tests/qemu-iotests/117.out
@@ -7,7 +7,7 @@ wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
No errors were found on the image.
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/119.out b/tests/qemu-iotests/119.out
index 58e7114e8b..a8743b810e 100644
--- a/tests/qemu-iotests/119.out
+++ b/tests/qemu-iotests/119.out
@@ -6,6 +6,6 @@ read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
*** done
diff --git a/tests/qemu-iotests/120.out b/tests/qemu-iotests/120.out
index 9131b1bce9..1af1aeb38d 100644
--- a/tests/qemu-iotests/120.out
+++ b/tests/qemu-iotests/120.out
@@ -6,7 +6,7 @@ wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 65536/65536 bytes at offset 0
diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
index 6c0445603a..0689b2b41c 100644
--- a/tests/qemu-iotests/140.out
+++ b/tests/qemu-iotests/140.out
@@ -10,5 +10,5 @@ read 65536/65536 bytes at offset 0
{"return": {}}
can't open device nbd+unix:///drv?socket=TEST_DIR/nbd: No export with name 'drv' available
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
*** done
diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
index d24ad20db3..0978b8985a 100644
--- a/tests/qemu-iotests/143.out
+++ b/tests/qemu-iotests/143.out
@@ -3,5 +3,5 @@ QA output created by 143
{"return": {}}
can't open device nbd+unix:///no_such_export?socket=TEST_DIR/nbd: No export with name 'no_such_export' available
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
*** done
diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
index 3af82ae540..f96a564c1d 100644
--- a/tests/qemu-iotests/156.out
+++ b/tests/qemu-iotests/156.out
@@ -34,7 +34,7 @@ read 65536/65536 bytes at offset 196608
{"return": ""}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/vl.c b/vl.c
index 1064fd117f..25e1fb4e9f 100644
--- a/vl.c
+++ b/vl.c
@@ -1705,8 +1705,8 @@ void qemu_system_reset(ShutdownCause reason)
qemu_devices_reset();
}
if (reason) {
- /* TODO update event based on reason */
- qapi_event_send_reset(&error_abort);
+ qapi_event_send_reset(shutdown_caused_by_guest(reason),
+ &error_abort);
}
cpu_synchronize_all_post_reset();
}
@@ -1863,8 +1863,8 @@ static bool main_loop_should_exit(void)
request = qemu_shutdown_requested();
if (request) {
qemu_kill_report();
- /* TODO update event based on request */
- qapi_event_send_shutdown(&error_abort);
+ qapi_event_send_shutdown(shutdown_caused_by_guest(request),
+ &error_abort);
if (no_shutdown) {
vm_stop(RUN_STATE_SHUTDOWN);
} else {