This patch uses a "migrate"+"cont" combination to implement
"virsh dump"
for QEMU guests (BZ507551).
The code is mostly based on qemudDomainSave, except that the XML
prolog is not included as it is not needed to examine the dump
with e.g. crash.
Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
Acked-by: Daniel P. Berrange <berrange(a)redhat.com>
2009-07-08 Paolo Bonzini <bonzini(a)gnu.org>
* qemu_driver.c (qemudDomainCoreDump): New.
(qemuDriver): Add core dump function.
---
The only change from v1 is moving the unlocking up.
src/qemu_driver.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 84 insertions(+), 1 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 95ea882..3e6d639 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -2844,6 +2844,89 @@ cleanup:
}
+static int qemudDomainCoreDump(virDomainPtr dom,
+ const char *path,
+ int flags ATTRIBUTE_UNUSED) {
+ struct qemud_driver *driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ char *command = NULL;
+ char *info = NULL;
+ char *safe_path = NULL;
+ int ret = -1;
+
+ qemuDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemuDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"),
uuidstr);
+ goto cleanup;
+ }
+
+ if (!virDomainIsActive(vm)) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
+
+ /* Migrate to file */
+ safe_path = qemudEscapeShellArg(path);
+ if (!safe_path) {
+ virReportOOMError(dom->conn);
+ goto cleanup;
+ }
+ if (virAsprintf(&command, "migrate \"exec:"
+ "dd of='%s' 2>/dev/null"
+ "\"", safe_path) == -1) {
+ virReportOOMError(dom->conn);
+ command = NULL;
+ goto cleanup;
+ }
+
+ if (qemudMonitorCommand(vm, command, &info) < 0) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("migrate operation failed"));
+ goto cleanup;
+ }
+
+ DEBUG ("%s: migrate reply: %s", vm->def->name, info);
+
+ /* If the command isn't supported then qemu prints:
+ * unknown command: migrate" */
+ if (strstr(info, "unknown command:")) {
+ qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+ "%s",
+ _("'migrate' not supported by this qemu"));
+ goto cleanup;
+ }
+
+ /* Migrate always stops the VM. However, since the monitor is always
+ attached to a pty for libvirt, it will support synchronous
+ operations so we get here just after the end of the migration. */
+ if (vm->state == VIR_DOMAIN_RUNNING) {
+ if (qemudMonitorCommand(vm, "cont", &info) < 0) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("continue operation failed"));
+ goto cleanup;
+ }
+ DEBUG("Reply %s", info);
+ VIR_FREE(info);
+ }
+ ret = 0;
+
+cleanup:
+ VIR_FREE(safe_path);
+ VIR_FREE(command);
+ VIR_FREE(info);
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
+
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
@@ -5310,7 +5393,7 @@ static virDriver qemuDriver = {
qemudDomainGetInfo, /* domainGetInfo */
qemudDomainSave, /* domainSave */
qemudDomainRestore, /* domainRestore */
- NULL, /* domainCoreDump */
+ qemudDomainCoreDump, /* domainCoreDump */
qemudDomainSetVcpus, /* domainSetVcpus */
#if HAVE_SCHED_GETAFFINITY
qemudDomainPinVcpu, /* domainPinVcpu */
--
1.6.2.5