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 */
virDomainObjPtr vm;
int resume = 0, paused = 0;
int ret = -1, fd = -1;
+ virDomainEventPtr event = NULL;
const char *args[] = {
"cat",
NULL,
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)
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;
}
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;
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);
}
/**
};
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}
char *name;
char *to;
int ret = TRUE;
+ int flags = 0;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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);