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(a)redhat.com
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 */