diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 7cb483e76e..a9be8798f6 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -638,6 +638,16 @@ int virDomainSave (virDomainPtr domain, int virDomainRestore (virConnectPtr conn, const char *from); +/* + * Managed domain save + */ +int virDomainManagedSave (virDomainPtr dom, + unsigned int flags); +int virDomainHasManagedSaveImage(virDomainPtr dom, + unsigned int flags); +int virDomainManagedSaveRemove(virDomainPtr dom, + unsigned int flags); + /* * Domain core dump */ diff --git a/src/driver.h b/src/driver.h index 8f864638c7..7e2536d3c4 100644 --- a/src/driver.h +++ b/src/driver.h @@ -402,6 +402,15 @@ typedef int (*virDrvDomainEventDeregisterAny)(virConnectPtr conn, int callbackID); +typedef int + (*virDrvDomainManagedSave)(virDomainPtr domain, unsigned int flags); + +typedef int + (*virDrvDomainHasManagedSaveImage)(virDomainPtr domain, unsigned int flags); + +typedef int + (*virDrvDomainManagedSaveRemove)(virDomainPtr domain, unsigned int flags); + /** * _virDriver: * @@ -499,6 +508,9 @@ struct _virDriver { virDrvDomainMigrateSetMaxDowntime domainMigrateSetMaxDowntime; virDrvDomainEventRegisterAny domainEventRegisterAny; virDrvDomainEventDeregisterAny domainEventDeregisterAny; + virDrvDomainManagedSave domainManagedSave; + virDrvDomainHasManagedSaveImage domainHasManagedSaveImage; + virDrvDomainManagedSaveRemove domainManagedSaveRemove; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 7a92c4dc4b..e55c948724 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -3389,6 +3389,9 @@ static virDriver esxDriver = { NULL, /* domainMigrateSetMaxDowntime */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; diff --git a/src/libvirt.c b/src/libvirt.c index 5247fe7265..fb683c0a73 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -12136,3 +12136,143 @@ error: virDispatchError(conn); return -1; } + +/** + * virDomainManagedSave: + * @dom: pointer to the domain + * @flags: optional flags currently unused + * + * 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. + * The difference from virDomainSave() is that libvirt is keeping track of + * the saved state itself, and will reuse it once the domain is being + * restarted (automatically or via an explicit libvirt call). + * As a result any running domain is sure to not have a managed saved image. + * + * Returns 0 in case of success or -1 in case of failure + */ +int virDomainManagedSave(virDomainPtr dom, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DEBUG("dom=%p, flags=%u", dom, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(dom)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + conn = dom->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibDomainError(dom, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainManagedSave) { + int ret; + + ret = conn->driver->domainManagedSave(dom, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} + +/** + * virDomainHasManagedSaveImage: + * @dom: pointer to the domain + * @flags: optional flags currently unused + * + * Check if a domain has a managed save image as created by + * virDomainManagedSave(). Note that any running domain should not have + * such an image, as it should have been removed on restart. + * + * Returns 0 if no image is present, 1 if an image is present, and + * -1 in case of error + */ +int virDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DEBUG("dom=%p, flags=%u", dom, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(dom)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + conn = dom->conn; + + if (conn->driver->domainHasManagedSaveImage) { + int ret; + + ret = conn->driver->domainHasManagedSaveImage(dom, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} + +/** + * virDomainManagedSaveRemove: + * @dom: pointer to the domain + * @flags: optional flags currently unused + * + * Remove any managed save image as for this domain. + * + * Returns 0 in case of success, and -1 in case of error + */ +int virDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DEBUG("dom=%p, flags=%u", dom, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(dom)) { + virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + conn = dom->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibDomainError(dom, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainManagedSaveRemove) { + int ret; + + ret = conn->driver->domainManagedSaveRemove(dom, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 2f812a1585..24a422fc63 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -378,6 +378,9 @@ LIBVIRT_0.7.8 { virNWFilterRef; virNWFilterDefineXML; virNWFilterUndefine; + virDomainManagedSave; + virDomainHasManagedSaveImage; + virDomainManagedSaveRemove; } LIBVIRT_0.7.7; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 9caefa13a4..01330ec352 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2538,6 +2538,9 @@ static virDriver lxcDriver = { NULL, /* domainMigrateSetMaxDowntime */ lxcDomainEventRegisterAny, /* domainEventRegisterAny */ lxcDomainEventDeregisterAny, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; static virStateDriver lxcStateDriver = { diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c index e901a03fa3..91d7459cd9 100644 --- a/src/opennebula/one_driver.c +++ b/src/opennebula/one_driver.c @@ -792,6 +792,9 @@ static virDriver oneDriver = { NULL, /* domainMigrateSetMaxDowntime */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; static virStateDriver oneStateDriver = { diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 61765771f1..32bc3c2e70 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1544,6 +1544,9 @@ static virDriver openvzDriver = { NULL, /* domainMigrateSetMaxDowntime */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; int openvzRegister(void) { diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 4f7efdbb48..0e1d35fa01 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -1651,6 +1651,9 @@ virDriver phypDriver = { NULL, /* domainMigrateSetMaxDowntime */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; int diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 70d2781ef7..94f7fef522 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10312,6 +10312,9 @@ static virDriver qemuDriver = { qemuDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */ qemuDomainEventRegisterAny, /* domainEventRegisterAny */ qemuDomainEventDeregisterAny, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 3b8be2159d..9b500d0901 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -9818,6 +9818,9 @@ static virDriver remote_driver = { remoteDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */ remoteDomainEventRegisterAny, /* domainEventRegisterAny */ remoteDomainEventDeregisterAny, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; static virNetworkDriver network_driver = { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 646c7db519..105f8250c4 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5306,6 +5306,9 @@ static virDriver testDriver = { NULL, /* domainMigrateSetMaxDowntime */ testDomainEventRegisterAny, /* domainEventRegisterAny */ testDomainEventDeregisterAny, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; static virNetworkDriver testNetworkDriver = { diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 08fbf930bd..443d82ed90 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1937,6 +1937,9 @@ static virDriver umlDriver = { NULL, /* domainMigrateSetMaxDowntime */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 59ad1b8ad7..8450266003 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -7184,6 +7184,9 @@ virDriver NAME(Driver) = { vboxDomainEventRegisterAny, /* domainEventRegisterAny */ vboxDomainEventDeregisterAny, /* domainEventDeregisterAny */ #endif + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; virNetworkDriver NAME(NetworkDriver) = { diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index ebdc6009e6..a5d58d0418 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1980,6 +1980,9 @@ static virDriver xenUnifiedDriver = { NULL, /* domainMigrateSetMaxDowntime */ xenUnifiedDomainEventRegisterAny, /* domainEventRegisterAny */ xenUnifiedDomainEventDeregisterAny, /* domainEventDeregisterAny */ + NULL, /* domainManagedSave */ + NULL, /* domainHasManagedSaveImage */ + NULL, /* domainManagedSaveRemove */ }; /**