diff -ur libvirt.orig/docs/libvirt-api.xml libvirt/docs/libvirt-api.xml
--- libvirt.orig/docs/libvirt-api.xml 2009-01-31 20:46:29.000000000 +0900
+++ libvirt/docs/libvirt-api.xml 2009-02-24 18:12:34.000000000 +0900
@@ -40,6 +40,7 @@
<exports symbol='VIR_CRED_NOECHOPROMPT' type='enum'/>
<exports symbol='VIR_DOMAIN_EVENT_UNDEFINED' type='enum'/>
<exports symbol='VIR_MIGRATE_LIVE' type='enum'/>
+ <exports symbol='VIR_SAVE_CHECKPOINT' type='enum'/>
<exports symbol='VIR_DOMAIN_EVENT_STOPPED_DESTROYED'
type='enum'/>
<exports symbol='VIR_DOMAIN_EVENT_DEFINED_ADDED'
type='enum'/>
<exports symbol='VIR_DOMAIN_EVENT_STARTED_MIGRATED'
type='enum'/>
@@ -593,6 +594,7 @@
<enum name='VIR_FROM_XML' file='virterror' value='5'
type='virErrorDomain' info='Error in the XML code'/>
<enum name='VIR_MEMORY_VIRTUAL' file='libvirt' value='1'
type='virDomainMemoryFlags' info=' addresses are virtual addresses'/>
<enum name='VIR_MIGRATE_LIVE' file='libvirt' value='1'
type='virDomainMigrateFlags' info=' live migration'/>
+ <enum name='VIR_SAVE_CHECKPOINT' file='libvirt' value='1'
type='virDomainSaveFlags' info=' checkpoint save'/>
<enum name='VIR_STORAGE_POOL_BUILDING' file='libvirt'
value='1' type='virStoragePoolState' info='Initializing pool, not
available'/>
<enum name='VIR_STORAGE_POOL_BUILD_NEW' file='libvirt'
value='0' type='virStoragePoolBuildFlags' info='Regular build from
scratch'/>
<enum name='VIR_STORAGE_POOL_BUILD_REPAIR' file='libvirt'
value='1' type='virStoragePoolBuildFlags' info='Repair /
reinitialize'/>
@@ -1207,9 +1209,10 @@
<arg name='domain' type='virDomainPtr' info='a domain
object'/>
</function>
<function name='virDomainSave' file='libvirt'
module='libvirt'>
- <info>This method will suspend a domain and save its memory contents to a
file on disk. After the call, if successful, the domain is not listed as running anymore
(this may be a problem). Use virDomainRestore() to restore a domain after
saving.</info>
+ <info>This method will suspend a domain and save its memory contents to a
file on disk. Flags may be one of more of the following: VIR_SAVE_CHECKPOINT. After the
call, if successful, the domain may be suspended (CHECKPOINT) or not listed as running
anymore (this may be a problem). Use virDomainRestore() to restore a domain after
saving.</info>
<return type='int' info='0 in case of success and -1 in case of
failure.'/>
<arg name='domain' type='virDomainPtr' info='a domain
object'/>
+ <arg name='flags' type='unsigned long' info='save
flags'/>
<arg name='to' type='const char *' info='path for the output
file'/>
</function>
<function name='virDomainSetAutostart' file='libvirt'
module='libvirt'>
diff -ur libvirt.orig/docs/libvirt-refs.xml libvirt/docs/libvirt-refs.xml
--- libvirt.orig/docs/libvirt-refs.xml 2009-01-31 20:46:29.000000000 +0900
+++ libvirt/docs/libvirt-refs.xml 2009-02-24 13:09:07.000000000 +0900
@@ -2875,6 +2875,9 @@
<ref name='virConnectListDefinedStoragePools'/>
<ref name='virConnectListStoragePools'/>
</word>
+ <word name='checkpoint'>
+ <ref name='virDomainSave'/>
+ </word>
<word name='choose'>
<ref name='virDomainMigrate'/>
</word>
diff -ur libvirt.orig/include/libvirt/libvirt.h.in libvirt/include/libvirt/libvirt.h.in
--- libvirt.orig/include/libvirt/libvirt.h.in 2009-01-20 21:14:03.000000000 +0900
+++ libvirt/include/libvirt/libvirt.h.in 2009-02-24 13:09:07.000000000 +0900
@@ -463,10 +463,16 @@
int virDomainSuspend (virDomainPtr domain);
int virDomainResume (virDomainPtr domain);
+/* Domain save flags. */
+typedef enum {
+ VIR_SAVE_CHECKPOINT = 1, /* checkpoint save */
+} virDomainSaveFlags;
+
/*
* Domain save/restore
*/
int virDomainSave (virDomainPtr domain,
+ unsigned long flags,
const char *to);
int virDomainRestore (virConnectPtr conn,
const char *from);
diff -ur libvirt.orig/qemud/remote.c libvirt/qemud/remote.c
--- libvirt.orig/qemud/remote.c 2009-02-06 01:28:30.000000000 +0900
+++ libvirt/qemud/remote.c 2009-02-24 13:09:07.000000000 +0900
@@ -1861,7 +1861,7 @@
return -1;
}
- if (virDomainSave (dom, args->to) == -1) {
+ if (virDomainSave (dom, args->flags, args->to) == -1) {
virDomainFree(dom);
remoteDispatchConnError(rerr, conn);
return -1;
diff -ur libvirt.orig/qemud/remote_protocol.c libvirt/qemud/remote_protocol.c
--- libvirt.orig/qemud/remote_protocol.c 2009-01-29 06:33:56.000000000 +0900
+++ libvirt/qemud/remote_protocol.c 2009-02-24 13:09:07.000000000 +0900
@@ -855,6 +855,8 @@
if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
return FALSE;
+ if (!xdr_uint64_t (xdrs, &objp->flags))
+ return FALSE;
if (!xdr_remote_nonnull_string (xdrs, &objp->to))
return FALSE;
return TRUE;
diff -ur libvirt.orig/qemud/remote_protocol.h libvirt/qemud/remote_protocol.h
--- libvirt.orig/qemud/remote_protocol.h 2009-01-29 06:33:56.000000000 +0900
+++ libvirt/qemud/remote_protocol.h 2009-02-24 13:09:07.000000000 +0900
@@ -446,6 +446,7 @@
struct remote_domain_save_args {
remote_nonnull_domain dom;
+ uint64_t flags;
remote_nonnull_string to;
};
typedef struct remote_domain_save_args remote_domain_save_args;
diff -ur libvirt.orig/qemud/remote_protocol.x libvirt/qemud/remote_protocol.x
--- libvirt.orig/qemud/remote_protocol.x 2008-12-18 02:23:21.000000000 +0900
+++ libvirt/qemud/remote_protocol.x 2009-02-24 13:09:07.000000000 +0900
@@ -480,6 +480,7 @@
struct remote_domain_save_args {
remote_nonnull_domain dom;
+ unsigned hyper flags;
remote_nonnull_string to;
};
diff -ur libvirt.orig/src/driver.h libvirt/src/driver.h
--- libvirt.orig/src/driver.h 2008-12-18 06:48:20.000000000 +0900
+++ libvirt/src/driver.h 2009-02-24 13:09:07.000000000 +0900
@@ -140,6 +140,7 @@
virDomainInfoPtr info);
typedef int
(*virDrvDomainSave) (virDomainPtr domain,
+ unsigned long flags,
const char *to);
typedef int
(*virDrvDomainRestore) (virConnectPtr conn,
diff -ur libvirt.orig/src/libvirt.c libvirt/src/libvirt.c
--- libvirt.orig/src/libvirt.c 2009-02-17 19:33:41.000000000 +0900
+++ libvirt/src/libvirt.c 2009-02-24 13:09:07.000000000 +0900
@@ -1937,21 +1937,25 @@
/**
* virDomainSave:
* @domain: a domain object
+ * @flags: flags
* @to: path for the output file
*
* This method will suspend a domain and save its memory contents to
* a file on disk. After the call, if successful, the domain is not
* listed as running anymore (this may be a problem).
* Use virDomainRestore() to restore a domain after saving.
+ * Flags may be one of more of the following:
+ * VIR_SAVE_CHECKPOINT Don't exit after save
*
* Returns 0 in case of success and -1 in case of failure.
*/
int
-virDomainSave(virDomainPtr domain, const char *to)
+virDomainSave(virDomainPtr domain, unsigned long flags,
+ const char *to)
{
char filepath[4096];
virConnectPtr conn;
- DEBUG("domain=%p, to=%s", domain, to);
+ DEBUG("domain=%p, flags=%lu, to=%s", domain, flags, to);
virResetLastError();
@@ -1991,7 +1995,7 @@
if (conn->driver->domainSave) {
int ret;
- ret = conn->driver->domainSave (domain, to);
+ ret = conn->driver->domainSave (domain, flags, to);
if (ret < 0)
goto error;
return ret;
diff -ur libvirt.orig/src/qemu_driver.c libvirt/src/qemu_driver.c
--- libvirt.orig/src/qemu_driver.c 2009-02-19 17:18:31.000000000 +0900
+++ libvirt/src/qemu_driver.c 2009-02-24 13:09:07.000000000 +0900
@@ -2393,6 +2393,7 @@
};
static int qemudDomainSave(virDomainPtr dom,
+ unsigned long flags ATTRIBUTE_UNUSED,
const char *path) {
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
@@ -2504,15 +2505,17 @@
goto cleanup;
}
- /* Shut it down */
- qemudShutdownVMDaemon(dom->conn, driver, vm);
- event = virDomainEventNewFromObj(vm,
+ if (!(flags & VIR_SAVE_CHECKPOINT)) {
+ /* Shut it down */
+ qemudShutdownVMDaemon(dom->conn, driver, vm);
+ event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_SAVED);
- if (!vm->persistent) {
- virDomainRemoveInactive(&driver->domains,
+ if (!vm->persistent) {
+ virDomainRemoveInactive(&driver->domains,
vm);
- vm = NULL;
+ vm = NULL;
+ }
}
ret = 0;
diff -ur libvirt.orig/src/remote_internal.c libvirt/src/remote_internal.c
--- libvirt.orig/src/remote_internal.c 2009-02-17 18:44:18.000000000 +0900
+++ libvirt/src/remote_internal.c 2009-02-24 13:09:07.000000000 +0900
@@ -2065,7 +2065,7 @@
}
static int
-remoteDomainSave (virDomainPtr domain, const char *to)
+remoteDomainSave (virDomainPtr domain, unsigned long flags, const char *to)
{
int rv = -1;
remote_domain_save_args args;
@@ -2075,6 +2075,7 @@
make_nonnull_domain (&args.dom, domain);
args.to = (char *) to;
+ args.flags = flags;
if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE,
(xdrproc_t) xdr_remote_domain_save_args, (char *) &args,
diff -ur libvirt.orig/src/test.c libvirt/src/test.c
--- libvirt.orig/src/test.c 2009-02-14 03:11:03.000000000 +0900
+++ libvirt/src/test.c 2009-02-24 13:09:07.000000000 +0900
@@ -1176,7 +1176,7 @@
#define TEST_SAVE_MAGIC "TestGuestMagic"
-static int testDomainSave(virDomainPtr domain,
+static int testDomainSave(virDomainPtr domain, unsigned long flags,
const char *path)
{
testConnPtr privconn = domain->conn->privateData;
@@ -1206,34 +1206,34 @@
if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
virReportSystemError(domain->conn, errno,
- _("saving domain '%s' to '%s': open
failed"),
- domain->name, path);
+ _("saving domain '%s' with '%lu' to
'%s': open failed"),
+ domain->name, flags, path);
goto cleanup;
}
len = strlen(xml);
if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) {
virReportSystemError(domain->conn, errno,
- _("saving domain '%s' to '%s': write
failed"),
- domain->name, path);
+ _("saving domain '%s' with '%lu' to
'%s': write failed"),
+ domain->name, flags, path);
goto cleanup;
}
if (safewrite(fd, (char*)&len, sizeof(len)) < 0) {
virReportSystemError(domain->conn, errno,
- _("saving domain '%s' to '%s': write
failed"),
- domain->name, path);
+ _("saving domain '%s' with '%lu' to
'%s': write failed"),
+ domain->name, flags, path);
goto cleanup;
}
if (safewrite(fd, xml, len) < 0) {
virReportSystemError(domain->conn, errno,
- _("saving domain '%s' to '%s': write
failed"),
- domain->name, path);
+ _("saving domain '%s' with '%lu' to
'%s': write failed"),
+ domain->name, flags, path);
goto cleanup;
}
if (close(fd) < 0) {
virReportSystemError(domain->conn, errno,
- _("saving domain '%s' to '%s': write
failed"),
- domain->name, path);
+ _("saving domain '%s' with '%lu' to
'%s': write failed"),
+ domain->name, flags, path);
goto cleanup;
}
fd = -1;
diff -ur libvirt.orig/src/virsh.c libvirt/src/virsh.c
--- libvirt.orig/src/virsh.c 2009-02-17 07:51:31.000000000 +0900
+++ libvirt/src/virsh.c 2009-02-24 18:09:30.000000000 +0900
@@ -1067,11 +1067,12 @@
*/
static const vshCmdInfo info_save[] = {
{"help", gettext_noop("save a domain state to a file")},
- {"desc", gettext_noop("Save a running domain.")},
+ {"desc", gettext_noop("Save a running domain. Add --checkpoint to not
quit")},
{NULL, NULL}
};
static const vshCmdOptDef opts_save[] = {
+ {"checkpoint", VSH_OT_BOOL, 0, gettext_noop("checkpoint save")},
{"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")},
{NULL, 0, 0, NULL}
@@ -1083,6 +1084,7 @@
virDomainPtr dom;
char *name;
char *to;
+ long unsigned int flags = 0;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
@@ -1094,10 +1096,14 @@
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
- if (virDomainSave(dom, to) == 0) {
+ if (vshCommandOptBool (cmd, "checkpoint"))
+ flags |= VIR_SAVE_CHECKPOINT;
+
+ if (virDomainSave(dom, flags, to) == 0) {
vshPrint(ctl, _("Domain %s saved to %s\n"), name, to);
} else {
- vshError(ctl, FALSE, _("Failed to save domain %s to %s"), name, to);
+ vshError(ctl, FALSE,
+ _("Failed to save domain %s with %lu to %s"), name, flags, to);
ret = FALSE;
}
diff -ur libvirt.orig/src/xen_unified.c libvirt/src/xen_unified.c
--- libvirt.orig/src/xen_unified.c 2009-02-06 01:03:11.000000000 +0900
+++ libvirt/src/xen_unified.c 2009-02-24 13:09:07.000000000 +0900
@@ -899,7 +899,7 @@
}
static int
-xenUnifiedDomainSave (virDomainPtr dom, const char *to)
+xenUnifiedDomainSave (virDomainPtr dom, unsigned long flags, const char *to)
{
GET_PRIVATE(dom->conn);
int i;
diff -ur libvirt.orig/src/xend_internal.c libvirt/src/xend_internal.c
--- libvirt.orig/src/xend_internal.c 2009-02-14 03:23:23.000000000 +0900
+++ libvirt/src/xend_internal.c 2009-02-24 13:09:07.000000000 +0900
@@ -2999,6 +2999,7 @@
/**
* xenDaemonDomainSave:
* @domain: pointer to the Domain block
+ * @flags: flags
* @filename: path for the output file
*
* This method will suspend a domain and save its memory contents to
@@ -3010,7 +3011,9 @@
* Returns 0 in case of success, -1 (with errno) in case of error.
*/
int
-xenDaemonDomainSave(virDomainPtr domain, const char *filename)
+xenDaemonDomainSave(virDomainPtr domain,
+ unsigned long flags ATTRIBUTE_UNUSED,
+ const char *filename)
{
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
(filename == NULL)) {
diff -ur libvirt.orig/src/xend_internal.h libvirt/src/xend_internal.h
--- libvirt.orig/src/xend_internal.h 2008-12-18 06:26:16.000000000 +0900
+++ libvirt/src/xend_internal.h 2009-02-24 13:09:07.000000000 +0900
@@ -140,7 +140,8 @@
int xenDaemonDomainShutdown(virDomainPtr domain);
int xenDaemonDomainReboot(virDomainPtr domain, unsigned int flags);
int xenDaemonDomainDestroy(virDomainPtr domain);
-int xenDaemonDomainSave(virDomainPtr domain, const char *filename);
+int xenDaemonDomainSave(virDomainPtr domain, unsigned long flags,
+ const char *filename);
int xenDaemonDomainRestore(virConnectPtr conn, const char *filename);
int xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory);
int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);