(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 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list