diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 6afd59160ee9180809b6d61a84e53eb260f97c60..8fa7daec8576501b8ee04239df1436c2ac9fbca4 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -232,9 +232,10 @@ typedef virDomainInfo *virDomainInfoPtr; * Domain. */ typedef enum { - VIR_DOMAIN_NONE = 0, /* Default behavior */ - VIR_DOMAIN_START_PAUSED = 1 << 0, /* Launch guest in paused state */ - VIR_DOMAIN_START_AUTODESTROY = 1 << 1, /* Automatically kill guest when virConnectPtr is closed */ + VIR_DOMAIN_NONE = 0, /* Default behavior */ + VIR_DOMAIN_START_PAUSED = 1 << 0, /* Launch guest in paused state */ + VIR_DOMAIN_START_AUTODESTROY = 1 << 1, /* Automatically kill guest when virConnectPtr is closed */ + VIR_DOMAIN_START_BYPASS_CACHE = 1 << 2, /* Avoid file system cache pollution */ } virDomainCreateFlags; @@ -657,8 +658,9 @@ typedef virDomainMemoryStatStruct *virDomainMemoryStatPtr; /* Domain core dump flags. */ typedef enum { - VIR_DUMP_CRASH = (1 << 0), /* crash after dump */ - VIR_DUMP_LIVE = (1 << 1), /* live dump */ + VIR_DUMP_CRASH = (1 << 0), /* crash after dump */ + VIR_DUMP_LIVE = (1 << 1), /* live dump */ + VIR_DUMP_BYPASS_CACHE = (1 << 2), /* avoid file system cache pollution */ } virDomainCoreDumpFlags; /* Domain migration flags. */ @@ -941,10 +943,28 @@ int virDomainResume (virDomainPtr domain); /* * Domain save/restore */ + +/** + * virDomainSaveRestoreFlags: + * Flags for use in virDomainSaveFlags(), virDomainManagedSave(), and + * virDomainRestoreFlags(). + */ +typedef enum { + VIR_DOMAIN_SAVE_BYPASS_CACHE = 1 << 0, /* Avoid file system cache pollution */ +} virDomainSaveRestoreFlags; + int virDomainSave (virDomainPtr domain, const char *to); +int virDomainSaveFlags (virDomainPtr domain, + const char *to, + const char *dxml, + unsigned int flags); int virDomainRestore (virConnectPtr conn, const char *from); +int virDomainRestoreFlags (virConnectPtr conn, + const char *from, + const char *dxml, + unsigned int flags); /* * Managed domain save diff --git a/src/driver.h b/src/driver.h index 4c4955f78b6dc515577e363442eb57864e66dd58..d931c9b9b75941ea5c42c3328d48774138ddc617 100644 --- a/src/driver.h +++ b/src/driver.h @@ -177,9 +177,19 @@ typedef int typedef int (*virDrvDomainSave) (virDomainPtr domain, const char *to); +typedef int + (*virDrvDomainSaveFlags) (virDomainPtr domain, + const char *to, + const char *dxml, + unsigned int flags); typedef int (*virDrvDomainRestore) (virConnectPtr conn, const char *from); +typedef int + (*virDrvDomainRestoreFlags) (virConnectPtr conn, + const char *from, + const char *dxml, + unsigned int flags); typedef int (*virDrvDomainCoreDump) (virDomainPtr domain, const char *to, @@ -714,7 +724,9 @@ struct _virDriver { virDrvDomainGetState domainGetState; virDrvDomainGetControlInfo domainGetControlInfo; virDrvDomainSave domainSave; + virDrvDomainSaveFlags domainSaveFlags; virDrvDomainRestore domainRestore; + virDrvDomainRestoreFlags domainRestoreFlags; virDrvDomainCoreDump domainCoreDump; virDrvDomainScreenshot domainScreenshot; virDrvDomainSetVcpus domainSetVcpus; diff --git a/src/libvirt.c b/src/libvirt.c index 16a9a027c3c2e26069155a558ec03b01dc8d02bf..67041c67295154d8a6ace00191b2c503576e97be 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2242,6 +2242,8 @@ error: * listed as running anymore (this may be a problem). * Use virDomainRestore() to restore a domain after saving. * + * See virDomainSaveFlags() for more control. + * * Returns 0 in case of success and -1 in case of failure. */ int @@ -2295,6 +2297,85 @@ error: return -1; } +/** + * virDomainSaveFlags: + * @domain: a domain object + * @to: path for the output file + * @dxml: (optional) XML config for adjusting guest xml used on restore + * @flags: bitwise-OR of virDomainSaveRestoreFlags + * + * 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. + * + * If the hypervisor supports it, @dxml can be used to alter + * host-specific portions of the domain XML that will be used when + * restoring an image. For example, it is possible to alter the + * backing filename that is associated with a disk device, in order to + * prepare for file renaming done as part of backing up the disk + * device while the domain is stopped. + * + * If @flags includes VIR_DOMAIN_SAVE_BYPASS_CACHE, then libvirt will + * attempt to bypass the file system cache while creating the file, or + * fail if it cannot do so for the given system; this can allow less + * pressure on file system cache, but also risks slowing saves to NFS. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virDomainSaveFlags(virDomainPtr domain, const char *to, + const char *dxml, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "to=%s dxml=%s flags=%x", + to, NULLSTR(dxml), flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + conn = domain->conn; + if (to == NULL) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->driver->domainSaveFlags) { + int ret; + char *absolute_to; + + /* We must absolutize the file path as the save is done out of process */ + if (virFileAbsPath(to, &absolute_to) < 0) { + virLibConnError(VIR_ERR_INTERNAL_ERROR, + _("could not build absolute output file path")); + goto error; + } + + ret = conn->driver->domainSaveFlags(domain, absolute_to, dxml, flags); + + VIR_FREE(absolute_to); + + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + /** * virDomainRestore: * @conn: pointer to the hypervisor connection @@ -2302,6 +2383,8 @@ error: * * This method will restore a domain saved to disk by virDomainSave(). * + * See virDomainRestoreFlags() for more control. + * * Returns 0 in case of success and -1 in case of failure. */ int @@ -2352,6 +2435,80 @@ error: return -1; } +/** + * virDomainRestoreFlags: + * @conn: pointer to the hypervisor connection + * @from: path to the input file + * @dxml: (optional) XML config for adjusting guest xml used on restore + * @flags: bitwise-OR of virDomainSaveRestoreFlags + * + * This method will restore a domain saved to disk by virDomainSave(). + * + * If the hypervisor supports it, @dxml can be used to alter + * host-specific portions of the domain XML that will be used when + * restoring an image. For example, it is possible to alter the + * backing filename that is associated with a disk device, in order to + * prepare for file renaming done as part of backing up the disk + * device while the domain is stopped. + * + * If @flags includes VIR_DOMAIN_SAVE_BYPASS_CACHE, then libvirt will + * attempt to bypass the file system cache while restoring the file, or + * fail if it cannot do so for the given system; this can allow less + * pressure on file system cache, but also risks slowing saves to NFS. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virDomainRestoreFlags(virConnectPtr conn, const char *from, const char *dxml, + unsigned int flags) +{ + VIR_DEBUG("conn=%p, from=%s, dxml=%s, flags=%x", + conn, from, NULLSTR(dxml), flags); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + if (from == NULL) { + virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->driver->domainRestoreFlags) { + int ret; + char *absolute_from; + + /* We must absolutize the file path as the restore is done out of process */ + if (virFileAbsPath(from, &absolute_from) < 0) { + virLibConnError(VIR_ERR_INTERNAL_ERROR, + _("could not build absolute input file path")); + goto error; + } + + ret = conn->driver->domainRestoreFlags(conn, absolute_from, dxml, + flags); + + VIR_FREE(absolute_from); + + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} + /** * virDomainCoreDump: * @domain: a domain object @@ -2362,6 +2519,17 @@ error: * Note that for remote Xen Daemon the file path will be interpreted in * the remote host. * + * If @flags includes VIR_DUMP_CRASH, then leave the guest shut off with + * a crashed state after the dump completes. If @flags includes + * VIR_DUMP_LIVE, then make the core dump while continuing to allow + * the guest to run; otherwise, the guest is suspended during the dump. + * The above two flags are mutually exclusive. + * + * Additionally, if @flags includes VIR_DUMP_BYPASS_CACHE, then libvirt + * will attempt to bypass the file system cache while creating the file, + * or fail if it cannot do so for the given system; this can allow less + * pressure on file system cache, but also risks slowing saves to NFS. + * * Returns 0 in case of success and -1 in case of failure. */ int @@ -6612,6 +6780,12 @@ error: * libvirtd daemon. Any domains marked for auto destroy will * block attempts at migration or save-to-file * + * If the VIR_DOMAIN_START_BYPASS_CACHE flag is set, and there is a + * managed save file for this domain (created by virDomainManagedSave()), + * then libvirt will attempt to bypass the file system cache while restoring + * the file, or fail if it cannot do so for the given system; this can allow + * less pressure on file system cache, but also risks slowing loads from NFS. + * * Returns 0 in case of success, -1 in case of error */ int @@ -14837,7 +15011,7 @@ error: /** * virDomainManagedSave: * @dom: pointer to the domain - * @flags: optional flags currently unused + * @flags: bitwise-OR of virDomainSaveRestoreFlags * * 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 @@ -14847,6 +15021,11 @@ error: * restarted (automatically or via an explicit libvirt call). * As a result any running domain is sure to not have a managed saved image. * + * If @flags includes VIR_DOMAIN_SAVE_BYPASS_CACHE, then libvirt will + * attempt to bypass the file system cache while creating the file, or + * fail if it cannot do so for the given system; this can allow less + * pressure on file system cache, but also risks slowing saves to NFS. + * * Returns 0 in case of success or -1 in case of failure */ int virDomainManagedSave(virDomainPtr dom, unsigned int flags) diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 5cc480ef5b326dedbcecd843bc2551201b6ea34a..6935140df85e8de1bb58321504875b9e62a71669 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -468,6 +468,8 @@ LIBVIRT_0.9.3 { LIBVIRT_0.9.4 { global: + virDomainRestoreFlags; + virDomainSaveFlags; virDomainUndefineFlags; } LIBVIRT_0.9.3;