Patches for the drivers and header Here's hoping jolly Evolution doesn't play silly buggers with wrapping. If so I'll be resending with claws :( > Matt McCowan > > -- > Libvir-list mailing list > Libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list --- libvirt.orig/src/driver.h 2009-03-03 18:14:28.000000000 +0900 +++ libvirt-0.6.1.1/src/driver.h 2009-03-09 17:28:54.000000000 +0900 @@ -141,6 +141,12 @@ typedef int (*virDrvDomainSave) (virDomainPtr domain, const char *to); + +typedef int + (*virDrvDomainCheckpoint) (virDomainPtr domain, + const char *to, + const char *script); + typedef int (*virDrvDomainRestore) (virConnectPtr conn, const char *from); @@ -372,6 +378,7 @@ virDrvDomainSetMemory domainSetMemory; virDrvDomainGetInfo domainGetInfo; virDrvDomainSave domainSave; + virDrvDomainCheckpoint domainCheckpoint; virDrvDomainRestore domainRestore; virDrvDomainCoreDump domainCoreDump; virDrvDomainSetVcpus domainSetVcpus; diff -ur libvirt.orig/src/lxc_driver.c libvirt-0.6.1.1/src/lxc_driver.c --- libvirt.orig/src/lxc_driver.c 2009-03-09 12:42:43.000000000 +0900 +++ libvirt-0.6.1.1/src/lxc_driver.c 2009-03-05 11:44:42.000000000 +0900 @@ -1435,6 +1423,7 @@ NULL, /* domainSetMemory */ lxcDomainGetInfo, /* domainGetInfo */ NULL, /* domainSave */ + NULL, /* domainCheckpoint */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ NULL, /* domainSetVcpus */ diff -ur libvirt.orig/src/openvz_driver.c libvirt-0.6.1.1/src/openvz_driver.c --- libvirt.orig/src/openvz_driver.c 2009-03-03 18:14:28.000000000 +0900 +++ libvirt-0.6.1.1/src/openvz_driver.c 2009-03-05 11:44:42.000000000 +0900 @@ -1293,6 +1293,7 @@ NULL, /* domainSetMemory */ openvzDomainGetInfo, /* domainGetInfo */ NULL, /* domainSave */ + NULL, /* domainCheckpoint */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ openvzDomainSetVcpus, /* domainSetVcpus */ diff -ur libvirt.orig/src/proxy_internal.c libvirt-0.6.1.1/src/proxy_internal.c --- libvirt.orig/src/proxy_internal.c 2009-01-29 21:10:32.000000000 +0900 +++ libvirt-0.6.1.1/src/proxy_internal.c 2009-03-05 14:39:58.000000000 +0900 @@ -67,6 +67,7 @@ NULL, /* domainSetMemory */ xenProxyDomainGetInfo, /* domainGetInfo */ NULL, /* domainSave */ + NULL, /* domainCheckpoint */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ NULL, /* domainSetVcpus */ diff -ur libvirt.orig/src/test.c libvirt-0.6.1.1/src/test.c --- libvirt.orig/src/test.c 2009-03-03 18:14:28.000000000 +0900 +++ libvirt-0.6.1.1/src/test.c 2009-03-05 11:44:42.000000000 +0900 @@ -3495,6 +3495,7 @@ testSetMemory, /* domainSetMemory */ testGetDomainInfo, /* domainGetInfo */ testDomainSave, /* domainSave */ + NULL, /* domainCheckpoint */ testDomainRestore, /* domainRestore */ testDomainCoreDump, /* domainCoreDump */ testSetVcpus, /* domainSetVcpus */ diff -ur libvirt.orig/src/uml_driver.c libvirt-0.6.1.1/src/uml_driver.c --- libvirt.orig/src/uml_driver.c 2009-03-03 18:14:28.000000000 +0900 +++ libvirt-0.6.1.1/src/uml_driver.c 2009-03-05 11:44:42.000000000 +0900 @@ -1848,6 +1848,7 @@ umlDomainSetMemory, /* domainSetMemory */ umlDomainGetInfo, /* domainGetInfo */ NULL, /* domainSave */ + NULL, /* domainCheckpoint */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ NULL, /* domainSetVcpus */ diff -ur libvirt.orig/src/qemu_driver.c libvirt-0.6.1.1/src/qemu_driver.c --- libvirt.orig/src/qemu_driver.c 2009-03-04 10:24:50.000000000 +0900 +++ libvirt-0.6.1.1/src/qemu_driver.c 2009-03-06 16:30:39.000000000 +0900 @@ -2718,6 +2718,156 @@ return ret; } +static int qemudDomainCheckpoint(virDomainPtr dom, + const char *path, + const char *script) { + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *command = NULL; + char *info = NULL; + int fd = -1; + char *safe_path = NULL; + char *xml = NULL; + struct qemud_save_header header; + int ret = -1; + virDomainEventPtr event = NULL; + const char *argv[3]; + + memset(&header, 0, sizeof(header)); + memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); + header.version = QEMUD_SAVE_VERSION; + + qemuDriverLock(driver); + vm = virDomainFindByID(&driver->domains, dom->id); + + if (!vm) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, + _("no domain with matching id %d"), dom->id); + goto cleanup; + } + + if (!virDomainIsActive(vm)) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("domain is not running")); + goto cleanup; + } + + /* Pause */ + if (vm->state == VIR_DOMAIN_RUNNING) { + header.was_running = 1; + if (qemudMonitorCommand(vm, "stop", &info) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("suspend operation failed")); + goto cleanup; + } + vm->state = VIR_DOMAIN_PAUSED; + qemudDebug("Reply %s", info); + VIR_FREE(info); + } + + /* Get XML for the domain */ + xml = virDomainDefFormat(dom->conn, vm->def, VIR_DOMAIN_XML_SECURE); + if (!xml) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("failed to get domain xml")); + goto cleanup; + } + header.xml_len = strlen(xml) + 1; + + /* Write header to file, followed by XML */ + if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + _("failed to create '%s'"), path); + goto cleanup; + } + + if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("failed to write save header")); + goto cleanup; + } + + if (safewrite(fd, xml, header.xml_len) != header.xml_len) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("failed to write xml")); + goto cleanup; + } + + if (close(fd) < 0) { + virReportSystemError(dom->conn, errno, + _("unable to save file %s"), + path); + goto cleanup; + } + fd = -1; + + /* Migrate to file */ + safe_path = qemudEscapeShellArg(path); + if (!safe_path) { + virReportOOMError(dom->conn); + goto cleanup; + } + if (virAsprintf(&command, "migrate \"exec:" + "dd of='%s' oflag=append conv=notrunc 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 ("migrate reply: %s", 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; + } + + /* Call optional script */ + if (script != NULL ) { + argv[0] = qemudEscapeShellArg(script); + argv[1] = virDomainGetName(dom); + argv[2] = NULL; + if (virRun(dom->conn, argv, NULL) < 0) + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + _("Failed to run '%s'"), script); + } + + if (qemudMonitorCommand(vm, "cont", &info) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("resume operation failed")); + goto cleanup; + } + vm->state = VIR_DOMAIN_RUNNING; + DEBUG ("cont reply: %s", info); + + ret = 0; + +cleanup: + if (fd != -1) + close(fd); + VIR_FREE(xml); + VIR_FREE(safe_path); + VIR_FREE(command); + VIR_FREE(info); + if (ret != 0) + unlink(path); + if (vm) + virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); + qemuDriverUnlock(driver); + return ret; +} static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { struct qemud_driver *driver = dom->conn->privateData; @@ -4931,6 +5081,7 @@ qemudDomainSetMemory, /* domainSetMemory */ qemudDomainGetInfo, /* domainGetInfo */ qemudDomainSave, /* domainSave */ + qemudDomainCheckpoint, /* domainCheckpoint */ qemudDomainRestore, /* domainRestore */ NULL, /* domainCoreDump */ qemudDomainSetVcpus, /* domainSetVcpus */ -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list