(only 3 patches sorry). Finally the rest. Note, will probably have to
'make rpcgen' and 'make remote.c' in qemud to reparse remote_protocol.x
and friends
Matt McCowan
diff -ur libvirt.orig/include/libvirt/libvirt.h.in
libvirt-0.6.1.1/include/libvirt/libvirt.h.in
--- libvirt.orig/include/libvirt/libvirt.h.in 2009-03-03
18:09:00.000000000 +0900
+++ libvirt-0.6.1.1/include/libvirt/libvirt.h.in 2009-03-05
11:44:42.000000000 +0900
@@ -529,10 +529,13 @@
int virDomainResume (virDomainPtr domain);
/*
- * Domain save/restore
+ * Domain save/checkpoint/restore
*/
int virDomainSave (virDomainPtr domain,
const char *to);
+int virDomainCheckpoint (virDomainPtr domain,
+ const char *to,
+ const char *script);
int virDomainRestore (virConnectPtr conn,
const char *from);
diff -ur libvirt.orig/qemud/remote_protocol.x
libvirt-0.6.1.1/qemud/remote_protocol.x
--- libvirt.orig/qemud/remote_protocol.x 2009-03-03 18:27:03.000000000
+0900
+++ libvirt-0.6.1.1/qemud/remote_protocol.x 2009-03-05
12:35:34.000000000 +0900
@@ -498,6 +498,12 @@
remote_nonnull_string to;
};
+struct remote_domain_checkpoint_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string to;
+ remote_string script;
+};
+
struct remote_domain_restore_args {
remote_nonnull_string from;
};
@@ -1270,7 +1276,8 @@
REMOTE_PROC_NODE_DEVICE_RESET = 120,
REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121,
- REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122
+ REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122,
+ REMOTE_PROC_DOMAIN_CHECKPOINT = 123
};
/* Custom RPC structure. */
diff -ur libvirt.orig/src/libvirt_public.syms
libvirt-0.6.1.1/src/libvirt_public.syms
--- libvirt.orig/src/libvirt_public.syms 2009-03-03 18:09:00.000000000
+0900
+++ libvirt-0.6.1.1/src/libvirt_public.syms 2009-03-05
11:44:42.000000000 +0900
@@ -254,6 +254,7 @@
virNodeDeviceDettach;
virNodeDeviceReAttach;
virNodeDeviceReset;
+ virDomainCheckpoint;
virDomainGetSecurityLabel;
virNodeGetSecurityModel;
} LIBVIRT_0.6.0;
--- libvirt.orig/qemud/remote.c 2009-03-03 18:27:03.000000000 +0900
+++ libvirt-0.6.1.1/qemud/remote.c 2009-03-09 14:10:41.000000000 +0900
@@ -1940,6 +1940,33 @@
return 0;
}
+
+static int
+remoteDispatchDomainCheckpoint (struct qemud_server *server
ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_error *rerr,
+ remote_domain_checkpoint_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ virDomainPtr dom;
+
+ dom = get_nonnull_domain (conn, args->dom);
+ if (dom == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ if (virDomainCheckpoint (dom, args->to,
+ args->script ? *args->script : NULL) ==
-1) {
+ virDomainFree(dom);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+ virDomainFree(dom);
+ return 0;
+}
+
static int
remoteDispatchDomainCoreDump (struct qemud_server *server
ATTRIBUTE_UNUSED,
struct qemud_client *client
ATTRIBUTE_UNUSED,
--- libvirt.orig/src/remote_internal.c 2009-03-04 10:24:58.000000000
+0900
+++ libvirt-0.6.1.1/src/remote_internal.c 2009-03-09 14:14:22.000000000
+0900
@@ -2089,6 +2089,32 @@
return rv;
}
+
+static int
+remoteDomainCheckpoint (virDomainPtr domain, const char *to, const char
*script)
+{
+ int rv = -1;
+ remote_domain_checkpoint_args args;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain (&args.dom, domain);
+ args.to = (char *) to;
+ args.script = script == NULL ? NULL : (char **) &script;
+
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CHECKPOINT,
+ (xdrproc_t) xdr_remote_domain_checkpoint_args, (char *)
&args,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto done;
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
static int
remoteDomainRestore (virConnectPtr conn, const char *from)
{
@@ -6855,6 +6881,7 @@
.domainSetMemory = remoteDomainSetMemory,
.domainGetInfo = remoteDomainGetInfo,
.domainSave = remoteDomainSave,
+ .domainCheckpoint = remoteDomainCheckpoint,
.domainRestore = remoteDomainRestore,
.domainCoreDump = remoteDomainCoreDump,
.domainSetVcpus = remoteDomainSetVcpus,
--- libvirt.orig/src/virsh.c 2009-03-05 10:17:49.000000000 +0900
+++ libvirt-0.6.1.1/src/virsh.c 2009-03-09 15:43:58.000000000 +0900
@@ -1062,6 +1062,61 @@
return ret;
}
+
+/*
+ * "checkpoint" command
+ */
+static const vshCmdInfo info_checkpoint[] = {
+ {"help", gettext_noop("checkpoint a domain state to a file")},
+ {"desc", gettext_noop("Checkpoint a running domain.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_checkpoint[] = {
+ {"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 save
the data")},
+ {"script", VSH_OT_DATA, 0, gettext_noop("script run while domain
suspended")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdCheckpoint(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ char *name;
+ char *to;
+ char *script;
+ int found;
+ int ret = TRUE;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ return FALSE;
+
+ if (!(to = vshCommandOptString(cmd, "file", NULL)))
+ return FALSE;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ return FALSE;
+
+ script = vshCommandOptString(cmd, "script", NULL);
+
+ if (script != NULL) {
+ script = vshCommandOptString(cmd, "script", &found);
+ if (!found)
+ return FALSE;
+ }
+
+ if (virDomainCheckpoint(dom, to, script) == 0) {
+ vshPrint(ctl, _("Domain %s saved to %s running %s\n"), name, to,
script);
+ } else {
+ vshError(ctl, FALSE, _("Failed to save domain %s to %s running %s"),
name, to, script);
+ ret = FALSE;
+ }
+
+ virDomainFree(dom);
+ return ret;
+}
+
/*
* "save" command
*/
@@ -5761,6 +5816,7 @@
{"reboot", cmdReboot, opts_reboot, info_reboot},
{"restore", cmdRestore, opts_restore, info_restore},
{"resume", cmdResume, opts_resume, info_resume},
+ {"checkpoint", cmdCheckpoint, opts_checkpoint, info_checkpoint},
{"save", cmdSave, opts_save, info_save},
{"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo},
{"dump", cmdDump, opts_dump, info_dump},
--- libvirt.orig/src/libvirt.c 2009-03-04 10:24:46.000000000 +0900
+++ libvirt-0.6.1.1/src/libvirt.c 2009-03-09 17:24:38.000000000 +0900
@@ -1934,6 +1934,77 @@
return -1;
}
+
+/**
+ * virDomainCheckpoint:
+ * @domain: a domain object
+ * @to: path for the output file
+ * @script: script
+ *
+ * This method will suspend a domain and save its memory contents to
+ * a file on disk. If specified a script will be executed before
resuming the
+ * domain.
+ *
+ * script is optional and so could be NULL
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainCheckpoint(virDomainPtr domain, const char *to, const char
*script)
+{
+ virConnectPtr conn;
+
+ DEBUG("domain=%p, to=%s, script=%s", domain, to, script ? script :
"");
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ return (-1);
+ }
+ if (domain->conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED,
__FUNCTION__);
+ goto error;
+ }
+ conn = domain->conn;
+ if (to == NULL) {
+ virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
+ /*
+ * We must absolutize the file path as the save is done out of
process
+ * TODO: check for URI when libxml2 is linked in.
+ */
+ if (to[0] != '/')
+ to = virFileAbsPath(to);
+
+ if (to == NULL)
+ return (-1);
+
+ if (script != NULL) {
+ if (script[0] != '/')
+ script = virFileAbsPath(script);
+ if (script == NULL)
+ return (-1);
+ }
+
+ if (conn->driver->domainCheckpoint) {
+ int ret;
+ ret = conn->driver->domainCheckpoint(domain, to, script);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ /* Copy to connection error object for back compatability */
+ virSetConnError(domain->conn);
+ return -1;
+}
+
/**
* virDomainSave:
* @domain: a domain object