diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index d5b617eb8625671ba9d7af4908eb802a09aabf51..2a108b81aa14c41607a6d261fa65d281d718261a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2542,8 +2542,8 @@ typedef enum { * flags), job ends on completion */ VIR_DOMAIN_BLOCK_JOB_TYPE_COPY = 2, - /* Block Copy (virDomainBlockRebase with flags), job exists as - * long as mirroring is active */ + /* Block Copy (virDomainBlockCopy, or virDomainBlockRebase with + * flags), job exists as long as mirroring is active */ VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT = 3, /* Block Commit (virDomainBlockCommit without flags), job ends on @@ -2620,6 +2620,60 @@ int virDomainBlockRebase(virDomainPtr dom, const char *disk, const char *base, unsigned long bandwidth, unsigned int flags); +/** + * virDomainBlockCopyFlags: + * + * Flags available for virDomainBlockCopy(). + */ +typedef enum { + VIR_DOMAIN_BLOCK_COPY_SHALLOW = 1 << 0, /* Limit copy to top of source + backing chain */ + VIR_DOMAIN_BLOCK_COPY_REUSE_EXT = 1 << 1, /* Reuse existing external + file for a copy */ +} virDomainBlockCopyFlags; + +/** + * VIR_DOMAIN_BLOCK_COPY_BANDWIDTH: + * Macro for the virDomainBlockCopy bandwidth tunable: it represents + * the maximum bandwidth in bytes/s, and is used while getting the + * copy operation into the mirrored phase, with a type of ullong. For + * compatibility with virDomainBlockJobSetSpeed(), values larger than + * 2^52 bytes/sec (a 32-bit MiB/s value) may be rejected due to + * overflow considerations, and hypervisors may further restrict the + * set of valid values. Specifying 0 is the same as omitting this + * parameter, to request no bandwidth limiting. Some hypervisors may + * lack support for this parameter, while still allowing a subsequent + * change of bandwidth via virDomainBlockJobSetSpeed(). The actual + * speed can be determined with virDomainGetBlockJobInfo(). + */ +#define VIR_DOMAIN_BLOCK_COPY_BANDWIDTH "bandwidth" + +/** + * VIR_DOMAIN_BLOCK_COPY_GRANULARITY: + * Macro for the virDomainBlockCopy granularity tunable: it represents + * the granularity in bytes at which the copy operation recognizes + * dirty blocks that need copying, as an unsigned int. Hypervisors may + * restrict this to be a power of two or fall within a certain + * range. Specifying 0 is the same as omitting this parameter, to + * request the hypervisor default. + */ +#define VIR_DOMAIN_BLOCK_COPY_GRANULARITY "granularity" + +/** + * VIR_DOMAIN_BLOCK_COPY_BUF_SIZE: + * Macro for the virDomainBlockCopy buffer size tunable: it represents + * how much data in bytes can be in flight between source and destination, + * as an unsigned int. Specifying 0 is the same as omitting this parameter, + * to request the hypervisor default. + */ +#define VIR_DOMAIN_BLOCK_COPY_BUF_SIZE "buf-size" + +int virDomainBlockCopy(virDomainPtr dom, const char *disk, + const char *destxml, + virTypedParameterPtr params, + int nparams, + unsigned int flags); + /** * virDomainBlockCommitFlags: * @@ -4854,7 +4908,7 @@ typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn, * virConnectDomainEventBlockJobStatus: * * Tracks status of a virDomainBlockPull(), virDomainBlockRebase(), - * or virDomainBlockCommit() operation + * virDomainBlockCopy(), or virDomainBlockCommit() operation */ typedef enum { VIR_DOMAIN_BLOCK_JOB_COMPLETED = 0, diff --git a/src/driver.h b/src/driver.h index 8c6475bf54c793fbb9e96a8527b78499fc1bcba2..cd136ba3d704550445217bfd704a1e47e678f22f 100644 --- a/src/driver.h +++ b/src/driver.h @@ -2,7 +2,7 @@ * driver.h: description of the set of interfaces provided by a * entry point to the virtualization engine * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1014,6 +1014,14 @@ typedef int unsigned long bandwidth, unsigned int flags); +typedef int +(*virDrvDomainBlockCopy)(virDomainPtr dom, + const char *path, + const char *destxml, + virTypedParameterPtr params, + int nparams, + unsigned int flags); + typedef int (*virDrvDomainBlockCommit)(virDomainPtr dom, const char *disk, @@ -1397,6 +1405,7 @@ struct _virDriver { virDrvDomainBlockJobSetSpeed domainBlockJobSetSpeed; virDrvDomainBlockPull domainBlockPull; virDrvDomainBlockRebase domainBlockRebase; + virDrvDomainBlockCopy domainBlockCopy; virDrvDomainBlockCommit domainBlockCommit; virDrvConnectSetKeepAlive connectSetKeepAlive; virDrvConnectIsAlive connectIsAlive; diff --git a/src/libvirt.c b/src/libvirt.c index ff878c472379cfca4fabbddec97b42a0461470e7..772cc0d4bbb1f9dbee558919f0fc74f41dda78fd 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -19924,7 +19924,13 @@ virDomainBlockPull(virDomainPtr dom, const char *disk, * The actual speed can be determined with virDomainGetBlockJobInfo(). * * When @base is NULL and @flags is 0, this is identical to - * virDomainBlockPull(). + * virDomainBlockPull(). When @flags contains VIR_DOMAIN_BLOCK_REBASE_COPY, + * this command is shorthand for virDomainBlockCopy() where the destination + * XML encodes @base as a , @bandwidth is properly scaled + * and passed as a typed parameter, the shallow and reuse external flags + * are preserved, and remaining flags control whether the XML encodes a + * destination format of raw instead of leaving the destination identical + * to the source format or probed from the reused file. * * Returns 0 if the operation has started, -1 on failure. */ @@ -19974,6 +19980,120 @@ virDomainBlockRebase(virDomainPtr dom, const char *disk, } +/** + * virDomainBlockCopy: + * @dom: pointer to domain object + * @disk: path to the block device, or device shorthand + * @destxml: XML description of the copy destination + * @params: Pointer to block copy parameter objects, or NULL + * @nparams: Number of block copy parameters (this value can be the same or + * less than the number of parameters supported) + * @flags: bitwise-OR of virDomainBlockCopyFlags + * + * Copy the guest-visible contents of a disk image to a new file described + * by @destxml. The destination XML has a top-level element of , and + * resembles what is used when hot-plugging a disk via virDomainAttachDevice(), + * except that only sub-elements related to describing the new host resource + * are necessary (sub-elements related to the guest view, such as , + * are ignored). It is strongly recommended to include a + * format designation for the destination, to avoid the potential of any + * security problem that might be caused by probing a file for its format. + * + * This command starts a long-running copy. By default, the copy will pull + * the entire source chain into the destination file, but if @flags also + * contains VIR_DOMAIN_BLOCK_COPY_SHALLOW, then only the top of the source + * chain will be copied (the source and destination have a common backing + * file). The format of the destination file is controlled by the + * sub-element of the XML. The destination will be created unless the + * VIR_DOMAIN_BLOCK_COPY_REUSE_EXT flag is present stating that the file + * was pre-created with the correct format and metadata and sufficient + * size to hold the copy. In case the VIR_DOMAIN_BLOCK_COPY_SHALLOW flag + * is used the pre-created file has to exhibit the same guest visible contents + * as the backing file of the original image. This allows a management app to + * pre-create files with relative backing file names, rather than the default + * of absolute backing file names. + * + * A copy job has two parts; in the first phase, the source is copied into + * the destination, and the job can only be canceled by reverting to the + * source file; progress in this phase can be tracked via the + * virDomainBlockJobInfo() command, with a job type of + * VIR_DOMAIN_BLOCK_JOB_TYPE_COPY. The job transitions to the second + * phase when the job info states cur == end, and remains alive to mirror + * all further changes to both source and destination. The user must + * call virDomainBlockJobAbort() to end the mirroring while choosing + * whether to revert to source or pivot to the destination. An event is + * issued when the job ends, and depending on the hypervisor, an event may + * also be issued when the job transitions from pulling to mirroring. If + * the job is aborted, a new job will have to start over from the beginning + * of the first phase. + * + * Some hypervisors will restrict certain actions, such as virDomainSave() + * or virDomainDetachDevice(), while a copy job is active; they may + * also restrict a copy job to transient domains. + * + * The @disk parameter is either an unambiguous source name of the + * block device (the sub-element, such as + * "/path/to/image"), or the device target shorthand (the + * sub-element, such as "vda"). Valid names + * can be found by calling virDomainGetXMLDesc() and inspecting + * elements within //domain/devices/disk. + * + * The @params and @nparams arguments can be used to set hypervisor-specific + * tuning parameters, such as maximum bandwidth or granularity. For a + * parameter that the hypervisor understands, explicitly specifying 0 + * behaves the same as omitting the parameter, to use the hypervisor + * default; however, omitting a parameter is less likely to fail. + * + * This command is a superset of the older virDomainBlockRebase() when used + * with the VIR_DOMAIN_BLOCK_REBASE_COPY flag, and offers better control + * over the destination format, the ability to copy to a destination that + * is not a local file, and the possibility of additional tuning parameters. + * + * Returns 0 if the operation has started, -1 on failure. + */ +int +virDomainBlockCopy(virDomainPtr dom, const char *disk, + const char *destxml, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(dom, + "disk=%s, destxml=%s, params=%p, nparams=%d, flags=%x", + disk, destxml, params, nparams, flags); + VIR_TYPED_PARAMS_DEBUG(params, nparams); + + virResetLastError(); + + virCheckDomainReturn(dom, -1); + conn = dom->conn; + + virCheckReadOnlyGoto(conn->flags, error); + virCheckNonNullArgGoto(disk, error); + virCheckNonNullArgGoto(destxml, error); + virCheckNonNegativeArgGoto(nparams, error); + if (nparams) + virCheckNonNullArgGoto(params, error); + + if (conn->driver->domainBlockCopy) { + int ret; + ret = conn->driver->domainBlockCopy(dom, disk, destxml, + params, nparams, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(dom->conn); + return -1; +} + + /** * virDomainBlockCommit: * @dom: pointer to domain object diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 68fa82aa81254295bda3adbaaa152fe5ec7a2d86..e1f013fad287a2714969957ee92ef0903eba193f 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -673,6 +673,7 @@ LIBVIRT_1.2.7 { LIBVIRT_1.2.8 { global: virConnectGetAllDomainStats; + virDomainBlockCopy; virDomainListGetStats; virDomainOpenGraphicsFD; virDomainStatsRecordListFree;