[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v3] implement virsh dump for qemu guests



This patch uses a stop/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.

The plan is to implement live dumping in the future.  When that is
done, it shouldn't require reindentation.  This plan is also the
reason for the "weird"

    resume = (vm->state == VIR_DOMAIN_RUNNING);
    if (vm->state == VIR_DOMAIN_RUNNING) {
        ...
    }

* src/qemu_driver.c (qemudDomainCoreDump): New.
(qemuDriver): Add core dump function.
---
	The virsh dump for xen does not crash the VM, and so does
	this KVM implementation.

 src/qemu_driver.c |  104 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 103 insertions(+), 1 deletions(-)

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 3b2c167..43f93c5 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -2845,6 +2845,108 @@ 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 resume = 0, paused = 0;
+    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 will always stop the VM, so once we support live dumping
+       the resume condition will stay the same, independent of whether
+       the stop command is issued.  */
+    resume = (vm->state == VIR_DOMAIN_RUNNING);
+
+    /* Pause domain for non-live dump */
+    if (vm->state == VIR_DOMAIN_RUNNING) {
+        if (qemudMonitorCommand (vm, "stop", &info) < 0) {
+            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                             "%s", _("suspending before dump failed"));
+            goto cleanup;
+        }
+        DEBUG ("%s: stop reply: %s", vm->def->name, info);
+        VIR_FREE(info);
+        paused = 1;
+    }
+
+    /* 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;
+    }
+
+    paused = 1;
+    ret = 0;
+cleanup:
+    VIR_FREE(safe_path);
+    VIR_FREE(command);
+    VIR_FREE(info);
+
+    /* 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) {
+        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
+            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+                             "%s", _("resuming after dump failed"));
+            goto cleanup;
+        }
+        DEBUG ("%s: cont reply: %s", vm->def->name, info);
+        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;
@@ -5311,7 +5413,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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]