[libvirt] [patch 3/3] checkpoint functionality

Matt McCowan matt.mccowan at metoceanengineers.com
Mon Mar 9 14:35:02 UTC 2009


(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





More information about the libvir-list mailing list