11 use PVE
::Tools
qw(file_set_contents file_get_contents run_command);
13 my $QM_LIB_PATH = '..';
14 my $MIGRATE_LIB_PATH = '..';
15 my $RUN_DIR_PATH = './MigrationTest/run/';
17 # test configuration shared by all tests
19 my $replication_config = {
35 my $storage_config = {
41 path
=> "/var/lib/vz",
67 monhost
=> "127.0.0.42,127.0.0.21,::1",
87 path
=> "/some/other/dir/",
95 'bootdisk' => 'scsi0',
97 'ide0' => 'local-zfs:vm-105-disk-1,size=103M',
98 'ide2' => 'none,media=cdrom',
100 'name' => 'Copy-of-VM-newapache',
101 'net0' => 'virtio=4A:A3:E4:4C:CF:F0,bridge=vmbr0,firewall=1',
104 'parent' => 'ohsnap',
106 'scsi0' => 'local-zfs:vm-105-disk-0,size=4G',
107 'scsihw' => 'virtio-scsi-pci',
108 'smbios1' => 'uuid=1ddfe18b-77e0-47f6-a4bd-f1761bf6d763',
111 'bootdisk' => 'scsi0',
113 'ide2' => 'none,media=cdrom',
115 'name' => 'Copy-of-VM-newapache',
116 'net0' => 'virtio=4A:A3:E4:4C:CF:F0,bridge=vmbr0,firewall=1',
119 'scsi0' => 'local-zfs:vm-105-disk-0,size=4G',
120 'scsihw' => 'virtio-scsi-pci',
121 'smbios1' => 'uuid=1ddfe18b-77e0-47f6-a4bd-f1761bf6d763',
122 'snaptime' => 1580976924,
124 'startup' => 'order=2',
125 'vmgenid' => '4eb1d535-9381-4ddc-a8aa-af50c4d9177b'
129 'startup' => 'order=2',
130 'vmgenid' => '4eb1d535-9381-4ddc-a8aa-af50c4d9177b',
134 'bootdisk' => 'scsi0',
136 'hotplug' => 'disk,network,usb,memory,cpu',
137 'ide2' => 'none,media=cdrom',
140 'net0' => 'virtio=52:5D:7E:62:85:97,bridge=vmbr1',
143 'scsi0' => 'local-lvm:vm-149-disk-0,format=raw,size=4G',
144 'scsi1' => 'local-dir:149/vm-149-disk-0.qcow2,format=qcow2,size=1G',
145 'scsihw' => 'virtio-scsi-pci',
147 'smbios1' => 'uuid=e980bd43-a405-42e2-b5f4-31efe6517460',
149 'startup' => 'order=2',
150 'vmgenid' => '36c6c50c-6ef5-4adc-9b6f-6ba9c8071db0',
154 'bootdisk' => 'scsi0',
156 'efidisk0' => 'local-lvm:vm-341-disk-0',
157 'ide2' => 'none,media=cdrom',
158 'ipconfig0' => 'ip=103.214.69.10/25,gw=103.214.69.1',
161 'net0' => 'virtio=4E:F1:82:6D:D7:4B,bridge=vmbr0,firewall=1,rate=10',
164 'scsi0' => 'rbd-store:vm-341-disk-0,size=1G',
165 'scsihw' => 'virtio-scsi-pci',
167 'smbios1' => 'uuid=e01e4c73-46f1-47c8-af79-288fdf6b7462',
169 'vmgenid' => 'af47c000-eb0c-48e8-8991-ca4593cd6916',
172 'bootdisk' => 'scsi0',
174 'ide0' => 'rbd-store:vm-1033-cloudinit,media=cdrom,size=4M',
175 'ide2' => 'none,media=cdrom',
176 'ipconfig0' => 'ip=103.214.69.10/25,gw=103.214.69.1',
179 'net0' => 'virtio=4E:F1:82:6D:D7:4B,bridge=vmbr0,firewall=1,rate=10',
182 'scsi0' => 'rbd-store:vm-1033-disk-1,size=1G',
183 'scsihw' => 'virtio-scsi-pci',
185 'smbios1' => 'uuid=e01e4c73-46f1-47c8-af79-288fdf6b7462',
187 'vmgenid' => 'af47c000-eb0c-48e8-8991-ca4593cd6916',
190 'bootdisk' => 'scsi0',
192 'ide2' => 'none,media=cdrom',
195 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
200 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
201 'scsihw' => 'virtio-scsi-pci',
202 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
205 'bootdisk' => 'scsi0',
207 'ide2' => 'none,media=cdrom',
210 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
213 'runningcpu' => 'kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep',
214 'runningmachine' => 'pc-i440fx-5.0+pve0',
215 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
216 'scsihw' => 'virtio-scsi-pci',
217 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
218 'snaptime' => 1595928799,
220 'startup' => 'order=2',
221 'vmgenid' => '932b227a-8a39-4ede-955a-dbd4bc4385ed',
222 'vmstate' => 'local-dir:4567/vm-4567-state-snap1.raw',
225 'bootdisk' => 'scsi0',
227 'ide2' => 'none,media=cdrom',
230 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
234 'runningcpu' => 'kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep',
235 'runningmachine' => 'pc-i440fx-5.0+pve0',
236 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
237 'scsi1' => 'local-zfs:vm-4567-disk-0,size=1G',
238 'scsihw' => 'virtio-scsi-pci',
239 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
240 'snaptime' => 1595928871,
242 'startup' => 'order=2',
243 'vmgenid' => '932b227a-8a39-4ede-955a-dbd4bc4385ed',
244 'vmstate' => 'local-dir:4567/vm-4567-state-snap2.raw',
248 'startup' => 'order=2',
249 'unused0' => 'local-zfs:vm-4567-disk-0',
250 'vmgenid' => 'e698e60c-9278-4dd9-941f-416075383f2a',
254 my $source_vdisks = {
257 'ctime' => 1589439681,
260 'size' => 1073741824,
263 'volid' => 'local-dir:149/vm-149-disk-0.qcow2',
266 'ctime' => 1595928898,
269 'size' => 4294967296,
270 'used' => 1811664896,
272 'volid' => 'local-dir:4567/vm-4567-disk-0.qcow2',
275 'ctime' => 1595928800,
281 'volid' => 'local-dir:4567/vm-4567-state-snap1.raw',
284 'ctime' => 1595928872,
290 'volid' => 'local-dir:4567/vm-4567-state-snap2.raw',
295 'ctime' => '1589277334',
297 'size' => 4294967296,
299 'volid' => 'local-lvm:vm-149-disk-0',
302 'ctime' => '1589277334',
306 'volid' => 'local-lvm:vm-341-disk-0',
311 'ctime' => '1589277334',
313 'size' => 4294967296,
315 'volid' => 'local-zfs:vm-105-disk-0',
318 'ctime' => '1589277334',
322 'volid' => 'local-zfs:vm-105-disk-1',
326 'name' => 'vm-4567-disk-0',
328 'size' => 1073741824,
330 'volid' => 'local-zfs:vm-4567-disk-0',
335 'ctime' => '1589277334',
337 'size' => 1073741824,
339 'volid' => 'rbd-store:vm-1033-disk-1',
342 'ctime' => '1589277334',
344 'size' => 1073741824,
346 'volid' => 'rbd-store:vm-1033-cloudinit',
351 my $default_expected_calls_online = {
352 move_config_to_node
=> 1,
357 my $default_expected_calls_offline = {
358 move_config_to_node
=> 1,
361 my $replicated_expected_calls_online = {
362 %{$default_expected_calls_online},
363 transfer_replication_state
=> 1,
364 switch_replication_job_target
=> 1,
367 my $replicated_expected_calls_offline = {
368 %{$default_expected_calls_offline},
369 transfer_replication_state
=> 1,
370 switch_replication_job_target
=> 1,
375 sub get_patched_config
{
376 my ($vmid, $patch) = @_;
378 my $new_config = { %{$vm_configs->{$vmid}} };
379 patch_config
($new_config, $patch) if defined($patch);
385 my ($config, $patch) = @_;
387 foreach my $key (keys %{$patch}) {
388 if ($key eq 'snapshots' && defined($patch->{$key})) {
389 my $new_snapshot_configs = {};
390 foreach my $snap (keys %{$patch->{snapshots
}}) {
391 my $new_snapshot_config = { %{$config->{snapshots
}->{$snap}} };
392 patch_config
($new_snapshot_config, $patch->{snapshots
}->{$snap});
393 $new_snapshot_configs->{$snap} = $new_snapshot_config;
395 $config->{snapshots
} = $new_snapshot_configs;
396 } elsif (defined($patch->{$key})) {
397 $config->{$key} = $patch->{$key};
398 } else { # use undef value for deletion
399 delete $config->{$key};
404 sub local_volids_for_vm
{
408 foreach my $storeid (keys %{$source_vdisks}) {
409 next if $storage_config->{ids
}->{$storeid}->{shared
};
412 map { $_->{vmid
} eq $vmid ?
($_->{volid
} => 1) : () } @{$source_vdisks->{$storeid}}
419 # each test consists of the following:
420 # name - unique name for the test which also serves as a dir name and
421 # gets passed to make, so don't use whitespace or slash
422 # target - hostname of target node
423 # vmid - ID of the VM to migrate
424 # opts - options for the migrate() call
425 # target_volids - hash of volids on the target at the beginning
426 # vm_status - hash with running, runningmachine and optionally runningcpu
427 # expected_calls - hash whose keys are calls which are required
428 # to be made if the migration gets far enough
429 # expect_die - expect the migration call to fail, and an error message
430 # matching the specified text in the log
431 # expected - hash consisting of:
432 # source_volids - hash of volids expected on the source
433 # target_volids - hash of volids expected on the target
434 # vm_config - vm configuration hash
435 # vm_status - hash with running, runningmachine and optionally runningcpu
437 # NOTE get_efivars_size is mocked and returns 128K
438 name
=> '341_running_efidisk_targetstorage_dir',
443 runningmachine
=> 'pc-q35-5.0+pve0',
447 'with-local-disks' => 1,
448 targetstorage
=> 'local-dir',
450 expected_calls
=> $default_expected_calls_online,
454 'local-dir:341/vm-341-disk-10.raw' => 1,
456 vm_config
=> get_patched_config
(341, {
457 efidisk0
=> 'local-dir:341/vm-341-disk-10.raw,format=raw,size=128K',
461 runningmachine
=> 'pc-q35-5.0+pve0',
466 # NOTE get_efivars_size is mocked and returns 128K
467 name
=> '341_running_efidisk',
472 runningmachine
=> 'pc-q35-5.0+pve0',
476 'with-local-disks' => 1,
478 expected_calls
=> $default_expected_calls_online,
482 'local-lvm:vm-341-disk-10' => 1,
484 vm_config
=> get_patched_config
(341, {
485 efidisk0
=> 'local-lvm:vm-341-disk-10,format=raw,size=128K',
489 runningmachine
=> 'pc-q35-5.0+pve0',
494 name
=> '149_running_vdisk_alloc_and_pvesm_free_fail',
499 runningmachine
=> 'pc-q35-5.0+pve0',
503 'with-local-disks' => 1,
506 vdisk_alloc
=> 'local-dir:149/vm-149-disk-11.qcow2',
507 pvesm_free
=> 'local-lvm:vm-149-disk-10',
509 expected_calls
=> {},
510 expect_die
=> "remote command failed with exit code",
512 source_volids
=> local_volids_for_vm
(149),
514 'local-lvm:vm-149-disk-10' => 1,
516 vm_config
=> $vm_configs->{149},
519 runningmachine
=> 'pc-q35-5.0+pve0',
524 name
=> '149_running_vdisk_alloc_fail',
529 runningmachine
=> 'pc-q35-5.0+pve0',
533 'with-local-disks' => 1,
536 vdisk_alloc
=> 'local-lvm:vm-149-disk-10',
538 expected_calls
=> {},
539 expect_die
=> "remote command failed with exit code",
541 source_volids
=> local_volids_for_vm
(149),
543 vm_config
=> $vm_configs->{149},
546 runningmachine
=> 'pc-q35-5.0+pve0',
551 name
=> '149_vdisk_free_fail',
558 'with-local-disks' => 1,
561 'vdisk_free' => 'local-lvm:vm-149-disk-0',
563 expected_calls
=> $default_expected_calls_offline,
564 expect_die
=> "vdisk_free 'local-lvm:vm-149-disk-0' error",
567 'local-lvm:vm-149-disk-0' => 1,
569 target_volids
=> local_volids_for_vm
(149),
570 vm_config
=> $vm_configs->{149},
577 name
=> '105_replicated_run_replication_fail',
583 target_volids
=> local_volids_for_vm
(105),
585 run_replication
=> 1,
587 expected_calls
=> {},
588 expect_die
=> 'run_replication error',
590 source_volids
=> local_volids_for_vm
(105),
591 target_volids
=> local_volids_for_vm
(105),
592 vm_config
=> $vm_configs->{105},
599 name
=> '1033_running_query_migrate_fail',
604 runningmachine
=> 'pc-q35-5.0+pve0',
610 'query-migrate' => 1,
612 expected_calls
=> {},
613 expect_die
=> 'online migrate failure - aborting',
617 vm_config
=> $vm_configs->{1033},
620 runningmachine
=> 'pc-q35-5.0+pve0',
625 name
=> '4567_targetstorage_dirotherdir',
632 targetstorage
=> 'local-dir:other-dir,local-zfs:local-zfs',
634 storage_migrate_map
=> {
635 'local-dir:4567/vm-4567-disk-0.qcow2' => '4567/vm-4567-disk-0.qcow2',
636 'local-dir:4567/vm-4567-state-snap1.raw' => '4567/vm-4567-state-snap1.raw',
637 'local-dir:4567/vm-4567-state-snap2.raw' => '4567/vm-4567-state-snap2.raw',
639 expected_calls
=> $default_expected_calls_offline,
643 'other-dir:4567/vm-4567-disk-0.qcow2' => 1,
644 'other-dir:4567/vm-4567-state-snap1.raw' => 1,
645 'other-dir:4567/vm-4567-state-snap2.raw' => 1,
646 'local-zfs:vm-4567-disk-0' => 1,
648 vm_config
=> get_patched_config
(4567, {
649 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
652 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
653 'vmstate' => 'other-dir:4567/vm-4567-state-snap1.raw',
656 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
657 'scsi1' => 'local-zfs:vm-4567-disk-0,size=1G',
658 'vmstate' => 'other-dir:4567/vm-4567-state-snap2.raw',
668 name
=> '4567_running',
673 runningmachine
=> 'pc-i440fx-5.0+pve0',
677 'with-local-disks' => 1,
679 expected_calls
=> {},
680 expect_die
=> 'online storage migration not possible if snapshot exists',
682 source_volids
=> local_volids_for_vm
(4567),
684 vm_config
=> $vm_configs->{4567},
687 runningmachine
=> 'pc-i440fx-5.0+pve0',
692 name
=> '4567_offline',
698 expected_calls
=> $default_expected_calls_offline,
701 target_volids
=> local_volids_for_vm
(4567),
702 vm_config
=> $vm_configs->{4567},
709 # FIXME: Maybe add orphaned drives as unused?
710 name
=> '149_running_orphaned_disk_targetstorage_zfs',
715 runningmachine
=> 'pc-q35-5.0+pve0',
719 'with-local-disks' => 1,
720 targetstorage
=> 'local-zfs',
725 storage_migrate_map
=> {
726 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
728 expected_calls
=> $default_expected_calls_online,
732 'local-zfs:vm-149-disk-10' => 1,
733 'local-zfs:vm-149-disk-0' => 1,
735 vm_config
=> get_patched_config
(149, {
736 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
741 runningmachine
=> 'pc-q35-5.0+pve0',
746 # FIXME: Maybe add orphaned drives as unused?
747 name
=> '149_running_orphaned_disk',
752 runningmachine
=> 'pc-q35-5.0+pve0',
756 'with-local-disks' => 1,
761 storage_migrate_map
=> {
762 'local-dir:149/vm-149-disk-0.qcow2' => '149/vm-149-disk-0.qcow2',
764 expected_calls
=> $default_expected_calls_online,
768 'local-lvm:vm-149-disk-10' => 1,
769 'local-dir:149/vm-149-disk-0.qcow2' => 1,
771 vm_config
=> get_patched_config
(149, {
772 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
777 runningmachine
=> 'pc-q35-5.0+pve0',
782 # FIXME: This test is not (yet) a realistic situation, because
783 # storage_migrate currently never changes the format (AFAICT)
784 # But if such migrations become possible, we need to either update
785 # the 'format' property or simply remove it for drives migrated
786 # with storage_migrate (the property is optional, so it shouldn't be a problem)
787 name
=> '149_targetstorage_map_lvmzfs_defaultlvm',
794 targetstorage
=> 'local-lvm:local-zfs,local-lvm',
796 storage_migrate_map
=> {
797 'local-lvm:vm-149-disk-0' => 'vm-149-disk-0',
798 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
800 expected_calls
=> $default_expected_calls_offline,
804 'local-zfs:vm-149-disk-0' => 1,
805 'local-lvm:vm-149-disk-0' => 1,
807 vm_config
=> get_patched_config
(149, {
808 scsi0
=> 'local-zfs:vm-149-disk-0,format=raw,size=4G',
809 scsi1
=> 'local-lvm:vm-149-disk-0,format=qcow2,size=1G',
817 # FIXME same as for the previous test
818 name
=> '149_targetstorage_map_dirzfs_lvmdir',
826 'with-local-disks' => 1,
827 targetstorage
=> 'local-dir:local-zfs,local-lvm:local-dir',
829 storage_migrate_map
=> {
830 'local-lvm:vm-149-disk-0' => '149/vm-149-disk-0.raw',
831 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
833 expected_calls
=> $default_expected_calls_offline,
837 'local-dir:149/vm-149-disk-0.raw' => 1,
838 'local-zfs:vm-149-disk-0' => 1,
840 vm_config
=> get_patched_config
(149, {
841 scsi0
=> 'local-dir:149/vm-149-disk-0.raw,format=raw,size=4G',
842 scsi1
=> 'local-zfs:vm-149-disk-0,format=qcow2,size=1G',
850 name
=> '149_running_targetstorage_map_lvmzfs_defaultlvm',
855 runningmachine
=> 'pc-q35-5.0+pve0',
859 'with-local-disks' => 1,
860 targetstorage
=> 'local-lvm:local-zfs,local-lvm',
862 expected_calls
=> $default_expected_calls_online,
866 'local-zfs:vm-149-disk-10' => 1,
867 'local-lvm:vm-149-disk-11' => 1,
869 vm_config
=> get_patched_config
(149, {
870 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
871 scsi1
=> 'local-lvm:vm-149-disk-11,format=raw,size=1G',
875 runningmachine
=> 'pc-q35-5.0+pve0',
880 name
=> '149_running_targetstorage_map_lvmzfs_dirdir',
885 runningmachine
=> 'pc-q35-5.0+pve0',
889 'with-local-disks' => 1,
890 targetstorage
=> 'local-lvm:local-zfs,local-dir:local-dir',
892 expected_calls
=> $default_expected_calls_online,
896 'local-zfs:vm-149-disk-10' => 1,
897 'local-dir:149/vm-149-disk-11.qcow2' => 1,
899 vm_config
=> get_patched_config
(149, {
900 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
901 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
905 runningmachine
=> 'pc-q35-5.0+pve0',
910 name
=> '149_running_targetstorage_zfs',
915 runningmachine
=> 'pc-q35-5.0+pve0',
919 'with-local-disks' => 1,
920 targetstorage
=> 'local-zfs',
922 expected_calls
=> $default_expected_calls_online,
926 'local-zfs:vm-149-disk-10' => 1,
927 'local-zfs:vm-149-disk-11' => 1,
929 vm_config
=> get_patched_config
(149, {
930 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
931 scsi1
=> 'local-zfs:vm-149-disk-11,format=raw,size=1G',
935 runningmachine
=> 'pc-q35-5.0+pve0',
940 name
=> '149_running_wrong_size',
945 runningmachine
=> 'pc-q35-5.0+pve0',
949 'with-local-disks' => 1,
952 scsi0
=> 'local-lvm:vm-149-disk-0,size=123T',
954 expected_calls
=> $default_expected_calls_online,
958 'local-lvm:vm-149-disk-10' => 1,
959 'local-dir:149/vm-149-disk-11.qcow2' => 1,
961 vm_config
=> get_patched_config
(149, {
962 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
963 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
967 runningmachine
=> 'pc-q35-5.0+pve0',
972 name
=> '149_running_missing_size',
977 runningmachine
=> 'pc-q35-5.0+pve0',
981 'with-local-disks' => 1,
984 scsi0
=> 'local-lvm:vm-149-disk-0',
986 expected_calls
=> $default_expected_calls_online,
990 'local-lvm:vm-149-disk-10' => 1,
991 'local-dir:149/vm-149-disk-11.qcow2' => 1,
993 vm_config
=> get_patched_config
(149, {
994 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
995 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
999 runningmachine
=> 'pc-q35-5.0+pve0',
1004 name
=> '105_local_device_shared',
1011 ide2
=> '/dev/sde,shared=1',
1013 expected_calls
=> $default_expected_calls_offline,
1015 source_volids
=> {},
1016 target_volids
=> local_volids_for_vm
(105),
1017 vm_config
=> get_patched_config
(105, {
1018 ide2
=> '/dev/sde,shared=1',
1026 name
=> '105_local_device_in_snapshot',
1039 expected_calls
=> {},
1040 expect_die
=> "can't migrate local disk '/dev/sde': local file/device",
1042 source_volids
=> local_volids_for_vm
(105),
1043 target_volids
=> {},
1044 vm_config
=> get_patched_config
(105, {
1057 name
=> '105_local_device',
1066 expected_calls
=> {},
1067 expect_die
=> "can't migrate local disk '/dev/sde': local file/device",
1069 source_volids
=> local_volids_for_vm
(105),
1070 target_volids
=> {},
1071 vm_config
=> get_patched_config
(105, {
1080 name
=> '105_cdrom_in_snapshot',
1089 ide2
=> 'cdrom,media=cdrom',
1093 expected_calls
=> {},
1094 expect_die
=> "can't migrate local cdrom drive (referenced in snapshot - ohsnap",
1096 source_volids
=> local_volids_for_vm
(105),
1097 target_volids
=> {},
1098 vm_config
=> get_patched_config
(105, {
1101 ide2
=> 'cdrom,media=cdrom',
1111 name
=> '105_cdrom',
1118 ide2
=> 'cdrom,media=cdrom',
1120 expected_calls
=> {},
1121 expect_die
=> "can't migrate local cdrom drive",
1123 source_volids
=> local_volids_for_vm
(105),
1124 target_volids
=> {},
1125 vm_config
=> get_patched_config
(105, {
1126 ide2
=> 'cdrom,media=cdrom',
1134 name
=> '149_running_missing_option_withlocaldisks',
1139 runningmachine
=> 'pc-q35-5.0+pve0',
1144 expected_calls
=> {},
1145 expect_die
=> "can't live migrate attached local disks without with-local-disks option",
1147 source_volids
=> local_volids_for_vm
(149),
1148 target_volids
=> {},
1149 vm_config
=> $vm_configs->{149},
1152 runningmachine
=> 'pc-q35-5.0+pve0',
1157 name
=> '149_running_missing_option_online',
1162 runningmachine
=> 'pc-q35-5.0+pve0',
1165 'with-local-disks' => 1,
1167 expected_calls
=> {},
1168 expect_die
=> "can't migrate running VM without --online",
1170 source_volids
=> local_volids_for_vm
(149),
1171 target_volids
=> {},
1172 vm_config
=> $vm_configs->{149},
1175 runningmachine
=> 'pc-q35-5.0+pve0',
1180 name
=> '1033_running_customcpu',
1185 runningmachine
=> 'pc-q35-5.0+pve0',
1186 runningcpu
=> 'host,+kvm_pv_eoi,+kvm_pv_unhalt',
1192 cpu
=> 'custom-mycpu',
1194 expected_calls
=> $default_expected_calls_online,
1196 source_volids
=> {},
1197 target_volids
=> {},
1198 vm_config
=> get_patched_config
(1033, {
1199 cpu
=> 'custom-mycpu',
1203 runningmachine
=> 'pc-q35-5.0+pve0',
1204 runningcpu
=> 'host,+kvm_pv_eoi,+kvm_pv_unhalt',
1209 name
=> '105_replicated_to_non_replication_target',
1215 target_volids
=> {},
1216 expected_calls
=> $replicated_expected_calls_offline,
1218 source_volids
=> {},
1219 target_volids
=> local_volids_for_vm
(105),
1220 vm_config
=> $vm_configs->{105},
1227 name
=> '105_running_replicated',
1232 runningmachine
=> 'pc-i440fx-5.0+pve0',
1236 'with-local-disks' => 1,
1238 target_volids
=> local_volids_for_vm
(105),
1239 expected_calls
=> {},
1240 expect_die
=> "online storage migration not possible if snapshot exists",
1242 source_volids
=> local_volids_for_vm
(105),
1243 target_volids
=> local_volids_for_vm
(105),
1244 vm_config
=> $vm_configs->{105},
1247 runningmachine
=> 'pc-i440fx-5.0+pve0',
1252 name
=> '105_replicated',
1258 target_volids
=> local_volids_for_vm
(105),
1259 expected_calls
=> $replicated_expected_calls_offline,
1261 source_volids
=> local_volids_for_vm
(105),
1262 target_volids
=> local_volids_for_vm
(105),
1263 vm_config
=> $vm_configs->{105},
1270 name
=> '105_running_replicated_without_snapshot',
1275 runningmachine
=> 'pc-i440fx-5.0+pve0',
1282 'with-local-disks' => 1,
1284 target_volids
=> local_volids_for_vm
(105),
1286 %{$replicated_expected_calls_online},
1287 'block-dirty-bitmap-add-drive-scsi0' => 1,
1288 'block-dirty-bitmap-add-drive-ide0' => 1,
1291 source_volids
=> local_volids_for_vm
(105),
1292 target_volids
=> local_volids_for_vm
(105),
1293 vm_config
=> get_patched_config
(105, {
1298 runningmachine
=> 'pc-i440fx-5.0+pve0',
1303 name
=> '105_replicated_without_snapshot',
1315 target_volids
=> local_volids_for_vm
(105),
1316 expected_calls
=> $replicated_expected_calls_offline,
1318 source_volids
=> local_volids_for_vm
(105),
1319 target_volids
=> local_volids_for_vm
(105),
1320 vm_config
=> get_patched_config
(105, {
1329 name
=> '1033_running',
1334 runningmachine
=> 'pc-q35-5.0+pve0',
1339 expected_calls
=> $default_expected_calls_online,
1341 source_volids
=> {},
1342 target_volids
=> {},
1343 vm_config
=> $vm_configs->{1033},
1346 runningmachine
=> 'pc-q35-5.0+pve0',
1351 name
=> '149_locked',
1360 expected_calls
=> {},
1361 expect_die
=> "VM is locked",
1363 source_volids
=> local_volids_for_vm
(149),
1364 target_volids
=> {},
1365 vm_config
=> get_patched_config
(149, {
1374 name
=> '149_storage_not_available',
1380 expected_calls
=> {},
1381 expect_die
=> "storage 'local-lvm' is not available on node 'pve2'",
1383 source_volids
=> local_volids_for_vm
(149),
1384 target_volids
=> {},
1385 vm_config
=> $vm_configs->{149},
1392 name
=> '149_running',
1397 runningmachine
=> 'pc-q35-5.0+pve0',
1401 'with-local-disks' => 1,
1403 expected_calls
=> $default_expected_calls_online,
1405 source_volids
=> {},
1407 'local-lvm:vm-149-disk-10' => 1,
1408 'local-dir:149/vm-149-disk-11.qcow2' => 1,
1410 vm_config
=> get_patched_config
(149, {
1411 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
1412 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
1416 runningmachine
=> 'pc-q35-5.0+pve0',
1421 name
=> '149_running_drive_mirror_fail',
1426 runningmachine
=> 'pc-q35-5.0+pve0',
1430 'with-local-disks' => 1,
1432 expected_calls
=> {},
1433 expect_die
=> "qemu_drive_mirror 'scsi1' error",
1435 'qemu_drive_mirror' => 'scsi1',
1438 source_volids
=> local_volids_for_vm
(149),
1439 target_volids
=> {},
1440 vm_config
=> $vm_configs->{149},
1443 runningmachine
=> 'pc-q35-5.0+pve0',
1448 name
=> '149_running_unused_block_job_cancel_fail',
1453 runningmachine
=> 'pc-q35-5.0+pve0',
1457 'with-local-disks' => 1,
1461 unused0
=> 'local-dir:149/vm-149-disk-0.qcow2',
1463 expected_calls
=> {},
1464 expect_die
=> "qemu_drive_mirror_monitor 'cancel' error",
1465 # note that 'cancel' is also used to finish and that's what this test is about
1467 'qemu_drive_mirror_monitor' => 'cancel',
1470 source_volids
=> local_volids_for_vm
(149),
1471 target_volids
=> {},
1472 vm_config
=> get_patched_config
(149, {
1474 unused0
=> 'local-dir:149/vm-149-disk-0.qcow2',
1478 runningmachine
=> 'pc-q35-5.0+pve0',
1483 name
=> '149_offline',
1490 'with-local-disks' => 1,
1492 expected_calls
=> $default_expected_calls_offline,
1494 source_volids
=> {},
1495 target_volids
=> local_volids_for_vm
(149),
1496 vm_config
=> $vm_configs->{149},
1503 name
=> '149_storage_migrate_fail',
1510 'with-local-disks' => 1,
1513 'storage_migrate' => 'local-lvm:vm-149-disk-0',
1515 expected_calls
=> {},
1516 expect_die
=> "storage_migrate 'local-lvm:vm-149-disk-0' error",
1518 source_volids
=> local_volids_for_vm
(149),
1519 target_volids
=> {},
1520 vm_config
=> $vm_configs->{149},
1528 my $single_test_name = shift;
1530 if (defined($single_test_name) && $single_test_name eq 'DUMP_NAMES') {
1532 foreach my $test (@{$tests}) {
1533 $output .= $test->{name
} . ' ';
1539 mkdir $RUN_DIR_PATH;
1541 foreach my $test (@{$tests}) {
1542 my $name = $test->{name
};
1543 next if defined($single_test_name) && $name ne $single_test_name;
1545 my $run_dir = "${RUN_DIR_PATH}/${name}";
1548 file_set_contents
("${run_dir}/replication_config", to_json
($replication_config));
1549 file_set_contents
("${run_dir}/storage_config", to_json
($storage_config));
1550 file_set_contents
("${run_dir}/source_vdisks", to_json
($source_vdisks));
1552 my $expect_die = $test->{expect_die
};
1553 my $expected = $test->{expected
};
1555 my $source_volids = local_volids_for_vm
($test->{vmid
});
1556 my $target_volids = $test->{target_volids
} // {};
1558 my $config_patch = $test->{config_patch
};
1559 my $vm_config = get_patched_config
($test->{vmid
}, $test->{config_patch
});
1561 my $fail_config = $test->{fail_config
} // {};
1562 my $storage_migrate_map = $test->{storage_migrate_map
} // {};
1564 if (my $targetstorage = $test->{opts
}->{targetstorage
}) {
1565 $test->{opts
}->{storagemap
} = PVE
::JSONSchema
::parse_idmap
($targetstorage, 'pve-storage-id');
1568 my $migrate_params = {
1569 target
=> $test->{target
},
1570 vmid
=> $test->{vmid
},
1571 opts
=> $test->{opts
},
1574 file_set_contents
("${run_dir}/nbd_info", to_json
({}));
1575 file_set_contents
("${run_dir}/source_volids", to_json
($source_volids));
1576 file_set_contents
("${run_dir}/target_volids", to_json
($target_volids));
1577 file_set_contents
("${run_dir}/vm_config", to_json
($vm_config));
1578 file_set_contents
("${run_dir}/vm_status", to_json
($test->{vm_status
}));
1579 file_set_contents
("${run_dir}/expected_calls", to_json
($test->{expected_calls
}));
1580 file_set_contents
("${run_dir}/fail_config", to_json
($fail_config));
1581 file_set_contents
("${run_dir}/storage_migrate_map", to_json
($storage_migrate_map));
1582 file_set_contents
("${run_dir}/migrate_params", to_json
($migrate_params));
1584 $ENV{QM_LIB_PATH
} = $QM_LIB_PATH;
1585 $ENV{RUN_DIR_PATH
} = $run_dir;
1586 my $exitcode = run_command
([
1588 "-I${MIGRATE_LIB_PATH}",
1589 "-I${MIGRATE_LIB_PATH}/test",
1590 "${MIGRATE_LIB_PATH}/test/MigrationTest/QemuMigrateMock.pm",
1591 ], noerr
=> 1, errfunc
=> sub {print "#$name - $_[0]\n"} );
1593 if (defined($expect_die) && $exitcode) {
1594 my $log = file_get_contents
("${run_dir}/log");
1595 my @lines = split /\n/, $log;
1598 foreach my $line (@lines) {
1599 $matched = 1 if $line =~ m/^err:.*\Q${expect_die}\E/;
1600 $matched = 1 if $line =~ m/^warn:.*\Q${expect_die}\E/;
1604 note
("expected error message is not present in log");
1606 } elsif (defined($expect_die) && !$exitcode) {
1608 note
("mocked migrate call didn't fail, but it was expected to - check log");
1609 } elsif (!defined($expect_die) && $exitcode) {
1611 note
("mocked migrate call failed, but it was not expected - check log");
1614 my $expected_calls = decode_json
(file_get_contents
("${run_dir}/expected_calls"));
1615 foreach my $call (keys %{$expected_calls}) {
1617 note
("expected call '$call' was not made");
1620 if (!defined($expect_die)) {
1621 my $nbd_info = decode_json
(file_get_contents
("${run_dir}/nbd_info"));
1622 foreach my $drive (keys %{$nbd_info}) {
1624 note
("drive '$drive' was not mirrored");
1629 source_volids
=> decode_json
(file_get_contents
("${run_dir}/source_volids")),
1630 target_volids
=> decode_json
(file_get_contents
("${run_dir}/target_volids")),
1631 vm_config
=> decode_json
(file_get_contents
("${run_dir}/vm_config")),
1632 vm_status
=> decode_json
(file_get_contents
("${run_dir}/vm_status")),
1635 is_deeply
($actual, $expected, $name);