Right now, the existing virDomainBlockPull API has a tough limitation - it is an all-or-none approach. In all my examples below, I'm starting from the following relationship, where '<-' means 'is a backing file of': template <- intermediate <- current virDomainBlockPull can only convert things in a forward direction, with the merge destination being the current image, resulting in: merge template and intermediate into current, creating: current Meanwhile, qemu is adding support for a partial block pull operation, still on the current image as the merge destination, but where you can now specify an optional argument to limit the pull to just the intermediate files and altering the current image to be backed by an ancestor file, as in: merge intermediate into current, creating: template <- current For 0.9.10, I'd like to add the following API: /** * virDomainBlockRebase: * @dom: pointer to domain object * @disk: path to the block device, or device shorthand * @base: new base image, or NULL for entire block pull * @bandwidth: (optional) specify copy bandwidth limit in Mbps * @flags: extra flags; not used yet, so callers should always pass 0 * * Populate a disk image with data from its backing image chain, and * setting the new backing image to @base, where base is the absolute * path of one of the backing images in the chain. If @base is NULL, * then this operation is identical to virDomainBlockPull(). Once all * data from its backing image chain has been pulled, the disk no * longer depends on those intermediate backing images. This function * pulls data for the entire device in the background. Progress of the * operation can be checked with virDomainGetBlockJobInfo() and * the operation can be aborted with virDomainBlockJobAbort(). When * finished, an asynchronous event is raised to indicate the final * status. * * The @disk, @bandwidth, and @flags parameters are handled as in * virDomainBlockPull(). * * Returns 0 if the operation has started, -1 on failure. */ int virDomainBlockRebase(virDomainPtr dom, const char *disk, const char *base, unsigned long bandwidth, unsigned int flags); Given that Adam has a pending patch to support a VIR_DOMAIN_BLOCK_PULL_ASYNC flag, this same flag would have to be supported in virDomainBlockRebase. I've also been chatting with Federico Simoncelli about how the above operation would work for VDSM purposes in doing a live block move, while preserving a common template base file: start with: vda: template <- current1 create a disk-only snapshot, with: tmpsnap = virDomainSnapshotCreateXML(dom, "<domainsnapshot>\n" " <disks>\n" " <disk name='vda'>\n" " <source>/path/to/current2</source>\n" " </disk>\n" " <disks>\n" "</domainsnapshot>", VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) where the xml calls out the destination file name, resulting in: vda: template <- current1 <- current2 perform the block rebase, with: virDomainBlockRebase(dom, "vda", "/path/to/template", VIR_DOMAIN_BLOCK_PULL_ASYNC) as well as waiting for the event (or polling status) to wait for completion, resulting in: vda: template <- current2 delete the disk-only snapshot metadata as no longer useful, with: virDomainSnapshotDelete(tmpsnap, VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) At one point, I thought of creating a single libvirt API that performs all of those steps in one call; but right now, I'm not proposing that, because of the fact that qemu has no way to undo a snapshot. In other words, without an undo operation, if the snapshot phase succeeds but the block rebase phase fails, a single API would have to report failure even though the domain was altered, while the ideal scenario is that reporting failure means things were in the same state as before the API started. Beyond 0.9.10, there are some additional useful merge patterns that might be worth exposing. All of these operations are already possible on offline images, using qemu-img; but none of them are possible on live images using current qemu, which is why I'm thinking it is something for another day. I'm also hoping to someday enhance the set of virStorageVol APIs to make backing file manipulation of offline images easier. At any rate, the addition merge operations are: forward live merge with a non-current image as the merge destination, as in: merge template into intermediate, creating: intermediate <- current backward merge of a current image (that is, undoing a current snapshot): merge current into intermediate, creating: template <- intermediate and backward merge of a non-current image (that is, undoing an earlier snapshot, but by modifying the template rather than the current image): merge intermediate into base, creating: template <- current Backward merge of the current image seems like something easy to fit into my proposed API (add a new flag, maybe called VIR_DOMAIN_BLOCK_REBASE_BACKWARD). Manipulations of anything that does not involve the current image seems tougher, assuming qemu ever even reaches the point where it exposes those operations on live volumes - the user has to specify not one, but two backing file names. But even that could possibly be fit into my API, by adding a flag that states that the const char *backing argument is treated as an XML snippet describing the full details of the merge, with the XML listing which image is being merged to which destination, rather than as just the name of the backing file becoming the new base of the current image. Perhaps something like: virDomainBlockRebase(dom, block, "<rebase>\n" " <source>/path/to/intermediate</source>\n" " <dest>/path/to/template</dest>\n" "</rebase>", VIR_DOMAIN_BLOCK_REBASE_XML|VIR_DOMAIN_BLOCK_REBASE_BACKWARD) as a specification to take the contents of intermediate, merge those backwards into template, and as well as adjusting the rest of the backing file chain so that whatever used to be backed by intermediate is now backed by template. Or, if qemu ever gives us the ability to merge non-current images, we may decide at that time that it is worth a new API to expose those new complexities. Another thing I have been thinking about is virDomainSnapshotDelete. The above conversation talks about merging of a single disk, but a live disk snapshot operation can create backing file chains for multiple disks at once, all tracked by a snapshot. Additionally, the current code allows a snapshot delete of internal snapshots, but refuses to do anything useful with an external snapshot, because there is currently no way to specify if the snapshot is removed by merging the base into the new current, or by undoing the current and merging it backwards into the base. Alas, virDomainSnapshotDelete doesn't take any arguments for how to handle the situation, and use of a flag to make the decision would limit all disks to be handled in the same manner. So what I'm thinking is that when a snapshot is created (or redefined, using redefinition as the vehicle to add in the new XML), that the snapshot XML itself can record the preferred direction for undoing the snapshot; for example: <domainsnapshot> <disks> <disk name='/path/to/old_vda'> <source file='/path/to/new_vda'/> <on_delete merge='forward'/> </disk> <disk name='/path/to/old_vdb'> <source file='/path/to/new_vdb'/> <on_delete merge='backward'/> </disk> <disks> </domainsnapshot> then when virDomainSnapshotDelete is called on that snapshot, old_vda would be forward merged into new_vda, while new_vdb would be backward merged into old_vdb. Again, that's food for thought for post-0.9.10, and shouldn't get in the way of adding virDomainBlockRebase() now. -- Eric Blake eblake@xxxxxxxxxx +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Attachment:
signature.asc
Description: OpenPGP digital signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list