diff options
author | Cole Robinson <crobinso@redhat.com> | 2020-09-03 12:03:38 -0400 |
---|---|---|
committer | Cole Robinson <crobinso@redhat.com> | 2020-09-05 15:49:55 -0400 |
commit | f23a27639f61d8eeb0268d03ccaefecc1be78637 (patch) | |
tree | 4d8802a7bd0e6c0034aca028aad07ffd035b6990 | |
parent | c0d1e76941c7d51c8e8278231a252db976149b00 (diff) | |
download | virt-manager-f23a27639f61d8eeb0268d03ccaefecc1be78637.tar.gz |
cloner: Big API rework
* Centralize lots of disk building
* Open code virt-clone specific behavior at the source
* Drop a lot or properties
* Move most testing to test_cli.py
* Generally a ton of cleanup
virt-manager clone wizard has not been converted yet so is totally
broken after this commit
Signed-off-by: Cole Robinson <crobinso@redhat.com>
45 files changed, 575 insertions, 1808 deletions
diff --git a/tests/data/cli/clone-disk-managed.xml b/tests/data/cli/clone/clone-disk-managed.xml index 8fe1fe2d..8fe1fe2d 100644 --- a/tests/data/cli/clone-disk-managed.xml +++ b/tests/data/cli/clone/clone-disk-managed.xml diff --git a/tests/data/cli/clone-disk-noexist.xml b/tests/data/cli/clone/clone-disk-noexist.xml index d99b1aec..d99b1aec 100644 --- a/tests/data/cli/clone-disk-noexist.xml +++ b/tests/data/cli/clone/clone-disk-noexist.xml diff --git a/tests/data/cli/clone-disk.xml b/tests/data/cli/clone/clone-disk.xml index da1eb0a6..da1eb0a6 100644 --- a/tests/data/cli/clone-disk.xml +++ b/tests/data/cli/clone/clone-disk.xml diff --git a/tests/data/cli/clone-empty.xml b/tests/data/cli/clone/clone-empty.xml index 08d5699e..538d9f92 100644 --- a/tests/data/cli/clone-empty.xml +++ b/tests/data/cli/clone/clone-empty.xml @@ -1,5 +1,5 @@ <domain type='test'> - <name>clone-empty</name> + <name>empty-clone5</name> <uuid>4a64cc71-7272-2fd0-2323-3050941ea3c3</uuid> <memory>8388608</memory> <currentMemory>2097152</currentMemory> diff --git a/tests/data/cli/clone-nvram-auto.xml b/tests/data/cli/clone/clone-nvram-auto.xml index dc95f6ac..dc95f6ac 100644 --- a/tests/data/cli/clone-nvram-auto.xml +++ b/tests/data/cli/clone/clone-nvram-auto.xml diff --git a/tests/data/cli/clone-nvram-missing.xml b/tests/data/cli/clone/clone-nvram-missing.xml index fcbce533..fcbce533 100644 --- a/tests/data/cli/clone-nvram-missing.xml +++ b/tests/data/cli/clone/clone-nvram-missing.xml diff --git a/tests/data/cli/clone-nvram-newpool.xml b/tests/data/cli/clone/clone-nvram-newpool.xml index d27da472..d27da472 100644 --- a/tests/data/cli/clone-nvram-newpool.xml +++ b/tests/data/cli/clone/clone-nvram-newpool.xml diff --git a/tests/data/clone/nvram-missing-out.xml b/tests/data/cli/compare/virt-clone-clone-nvram-path.xml index c59eaea8..590f4c9b 100644 --- a/tests/data/clone/nvram-missing-out.xml +++ b/tests/data/cli/compare/virt-clone-clone-nvram-path.xml @@ -1,6 +1,6 @@ <domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> + <name>clone-orig-clone</name> + <uuid>00000000-1111-2222-3333-444444444444</uuid> <memory>262144</memory> <currentMemory>262144</currentMemory> <vcpu>1</vcpu> @@ -8,7 +8,7 @@ <type arch="i686" machine="pc">hvm</type> <boot dev="cdrom"/> <loader readonly="yes" type="pflash">/usr/share/ovmf/ovmf-efi.fd</loader> - <nvram>/nvram/clone-new_VARS.fd</nvram> + <nvram>/nvram/my-custom-path</nvram> </os> <features> <acpi/> diff --git a/tests/data/cli/compare/virt-clone-empty.xml b/tests/data/cli/compare/virt-clone-empty.xml index cf794bcb..939d0c59 100644 --- a/tests/data/cli/compare/virt-clone-empty.xml +++ b/tests/data/cli/compare/virt-clone-empty.xml @@ -1,5 +1,5 @@ <domain type="test"> - <name>clone-empty-clone</name> + <name>empty-clone6</name> <uuid>00000000-1111-2222-3333-444444444444</uuid> <memory>8388608</memory> <currentMemory>2097152</currentMemory> diff --git a/tests/data/cli/compare/virt-clone-replace.xml b/tests/data/cli/compare/virt-clone-replace.xml new file mode 100644 index 00000000..4c94c6b6 --- /dev/null +++ b/tests/data/cli/compare/virt-clone-replace.xml @@ -0,0 +1,83 @@ +<domain type="test"> + <name>test</name> + <uuid>00000000-1111-2222-3333-444444444444</uuid> + <memory unit="KiB">409600</memory> + <currentMemory unit="KiB">204800</currentMemory> + <vcpu placement="static">5</vcpu> + <os> + <type arch="i686">hvm</type> + <loader type="rom">/usr/lib/xen/boot/hvmloader</loader> + <boot dev="hd"/> + </os> + <features> + <acpi/> + <apic/> + </features> + <clock offset="utc"/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <disk type="block" device="floppy"> + <driver type="vmdk"/> + <source dev="/dev/disk-pool/diskvol1-clone"/> + <target dev="fda" bus="fdc"/> + <address type="drive" controller="0" bus="0" target="0" unit="0"/> + </disk> + <disk type="block" device="disk"> + <source dev="/dev/disk-pool/diskvol2"/> + <target dev="sda" bus="scsi"/> + <readonly/> + <address type="drive" controller="0" bus="0" target="0" unit="0"/> + </disk> + <disk type="file" device="cdrom"> + <target dev="sdb" bus="scsi"/> + <readonly/> + <address type="drive" controller="0" bus="0" target="0" unit="1"/> + </disk> + <disk type="block" device="disk"> + <driver type="qcow2"/> + <source dev="/dev/default-pool/collidevol1.img"/> + <target dev="sdc" bus="scsi"/> + <shareable/> + <address type="drive" controller="0" bus="0" target="0" unit="2"/> + </disk> + <disk type="file" device="disk"> + <source file="/dev/default-pool/default-vol-clone"/> + <target dev="hda" bus="ide"/> + <address type="drive" controller="0" bus="0" target="0" unit="0"/> + </disk> + <disk type="file" device="disk"> + <source file="/dev/default-pool/testvol9-clone.img"/> + <target dev="hdb" bus="ide"/> + <address type="drive" controller="0" bus="0" target="0" unit="1"/> + </disk> + <controller type="scsi" index="0"/> + <controller type="fdc" index="0"/> + <controller type="ide" index="0"/> + <controller type="virtio-serial" index="0"/> + <interface type="network"> + <mac address="00:11:22:33:44:55"/> + <source network="default"/> + <model type="e1000"/> + </interface> + <interface type="user"> + <mac address="00:11:22:33:44:55"/> + </interface> + <parallel type="file"> + <source path="/tmp/foo.log"/> + <target port="0"/> + </parallel> + <channel type="unix"> + <source mode="bind"/> + <target type="virtio" name="org.qemu.guest_agent.0"/> + </channel> + <graphics type="vnc" port="-1" listen="127.0.0.1"> + <listen type="address" address="127.0.0.1"/> + </graphics> + <video> + <model type="cirrus" vram="16384" heads="1" primary="yes"/> + </video> + </devices> +</domain> diff --git a/tests/data/clone/channel-source-in.xml b/tests/data/clone/channel-source-in.xml deleted file mode 100644 index f69054c4..00000000 --- a/tests/data/clone/channel-source-in.xml +++ /dev/null @@ -1,35 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <channel type='unix'> - <source mode='bind' path='/tmp/guestfwd'/> - <target type='guestfwd' address='10.0.0.1' port='1234'/> - </channel> - <channel type='unix'> - <source mode='bind' path='/var/lib/libvirt/qemu/channel/target/domain-2-generic/org.qemu.guest_agent.0'/> - <target type='virtio' name='org.qemu.guest_agent.0'/> - </channel> - <channel type='unix'> - <target type='virtio' name='org.qemu.guest_agent.0'/> - </channel> - <channel type='unix'> - <target type='virtio'/> - </channel> - </devices> -</domain> diff --git a/tests/data/clone/channel-source-out.xml b/tests/data/clone/channel-source-out.xml deleted file mode 100644 index 210e7a7b..00000000 --- a/tests/data/clone/channel-source-out.xml +++ /dev/null @@ -1,35 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <channel type="unix"> - <source mode="bind" path="/tmp/guestfwd"/> - <target type="guestfwd" address="10.0.0.1" port="1234"/> - </channel> - <channel type="unix"> - <source mode="bind"/> - <target type="virtio" name="org.qemu.guest_agent.0"/> - </channel> - <channel type="unix"> - <target type="virtio" name="org.qemu.guest_agent.0"/> - </channel> - <channel type="unix"> - <target type="virtio"/> - </channel> - </devices> -</domain> diff --git a/tests/data/clone/cross-pool-disks-out.xml b/tests/data/clone/cross-pool-disks-out.xml deleted file mode 100644 index 260f321c..00000000 --- a/tests/data/clone/cross-pool-disks-out.xml +++ /dev/null @@ -1,22 +0,0 @@ -<volume> - <name>new1.img</name> - <capacity>1000000</capacity> - <allocation>50000</allocation> - <target> - <format type="qcow2"/> - <features> - <lazy_refcounts/> - </features> - </target> -</volume> -<volume> - <name>new2.img</name> - <capacity>1000000</capacity> - <allocation>50000</allocation> - <target> - <format type="qcow2"/> - <features> - <lazy_refcounts/> - </features> - </target> -</volume> diff --git a/tests/data/clone/cross-pool-in.xml b/tests/data/clone/cross-pool-in.xml deleted file mode 100644 index 6177a6f9..00000000 --- a/tests/data/clone/cross-pool-in.xml +++ /dev/null @@ -1,39 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type='file' device='disk'> - <source file='/dev/default-pool/testvol1.img'/> - <target dev='hda' bus='ide'/> - </disk> - <disk type='file' device='disk'> - <source file='/dev/default-pool/testvol2.img'/> - <target dev='hdb' bus='ide'/> - </disk> - <interface type='network'> - <mac address='52:54:00:6c:a0:cb'/> - <source network='test1'/> - </interface> - <interface type='network'> - <mac address='52:54:00:6c:bb:ca'/> - <source network='test2'/> - </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/> - </devices> -</domain> diff --git a/tests/data/clone/cross-pool-out.xml b/tests/data/clone/cross-pool-out.xml deleted file mode 100644 index 5541adf7..00000000 --- a/tests/data/clone/cross-pool-out.xml +++ /dev/null @@ -1,39 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type="file" device="disk"> - <source file="/dev/cross-pool/new1.img"/> - <target dev="hda" bus="ide"/> - </disk> - <disk type="file" device="disk"> - <source file="/dev/default-pool/new2.img"/> - <target dev="hdb" bus="ide"/> - </disk> - <interface type="network"> - <mac address="22:23:45:67:89:00"/> - <source network="test1"/> - </interface> - <interface type="network"> - <mac address="22:23:45:67:89:01"/> - <source network="test2"/> - </interface> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1"/> - </devices> -</domain> diff --git a/tests/data/clone/empty-disks-in.xml b/tests/data/clone/empty-disks-in.xml deleted file mode 100644 index a88c2666..00000000 --- a/tests/data/clone/empty-disks-in.xml +++ /dev/null @@ -1,46 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test1.img'/> - <target dev='hda' bus='ide'/> - </disk> - <disk type='file' device='floppy'> - <target dev='fdb' bus='fdc'/> - </disk> - <disk type='block' device='cdrom'> - <target dev='sda' bus='scsi'/> - <readonly/> - </disk> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test2.img'/> - <target dev='sdb' bus='scsi'/> - </disk> - <interface type='network'> - <mac address='52:54:00:6c:a0:cb'/> - <source network='test1'/> - </interface> - <interface type='network'> - <mac address='52:54:00:6c:bb:ca'/> - <source network='test2'/> - </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/> - </devices> -</domain> diff --git a/tests/data/clone/empty-disks-out.xml b/tests/data/clone/empty-disks-out.xml deleted file mode 100644 index 318f08d9..00000000 --- a/tests/data/clone/empty-disks-out.xml +++ /dev/null @@ -1,46 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type="block" device="disk"> - <target dev="hda" bus="ide"/> - <source dev="/dev/disk-pool/disk-vol1"/> - </disk> - <disk type="file" device="floppy"> - <target dev="fdb" bus="fdc"/> - </disk> - <disk type="block" device="cdrom"> - <target dev="sda" bus="scsi"/> - <readonly/> - </disk> - <disk type="file" device="disk"> - <source file="/tmp/clone2.img"/> - <target dev="sdb" bus="scsi"/> - </disk> - <interface type="network"> - <mac address="22:23:45:67:89:00"/> - <source network="test1"/> - </interface> - <interface type="network"> - <mac address="22:23:45:67:89:01"/> - <source network="test2"/> - </interface> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1"/> - </devices> -</domain> diff --git a/tests/data/clone/force-in.xml b/tests/data/clone/force-in.xml deleted file mode 100644 index 1a431e8f..00000000 --- a/tests/data/clone/force-in.xml +++ /dev/null @@ -1,46 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type='file' device='disk'> - <source file='/dev/default-pool/default-vol'/> - <target dev='hda' bus='ide'/> - </disk> - <disk type='file' device='floppy'> - <target dev='fdb' bus='fdc'/> - </disk> - <disk type='block' device='cdrom'> - <target dev='sda' bus='scsi'/> - <readonly/> - </disk> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test2.img'/> - <target dev='sdb' bus='scsi'/> - </disk> - <interface type='network'> - <mac address='52:54:00:6c:a0:cb'/> - <source network='test1'/> - </interface> - <interface type='network'> - <mac address='52:54:00:6c:bb:ca'/> - <source network='test2'/> - </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/> - </devices> -</domain> diff --git a/tests/data/clone/force-out.xml b/tests/data/clone/force-out.xml deleted file mode 100644 index 63bf6102..00000000 --- a/tests/data/clone/force-out.xml +++ /dev/null @@ -1,46 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type="file" device="disk"> - <source file="/dev/default-pool/1234.img"/> - <target dev="hda" bus="ide"/> - </disk> - <disk type="file" device="floppy"> - <target dev="fdb" bus="fdc"/> - </disk> - <disk type="block" device="cdrom"> - <target dev="sda" bus="scsi"/> - <readonly/> - </disk> - <disk type="file" device="disk"> - <source file="/clone2.img"/> - <target dev="sdb" bus="scsi"/> - </disk> - <interface type="network"> - <mac address="22:23:45:67:89:00"/> - <source network="test1"/> - </interface> - <interface type="network"> - <mac address="22:23:45:67:89:01"/> - <source network="test2"/> - </interface> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1"/> - </devices> -</domain> diff --git a/tests/data/clone/fullpool-in.xml b/tests/data/clone/fullpool-in.xml deleted file mode 100644 index 9b5cc47a..00000000 --- a/tests/data/clone/fullpool-in.xml +++ /dev/null @@ -1,29 +0,0 @@ -<domain type='xen'> - <name>test-full-clone</name> - <currentMemory>204800</currentMemory> - <memory>409600</memory> - <uuid>abcd5678-aaaa-1234-1234-12345678FFFF</uuid> - <os> - <type arch='i686'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> - <boot dev='hd'/> - </os> - <features> - <acpi/><apic/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <vcpu>5</vcpu> - <devices> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> - <disk type='block' device='disk'> - <source dev='/full-pool/testvol1.img'/> - <target dev='hda' bus='ide'/> - </disk> - <interface type='user'> - <mac address='22:11:11:11:11:11'/> - </interface> - </devices> -</domain> diff --git a/tests/data/clone/general-cfg-in.xml b/tests/data/clone/general-cfg-in.xml deleted file mode 100644 index b859bdf2..00000000 --- a/tests/data/clone/general-cfg-in.xml +++ /dev/null @@ -1,43 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <title>footitle</title> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test1.img'/> - <target dev='hda' bus='ide'/> - </disk> - <disk type='block' device='disk'> - <source dev='/dev/null'/> - <target dev='hdb' bus='ide'/> - </disk> - <interface type='network'> - <mac address='52:54:00:6c:a0:cb'/> - <source network='test1'/> - <target dev='vnet0'/> - </interface> - <interface type='bridge'> - <mac address='52:54:00:6c:bb:ca'/> - <source bridge='br0'/> - <target dev='my_manual_dev'/> - </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/> - <graphics type='vnc' port='5905'/> - </devices> -</domain> diff --git a/tests/data/clone/general-cfg-out.xml b/tests/data/clone/general-cfg-out.xml deleted file mode 100644 index 961d7aba..00000000 --- a/tests/data/clone/general-cfg-out.xml +++ /dev/null @@ -1,40 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type="block" device="disk"> - <target dev="hda" bus="ide"/> - <source dev="/dev/disk-pool/disk-vol1"/> - </disk> - <disk type="file" device="disk"> - <source file="/tmp/clone2.img"/> - <target dev="hdb" bus="ide"/> - </disk> - <interface type="network"> - <mac address="22:23:45:67:89:00"/> - <source network="test1"/> - </interface> - <interface type="bridge"> - <mac address="22:23:45:67:89:01"/> - <source bridge="br0"/> - </interface> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1"/> - <graphics type="vnc" port="-1"/> - </devices> -</domain> diff --git a/tests/data/clone/graphics-password-in.xml b/tests/data/clone/graphics-password-in.xml deleted file mode 100644 index 13b14dd6..00000000 --- a/tests/data/clone/graphics-password-in.xml +++ /dev/null @@ -1,23 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='foo'/> - </devices> -</domain> diff --git a/tests/data/clone/graphics-password-out.xml b/tests/data/clone/graphics-password-out.xml deleted file mode 100644 index e730efef..00000000 --- a/tests/data/clone/graphics-password-out.xml +++ /dev/null @@ -1,23 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1" passwd="foo"/> - </devices> -</domain> diff --git a/tests/data/clone/managed-storage-in.xml b/tests/data/clone/managed-storage-in.xml deleted file mode 100644 index 8cac51ee..00000000 --- a/tests/data/clone/managed-storage-in.xml +++ /dev/null @@ -1,40 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type='file' device='disk'> - <driver name="qemu" type="vmdk"/> - <source file='/dev/default-pool/testvol1.img'/> - <target dev='hda' bus='ide'/> - </disk> - <disk type='block' device='disk'> - <source dev='/dev/disk-pool/diskvol1'/> - <target dev='hdb' bus='ide'/> - </disk> - <interface type='network'> - <mac address='52:54:00:6c:a0:cb'/> - <source network='test1'/> - </interface> - <interface type='network'> - <mac address='52:54:00:6c:bb:ca'/> - <source network='test2'/> - </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/> - </devices> -</domain> diff --git a/tests/data/clone/managed-storage-out.xml b/tests/data/clone/managed-storage-out.xml deleted file mode 100644 index 540f8d7a..00000000 --- a/tests/data/clone/managed-storage-out.xml +++ /dev/null @@ -1,40 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type="file" device="disk"> - <driver name="qemu" type="vmdk"/> - <source file="/dev/default-pool/new1.img"/> - <target dev="hda" bus="ide"/> - </disk> - <disk type="block" device="disk"> - <source dev="/dev/disk-pool/new2.img"/> - <target dev="hdb" bus="ide"/> - </disk> - <interface type="network"> - <mac address="22:23:45:67:89:00"/> - <source network="test1"/> - </interface> - <interface type="network"> - <mac address="22:23:45:67:89:01"/> - <source network="test2"/> - </interface> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1"/> - </devices> -</domain> diff --git a/tests/data/clone/noclone-storage-in.xml b/tests/data/clone/noclone-storage-in.xml deleted file mode 100644 index 26303835..00000000 --- a/tests/data/clone/noclone-storage-in.xml +++ /dev/null @@ -1,43 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test1.img'/> - <target dev='hda' bus='ide'/> - <readonly/> - </disk> - <disk type='file' device='floppy'> - <target dev='fdb' bus='fdc'/> - </disk> - <disk type='block' device='cdrom'> - <target dev='sda' bus='scsi'/> - <readonly/> - </disk> - <interface type='network'> - <mac address='52:54:00:6c:a0:cb'/> - <source network='test1'/> - </interface> - <interface type='network'> - <mac address='52:54:00:6c:bb:ca'/> - <source network='test2'/> - </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/> - </devices> -</domain> diff --git a/tests/data/clone/noclone-storage-out.xml b/tests/data/clone/noclone-storage-out.xml deleted file mode 100644 index a76efba1..00000000 --- a/tests/data/clone/noclone-storage-out.xml +++ /dev/null @@ -1,43 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type="file" device="disk"> - <source file="/tmp/virtinst-test1.img"/> - <target dev="hda" bus="ide"/> - <readonly/> - </disk> - <disk type="file" device="floppy"> - <target dev="fdb" bus="fdc"/> - </disk> - <disk type="block" device="cdrom"> - <target dev="sda" bus="scsi"/> - <readonly/> - </disk> - <interface type="network"> - <mac address="22:23:45:67:89:00"/> - <source network="test1"/> - </interface> - <interface type="network"> - <mac address="22:23:45:67:89:01"/> - <source network="test2"/> - </interface> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1"/> - </devices> -</domain> diff --git a/tests/data/clone/nostorage-in.xml b/tests/data/clone/nostorage-in.xml deleted file mode 100644 index 72b97742..00000000 --- a/tests/data/clone/nostorage-in.xml +++ /dev/null @@ -1,18 +0,0 @@ -<domain type='test'> - <name>clone-orig</name> - <uuid>19618dc6-7895-956d-6056-8ebcd8061234</uuid> - <memory>8388608</memory> - <currentMemory>2097152</currentMemory> - <vcpu>2</vcpu> - <os> - <type arch='i686'>hvm</type> - <boot dev='hd'/> - </os> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - </devices> -</domain> - diff --git a/tests/data/clone/nostorage-out.xml b/tests/data/clone/nostorage-out.xml deleted file mode 100644 index 990a7712..00000000 --- a/tests/data/clone/nostorage-out.xml +++ /dev/null @@ -1,17 +0,0 @@ -<domain type="test"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>8388608</memory> - <currentMemory>2097152</currentMemory> - <vcpu>2</vcpu> - <os> - <type arch="i686">hvm</type> - <boot dev="hd"/> - </os> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - </devices> -</domain> diff --git a/tests/data/clone/nvram-auto-in.xml b/tests/data/clone/nvram-auto-in.xml deleted file mode 100644 index dc95f6ac..00000000 --- a/tests/data/clone/nvram-auto-in.xml +++ /dev/null @@ -1,23 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - <loader readonly='yes' type='pflash'>/usr/share/ovmf/ovmf-efi.fd</loader> - <nvram>/nvram/clone-orig_VARS.fd</nvram> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - </devices> -</domain> diff --git a/tests/data/clone/nvram-auto-out.xml b/tests/data/clone/nvram-auto-out.xml deleted file mode 100644 index c59eaea8..00000000 --- a/tests/data/clone/nvram-auto-out.xml +++ /dev/null @@ -1,23 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - <loader readonly="yes" type="pflash">/usr/share/ovmf/ovmf-efi.fd</loader> - <nvram>/nvram/clone-new_VARS.fd</nvram> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - </devices> -</domain> diff --git a/tests/data/clone/nvram-missing-in.xml b/tests/data/clone/nvram-missing-in.xml deleted file mode 100644 index fcbce533..00000000 --- a/tests/data/clone/nvram-missing-in.xml +++ /dev/null @@ -1,23 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - <loader readonly='yes' type='pflash'>/usr/share/ovmf/ovmf-efi.fd</loader> - <nvram>/nvram/clone-orig-missing_VARS.fd</nvram> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - </devices> -</domain> diff --git a/tests/data/clone/nvram-newpool-in.xml b/tests/data/clone/nvram-newpool-in.xml deleted file mode 100644 index d27da472..00000000 --- a/tests/data/clone/nvram-newpool-in.xml +++ /dev/null @@ -1,23 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - <loader readonly='yes' type='pflash'>/usr/share/ovmf/ovmf-efi.fd</loader> - <nvram>/nvram-newpool/clone-orig-vars.fd</nvram> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - </devices> -</domain> diff --git a/tests/data/clone/nvram-newpool-out.xml b/tests/data/clone/nvram-newpool-out.xml deleted file mode 100644 index 42d95460..00000000 --- a/tests/data/clone/nvram-newpool-out.xml +++ /dev/null @@ -1,23 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - <loader readonly="yes" type="pflash">/usr/share/ovmf/ovmf-efi.fd</loader> - <nvram>/nvram-newpool/clone-new_VARS.fd</nvram> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - </devices> -</domain> diff --git a/tests/data/clone/readonly-disks-in.xml b/tests/data/clone/readonly-disks-in.xml deleted file mode 100644 index c3962c9a..00000000 --- a/tests/data/clone/readonly-disks-in.xml +++ /dev/null @@ -1,54 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test1.img'/> - <target dev='hda' bus='ide'/> - </disk> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test1.img'/> - <target dev='hdb' bus='ide'/> - <readonly/> - </disk> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test2.img'/> - <target dev='sda' bus='scsi'/> - </disk> - <disk type='block' device='cdrom'> - <target dev='sdb' bus='scsi'/> - <readonly/> - </disk> - <disk type='file' device='cdrom'> - <source file='/tmp/virtinst-test2.img'/> - <target dev='sdc' bus='scsi'/> - <readonly/> - <shareable/> - </disk> - <interface type='network'> - <mac address='52:54:00:6c:a0:cb'/> - <source network='test1'/> - </interface> - <interface type='network'> - <mac address='52:54:00:6c:bb:ca'/> - <source network='test2'/> - </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/> - </devices> -</domain> diff --git a/tests/data/clone/readonly-disks-out.xml b/tests/data/clone/readonly-disks-out.xml deleted file mode 100644 index 83e1b385..00000000 --- a/tests/data/clone/readonly-disks-out.xml +++ /dev/null @@ -1,54 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type="block" device="disk"> - <target dev="hda" bus="ide"/> - <source dev="/dev/disk-pool/disk-vol1"/> - </disk> - <disk type="file" device="disk"> - <source file="/tmp/virtinst-test1.img"/> - <target dev="hdb" bus="ide"/> - <readonly/> - </disk> - <disk type="file" device="disk"> - <source file="/tmp/clone2.img"/> - <target dev="sda" bus="scsi"/> - </disk> - <disk type="block" device="cdrom"> - <target dev="sdb" bus="scsi"/> - <readonly/> - </disk> - <disk type="file" device="cdrom"> - <source file="/tmp/virtinst-test2.img"/> - <target dev="sdc" bus="scsi"/> - <readonly/> - <shareable/> - </disk> - <interface type="network"> - <mac address="22:23:45:67:89:00"/> - <source network="test1"/> - </interface> - <interface type="network"> - <mac address="22:23:45:67:89:01"/> - <source network="test2"/> - </interface> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1"/> - </devices> -</domain> diff --git a/tests/data/clone/skip-in.xml b/tests/data/clone/skip-in.xml deleted file mode 100644 index c04a6d6b..00000000 --- a/tests/data/clone/skip-in.xml +++ /dev/null @@ -1,46 +0,0 @@ -<domain type='kvm'> - <name>clone-orig</name> - <uuid>aaa3ae22-fed2-bfbd-ac02-3bea3bcfad82</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch='i686' machine='pc'>hvm</type> - <boot dev='cdrom'/> - </os> - <features> - <acpi/> - </features> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type='file' device='disk'> - <source file='/tmp/virtinst-test1.img'/> - <target dev='hda' bus='ide'/> - </disk> - <disk type='file' device='floppy'> - <target dev='fdb' bus='fdc'/> - </disk> - <disk type='block' device='cdrom'> - <target dev='sda' bus='scsi'/> - <readonly/> - </disk> - <disk type='file' device='disk'> - <source file='/dev/default-pool/default-vol'/> - <target dev='sdb' bus='scsi'/> - </disk> - <interface type='network'> - <mac address='52:54:00:6c:a0:cb'/> - <source network='test1'/> - </interface> - <interface type='network'> - <mac address='52:54:00:6c:bb:ca'/> - <source network='test2'/> - </interface> - <input type='mouse' bus='ps2'/> - <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/> - </devices> -</domain> diff --git a/tests/data/clone/skip-out.xml b/tests/data/clone/skip-out.xml deleted file mode 100644 index 01ba3e6f..00000000 --- a/tests/data/clone/skip-out.xml +++ /dev/null @@ -1,46 +0,0 @@ -<domain type="kvm"> - <name>clone-new</name> - <uuid>12345678-1234-1234-1234-123456789012</uuid> - <memory>262144</memory> - <currentMemory>262144</currentMemory> - <vcpu>1</vcpu> - <os> - <type arch="i686" machine="pc">hvm</type> - <boot dev="cdrom"/> - </os> - <features> - <acpi/> - </features> - <clock offset="utc"/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-kvm</emulator> - <disk type="file" device="disk"> - <source file="/tmp/virtinst-test1.img"/> - <target dev="hda" bus="ide"/> - </disk> - <disk type="file" device="floppy"> - <target dev="fdb" bus="fdc"/> - </disk> - <disk type="block" device="cdrom"> - <target dev="sda" bus="scsi"/> - <readonly/> - </disk> - <disk type="file" device="disk"> - <source file="/dev/default-pool/1234.img"/> - <target dev="sdb" bus="scsi"/> - </disk> - <interface type="network"> - <mac address="22:23:45:67:89:00"/> - <source network="test1"/> - </interface> - <interface type="network"> - <mac address="22:23:45:67:89:01"/> - <source network="test2"/> - </interface> - <input type="mouse" bus="ps2"/> - <graphics type="vnc" port="-1" autoport="yes" listen="127.0.0.1"/> - </devices> -</domain> diff --git a/tests/test_cli.py b/tests/test_cli.py index c50abf9c..a1de05e0 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1298,13 +1298,14 @@ c.add_compare("--add-device --network default --os-variant http://fedoraproject. # virt-clone tests # #################### -_CLONE_UNMANAGED = "--original-xml %s/clone-disk.xml" % XMLDIR -_CLONE_MANAGED = "--original-xml %s/clone-disk-managed.xml" % XMLDIR -_CLONE_NOEXIST = "--original-xml %s/clone-disk-noexist.xml" % XMLDIR -_CLONE_NVRAM = "--original-xml %s/clone-nvram-auto.xml" % XMLDIR -_CLONE_NVRAM_NEWPOOL = "--original-xml %s/clone-nvram-newpool.xml" % XMLDIR -_CLONE_NVRAM_MISSING = "--original-xml %s/clone-nvram-missing.xml" % XMLDIR -_CLONE_EMPTY = "--original-xml %s/clone-empty.xml" % XMLDIR +_CLONEXMLDIR = XMLDIR + "/clone" +_CLONE_UNMANAGED = "--original-xml %s/clone-disk.xml" % _CLONEXMLDIR +_CLONE_MANAGED = "--original-xml %s/clone-disk-managed.xml" % _CLONEXMLDIR +_CLONE_NOEXIST = "--original-xml %s/clone-disk-noexist.xml" % _CLONEXMLDIR +_CLONE_NVRAM = "--original-xml %s/clone-nvram-auto.xml" % _CLONEXMLDIR +_CLONE_NVRAM_NEWPOOL = "--original-xml %s/clone-nvram-newpool.xml" % _CLONEXMLDIR +_CLONE_NVRAM_MISSING = "--original-xml %s/clone-nvram-missing.xml" % _CLONEXMLDIR +_CLONE_EMPTY = "--original-xml %s/clone-empty.xml" % _CLONEXMLDIR vclon = App("virt-clone") c = vclon.add_category("remote", "--connect %(URI-TEST-REMOTE)s") @@ -1318,6 +1319,7 @@ c = vclon.add_category("misc", "") c.add_compare("--connect %(URI-KVM)s -o test-clone --auto-clone", "clone-auto1") c.add_compare("--connect %(URI-TEST-FULL)s -o test-clone-simple --name newvm --auto-clone", "clone-auto2") c.add_compare("--connect %(URI-KVM)s " + _CLONE_NVRAM + " --auto-clone", "clone-nvram") # hits a particular nvram code path +c.add_compare("--connect %(URI-KVM)s " + _CLONE_NVRAM + " --auto-clone --nvram /nvram/my-custom-path", "clone-nvram-path") # hits a particular nvram code path c.add_compare("--connect %(URI-KVM)s " + _CLONE_NVRAM_NEWPOOL + " --auto-clone", "nvram-newpool") # hits a particular nvram code path c.add_compare("--connect %(URI-KVM)s " + _CLONE_NVRAM_MISSING + " --auto-clone", "nvram-missing") # hits a particular nvram code path c.add_compare("--connect %(URI-KVM)s -o test-clone -n test-newclone --mac 12:34:56:1A:B2:C3 --mac 12:34:56:1A:B7:C3 --uuid 12345678-12F4-1234-1234-123456789AFA --file /dev/disk-pool/newclone1.img --file /dev/default-pool/newclone2.img --skip-copy=hdb --force-copy=sdb --file /dev/default-pool/newclone3.img", "clone-manual") @@ -1333,14 +1335,14 @@ c.add_invalid("-n clonetest " + _CLONE_UNMANAGED + " --auto-clone --mac 22:11:11 c.add_invalid("--auto-clone") # Just the auto flag c.add_invalid(_CLONE_EMPTY + " --file foo") # Didn't specify new name c.add_invalid(_CLONE_EMPTY + " --auto-clone -n test") # new name raises error -c.add_invalid("-o test --auto-clone", grep="shutoff") # VM is running, but --clone-running isn't passed +c.add_invalid("-o test --auto-clone", grep="shutoff") # VM is running c.add_invalid("--connect %(URI-TEST-FULL)s -o test-clone-simple -n newvm --file %(EXISTIMG1)s") # Should complain about overwriting existing file c.add_invalid("--connect %(URI-TEST-REMOTE)s -o test-clone-simple --auto-clone --file /dev/default-pool/testvol9.img --check all=off", grep="Clone onto existing storage volume") # hit a specific error message c.add_invalid("--connect %(URI-TEST-FULL)s -o test-clone-full --auto-clone", grep="not enough free space") # catch failure of clone path setting c = vclon.add_category("general", "-n clonetest") -c.add_valid("-o test --clone-running --auto-clone --replace") # Auto flag, no storage, --replace is redundant +c.add_valid(_CLONE_EMPTY + " --auto-clone --replace") # --replace but it doesn't matter, should be safely ignored c.add_valid(_CLONE_EMPTY + " --file %(NEWCLONEIMG1)s --file %(NEWCLONEIMG2)s") # Nodisk, but with spurious files passed c.add_valid(_CLONE_EMPTY + " --file %(NEWCLONEIMG1)s --file %(NEWCLONEIMG2)s --prompt") # Working scenario w/ prompt shouldn't ask anything c.add_valid(_CLONE_UNMANAGED + " --file %(NEWCLONEIMG1)s --file %(NEWCLONEIMG2)s") # XML File with 2 disks @@ -1350,18 +1352,17 @@ c.add_valid(_CLONE_UNMANAGED + " --file %(NEWCLONEIMG1)s --file %(NEWCLONEIMG2)s c.add_valid(_CLONE_UNMANAGED + " --file %(NEWCLONEIMG1)s --file %(NEWCLONEIMG2)s --force-copy=fda") # XML w/ disks, force copy a target with no media c.add_valid(_CLONE_MANAGED + " --file %(NEWIMG1)s") # XML w/ managed storage, specify managed path c.add_valid(_CLONE_MANAGED + " --file %(NEWIMG1)s --reflink") # XML w/ managed storage, specify managed path, use --reflink option -c.add_valid(_CLONE_NOEXIST + " --file %(EXISTIMG1)s --preserve") # XML w/ managed storage, specify managed path across pools# Libvirt test driver doesn't support cloning across pools# XML w/ non-existent storage, with --preserve -c.add_valid("--connect %(URI-TEST-FULL)s -o test-clone -n test --auto-clone --replace") # Overwriting existing running VM +c.add_valid(_CLONE_NOEXIST + " --file %(EXISTIMG1)s --preserve") # XML w/ managed storage, specify managed path across pools +c.add_compare("--connect %(URI-TEST-FULL)s -o test-clone -n test --auto-clone --replace", "replace") # Overwriting existing running VM +c.add_valid(_CLONE_MANAGED + " --auto-clone --force-copy fda") # force copy empty floppy drive c.add_invalid(_CLONE_EMPTY + " foobar") # Positional arguments error c.add_invalid("-o idontexist") # Non-existent vm name c.add_invalid("-o idontexist --auto-clone") # Non-existent vm name with auto flag, c.add_invalid(_CLONE_EMPTY + " -n test") # Colliding new name c.add_invalid(_CLONE_UNMANAGED + "") # XML file with several disks, but non specified -c.add_invalid(_CLONE_UNMANAGED + " --file virt-install --file %(EXISTIMG1)s") # XML w/ disks, overwriting existing files with no --preserve -c.add_invalid(_CLONE_UNMANAGED + " --file %(NEWCLONEIMG1)s --file %(NEWCLONEIMG2)s --force-copy=hdc") # XML w/ disks, force copy but not enough disks passed -c.add_invalid(_CLONE_MANAGED + " --file /tmp/clonevol") # XML w/ managed storage, specify unmanaged path (should fail) -c.add_invalid(_CLONE_NOEXIST + " --file %(EXISTIMG1)s") # XML w/ non-existent storage, WITHOUT --preserve -c.add_valid(_CLONE_MANAGED + " --auto-clone --force-copy fda") # force copy empty floppy drive +c.add_invalid(_CLONE_UNMANAGED + " --file virt-install", grep="overwrite the existing path 'virt-install'") # XML w/ disks, overwriting existing files with no --preserve +c.add_invalid(_CLONE_MANAGED + " --file /tmp/clonevol", grep="matching name 'default-vol'") # will attempt to clone across pools, which test driver doesn't support +c.add_invalid(_CLONE_NOEXIST + " --auto-clone", grep="'/i/really/dont/exist' does not exist.") # XML w/ non-existent storage, WITHOUT --preserve diff --git a/tests/test_cloner.py b/tests/test_cloner.py index 91e19bb5..f52e5147 100644 --- a/tests/test_cloner.py +++ b/tests/test_cloner.py @@ -3,209 +3,42 @@ # This work is licensed under the GNU GPLv2 or later. # See the COPYING file in the top-level directory. -import unittest import os +import tempfile from tests import utils from virtinst import Cloner -from virtinst import log -ORIG_NAME = "clone-orig" -CLONE_NAME = "clone-new" -# Create some files to use as test images -FILE1 = "/tmp/virtinst-test1.img" -FILE2 = "/tmp/virtinst-test2.img" -P1_VOL1 = "/dev/default-pool/testvol1.img" -P1_VOL2 = "/dev/default-pool/testvol2.img" -P2_VOL1 = "/dev/cross-pool/testvol1.img" -P2_VOL2 = "/dev/cross-pool/testvol2.img" +CLI_XMLDIR = utils.DATADIR + "/cli/clone/" -POOL1 = "/dev/default-pool" -POOL2 = "/dev/cross-pool" -DISKPOOL = "/dev/disk-pool" -local_files = [FILE1, FILE2] +def test_clone_unmanaged(): + """ + Test that unmanaged storage duplication via the clone wizard + actually copies data + """ + xmlpath = CLI_XMLDIR + "clone-disk.xml" + conn = utils.URIs.open_testdriver_cached() + xml = open(xmlpath).read() -CLONEXML_DIR = os.path.join(utils.DATADIR, "clone") + tmp1 = tempfile.NamedTemporaryFile() + tmp2 = tempfile.NamedTemporaryFile() + inp1 = os.path.abspath(__file__) + inp2 = xmlpath + xml = xml.replace("/tmp/__virtinst_cli_exist1.img", inp1) + xml = xml.replace("/tmp/__virtinst_cli_exist2.img", inp2) + cloner = Cloner(conn, src_xml=xml) -class TestClone(unittest.TestCase): + diskinfos = cloner.get_diskinfos_to_clone() + assert len(diskinfos) == 2 + diskinfos[0].set_clone_path(tmp1.name, True, False) + diskinfos[1].set_clone_path(tmp2.name, True, False) - def setUp(self): - for f in local_files: - open(f, "w").write("") + cloner.prepare() + cloner.start_duplicate(None) - def tearDown(self): - for f in local_files: - os.unlink(f) - - def _clone(self, filebase, disks=None, force_list=None, - skip_list=None, compare=True, conn=None, - clone_disks_file=None): - """Helper for comparing clone input/output from 2 xml files""" - infile = os.path.join(CLONEXML_DIR, filebase + "-in.xml") - in_content = open(infile).read() - - if not conn: - conn = utils.URIs.open_testdriver_cached() - cloneobj = Cloner(conn) - cloneobj.original_xml = in_content - - force_list = force_list or [] - for force in force_list: - cloneobj.force_target = force - self.assertEqual(cloneobj.force_target, force_list) - cloneobj.force_target = force_list - self.assertEqual(cloneobj.force_target, force_list) - - skip_list = skip_list or [] - for skip in skip_list: - cloneobj.skip_target = skip - self.assertEqual(cloneobj.skip_target, skip_list) - cloneobj.skip_target = skip_list - self.assertEqual(cloneobj.skip_target, skip_list) - - cloneobj = self._default_clone_values(cloneobj, disks) - - if compare: - self._clone_compare(cloneobj, filebase, - clone_disks_file=clone_disks_file) - self._clone_define(filebase) - else: - cloneobj.setup_original() - cloneobj.setup_clone() - - def _default_clone_values(self, cloneobj, disks=None): - """Sets default values for the cloned VM.""" - cloneobj.clone_name = "clone-new" - - uuid = "12345678-1234-1234-1234-123456789012" - cloneobj.clone_uuid = uuid - self.assertEqual(cloneobj.clone_uuid, uuid) - - macs = ["22:23:45:67:89:00", "22:23:45:67:89:01"] - cloneobj.clone_macs = macs - self.assertEqual(cloneobj.clone_macs, macs) - - if disks is None: - disks = ["/dev/disk-pool/disk-vol1", "/tmp/clone2.img", - "/clone3", "/tmp/clone4.img", - "/tmp/clone5.img", None] - - cloneobj.clone_paths = disks - self.assertEqual(cloneobj.clone_paths, disks) - return cloneobj - - def _clone_compare(self, cloneobj, outbase, clone_disks_file=None): - """Helps compare output from passed clone instance with an xml file""" - outfile = os.path.join(CLONEXML_DIR, outbase + "-out.xml") - - cloneobj.setup_original() - cloneobj.setup_clone() - - utils.diff_compare(cloneobj.clone_xml, outfile) - if clone_disks_file: - xml_clone_disks = "" - for i in cloneobj.clone_disks: - xml_clone_disks += i.get_vol_install().get_xml() - utils.diff_compare(xml_clone_disks, clone_disks_file) - - def _clone_define(self, filebase): - """Take the valid output xml and attempt to define it on the - connection to ensure we don't get any errors""" - outfile = os.path.join(CLONEXML_DIR, filebase + "-out.xml") - outxml = open(outfile).read() - conn = utils.URIs.open_testdriver_cached() - utils.test_create(conn, outxml) - - def testRemoteNoStorage(self): - """Test remote clone where VM has no storage that needs cloning""" - conn = utils.URIs.open_test_remote() - self._clone("nostorage", conn=conn) - self._clone("noclone-storage", conn=conn) - - def testRemoteWithStorage(self): - """ - Test remote clone with storage needing cloning. Should fail, - since libvirt has no storage clone api. - """ - conn = utils.URIs.open_test_remote() - disks = ["%s/1.img" % POOL1, "%s/2.img" % POOL1] - try: - self._clone("general-cfg", disks=disks, conn=conn) - # We shouldn't succeed, so test fails - raise AssertionError("Remote clone with storage passed " - "when it shouldn't.") - except (ValueError, RuntimeError) as e: - # Exception expected - log.debug("Received expected exception: %s", str(e)) - - def testCloneStorageManaged(self): - disks = ["%s/new1.img" % POOL1, "%s/new2.img" % DISKPOOL] - self._clone("managed-storage", disks=disks) - - def testCloneStorageCrossPool(self): - conn = utils.URIs.open_test_remote() - clone_disks_file = os.path.join( - CLONEXML_DIR, "cross-pool-disks-out.xml") - disks = ["%s/new1.img" % POOL2, "%s/new2.img" % POOL1] - self._clone("cross-pool", disks=disks, - clone_disks_file=clone_disks_file, conn=conn) - - def testCloneStorageForce(self): - disks = ["/dev/default-pool/1234.img", None, "/clone2.img"] - self._clone("force", disks=disks, force_list=["hda", "fdb", "sdb"]) - - def testCloneStorageSkip(self): - disks = ["/dev/default-pool/1234.img", None, "/tmp/clone2.img"] - skip_list = ["hda", "fdb"] - self._clone("skip", disks=disks, skip_list=skip_list) - - def testCloneFullPool(self): - with self.assertRaises(Exception): - self._clone("fullpool", - disks=["/full-pool/test.img"], compare=False) - - def testCloneNvramAuto(self): - self._clone("nvram-auto") - - def testCloneNvramNewpool(self): - self._clone("nvram-newpool") - - def testCloneNvramMissing(self): - self._clone("nvram-missing") - - def testCloneGraphicsPassword(self): - self._clone("graphics-password") - - def testCloneChannelSource(self): - self._clone("channel-source") - - def testCloneMisc(self): - conn = utils.URIs.open_testdriver_cached() - - with self.assertRaises(RuntimeError) as err: - cloner = Cloner(conn) - # Add this bit here for coverage testing - cloner.clone_xml = None - cloner.setup_original() - self.assertTrue("Original guest name or XML" in str(err.exception)) - - with self.assertRaises(RuntimeError) as err: - cloner = Cloner(conn) - cloner.original_guest = "test-snapshots" - cloner.setup_original() - self.assertTrue("must be shutoff" in str(err.exception)) - - with self.assertRaises(ValueError) as err: - cloner = Cloner(conn) - cloner.original_guest = "test-clone-simple" - cloner.setup_original() - cloner.setup_clone() - self.assertTrue("More disks to clone" in str(err.exception)) - - cloner = Cloner(conn) - self.assertEqual( - cloner.generate_clone_name("test-clone5"), "test-clone6") + assert open(tmp1.name).read() == open(inp1).read() + assert open(tmp2.name).read() == open(inp2).read() diff --git a/tests/test_xmlconfig.py b/tests/test_xmlconfig.py index 591723cc..ee430659 100644 --- a/tests/test_xmlconfig.py +++ b/tests/test_xmlconfig.py @@ -315,3 +315,15 @@ class TestXMLMisc(unittest.TestCase): newdisk.path = newdisk.path newdisk.set_local_disk_to_clone(srcdisk, True) newdisk.build_storage(None) + + newdisk = virtinst.DeviceDisk(conn) + newdisk.type = "block" + newdisk.path = "/dev/foo/idontexist" + assert newdisk.get_size() == 0 + + conn = utils.URIs.open_testdriver_cached() + volpath = "/dev/default-pool/test-clone-simple.img" + assert virtinst.DeviceDisk.path_definitely_exists(conn, volpath) + disk = virtinst.DeviceDisk(conn) + disk.path = volpath + assert disk.get_size() diff --git a/virtinst/cloner.py b/virtinst/cloner.py index 4ce56683..3c23e8cb 100644 --- a/virtinst/cloner.py +++ b/virtinst/cloner.py @@ -14,7 +14,6 @@ import libvirt from . import generatename from . import progress -from . import xmlutil from .guest import Guest from .devices import DeviceInterface from .devices import DeviceDisk @@ -49,394 +48,416 @@ def _replace_vm(conn, name): }) +def _generate_clone_name(conn, basename): + """ + If the orig name is "foo-clone", we don't want the clone to be + "foo-clone-clone", we want "foo-clone1" + """ + match = re.search("-clone[1-9]*$", basename) + start_num = 1 + force_num = False + if match: + num_match = re.search("[1-9]+$", match.group()) + if num_match: + start_num = int(str(num_match.group())) + 1 + force_num = True + basename = basename.replace(match.group(), "") + + def cb(n): + return generatename.check_libvirt_collision( + conn.lookupByName, n) + basename = basename + "-clone" + return generatename.generate_name(basename, cb, + sep="", start_num=start_num, force_num=force_num) + + +def _generate_clone_disk_path(conn, origname, newname, origpath): + """ + Generate desired cloned disk path name, derived from the + original path, original VM name, and proposed new VM name + """ + if origpath is None: + return None + + path = origpath + suffix = "" + + # Try to split the suffix off the existing disk name. Ex. + # foobar.img -> foobar-clone.img + # + # If the suffix is greater than 7 characters, assume it isn't + # a file extension and is part of the disk name, at which point + # just stick '-clone' on the end. + if "." in origpath and len(origpath.rsplit(".", 1)[1]) <= 7: + path, suffix = origpath.rsplit(".", 1) + suffix = "." + suffix + + dirname = os.path.dirname(path) + basename = os.path.basename(path) + + clonebase = basename + "-clone" + if origname and basename == origname: + clonebase = newname + + clonebase = os.path.join(dirname, clonebase) + def cb(p): + return DeviceDisk.path_definitely_exists(conn, p) + return generatename.generate_name(clonebase, cb, suffix=suffix) + + +def _lookup_vm(conn, name): + try: + return conn.lookupByName(name) + except libvirt.libvirtError: + e = ValueError(_("Domain '%s' was not found.") % str(name)) + raise e from None + + +def _build_clone_vol_install(orig_disk, clone_disk): + vol_install = DeviceDisk.build_vol_install( + orig_disk.conn, os.path.basename(clone_disk.path), + clone_disk.get_parent_pool(), .000001, False) + vol_install.input_vol = orig_disk.get_vol_object() + + # Source and dest are managed. If they share the same pool, + # replace vol_install with a CloneVolume instance, otherwise + # simply set input_vol on the dest vol_install + if (vol_install.pool.name() == + orig_disk.get_parent_pool().name()): + vol_install.sync_input_vol() + else: + # Cross pool cloning + # Sync only the format of the image. + vol_install.sync_input_vol(only_format=True) + + return vol_install + + +def _build_clone_disk(orig_disk, clonepath, allow_create, sparse): + conn = orig_disk.conn + device = DeviceDisk.DEVICE_DISK + if not clonepath: + device = DeviceDisk.DEVICE_CDROM + + clone_disk = DeviceDisk(conn) + clone_disk.path = clonepath + clone_disk.device = device + + if not allow_create: + clone_disk.validate() + return clone_disk + + if clone_disk.get_vol_object(): + # Special case: non remote cloning of a guest using + # managed block devices: fall back to local cloning if + # we have permissions to do so. This validation check + # caused a few bug reports in a short period of time, + # so must be a common case. + if (conn.is_remote() or + clone_disk.type != clone_disk.TYPE_BLOCK or + not orig_disk.path or + not os.access(orig_disk.path, os.R_OK) or + not clone_disk.path or + not os.access(clone_disk.path, os.W_OK)): + raise RuntimeError( + _("Clone onto existing storage volume is not " + "currently supported: '%s'") % clone_disk.path) + + if (orig_disk.get_vol_object() and + clone_disk.wants_storage_creation()): + vol_install = _build_clone_vol_install(orig_disk, clone_disk) + if not sparse: + vol_install.allocation = vol_install.capacity + clone_disk.set_vol_install(vol_install) + elif orig_disk.path: + clone_disk.set_local_disk_to_clone(orig_disk, sparse) + + clone_disk.validate() + return clone_disk + + +class _CloneDiskInfo: + """ + Class that tracks some additional information about how we want + to default handle each disk of the source VM + """ + def __init__(self, srcdisk): + self.disk = DeviceDisk(srcdisk.conn, parsexml=srcdisk.get_xml()) + self._do_clone = self._do_we_clone_default() + self.clone_disk = None + + def is_clone_requested(self): + return self._do_clone + def set_clone_requested(self, val): + self._do_clone = val + + def _do_we_clone_default(self): + if not self.disk.path: + return False + if self.disk.read_only: + return False + if self.disk.shareable: + return False + return True + + def check_clonable(self): + try: + # This forces DeviceDisk to resolve the storage backend + self.disk.path = self.disk.path + if self.disk.wants_storage_creation(): + raise ValueError( + _("Disk path '%s' does not exist.") % self.disk.path) + except Exception as e: + log.debug("Exception processing clone original path", exc_info=True) + err = _("Could not determine original disk information: %s" % str(e)) + raise ValueError(err) from None + + def set_clone_path(self, path, allow_create, sparse): + if allow_create: + self.check_clonable() + + try: + self.clone_disk = _build_clone_disk( + self.disk, path, allow_create, sparse) + except Exception as e: + log.debug("Error setting clone path.", exc_info=True) + raise ValueError( + _("Could not use path '%(path)s' for cloning: %(error)s") % { + "path": path, + "error": str(e), + }) + + class Cloner(object): + @staticmethod + def generate_clone_name(conn, basename): + return _generate_clone_name(conn, basename) - # Reasons why we don't default to cloning. - CLONE_POLICY_NO_READONLY = 1 - CLONE_POLICY_NO_SHAREABLE = 2 - CLONE_POLICY_NO_EMPTYMEDIA = 3 + @staticmethod + def generate_clone_disk_path(conn, origname, newname, origpath): + return _generate_clone_disk_path(conn, origname, newname, origpath) - def __init__(self, conn): + def __init__(self, conn, src_name=None, src_xml=None): self.conn = conn - # original guest name or uuid - self._original_guest = None - self.original_dom = None - self._original_disks = [] - self._original_xml = None - self._guest = None - - # clone guest - self._clone_name = None - self._clone_disks = [] - self._clone_macs = [] - self._clone_uuid = None - self._clone_sparse = True - self._clone_xml = None - self.clone_nvram = None + self._src_guest = None + self._new_guest = None + self._diskinfos = [] + self._init_src(src_name, src_xml) + + self._new_nvram_path = None self._nvram_disk = None - self._force_target = [] - self._skip_target = [] - self._preserve = True - self._clone_running = False + self._sparse = True + self._overwrite = True self._replace = False self._reflink = False - # Default clone policy for back compat: don't clone readonly, - # shareable, or empty disks - self._clone_policy = [] - self.clone_policy = [self.CLONE_POLICY_NO_READONLY, - self.CLONE_POLICY_NO_SHAREABLE, - self.CLONE_POLICY_NO_EMPTYMEDIA] - # Generate a random UUID at the start - self.clone_uuid = Guest.generate_uuid(conn) + ################# + # Init routines # + ################# + def _init_src(self, src_name, src_xml): + """ + Set up the source VM info we are cloning, from passed in VM name + or full XML + """ + if not src_xml: + dom = _lookup_vm(self.conn, src_name) + status = dom.info()[0] + if status not in [libvirt.VIR_DOMAIN_SHUTOFF]: + raise RuntimeError(_("Domain to clone must be shutoff.")) + flags = libvirt.VIR_DOMAIN_XML_SECURE + src_xml = dom.XMLDesc(flags) - ############## - # Properties # - ############## + log.debug("Original XML:\n%s", src_xml) - # Original guest name - def get_original_guest(self): - return self._original_guest - def set_original_guest(self, original_guest): - if self._lookup_vm(original_guest): - self._original_guest = original_guest - original_guest = property(get_original_guest, set_original_guest) - - # XML of the original guest - def set_original_xml(self, val): - self._original_xml = val - self._original_guest = Guest(self.conn, - parsexml=self._original_xml).name - def get_original_xml(self): - return self._original_xml - original_xml = property(get_original_xml, set_original_xml) - - # Name to use for the new guest clone - def get_clone_name(self): - return self._clone_name - def set_clone_name(self, name): - try: - Guest.validate_name(self.conn, name, - check_collision=not self.replace, - validate=False) - except ValueError as e: - raise ValueError(_("Invalid name for new guest: %s") % e) + self._src_guest = Guest(self.conn, parsexml=src_xml) + self._new_guest = Guest(self.conn, parsexml=src_xml) + self._init_new_guest() - self._clone_name = name - clone_name = property(get_clone_name, set_clone_name) + # Collect disk info for every disk to determine if we will + # default to cloning or not + for disk in self._src_guest.devices.disk: + self._diskinfos.append(_CloneDiskInfo(disk)) + for diskinfo in [d for d in self._diskinfos if d.is_clone_requested()]: + disk = diskinfo.disk + log.debug("Wants cloning: size=%s path=%s", + disk.get_size(), disk.path) - # UUID to use for the new guest clone - def set_clone_uuid(self, uuid): - self._clone_uuid = uuid - def get_clone_uuid(self): - return self._clone_uuid - clone_uuid = property(get_clone_uuid, set_clone_uuid) - - # Paths to use for the new disk locations - def set_clone_paths(self, paths): - disklist = [] - for path in xmlutil.listify(paths): - try: - device = DeviceDisk.DEVICE_DISK - if not path: - device = DeviceDisk.DEVICE_CDROM - - disk = DeviceDisk(self.conn) - disk.path = path - disk.device = device - - if (not self.preserve_dest_disks and - disk.wants_storage_creation()): - vol_install = DeviceDisk.build_vol_install( - self.conn, os.path.basename(disk.path), - disk.get_parent_pool(), .000001, False) - disk.set_vol_install(vol_install) - disk.validate() - disklist.append(disk) - except Exception as e: - log.debug("Error setting clone path.", exc_info=True) - raise ValueError( - _("Could not use path '%(path)s' for cloning: %(error)s") % { - "path": path, - "error": str(e), - }) + def _init_new_guest(self): + """ + Perform the series of unconditional new VM changes we always make + """ + self._new_guest.id = None + self._new_guest.title = None + self._new_guest.uuid = None + self._new_guest.uuid = Guest.generate_uuid(self.conn) - self._clone_disks = disklist - def get_clone_paths(self): - return [d.path for d in self.clone_disks] - clone_paths = property(get_clone_paths, set_clone_paths) + for dev in self._new_guest.devices.graphics: + if dev.port and dev.port != -1: + log.warning(_("Setting the graphics device port to autoport, " + "in order to avoid conflicting.")) + dev.port = -1 - # DeviceDisk instances for the new disk paths - @property - def clone_disks(self): - return self._clone_disks + for iface in self._new_guest.devices.interface: + iface.target_dev = None + iface.macaddr = DeviceInterface.generate_mac(self.conn) - # MAC address for the new guest clone - def set_clone_macs(self, mac): - self._clone_macs = xmlutil.listify(mac) - def get_clone_macs(self): - return self._clone_macs - clone_macs = property(get_clone_macs, set_clone_macs) + # For guest agent channel, remove a path to generate a new one with + # new guest name + for channel in self._new_guest.devices.channel: + if (channel.type == DeviceChannel.TYPE_UNIX and + channel.target_name and channel.source.path and + channel.target_name in channel.source.path): + channel.source.path = None - # DeviceDisk instances of the original disks being cloned - @property - def original_disks(self): - return self._original_disks - - # Generated XML for the guest clone - def get_clone_xml(self): - return self._clone_xml - def set_clone_xml(self, clone_xml): - self._clone_xml = clone_xml - clone_xml = property(get_clone_xml, set_clone_xml) - - # Whether to attempt sparse allocation during cloning - def get_clone_sparse(self): - return self._clone_sparse - def set_clone_sparse(self, flg): - self._clone_sparse = flg - clone_sparse = property(get_clone_sparse, set_clone_sparse) - - # If true, preserve ALL original disk devices - def get_preserve(self): - return self._preserve - def set_preserve(self, flg): - self._preserve = flg - preserve = property(get_preserve, set_preserve) - - # If true, preserve ALL disk devices for the NEW guest. - # This means no storage cloning. - # This is a convenience access for not Cloner.preserve - @property - def preserve_dest_disks(self): - return not self.preserve - - # List of disk targets that we force cloning despite - # Cloner's recommendation - def set_force_target(self, dev): - if isinstance(dev, list): - self._force_target = dev[:] - else: - self._force_target.append(dev) - def get_force_target(self): - return self._force_target - force_target = property(get_force_target, set_force_target) - - # List of disk targets that we skip cloning despite Cloner's - # recommendation. This takes precedence over force_target.") - def set_skip_target(self, dev): - if isinstance(dev, list): - self._skip_target = dev[:] - else: - self._skip_target.append(dev) - def get_skip_target(self): - return self._skip_target - skip_target = property(get_skip_target, set_skip_target) - - # List of policy rules for determining which vm disks to clone. - # See CLONE_POLICY_* - def set_clone_policy(self, policy_list): - self._clone_policy = policy_list - def get_clone_policy(self): - return self._clone_policy - clone_policy = property(get_clone_policy, set_clone_policy) - - # Allow cloning a running VM. If enabled, domain state is not - # checked before cloning. - def get_clone_running(self): - return self._clone_running - def set_clone_running(self, val): - self._clone_running = bool(val) - clone_running = property(get_clone_running, set_clone_running) - - # If enabled, don't check for clone name collision, simply undefine - # any conflicting guest. - def _get_replace(self): - return self._replace - def _set_replace(self, val): - self._replace = bool(val) - replace = property(_get_replace, _set_replace) + new_name = Cloner.generate_clone_name(self.conn, self.src_name) + log.debug("Auto-generated clone name '%s'", new_name) + self.set_clone_name(new_name) - # If true, use COW lightweight copy - def _get_reflink(self): - return self._reflink - def _set_reflink(self, reflink): - self._reflink = reflink - reflink = property(_get_reflink, _set_reflink) + ############## + # Properties # + ############## - ###################### - # Functional methods # - ###################### + @property + def src_name(self): + """ + The name of the original VM we are cloning + """ + return self._src_guest.name - def setup_original(self): + @property + def new_guest(self): """ - Validate and setup all parameters needed for the original (cloned) VM + The Guest instance of the new XML we will create """ - log.debug("Validating original guest parameters") + return self._new_guest - if self.original_guest is None and self.original_xml is None: - raise RuntimeError(_("Original guest name or XML is required.")) + def set_clone_name(self, name): + self._new_guest.name = name - if self.original_guest is not None and not self.original_xml: - self.original_dom = self._lookup_vm(self.original_guest) - flags = libvirt.VIR_DOMAIN_XML_SECURE - self.original_xml = self.original_dom.XMLDesc(flags) + def set_clone_uuid(self, uuid): + """ + Override the new VMs generated UUId + """ + self._new_guest.uuid = uuid + + def set_replace(self, val): + """ + If True, don't check for clone name collision, simply undefine + any conflicting guest. + """ + self._replace = bool(val) - log.debug("Original XML:\n%s", self.original_xml) + def set_reflink(self, reflink): + """ + If true, use COW lightweight copy + """ + self._reflink = reflink - self._guest = Guest(self.conn, parsexml=self.original_xml) - self._guest.id = None + def set_sparse(self, flg): + """ + If True, attempt sparse allocation during cloning + """ + self._sparse = flg - # Pull clonable storage info from the original xml - self._original_disks = self._get_original_disks_info() + def get_diskinfos(self): + """ + Return the list of _CloneDiskInfo instances + """ + return self._diskinfos[:] - log.debug("Original paths: %s", - [d.path for d in self.original_disks]) - log.debug("Original sizes: %s", - [d.get_size() for d in self.original_disks]) + def get_diskinfos_to_clone(self): + """ + Return a list of _CloneDiskInfo that are tagged for cloning + """ + return [di for di in self.get_diskinfos() if di.is_clone_requested()] - if not self.clone_running and self.original_dom: - status = self.original_dom.info()[0] - if status not in [libvirt.VIR_DOMAIN_SHUTOFF]: - raise RuntimeError(_("Domain to clone must be shutoff.")) + def set_nvram_path(self, val): + """ + If the VM needs to have nvram content cloned, this overrides the + destination path + """ + self._new_nvram_path = val - def _setup_disk_clone_destination(self, orig_disk, clone_disk): + def set_overwrite(self, flg): """ - Helper that validates the new path location + If False, no data is copied to the destination disks by default. + Storage may be created, but it is empty. """ - if self.preserve_dest_disks: - return - - if clone_disk.get_vol_object(): - # Special case: non remote cloning of a guest using - # managed block devices: fall back to local cloning if - # we have permissions to do so. This validation check - # caused a few bug reports in a short period of time, - # so must be a common case. - if (self.conn.is_remote() or - clone_disk.type != clone_disk.TYPE_BLOCK or - not orig_disk.path or - not os.access(orig_disk.path, os.R_OK) or - not clone_disk.path or - not os.access(clone_disk.path, os.W_OK)): - raise RuntimeError( - _("Clone onto existing storage volume is not " - "currently supported: '%s'") % clone_disk.path) - - # Setup proper cloning inputs for the new virtual disks - if (orig_disk.get_vol_object() and - clone_disk.get_vol_install()): - clone_vol_install = clone_disk.get_vol_install() - - # Source and dest are managed. If they share the same pool, - # replace vol_install with a CloneVolume instance, otherwise - # simply set input_vol on the dest vol_install - if (clone_vol_install.pool.name() == - orig_disk.get_parent_pool().name()): - vol_install = StorageVolume(self.conn) - vol_install.input_vol = orig_disk.get_vol_object() - vol_install.sync_input_vol() - vol_install.name = clone_vol_install.name - else: - # Cross pool cloning - # Sync only the format of the image. - clone_vol_install.input_vol = orig_disk.get_vol_object() - vol_install = clone_vol_install - vol_install.input_vol = orig_disk.get_vol_object() - vol_install.sync_input_vol(only_format=True) - - if not self.clone_sparse: - vol_install.allocation = vol_install.capacity - vol_install.reflink = self.reflink - clone_disk.set_vol_install(vol_install) - elif orig_disk.path: - clone_disk.set_local_disk_to_clone(orig_disk, self.clone_sparse) + self._overwrite = flg - clone_disk.validate() + ###################### + # Functional methods # + ###################### def _prepare_nvram(self): - if self.clone_nvram is None: - nvram_dir = os.path.dirname(self._guest.os.nvram) - self.clone_nvram = os.path.join(nvram_dir, - "%s_VARS.fd" % self._clone_name) + new_nvram_path = self._new_nvram_path + if new_nvram_path is None: + nvram_dir = os.path.dirname(self._new_guest.os.nvram) + new_nvram_path = os.path.join( + nvram_dir, "%s_VARS.fd" % self._new_guest.name) old_nvram = DeviceDisk(self.conn) - old_nvram.path = self._guest.os.nvram - + old_nvram.path = self._new_guest.os.nvram nvram = DeviceDisk(self.conn) - nvram.path = self.clone_nvram + nvram.path = new_nvram_path + diskinfo = _CloneDiskInfo(old_nvram) + allow_create = self._overwrite - if (not self.preserve_dest_disks and + if (allow_create and nvram.wants_storage_creation() and old_nvram.get_vol_object()): + # We only run validation if there's some existing nvram we + # can copy. It's valid for nvram to not exist at VM define + # time, libvirt will create it for us + diskinfo.set_clone_path(new_nvram_path, allow_create, self._sparse) + self._nvram_disk = diskinfo.clone_disk + self._nvram_disk.get_vol_install().reflink = self._reflink - nvram_install = DeviceDisk.build_vol_install( - self.conn, os.path.basename(nvram.path), - nvram.get_parent_pool(), nvram.get_size(), False) - nvram_install.input_vol = old_nvram.get_vol_object() - nvram_install.sync_input_vol(only_format=True) - nvram_install.reflink = self.reflink - nvram.set_vol_install(nvram_install) + self._new_guest.os.nvram = nvram.path - nvram.validate() - self._nvram_disk = nvram - self._guest.os.nvram = nvram.path - - - def setup_clone(self): + def prepare(self): """ Validate and set up all parameters needed for the new (clone) VM """ - log.debug("Validating clone parameters.") - - self._clone_xml = self.original_xml - - if len(self.clone_disks) < len(self.original_disks): - raise ValueError(_("More disks to clone than new paths specified. " - "(%(passed)d specified, %(need)d needed") % - {"passed": len(self.clone_disks), - "need": len(self.original_disks)}) - - log.debug("Clone paths: %s", [d.path for d in self.clone_disks]) - - self._guest.name = self._clone_name - self._guest.uuid = self._clone_uuid - self._guest.title = None + try: + Guest.validate_name(self.conn, self._new_guest.name, + check_collision=not self._replace, + validate=False) + except ValueError as e: + raise ValueError(_("Invalid name for new guest: %s") % e) - self._clone_macs.reverse() - for dev in self._guest.devices.graphics: - if dev.port and dev.port != -1: - log.warning(_("Setting the graphics device port to autoport, " - "in order to avoid conflicting.")) - dev.port = -1 + for diskinfo in self.get_diskinfos_to_clone(): + orig_disk = diskinfo.disk - clone_macs = self._clone_macs[:] - for iface in self._guest.devices.interface: - iface.target_dev = None + if not diskinfo.clone_disk: + # User didn't set a path, generate one + newpath = Cloner.generate_clone_disk_path( + self.conn, self.src_name, + self.new_guest.name, + orig_disk.path) + diskinfo.set_clone_path(newpath, + self._overwrite, self._sparse) - if clone_macs: - mac = clone_macs.pop() - else: - mac = DeviceInterface.generate_mac(self.conn) - iface.macaddr = mac + clone_disk = diskinfo.clone_disk + assert clone_disk + log.debug("Cloning srcpath=%s dstpath=%s", + orig_disk.path, clone_disk.path) - # Changing storage XML - for i, orig_disk in enumerate(self._original_disks): - clone_disk = self._clone_disks[i] + if self._reflink: + vol_install = clone_disk.get_vol_install() + vol_install.reflink = self._reflink - for disk in self._guest.devices.disk: + for disk in self._new_guest.devices.disk: if disk.target == orig_disk.target: xmldisk = disk - self._setup_disk_clone_destination(orig_disk, clone_disk) - # Change the XML xmldisk.path = None xmldisk.type = clone_disk.type @@ -444,20 +465,11 @@ class Cloner(object): xmldisk.driver_type = orig_disk.driver_type xmldisk.path = clone_disk.path - # For guest agent channel, remove a path to generate a new one with - # new guest name - for channel in self._guest.devices.channel: - if (channel.type == DeviceChannel.TYPE_UNIX and - channel.target_name and channel.source.path and - channel.target_name in channel.source.path): - channel.source.path = None - - if self._guest.os.nvram: + if self._new_guest.os.nvram: self._prepare_nvram() # Save altered clone xml - self._clone_xml = self._guest.get_xml() - log.debug("Clone guest xml is\n%s", self._clone_xml) + log.debug("Clone guest xml is\n%s", self._new_guest.get_xml()) def start_duplicate(self, meter=None): """ @@ -470,14 +482,15 @@ class Cloner(object): dom = None try: # Replace orig VM if required - if self.replace: - _replace_vm(self.conn, self.clone_name) + if self._replace: + _replace_vm(self.conn, self._new_guest.name) # Define domain early to catch any xml errors before duping storage - dom = self.conn.defineXML(self.clone_xml) + dom = self.conn.defineXML(self._new_guest.get_xml()) - if self.preserve: - for dst_dev in self.clone_disks: + if self._overwrite: + diskinfos = self.get_diskinfos_to_clone() + for dst_dev in [d.clone_disk for d in diskinfos]: dst_dev.build_storage(meter) if self._nvram_disk: self._nvram_disk.build_storage(meter) @@ -488,134 +501,3 @@ class Cloner(object): raise log.debug("Duplicating finished.") - - def generate_clone_disk_path(self, origpath, newname=None): - origname = self.original_guest - newname = newname or self.clone_name - path = origpath - suffix = "" - - # Try to split the suffix off the existing disk name. Ex. - # foobar.img -> foobar-clone.img - # - # If the suffix is greater than 7 characters, assume it isn't - # a file extension and is part of the disk name, at which point - # just stick '-clone' on the end. - if "." in origpath and len(origpath.rsplit(".", 1)[1]) <= 7: - path, suffix = origpath.rsplit(".", 1) - suffix = "." + suffix - - dirname = os.path.dirname(path) - basename = os.path.basename(path) - - clonebase = basename + "-clone" - if origname and basename == origname: - clonebase = newname - - clonebase = os.path.join(dirname, clonebase) - def cb(p): - return DeviceDisk.path_definitely_exists(self.conn, p) - return generatename.generate_name(clonebase, cb, suffix=suffix) - - def generate_clone_name(self, basename=None): - # If the orig name is "foo-clone", we don't want the clone to be - # "foo-clone-clone", we want "foo-clone1" - if not basename: - basename = self.original_guest - - match = re.search("-clone[1-9]*$", basename) - start_num = 1 - force_num = False - if match: - num_match = re.search("[1-9]+$", match.group()) - if num_match: - start_num = int(str(num_match.group())) + 1 - force_num = True - basename = basename.replace(match.group(), "") - - def cb(n): - return generatename.check_libvirt_collision( - self.conn.lookupByName, n) - basename = basename + "-clone" - return generatename.generate_name(basename, cb, - sep="", start_num=start_num, force_num=force_num) - - - ############################ - # Private helper functions # - ############################ - - # Parse disk paths that need to be cloned from the original guest's xml - # Return a list of DeviceDisk instances pointing to the original - # storage - def _get_original_disks_info(self): - clonelist = [] - retdisks = [] - - for disk in self._guest.devices.disk: - if self._do_we_clone_device(disk): - clonelist.append(disk) - continue - - # Set up virtual disk to encapsulate all relevant path info - for disk in clonelist: - validate = not self.preserve_dest_disks - - try: - device = DeviceDisk.DEVICE_DISK - if not disk.path: - # Tell DeviceDisk we are a cdrom to allow empty media - device = DeviceDisk.DEVICE_CDROM - - newd = DeviceDisk(self.conn) - newd.path = disk.path - newd.device = device - newd.driver_name = disk.driver_name - newd.driver_type = disk.driver_type - newd.target = disk.target - if validate: - if newd.wants_storage_creation(): - raise ValueError(_("Disk path '%s' does not exist.") % - newd.path) - except Exception as e: - log.debug("Exception creating clone disk objects", - exc_info=True) - raise ValueError(_("Could not determine original disk " - "information: %s" % str(e))) - retdisks.append(newd) - - return retdisks - - # Pull disk #i from the original guest xml, return it's source path - # if it should be cloned - # Cloning policy based on 'clone_policy', 'force_target' and 'skip_target' - def _do_we_clone_device(self, disk): - if disk.target in self.skip_target: - return False - - if disk.target in self.force_target: - return True - - # No media path - if (not disk.path and - self.CLONE_POLICY_NO_EMPTYMEDIA in self.clone_policy): - return False - - # Readonly disks - if (disk.read_only and - self.CLONE_POLICY_NO_READONLY in self.clone_policy): - return False - - # Shareable disks - if (disk.shareable and - self.CLONE_POLICY_NO_SHAREABLE in self.clone_policy): - return False - - return True - - # Simple wrapper for checking a vm exists and returning the domain - def _lookup_vm(self, name): - try: - return self.conn.lookupByName(name) - except libvirt.libvirtError: - raise ValueError(_("Domain '%s' was not found.") % str(name)) diff --git a/virtinst/diskbackend.py b/virtinst/diskbackend.py index e384e467..3fdae5f0 100644 --- a/virtinst/diskbackend.py +++ b/virtinst/diskbackend.py @@ -517,7 +517,7 @@ class CloneStorageCreator(_StorageCreator): if self.get_dev_type() == "block": avail = _get_size(self._path) # pragma: no cover else: - vfs = os.statvfs(os.path.dirname(self._path)) + vfs = os.statvfs(os.path.dirname(os.path.abspath(self._path))) avail = vfs.f_frsize * vfs.f_bavail need = int(self._size) * 1024 * 1024 * 1024 if need > avail: # pragma: no cover diff --git a/virtinst/virtclone.py b/virtinst/virtclone.py index 961cc0ab..d05c49ab 100644 --- a/virtinst/virtclone.py +++ b/virtinst/virtclone.py @@ -14,71 +14,54 @@ from .cloner import Cloner from .logger import log -# General input gathering functions -def get_clone_name(new_name, auto_clone, design): - if not new_name and auto_clone: - # Generate a name to use - new_name = design.generate_clone_name() - log.debug("Auto-generated clone name '%s'", new_name) - - if not new_name: - fail(_("A name is required for the new virtual machine," - " use '--name NEW_VM_NAME' to specify one.")) - design.clone_name = new_name - - -def get_original_guest(guest_name, origfile, design): - origxml = None - if origfile: - f = open(origfile, "r") - origxml = f.read() - f.close() - - try: - design.original_xml = origxml - return - except (ValueError, RuntimeError) as e: # pragma: no cover - fail(e) - - if not guest_name: +def _process_src(options): + src_name = options.src_name + src_xml = None + if options.original_xml: + src_xml = open(options.original_xml).read() + elif not src_name: fail(_("An original machine name is required," - " use '--original ORIGINAL_GUEST' and try again.")) - design.original_guest = guest_name + " use '--original src_name' and try again.")) + return src_name, src_xml -def get_clone_macaddr(new_mac, design): - if new_mac is None or new_mac[0] == "RANDOM": +def _process_macs(options, cloner): + new_macs = options.new_mac + if not new_macs or new_macs[0] == "RANDOM": return - design.clone_macs = new_mac - for mac in design.clone_macs: - cli.validate_mac(design.conn, mac) + for mac in new_macs: + cli.validate_mac(cloner.conn, mac) + for iface in cloner.new_guest.devices.interface[:]: + iface.macaddr = new_macs.pop(0) -def get_clone_diskfile(new_diskfiles, design, preserve, auto_clone): - if new_diskfiles is None: - new_diskfiles = [None] - newidx = 0 - clonepaths = [] - for origpath in [d.path for d in design.original_disks]: - if len(new_diskfiles) <= newidx: - # Extend the new/passed paths list with None if it's not - # long enough - new_diskfiles.append(None) - newpath = new_diskfiles[newidx] +def _process_disks(options, cloner): + newpaths = (options.new_diskfile or [])[:] + + diskinfos = cloner.get_diskinfos_to_clone() + for diskinfo in diskinfos: + origpath = diskinfo.disk.path + newpath = None + if newpaths: + newpath = newpaths.pop(0) + elif options.auto_clone: + break if origpath is None: newpath = None - elif newpath is None and auto_clone: - newpath = design.generate_clone_disk_path(origpath) + allow_create = options.overwrite + diskinfo.set_clone_path(newpath, allow_create, options.sparse) - clonepaths.append(newpath) - newidx += 1 - design.clone_paths = clonepaths - for disk in design.clone_disks: - cli.validate_disk(disk, warn_overwrite=not preserve) +def _validate_disks(options, cloner): + # Extra CLI validation for specified disks + warn_overwrite = options.overwrite + for diskinfo in cloner.get_diskinfos(): + if not diskinfo.clone_disk: + continue + cli.validate_disk(diskinfo.clone_disk, warn_overwrite=warn_overwrite) def parse_args(): @@ -93,7 +76,7 @@ def parse_args(): cli.add_connect_option(parser) geng = parser.add_argument_group(_("General Options")) - geng.add_argument("-o", "--original", dest="original_guest", + geng.add_argument("-o", "--original", dest="src_name", help=_("Name of the original guest to clone.")) geng.add_argument("--original-xml", help=_("XML file to use as the original guest.")) @@ -121,10 +104,12 @@ def parse_args(): default=True, help=_("Do not use a sparse file for the clone's " "disk image")) - stog.add_argument("--preserve-data", action="store_false", - dest="preserve", default=True, - help=_("Do not clone storage, new disk images specified " - "via --file are preserved unchanged")) + stog.add_argument("--preserve-data", dest="overwrite", + action="store_false", default=True, + help=_("Do not clone storage contents to specified file paths, " + "their contents will be left untouched. " + "This requires specifying existing paths for " + "every clonable disk image.")) stog.add_argument("--nvram", dest="new_nvram", help=_("New file to use as storage for nvram VARS")) @@ -136,9 +121,7 @@ def parse_args(): misc = parser.add_argument_group(_("Miscellaneous Options")) # Just used for clone tests - misc.add_argument("--clone-running", action="store_true", - default=False, help=argparse.SUPPRESS) - misc.add_argument("--__test-nodry", action="store_true", + misc.add_argument("--__test-nodry", action="store_true", dest="test_nodry", default=False, help=argparse.SUPPRESS) cli.add_misc_options(misc, prompt=True, replace=True, printxml=True) @@ -148,7 +131,6 @@ def parse_args(): return parser.parse_args() - def main(conn=None): cli.earlyLogging() options = parse_args() @@ -167,47 +149,49 @@ def main(conn=None): fail(_("Either --auto-clone or --file is required," " use '--auto-clone or --file' and try again.")) - design = Cloner(conn) + src_name, src_xml = _process_src(options) + cloner = Cloner(conn, src_name, src_xml) - design.clone_running = options.clone_running - design.replace = bool(options.replace) - get_original_guest(options.original_guest, options.original_xml, - design) - get_clone_name(options.new_name, options.auto_clone, design) + cloner.set_replace(bool(options.replace)) + cloner.set_reflink(bool(options.reflink)) + cloner.set_sparse(bool(options.sparse)) + cloner.set_overwrite(bool(options.overwrite)) - get_clone_macaddr(options.new_mac, design) if options.new_uuid is not None: - design.clone_uuid = options.new_uuid - if options.reflink is True: - design.reflink = True - for i in options.target or []: - design.force_target = i - for i in options.skip_copy or []: - design.skip_target = i - design.clone_sparse = options.sparse - design.preserve = options.preserve - - design.clone_nvram = options.new_nvram + cloner.set_clone_uuid(options.new_uuid) + if options.new_nvram: + cloner.set_nvram_path(options.new_nvram) + + force_targets = options.target or [] + skip_targets = options.skip_copy or [] + for diskinfo in cloner.get_diskinfos(): + if diskinfo.disk.target in force_targets: + diskinfo.set_clone_requested(True) + if diskinfo.disk.target in skip_targets: + diskinfo.set_clone_requested(False) + + if options.new_name: + cloner.set_clone_name(options.new_name) + elif not options.auto_clone: + fail(_("A name is required for the new virtual machine," + " use '--name NEW_VM_NAME' to specify one.")) - # This determines the devices that need to be cloned, so that - # get_clone_diskfile knows how many new disk paths it needs - design.setup_original() + _process_macs(options, cloner) + _process_disks(options, cloner) - get_clone_diskfile(options.new_diskfile, design, - not options.preserve, options.auto_clone) + cloner.prepare() - # setup design object - design.setup_clone() + _validate_disks(options, cloner) run = True if options.xmlonly: - run = options.__test_nodry - print_stdout(design.clone_xml, do_force=True) + run = options.test_nodry + print_stdout(cloner.new_guest.get_xml(), do_force=True) if run: - design.start_duplicate(cli.get_meter()) + cloner.start_duplicate(cli.get_meter()) print_stdout("") - print_stdout(_("Clone '%s' created successfully.") % design.clone_name) + print_stdout(_("Clone '%s' created successfully.") % cloner.new_guest.name) log.debug("end clone") return 0 |