[libvirt] [PATCH] qemu: Introduce shutdown reason for paused state

Qemu sends STOP event as part of the shutdown process. Detect such STOP event and consider shutdown to be reason of emitting such event. That's the best we can do until qemu provides us the reason directly in STOP event. This allows us to report shutdown reason for paused state so that apps can detect domains that failed to finish the shutdown process (e.g., because qemu is buggy and doesn't exit on SIGTERM or it is blocked in flushing disk buffers). --- include/libvirt/libvirt.h.in | 1 + src/conf/domain_conf.c | 5 +++-- src/libvirt_private.syms | 12 ++++++++++++ src/qemu/qemu_process.c | 14 +++++++++++--- tools/virsh.c | 2 ++ 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index ea7b3fc..39155a6 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -124,6 +124,7 @@ typedef enum { VIR_DOMAIN_PAUSED_IOERROR = 5, /* paused due to a disk I/O error */ VIR_DOMAIN_PAUSED_WATCHDOG = 6, /* paused due to a watchdog event */ VIR_DOMAIN_PAUSED_FROM_SNAPSHOT = 7, /* paused after restoring from snapshot */ + VIR_DOMAIN_PAUSED_SHUTTING_DOWN = 8, /* paused during shutdown process */ } virDomainPausedReason; typedef enum { diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index ea6b581..ad2a730 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -487,7 +487,7 @@ VIR_ENUM_IMPL(virDomainRunningReason, VIR_DOMAIN_RUNNING_LAST, VIR_ENUM_IMPL(virDomainBlockedReason, VIR_DOMAIN_BLOCKED_LAST, "unknown") -#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_FROM_SNAPSHOT + 1) +#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_SHUTTING_DOWN + 1) VIR_ENUM_IMPL(virDomainPausedReason, VIR_DOMAIN_PAUSED_LAST, "unknown", "user", @@ -496,7 +496,8 @@ VIR_ENUM_IMPL(virDomainPausedReason, VIR_DOMAIN_PAUSED_LAST, "dump", "ioerror", "watchdog", - "from snapshot") + "from snapshot", + "shutdown") #define VIR_DOMAIN_SHUTDOWN_LAST (VIR_DOMAIN_SHUTDOWN_USER + 1) VIR_ENUM_IMPL(virDomainShutdownReason, VIR_DOMAIN_SHUTDOWN_LAST, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e45965e..8235ea1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -231,6 +231,8 @@ virDiskNameToBusDeviceIndex; virDiskNameToIndex; virDomainActualNetDefFree; virDomainAssignDef; +virDomainBlockedReasonTypeFromString; +virDomainBlockedReasonTypeToString; virDomainChrConsoleTargetTypeFromString; virDomainChrConsoleTargetTypeToString; virDomainChrDefForeach; @@ -360,6 +362,8 @@ virDomainNetIndexByMac; virDomainNetInsert; virDomainNetRemoveByMac; virDomainNetTypeToString; +virDomainNostateReasonTypeFromString; +virDomainNostateReasonTypeToString; virDomainNumatuneMemModeTypeFromString; virDomainNumatuneMemModeTypeToString; virDomainObjAssignDef; @@ -379,12 +383,20 @@ virDomainObjSetState; virDomainObjTaint; virDomainObjUnlock; virDomainObjUnref; +virDomainPausedReasonTypeFromString; +virDomainPausedReasonTypeToString; virDomainRedirdevBusTypeFromString; virDomainRedirdevBusTypeToString; virDomainRemoveInactive; +virDomainRunningReasonTypeFromString; +virDomainRunningReasonTypeToString; virDomainSaveConfig; virDomainSaveStatus; virDomainSaveXML; +virDomainShutdownReasonTypeFromString; +virDomainShutdownReasonTypeToString; +virDomainShutoffReasonTypeFromString; +virDomainShutoffReasonTypeToString; virDomainSmartcardDefForeach; virDomainSmartcardDefFree; virDomainSmartcardTypeFromString; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index dbd697d..4de7ab5 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -473,14 +473,22 @@ qemuProcessHandleStop(qemuMonitorPtr mon ATTRIBUTE_UNUSED, { struct qemud_driver *driver = qemu_driver; virDomainEventPtr event = NULL; + virDomainPausedReason reason = VIR_DOMAIN_PAUSED_UNKNOWN; virDomainObjLock(vm); if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { qemuDomainObjPrivatePtr priv = vm->privateData; - VIR_DEBUG("Transitioned guest %s to paused state due to unknown event", - vm->def->name); - virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN); + if (priv->gotShutdown) { + VIR_DEBUG("Got STOP event after SHUTDOWN, assuming we are stopping" + " for shutdown"); + reason = VIR_DOMAIN_PAUSED_SHUTTING_DOWN; + } + + VIR_DEBUG("Transitioned guest %s to paused state, reason=%s", + vm->def->name, virDomainPausedReasonTypeToString(reason)); + + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, reason); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); diff --git a/tools/virsh.c b/tools/virsh.c index 3c6e65a..8d257bc 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -15137,6 +15137,8 @@ vshDomainStateReasonToString(int state, int reason) return N_("watchdog"); case VIR_DOMAIN_PAUSED_FROM_SNAPSHOT: return N_("from snapshot"); + case VIR_DOMAIN_PAUSED_SHUTTING_DOWN: + return N_("shutting down"); case VIR_DOMAIN_PAUSED_UNKNOWN: ; } -- 1.7.6.1

On 09/15/2011 07:29 AM, Jiri Denemark wrote:
Qemu sends STOP event as part of the shutdown process. Detect such STOP event and consider shutdown to be reason of emitting such event. That's the best we can do until qemu provides us the reason directly in STOP event. This allows us to report shutdown reason for paused state so that apps can detect domains that failed to finish the shutdown process (e.g., because qemu is buggy and doesn't exit on SIGTERM or it is blocked in flushing disk buffers). --- include/libvirt/libvirt.h.in | 1 + src/conf/domain_conf.c | 5 +++-- src/libvirt_private.syms | 12 ++++++++++++ src/qemu/qemu_process.c | 14 +++++++++++--- tools/virsh.c | 2 ++ 5 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index ea7b3fc..39155a6 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -124,6 +124,7 @@ typedef enum { VIR_DOMAIN_PAUSED_IOERROR = 5, /* paused due to a disk I/O error */ VIR_DOMAIN_PAUSED_WATCHDOG = 6, /* paused due to a watchdog event */ VIR_DOMAIN_PAUSED_FROM_SNAPSHOT = 7, /* paused after restoring from snapshot */ + VIR_DOMAIN_PAUSED_SHUTTING_DOWN = 8, /* paused during shutdown process */ } virDomainPausedReason;
typedef enum { diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index ea6b581..ad2a730 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -487,7 +487,7 @@ VIR_ENUM_IMPL(virDomainRunningReason, VIR_DOMAIN_RUNNING_LAST, VIR_ENUM_IMPL(virDomainBlockedReason, VIR_DOMAIN_BLOCKED_LAST, "unknown")
-#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_FROM_SNAPSHOT + 1) +#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_SHUTTING_DOWN + 1)
We have several other instances of *_LAST defined in libvirt.h.in as part of the enum, instead of a #define here; but this is a minimal change and doesn't make the situation any worse.
+++ b/src/libvirt_private.syms @@ -231,6 +231,8 @@ virDiskNameToBusDeviceIndex; virDiskNameToIndex; virDomainActualNetDefFree; virDomainAssignDef; +virDomainBlockedReasonTypeFromString; +virDomainBlockedReasonTypeToString;
Looks like we forgot to export these earlier; this could almost be a separate patch, but I'm okay keeping it in one. ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Thu, Sep 15, 2011 at 08:10:58 -0600, Eric Blake wrote:
On 09/15/2011 07:29 AM, Jiri Denemark wrote:
Qemu sends STOP event as part of the shutdown process. Detect such STOP event and consider shutdown to be reason of emitting such event. That's the best we can do until qemu provides us the reason directly in STOP event. This allows us to report shutdown reason for paused state so that apps can detect domains that failed to finish the shutdown process (e.g., because qemu is buggy and doesn't exit on SIGTERM or it is blocked in flushing disk buffers). --- ... -#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_FROM_SNAPSHOT + 1) +#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_SHUTTING_DOWN + 1)
We have several other instances of *_LAST defined in libvirt.h.in as part of the enum, instead of a #define here; but this is a minimal change and doesn't make the situation any worse.
OK, I thought we were trying to avoid that... it's probably worth fixing in a separate patch since this way it's too easy not to update the *_LAST macro.
+++ b/src/libvirt_private.syms @@ -231,6 +231,8 @@ virDiskNameToBusDeviceIndex; virDiskNameToIndex; virDomainActualNetDefFree; virDomainAssignDef; +virDomainBlockedReasonTypeFromString; +virDomainBlockedReasonTypeToString;
Looks like we forgot to export these earlier; this could almost be a separate patch, but I'm okay keeping it in one.
ACK.
Thanks, pushed. Jirka
participants (2)
-
Eric Blake
-
Jiri Denemark