After looking a little bit more (at' _live_snapshot' function in Nova[*]) , the below seem to be the precise equivalent sequence of (libvirt) operations of what's happening in Nova's '_live_snapshot' function. Thanks to libvirt developer Eric Blake for reviewing this:
(0) Take the Libvirt guest's XML backup:
$ virsh dumpxml --inactive vm1 > /var/tmp/vm1.xml
(1) Abort any failed/finished block operations:
$ virsh blockjob vm1 vda --abort
(2) Undefine a running domain. (Note: Undefining a running domain does not _kill_ the domain, it just converts it from persistent to
transient.)
$ virsh undefine vm1
(3) Invoke 'virsh blockcopy' (This will take time, depending on the size of disk image vm1):
(4) Abort any failed/finished block operations: (as Dan pointed out in comment #17, this the abort operation where QEMU
might be failing):
$ virsh blockjob vm1 vda --abort
NOTE: If we use '--finish' command in step 3 it is equivalent to the
above command (consequently, step 4 can be skipped).
(5) Define the guest again (to make it persistent):
$ virsh define /var/tmp/vm1.xml
(6) From the obtained new copy, convert the QCOW2 with a backing file to a flat (raw) image with no backing file:
$ qemu-img convert -f qcow2 -O raw vm1.qcow2 conv-vm1.img
Notes (from Eric Blake):
The _live_snapshot function concludes it all with redefining the
domain (umm, that part looks fishy in the code - you undefine it
only if it was persistent, but redefine the domain unconditionally;
so if you call your function on a domain that is initially
transient, you end up with a persistent domain at the end of your
function).
After looking a little bit more (at' _live_snapshot' function in Nova[*]) , the below seem to be the precise equivalent sequence of (libvirt) operations of what's happening in Nova's '_live_snapshot' function. Thanks to libvirt developer Eric Blake for reviewing this:
(0) Take the Libvirt guest's XML backup:
$ virsh dumpxml --inactive vm1 > /var/tmp/vm1.xml
(1) Abort any failed/finished block operations:
$ virsh blockjob vm1 vda --abort
(2) Undefine a running domain. (Note: Undefining a running domain does not _kill_ the domain, it just converts it from persistent to
transient.)
$ virsh undefine vm1
(3) Invoke 'virsh blockcopy' (This will take time, depending on the size of disk image vm1):
$ virsh blockcopy \
/export/ backups/ vm1-copy. qcow2 \
--domain vm1 vda \
--wait \
--verbose
(4) Abort any failed/finished block operations: (as Dan pointed out in comment #17, this the abort operation where QEMU
might be failing):
$ virsh blockjob vm1 vda --abort
NOTE: If we use '--finish' command in step 3 it is equivalent to the
above command (consequently, step 4 can be skipped).
(5) Define the guest again (to make it persistent):
$ virsh define /var/tmp/vm1.xml
(6) From the obtained new copy, convert the QCOW2 with a backing file to a flat (raw) image with no backing file:
$ qemu-img convert -f qcow2 -O raw vm1.qcow2 conv-vm1.img
Notes (from Eric Blake):
The _live_snapshot function concludes it all with redefining the
domain (umm, that part looks fishy in the code - you undefine it
only if it was persistent, but redefine the domain unconditionally;
so if you call your function on a domain that is initially
transient, you end up with a persistent domain at the end of your
function).
[*] https:/ /github. com/openstack/ nova/blob/ master/ nova/virt/ libvirt/ driver. py#L1593