diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 0488cbf90d..2dd3d06d91 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -334,6 +334,11 @@ struct _virDomainInterfaceStats { typedef virDomainInterfaceStatsStruct *virDomainInterfaceStatsPtr; +/* Domain core dump flags. */ +typedef enum { + VIR_DUMP_CRASH = (1 << 0), /* crash after dump */ +} virDomainCoreDumpFlags; + /* Domain migration flags. */ typedef enum { VIR_MIGRATE_LIVE = (1 << 0), /* live migration */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7e55c236f8..34fa582cb1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3802,6 +3802,7 @@ static int qemudDomainCoreDump(virDomainPtr dom, virDomainObjPtr vm; int resume = 0, paused = 0; int ret = -1, fd = -1; + virDomainEventPtr event = NULL; const char *args[] = { "cat", NULL, @@ -3892,10 +3893,17 @@ static int qemudDomainCoreDump(virDomainPtr dom, goto endjob; endjob: + if ((ret == 0) && (flags & VIR_DUMP_CRASH)) { + qemudShutdownVMDaemon(dom->conn, driver, vm); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_CRASHED); + } + /* Since the monitor is always attached to a pty for libvirt, it will support synchronous operations so we always get here after the migration is complete. */ - if (resume && paused) { + else if (resume && paused) { qemuDomainObjEnterMonitor(vm); if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) { if (virGetLastError() == NULL) @@ -3907,12 +3915,19 @@ endjob: if (qemuDomainObjEndJob(vm) == 0) vm = NULL; + if ((ret == 0) && (flags & VIR_DUMP_CRASH) && !vm->persistent) { + virDomainRemoveInactive(&driver->domains, + vm); + vm = NULL; + } cleanup: if (ret != 0) unlink(path); if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); return ret; } diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 35f7571a4d..7db9a4c08f 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -1911,15 +1911,16 @@ static int testDomainCoreDump(virDomainPtr domain, goto cleanup; } - testDomainShutdownState(domain, privdom); - event = virDomainEventNewFromObj(privdom, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_CRASHED); - - if (!privdom->persistent) { - virDomainRemoveInactive(&privconn->domains, - privdom); - privdom = NULL; + if (flags & VIR_DUMP_CRASH) { + testDomainShutdownState(domain, privdom); + event = virDomainEventNewFromObj(privdom, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_CRASHED); + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } } ret = 0; diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index d782a87224..3ce4dc338a 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -3253,8 +3253,10 @@ xenDaemonDomainCoreDump(virDomainPtr domain, const char *filename, return(-1); } - return xend_op(domain->conn, domain->name, "op", "dump", "file", filename, - "live", "0", "crash", "0", NULL); + return xend_op(domain->conn, domain->name, + "op", "dump", "file", filename, "live", "0", + "crash", (flags & VIR_DUMP_CRASH ? "1" : "0"), + NULL); } /** diff --git a/tools/virsh.c b/tools/virsh.c index b8ddaa6beb..62c127072e 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1431,6 +1431,7 @@ static const vshCmdInfo info_dump[] = { }; static const vshCmdOptDef opts_dump[] = { + {"crash", VSH_OT_BOOL, 0, gettext_noop("crash the domain after core dump")}, {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("where to dump the core")}, {NULL, 0, 0, NULL} @@ -1443,6 +1444,7 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) char *name; char *to; int ret = TRUE; + int flags = 0; if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) return FALSE; @@ -1453,7 +1455,10 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) return FALSE; - if (virDomainCoreDump(dom, to, 0) == 0) { + if (vshCommandOptBool (cmd, "crash")) + flags |= VIR_DUMP_CRASH; + + if (virDomainCoreDump(dom, to, flags) == 0) { vshPrint(ctl, _("Domain %s dumped to %s\n"), name, to); } else { vshError(ctl, _("Failed to core dump domain %s to %s"), name, to);