[libvirt] [RFC] Introduce virDomainBlockCopy API

This API starts asynchronous live copy of a block device (specified by target element of the xml argument) into a new source (which must already exist). The process can be controlled in the same way as migration: monitored with virDomainJobInfo() and canceled using virDomainAbortJob(). I don't particularly like the name (but I wasn't able to come up with a better one) since it doesn't reflect the fact that once a block device is switched to use the new source once copying finishes. In other words, the goal of this API is to update the device to use new source (just like virDomainUpdateDeviceFlags) but before doing so all data is copied from the old source into the new one (unlike the UpdateDevice API). --- include/libvirt/libvirt.h.in | 4 +++ src/driver.h | 6 ++++ src/libvirt.c | 54 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + 4 files changed, 65 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index cb9e8ca..41f6b2e 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2983,6 +2983,10 @@ typedef struct _virTypedParameter virMemoryParameter; */ typedef virMemoryParameter *virMemoryParameterPtr; +int virDomainBlockCopy(virDomainPtr domain, + const char *xml, + unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/src/driver.h b/src/driver.h index 62bbc1d..8731d68 100644 --- a/src/driver.h +++ b/src/driver.h @@ -666,6 +666,11 @@ typedef int virDomainBlockPullInfoPtr info, unsigned int flags); +typedef int + (*virDrvDomainBlockCopy)(virDomainPtr domain, + const char *xml, + unsigned int flags); + /** * _virDriver: * @@ -809,6 +814,7 @@ struct _virDriver { virDrvDomainBlockPullAll domainBlockPullAll; virDrvDomainBlockPullAbort domainBlockPullAbort; virDrvDomainGetBlockPullInfo domainGetBlockPullInfo; + virDrvDomainBlockCopy domainBlockCopy; }; typedef int diff --git a/src/libvirt.c b/src/libvirt.c index c57e0c3..ad5da9b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -15548,3 +15548,57 @@ error: virDispatchError(dom->conn); return -1; } + +/** + * virDomainBlockCopy: + * @domain: pointer to domain object + * @xml: pointer to XML description of the block device to copy + * @flags: currently unused, use 0 + * + * Starts asynchronous live copy of a block device (specified by target element + * of the xml) into a new source (which must already exist). The process can be + * controlled in the same way as migration: monitored with virDomainJobInfo() + * and canceled using virDomainAbortJob(). + * + * Returns -1 in case of failure, 0 when successful. + */ +int +virDomainBlockCopy(virDomainPtr domain, const char *xml, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "xml=%s, flags=%d", xml, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (xml == NULL) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + conn = domain->conn; + + if (conn->driver->domainBlockCopy) { + int ret; + ret = conn->driver->domainBlockCopy(domain, xml, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b2915f6..3028e15 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -452,6 +452,7 @@ LIBVIRT_0.9.2 { LIBVIRT_0.9.3 { global: + virDomainBlockCopy; virDomainBlockPull; virDomainBlockPullAbort; virDomainBlockPullAll; -- 1.7.5.3

On Mon, Jun 20, 2011 at 08:15:24PM +0200, Jiri Denemark wrote:
This API starts asynchronous live copy of a block device (specified by target element of the xml argument) into a new source (which must already exist). The process can be controlled in the same way as migration: monitored with virDomainJobInfo() and canceled using virDomainAbortJob().
I don't particularly like the name (but I wasn't able to come up with a better one) since it doesn't reflect the fact that once a block device is switched to use the new source once copying finishes. In other words, the goal of this API is to update the device to use new source (just like virDomainUpdateDeviceFlags) but before doing so all data is copied from the old source into the new one (unlike the UpdateDevice API).
How is this functionality different from the virDomainBlockPull APIs we just added from Adam. From this description, it sounds practically identical, except it only allows one job to be run at a time, instead of allowing many. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Tue, Jun 21, 2011 at 10:48:38 +0100, Daniel P. Berrange wrote:
On Mon, Jun 20, 2011 at 08:15:24PM +0200, Jiri Denemark wrote:
This API starts asynchronous live copy of a block device (specified by target element of the xml argument) into a new source (which must already exist). The process can be controlled in the same way as migration: monitored with virDomainJobInfo() and canceled using virDomainAbortJob().
I don't particularly like the name (but I wasn't able to come up with a better one) since it doesn't reflect the fact that once a block device is switched to use the new source once copying finishes. In other words, the goal of this API is to update the device to use new source (just like virDomainUpdateDeviceFlags) but before doing so all data is copied from the old source into the new one (unlike the UpdateDevice API).
How is this functionality different from the virDomainBlockPull APIs we just added from Adam. From this description, it sounds practically identical, except it only allows one job to be run at a time, instead of allowing many.
Assuming I understand Adam's virDomainBlockPull API correctly it takes a disk image which is based on a backing image and pulls all data from the backing image into the main image so that it becomes independent on the backing image. This new virDomainBlockCopy API is different. It can be used when you have a disk image (no matter what kind) stored somewhere and you need to copy it somewhere else. It takes two different and independent images, one currently assigned to a virtual block device and a new unassigned one, copies all data from the old one to the new one and reconfigures the block device to use the new image. Neither of the image formats has to be even capable of backing images. Jirka

On Tue, Jun 21, 2011 at 1:01 PM, Jiri Denemark <jdenemar@redhat.com> wrote:
On Tue, Jun 21, 2011 at 10:48:38 +0100, Daniel P. Berrange wrote:
On Mon, Jun 20, 2011 at 08:15:24PM +0200, Jiri Denemark wrote:
This API starts asynchronous live copy of a block device (specified by target element of the xml argument) into a new source (which must already exist). The process can be controlled in the same way as migration: monitored with virDomainJobInfo() and canceled using virDomainAbortJob().
I don't particularly like the name (but I wasn't able to come up with a better one) since it doesn't reflect the fact that once a block device is switched to use the new source once copying finishes. In other words, the goal of this API is to update the device to use new source (just like virDomainUpdateDeviceFlags) but before doing so all data is copied from the old source into the new one (unlike the UpdateDevice API).
How is this functionality different from the virDomainBlockPull APIs we just added from Adam. From this description, it sounds practically identical, except it only allows one job to be run at a time, instead of allowing many.
Assuming I understand Adam's virDomainBlockPull API correctly it takes a disk image which is based on a backing image and pulls all data from the backing image into the main image so that it becomes independent on the backing image.
This new virDomainBlockCopy API is different. It can be used when you have a disk image (no matter what kind) stored somewhere and you need to copy it somewhere else. It takes two different and independent images, one currently assigned to a virtual block device and a new unassigned one, copies all data from the old one to the new one and reconfigures the block device to use the new image. Neither of the image formats has to be even capable of backing images.
Right. Stefan

On 06/21/2011 07:14 AM, Stefan Hajnoczi wrote:
This new virDomainBlockCopy API is different. It can be used when you have a disk image (no matter what kind) stored somewhere and you need to copy it somewhere else. It takes two different and independent images, one currently assigned to a virtual block device and a new unassigned one, copies all data from the old one to the new one and reconfigures the block device to use the new image. Neither of the image formats has to be even capable of backing images.
Right.
This sounds related to my thread on snapshot capabilities, where if the disk is not in a format where qemu can do a live snapshot, then libvirt needs a command to pause guest I/O, libvirt snapshots the disk, then libvirt informs qemu that the block device has a new image. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Tue, Jun 21, 2011 at 07:36:23 -0600, Eric Blake wrote:
On 06/21/2011 07:14 AM, Stefan Hajnoczi wrote:
This new virDomainBlockCopy API is different. It can be used when you have a disk image (no matter what kind) stored somewhere and you need to copy it somewhere else. It takes two different and independent images, one currently assigned to a virtual block device and a new unassigned one, copies all data from the old one to the new one and reconfigures the block device to use the new image. Neither of the image formats has to be even capable of backing images.
Right.
This sounds related to my thread on snapshot capabilities, where if the disk is not in a format where qemu can do a live snapshot, then libvirt needs a command to pause guest I/O, libvirt snapshots the disk, then libvirt informs qemu that the block device has a new image.
It's all connected in some way, which is also why qemu will probably utilize common code to provide these functions. However, since BlockCopy is not a snapshot, it's about copying all data from one image to another qemu can do it all internally with a single monitor command to minimize the impact on running guest. Jirka

On Mon, Jun 20, 2011 at 08:15:24PM +0200, Jiri Denemark wrote:
This API starts asynchronous live copy of a block device (specified by target element of the xml argument) into a new source (which must already exist). The process can be controlled in the same way as migration: monitored with virDomainJobInfo() and canceled using virDomainAbortJob().
I don't particularly like the name (but I wasn't able to come up with a better one) since it doesn't reflect the fact that once a block device is switched to use the new source once copying finishes. In other words, the goal of this API is to update the device to use new source (just like virDomainUpdateDeviceFlags) but before doing so all data is copied from the old source into the new one (unlike the UpdateDevice API). --- include/libvirt/libvirt.h.in | 4 +++ src/driver.h | 6 ++++ src/libvirt.c | 54 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + 4 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index cb9e8ca..41f6b2e 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2983,6 +2983,10 @@ typedef struct _virTypedParameter virMemoryParameter; */ typedef virMemoryParameter *virMemoryParameterPtr;
+int virDomainBlockCopy(virDomainPtr domain, + const char *xml, + unsigned int flags);
Given that we do in fact need this API, the main problem with it is that it does not allow for multiple concurrent copy operations on a single VM. This is because the JobAbort/JobInfo APis are per-VM, not per block devices. We'd either need to add some new APIs, or somehow re-use the BlockPullAbort/Info APis for this copy operation too. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (4)
-
Daniel P. Berrange
-
Eric Blake
-
Jiri Denemark
-
Stefan Hajnoczi