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",
68 fsid
=> 'fc4181a6-56eb-4f68-b452-8ba1f381ca2a',
88 path
=> "/some/other/dir/",
96 'bootdisk' => 'scsi0',
98 'ide0' => 'local-zfs:vm-105-disk-1,size=103M',
99 'ide2' => 'none,media=cdrom',
101 'name' => 'Copy-of-VM-newapache',
102 'net0' => 'virtio=4A:A3:E4:4C:CF:F0,bridge=vmbr0,firewall=1',
105 'parent' => 'ohsnap',
107 'scsi0' => 'local-zfs:vm-105-disk-0,size=4G',
108 'scsihw' => 'virtio-scsi-pci',
109 'smbios1' => 'uuid=1ddfe18b-77e0-47f6-a4bd-f1761bf6d763',
112 'bootdisk' => 'scsi0',
114 'ide2' => 'none,media=cdrom',
116 'name' => 'Copy-of-VM-newapache',
117 'net0' => 'virtio=4A:A3:E4:4C:CF:F0,bridge=vmbr0,firewall=1',
120 'scsi0' => 'local-zfs:vm-105-disk-0,size=4G',
121 'scsihw' => 'virtio-scsi-pci',
122 'smbios1' => 'uuid=1ddfe18b-77e0-47f6-a4bd-f1761bf6d763',
123 'snaptime' => 1580976924,
125 'startup' => 'order=2',
126 'vmgenid' => '4eb1d535-9381-4ddc-a8aa-af50c4d9177b'
130 'startup' => 'order=2',
131 'vmgenid' => '4eb1d535-9381-4ddc-a8aa-af50c4d9177b',
135 'bootdisk' => 'scsi0',
137 'hotplug' => 'disk,network,usb,memory,cpu',
138 'ide2' => 'none,media=cdrom',
141 'net0' => 'virtio=52:5D:7E:62:85:97,bridge=vmbr1',
144 'scsi0' => 'local-lvm:vm-149-disk-0,format=raw,size=4G',
145 'scsi1' => 'local-dir:149/vm-149-disk-0.qcow2,format=qcow2,size=1G',
146 'scsihw' => 'virtio-scsi-pci',
148 'smbios1' => 'uuid=e980bd43-a405-42e2-b5f4-31efe6517460',
150 'startup' => 'order=2',
151 'vmgenid' => '36c6c50c-6ef5-4adc-9b6f-6ba9c8071db0',
155 'bootdisk' => 'scsi0',
157 'efidisk0' => 'local-lvm:vm-341-disk-0',
158 'ide2' => 'none,media=cdrom',
159 'ipconfig0' => 'ip=103.214.69.10/25,gw=103.214.69.1',
162 'net0' => 'virtio=4E:F1:82:6D:D7:4B,bridge=vmbr0,firewall=1,rate=10',
165 'scsi0' => 'rbd-store:vm-341-disk-0,size=1G',
166 'scsihw' => 'virtio-scsi-pci',
168 'smbios1' => 'uuid=e01e4c73-46f1-47c8-af79-288fdf6b7462',
170 'vmgenid' => 'af47c000-eb0c-48e8-8991-ca4593cd6916',
173 'bootdisk' => 'scsi0',
175 'ide0' => 'rbd-store:vm-1033-cloudinit,media=cdrom,size=4M',
176 'ide2' => 'none,media=cdrom',
177 'ipconfig0' => 'ip=103.214.69.10/25,gw=103.214.69.1',
180 'net0' => 'virtio=4E:F1:82:6D:D7:4B,bridge=vmbr0,firewall=1,rate=10',
183 'scsi0' => 'rbd-store:vm-1033-disk-1,size=1G',
184 'scsihw' => 'virtio-scsi-pci',
186 'smbios1' => 'uuid=e01e4c73-46f1-47c8-af79-288fdf6b7462',
188 'vmgenid' => 'af47c000-eb0c-48e8-8991-ca4593cd6916',
191 'bootdisk' => 'scsi0',
193 'ide2' => 'none,media=cdrom',
196 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
201 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
202 'scsihw' => 'virtio-scsi-pci',
203 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
206 'bootdisk' => 'scsi0',
208 'ide2' => 'none,media=cdrom',
211 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
214 'runningcpu' => 'kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep',
215 'runningmachine' => 'pc-i440fx-5.0+pve0',
216 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
217 'scsihw' => 'virtio-scsi-pci',
218 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
219 'snaptime' => 1595928799,
221 'startup' => 'order=2',
222 'vmgenid' => '932b227a-8a39-4ede-955a-dbd4bc4385ed',
223 'vmstate' => 'local-dir:4567/vm-4567-state-snap1.raw',
226 'bootdisk' => 'scsi0',
228 'ide2' => 'none,media=cdrom',
231 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
235 'runningcpu' => 'kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep',
236 'runningmachine' => 'pc-i440fx-5.0+pve0',
237 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
238 'scsi1' => 'local-zfs:vm-4567-disk-0,size=1G',
239 'scsihw' => 'virtio-scsi-pci',
240 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
241 'snaptime' => 1595928871,
243 'startup' => 'order=2',
244 'vmgenid' => '932b227a-8a39-4ede-955a-dbd4bc4385ed',
245 'vmstate' => 'local-dir:4567/vm-4567-state-snap2.raw',
249 'startup' => 'order=2',
250 'unused0' => 'local-zfs:vm-4567-disk-0',
251 'vmgenid' => 'e698e60c-9278-4dd9-941f-416075383f2a',
255 my $source_vdisks = {
258 'ctime' => 1589439681,
261 'size' => 1073741824,
264 'volid' => 'local-dir:149/vm-149-disk-0.qcow2',
267 'ctime' => 1595928898,
270 'size' => 4294967296,
271 'used' => 1811664896,
273 'volid' => 'local-dir:4567/vm-4567-disk-0.qcow2',
276 'ctime' => 1595928800,
282 'volid' => 'local-dir:4567/vm-4567-state-snap1.raw',
285 'ctime' => 1595928872,
291 'volid' => 'local-dir:4567/vm-4567-state-snap2.raw',
296 'ctime' => '1589277334',
298 'size' => 4294967296,
300 'volid' => 'local-lvm:vm-149-disk-0',
303 'ctime' => '1589277334',
307 'volid' => 'local-lvm:vm-341-disk-0',
312 'ctime' => '1589277334',
314 'size' => 4294967296,
316 'volid' => 'local-zfs:vm-105-disk-0',
319 'ctime' => '1589277334',
323 'volid' => 'local-zfs:vm-105-disk-1',
327 'name' => 'vm-4567-disk-0',
329 'size' => 1073741824,
331 'volid' => 'local-zfs:vm-4567-disk-0',
336 'ctime' => '1589277334',
338 'size' => 1073741824,
340 'volid' => 'rbd-store:vm-1033-disk-1',
343 'ctime' => '1589277334',
345 'size' => 1073741824,
347 'volid' => 'rbd-store:vm-1033-cloudinit',
352 my $default_expected_calls_online = {
353 move_config_to_node
=> 1,
358 my $default_expected_calls_offline = {
359 move_config_to_node
=> 1,
362 my $replicated_expected_calls_online = {
363 %{$default_expected_calls_online},
364 transfer_replication_state
=> 1,
365 switch_replication_job_target
=> 1,
368 my $replicated_expected_calls_offline = {
369 %{$default_expected_calls_offline},
370 transfer_replication_state
=> 1,
371 switch_replication_job_target
=> 1,
376 sub get_patched_config
{
377 my ($vmid, $patch) = @_;
379 my $new_config = { %{$vm_configs->{$vmid}} };
380 patch_config
($new_config, $patch) if defined($patch);
386 my ($config, $patch) = @_;
388 foreach my $key (keys %{$patch}) {
389 if ($key eq 'snapshots' && defined($patch->{$key})) {
390 my $new_snapshot_configs = {};
391 foreach my $snap (keys %{$patch->{snapshots
}}) {
392 my $new_snapshot_config = { %{$config->{snapshots
}->{$snap}} };
393 patch_config
($new_snapshot_config, $patch->{snapshots
}->{$snap});
394 $new_snapshot_configs->{$snap} = $new_snapshot_config;
396 $config->{snapshots
} = $new_snapshot_configs;
397 } elsif (defined($patch->{$key})) {
398 $config->{$key} = $patch->{$key};
399 } else { # use undef value for deletion
400 delete $config->{$key};
405 sub local_volids_for_vm
{
409 foreach my $storeid (keys %{$source_vdisks}) {
410 next if $storage_config->{ids
}->{$storeid}->{shared
};
413 map { $_->{vmid
} eq $vmid ?
($_->{volid
} => 1) : () } @{$source_vdisks->{$storeid}}
420 # each test consists of the following:
421 # name - unique name for the test which also serves as a dir name and
422 # gets passed to make, so don't use whitespace or slash
423 # target - hostname of target node
424 # vmid - ID of the VM to migrate
425 # opts - options for the migrate() call
426 # target_volids - hash of volids on the target at the beginning
427 # vm_status - hash with running, runningmachine and optionally runningcpu
428 # expected_calls - hash whose keys are calls which are required
429 # to be made if the migration gets far enough
430 # expect_die - expect the migration call to fail, and an error message
431 # matching the specified text in the log
432 # expected - hash consisting of:
433 # source_volids - hash of volids expected on the source
434 # target_volids - hash of volids expected on the target
435 # vm_config - vm configuration hash
436 # vm_status - hash with running, runningmachine and optionally runningcpu
438 # NOTE get_efivars_size is mocked and returns 128K
439 name
=> '341_running_efidisk_targetstorage_dir',
444 runningmachine
=> 'pc-q35-5.0+pve0',
448 'with-local-disks' => 1,
449 targetstorage
=> 'local-dir',
451 expected_calls
=> $default_expected_calls_online,
455 'local-dir:341/vm-341-disk-10.raw' => 1,
457 vm_config
=> get_patched_config
(341, {
458 efidisk0
=> 'local-dir:341/vm-341-disk-10.raw,format=raw,size=128K',
462 runningmachine
=> 'pc-q35-5.0+pve0',
467 # NOTE get_efivars_size is mocked and returns 128K
468 name
=> '341_running_efidisk',
473 runningmachine
=> 'pc-q35-5.0+pve0',
477 'with-local-disks' => 1,
479 expected_calls
=> $default_expected_calls_online,
483 'local-lvm:vm-341-disk-10' => 1,
485 vm_config
=> get_patched_config
(341, {
486 efidisk0
=> 'local-lvm:vm-341-disk-10,format=raw,size=128K',
490 runningmachine
=> 'pc-q35-5.0+pve0',
495 name
=> '149_running_vdisk_alloc_and_pvesm_free_fail',
500 runningmachine
=> 'pc-q35-5.0+pve0',
504 'with-local-disks' => 1,
507 vdisk_alloc
=> 'local-dir:149/vm-149-disk-11.qcow2',
508 pvesm_free
=> 'local-lvm:vm-149-disk-10',
510 expected_calls
=> {},
511 expect_die
=> "remote command failed with exit code",
513 source_volids
=> local_volids_for_vm
(149),
515 'local-lvm:vm-149-disk-10' => 1,
517 vm_config
=> $vm_configs->{149},
520 runningmachine
=> 'pc-q35-5.0+pve0',
525 name
=> '149_running_vdisk_alloc_fail',
530 runningmachine
=> 'pc-q35-5.0+pve0',
534 'with-local-disks' => 1,
537 vdisk_alloc
=> 'local-lvm:vm-149-disk-10',
539 expected_calls
=> {},
540 expect_die
=> "remote command failed with exit code",
542 source_volids
=> local_volids_for_vm
(149),
544 vm_config
=> $vm_configs->{149},
547 runningmachine
=> 'pc-q35-5.0+pve0',
552 name
=> '149_vdisk_free_fail',
559 'with-local-disks' => 1,
562 'vdisk_free' => 'local-lvm:vm-149-disk-0',
564 expected_calls
=> $default_expected_calls_offline,
565 expect_die
=> "vdisk_free 'local-lvm:vm-149-disk-0' error",
568 'local-lvm:vm-149-disk-0' => 1,
570 target_volids
=> local_volids_for_vm
(149),
571 vm_config
=> $vm_configs->{149},
578 name
=> '105_replicated_run_replication_fail',
584 target_volids
=> local_volids_for_vm
(105),
586 run_replication
=> 1,
588 expected_calls
=> {},
589 expect_die
=> 'run_replication error',
591 source_volids
=> local_volids_for_vm
(105),
592 target_volids
=> local_volids_for_vm
(105),
593 vm_config
=> $vm_configs->{105},
600 name
=> '1033_running_query_migrate_fail',
605 runningmachine
=> 'pc-q35-5.0+pve0',
611 'query-migrate' => 1,
613 expected_calls
=> {},
614 expect_die
=> 'online migrate failure - aborting',
618 vm_config
=> $vm_configs->{1033},
621 runningmachine
=> 'pc-q35-5.0+pve0',
626 name
=> '4567_targetstorage_dirotherdir',
633 targetstorage
=> 'local-dir:other-dir,local-zfs:local-zfs',
635 storage_migrate_map
=> {
636 'local-dir:4567/vm-4567-disk-0.qcow2' => '4567/vm-4567-disk-0.qcow2',
637 'local-dir:4567/vm-4567-state-snap1.raw' => '4567/vm-4567-state-snap1.raw',
638 'local-dir:4567/vm-4567-state-snap2.raw' => '4567/vm-4567-state-snap2.raw',
640 expected_calls
=> $default_expected_calls_offline,
644 'other-dir:4567/vm-4567-disk-0.qcow2' => 1,
645 'other-dir:4567/vm-4567-state-snap1.raw' => 1,
646 'other-dir:4567/vm-4567-state-snap2.raw' => 1,
647 'local-zfs:vm-4567-disk-0' => 1,
649 vm_config
=> get_patched_config
(4567, {
650 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
653 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
654 'vmstate' => 'other-dir:4567/vm-4567-state-snap1.raw',
657 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
658 'scsi1' => 'local-zfs:vm-4567-disk-0,size=1G',
659 'vmstate' => 'other-dir:4567/vm-4567-state-snap2.raw',
669 name
=> '4567_running',
674 runningmachine
=> 'pc-i440fx-5.0+pve0',
678 'with-local-disks' => 1,
680 expected_calls
=> {},
681 expect_die
=> 'online storage migration not possible if snapshot exists',
683 source_volids
=> local_volids_for_vm
(4567),
685 vm_config
=> $vm_configs->{4567},
688 runningmachine
=> 'pc-i440fx-5.0+pve0',
693 name
=> '4567_offline',
699 expected_calls
=> $default_expected_calls_offline,
702 target_volids
=> local_volids_for_vm
(4567),
703 vm_config
=> $vm_configs->{4567},
710 # FIXME: Maybe add orphaned drives as unused?
711 name
=> '149_running_orphaned_disk_targetstorage_zfs',
716 runningmachine
=> 'pc-q35-5.0+pve0',
720 'with-local-disks' => 1,
721 targetstorage
=> 'local-zfs',
726 storage_migrate_map
=> {
727 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
729 expected_calls
=> $default_expected_calls_online,
733 'local-zfs:vm-149-disk-10' => 1,
734 'local-zfs:vm-149-disk-0' => 1,
736 vm_config
=> get_patched_config
(149, {
737 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
742 runningmachine
=> 'pc-q35-5.0+pve0',
747 # FIXME: Maybe add orphaned drives as unused?
748 name
=> '149_running_orphaned_disk',
753 runningmachine
=> 'pc-q35-5.0+pve0',
757 'with-local-disks' => 1,
762 storage_migrate_map
=> {
763 'local-dir:149/vm-149-disk-0.qcow2' => '149/vm-149-disk-0.qcow2',
765 expected_calls
=> $default_expected_calls_online,
769 'local-lvm:vm-149-disk-10' => 1,
770 'local-dir:149/vm-149-disk-0.qcow2' => 1,
772 vm_config
=> get_patched_config
(149, {
773 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
778 runningmachine
=> 'pc-q35-5.0+pve0',
783 # FIXME: This test is not (yet) a realistic situation, because
784 # storage_migrate currently never changes the format (AFAICT)
785 # But if such migrations become possible, we need to either update
786 # the 'format' property or simply remove it for drives migrated
787 # with storage_migrate (the property is optional, so it shouldn't be a problem)
788 name
=> '149_targetstorage_map_lvmzfs_defaultlvm',
795 targetstorage
=> 'local-lvm:local-zfs,local-lvm',
797 storage_migrate_map
=> {
798 'local-lvm:vm-149-disk-0' => 'vm-149-disk-0',
799 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
801 expected_calls
=> $default_expected_calls_offline,
805 'local-zfs:vm-149-disk-0' => 1,
806 'local-lvm:vm-149-disk-0' => 1,
808 vm_config
=> get_patched_config
(149, {
809 scsi0
=> 'local-zfs:vm-149-disk-0,format=raw,size=4G',
810 scsi1
=> 'local-lvm:vm-149-disk-0,format=qcow2,size=1G',
818 # FIXME same as for the previous test
819 name
=> '149_targetstorage_map_dirzfs_lvmdir',
827 'with-local-disks' => 1,
828 targetstorage
=> 'local-dir:local-zfs,local-lvm:local-dir',
830 storage_migrate_map
=> {
831 'local-lvm:vm-149-disk-0' => '149/vm-149-disk-0.raw',
832 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
834 expected_calls
=> $default_expected_calls_offline,
838 'local-dir:149/vm-149-disk-0.raw' => 1,
839 'local-zfs:vm-149-disk-0' => 1,
841 vm_config
=> get_patched_config
(149, {
842 scsi0
=> 'local-dir:149/vm-149-disk-0.raw,format=raw,size=4G',
843 scsi1
=> 'local-zfs:vm-149-disk-0,format=qcow2,size=1G',
851 name
=> '149_running_targetstorage_map_lvmzfs_defaultlvm',
856 runningmachine
=> 'pc-q35-5.0+pve0',
860 'with-local-disks' => 1,
861 targetstorage
=> 'local-lvm:local-zfs,local-lvm',
863 expected_calls
=> $default_expected_calls_online,
867 'local-zfs:vm-149-disk-10' => 1,
868 'local-lvm:vm-149-disk-11' => 1,
870 vm_config
=> get_patched_config
(149, {
871 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
872 scsi1
=> 'local-lvm:vm-149-disk-11,format=raw,size=1G',
876 runningmachine
=> 'pc-q35-5.0+pve0',
881 name
=> '149_running_targetstorage_map_lvmzfs_dirdir',
886 runningmachine
=> 'pc-q35-5.0+pve0',
890 'with-local-disks' => 1,
891 targetstorage
=> 'local-lvm:local-zfs,local-dir:local-dir',
893 expected_calls
=> $default_expected_calls_online,
897 'local-zfs:vm-149-disk-10' => 1,
898 'local-dir:149/vm-149-disk-11.qcow2' => 1,
900 vm_config
=> get_patched_config
(149, {
901 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
902 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
906 runningmachine
=> 'pc-q35-5.0+pve0',
911 name
=> '149_running_targetstorage_zfs',
916 runningmachine
=> 'pc-q35-5.0+pve0',
920 'with-local-disks' => 1,
921 targetstorage
=> 'local-zfs',
923 expected_calls
=> $default_expected_calls_online,
927 'local-zfs:vm-149-disk-10' => 1,
928 'local-zfs:vm-149-disk-11' => 1,
930 vm_config
=> get_patched_config
(149, {
931 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
932 scsi1
=> 'local-zfs:vm-149-disk-11,format=raw,size=1G',
936 runningmachine
=> 'pc-q35-5.0+pve0',
941 name
=> '149_running_wrong_size',
946 runningmachine
=> 'pc-q35-5.0+pve0',
950 'with-local-disks' => 1,
953 scsi0
=> 'local-lvm:vm-149-disk-0,size=123T',
955 expected_calls
=> $default_expected_calls_online,
959 'local-lvm:vm-149-disk-10' => 1,
960 'local-dir:149/vm-149-disk-11.qcow2' => 1,
962 vm_config
=> get_patched_config
(149, {
963 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
964 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
968 runningmachine
=> 'pc-q35-5.0+pve0',
973 name
=> '149_running_missing_size',
978 runningmachine
=> 'pc-q35-5.0+pve0',
982 'with-local-disks' => 1,
985 scsi0
=> 'local-lvm:vm-149-disk-0',
987 expected_calls
=> $default_expected_calls_online,
991 'local-lvm:vm-149-disk-10' => 1,
992 'local-dir:149/vm-149-disk-11.qcow2' => 1,
994 vm_config
=> get_patched_config
(149, {
995 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
996 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
1000 runningmachine
=> 'pc-q35-5.0+pve0',
1005 name
=> '105_local_device_shared',
1012 ide2
=> '/dev/sde,shared=1',
1014 expected_calls
=> $default_expected_calls_offline,
1016 source_volids
=> {},
1017 target_volids
=> local_volids_for_vm
(105),
1018 vm_config
=> get_patched_config
(105, {
1019 ide2
=> '/dev/sde,shared=1',
1027 name
=> '105_local_device_in_snapshot',
1040 expected_calls
=> {},
1041 expect_die
=> "can't migrate local disk '/dev/sde': local file/device",
1043 source_volids
=> local_volids_for_vm
(105),
1044 target_volids
=> {},
1045 vm_config
=> get_patched_config
(105, {
1058 name
=> '105_local_device',
1067 expected_calls
=> {},
1068 expect_die
=> "can't migrate local disk '/dev/sde': local file/device",
1070 source_volids
=> local_volids_for_vm
(105),
1071 target_volids
=> {},
1072 vm_config
=> get_patched_config
(105, {
1081 name
=> '105_cdrom_in_snapshot',
1090 ide2
=> 'cdrom,media=cdrom',
1094 expected_calls
=> {},
1095 expect_die
=> "can't migrate local cdrom drive (referenced in snapshot - ohsnap",
1097 source_volids
=> local_volids_for_vm
(105),
1098 target_volids
=> {},
1099 vm_config
=> get_patched_config
(105, {
1102 ide2
=> 'cdrom,media=cdrom',
1112 name
=> '105_cdrom',
1119 ide2
=> 'cdrom,media=cdrom',
1121 expected_calls
=> {},
1122 expect_die
=> "can't migrate local cdrom drive",
1124 source_volids
=> local_volids_for_vm
(105),
1125 target_volids
=> {},
1126 vm_config
=> get_patched_config
(105, {
1127 ide2
=> 'cdrom,media=cdrom',
1135 name
=> '149_running_missing_option_withlocaldisks',
1140 runningmachine
=> 'pc-q35-5.0+pve0',
1145 expected_calls
=> {},
1146 expect_die
=> "can't live migrate attached local disks without with-local-disks option",
1148 source_volids
=> local_volids_for_vm
(149),
1149 target_volids
=> {},
1150 vm_config
=> $vm_configs->{149},
1153 runningmachine
=> 'pc-q35-5.0+pve0',
1158 name
=> '149_running_missing_option_online',
1163 runningmachine
=> 'pc-q35-5.0+pve0',
1166 'with-local-disks' => 1,
1168 expected_calls
=> {},
1169 expect_die
=> "can't migrate running VM without --online",
1171 source_volids
=> local_volids_for_vm
(149),
1172 target_volids
=> {},
1173 vm_config
=> $vm_configs->{149},
1176 runningmachine
=> 'pc-q35-5.0+pve0',
1181 name
=> '1033_running_customcpu',
1186 runningmachine
=> 'pc-q35-5.0+pve0',
1187 runningcpu
=> 'host,+kvm_pv_eoi,+kvm_pv_unhalt',
1193 cpu
=> 'custom-mycpu',
1195 expected_calls
=> $default_expected_calls_online,
1197 source_volids
=> {},
1198 target_volids
=> {},
1199 vm_config
=> get_patched_config
(1033, {
1200 cpu
=> 'custom-mycpu',
1204 runningmachine
=> 'pc-q35-5.0+pve0',
1205 runningcpu
=> 'host,+kvm_pv_eoi,+kvm_pv_unhalt',
1210 name
=> '105_replicated_to_non_replication_target',
1216 target_volids
=> {},
1217 expected_calls
=> $replicated_expected_calls_offline,
1219 source_volids
=> {},
1220 target_volids
=> local_volids_for_vm
(105),
1221 vm_config
=> $vm_configs->{105},
1228 name
=> '105_running_replicated',
1233 runningmachine
=> 'pc-i440fx-5.0+pve0',
1237 'with-local-disks' => 1,
1239 target_volids
=> local_volids_for_vm
(105),
1240 expected_calls
=> {},
1241 expect_die
=> "online storage migration not possible if snapshot exists",
1243 source_volids
=> local_volids_for_vm
(105),
1244 target_volids
=> local_volids_for_vm
(105),
1245 vm_config
=> $vm_configs->{105},
1248 runningmachine
=> 'pc-i440fx-5.0+pve0',
1253 name
=> '105_replicated',
1259 target_volids
=> local_volids_for_vm
(105),
1260 expected_calls
=> $replicated_expected_calls_offline,
1262 source_volids
=> local_volids_for_vm
(105),
1263 target_volids
=> local_volids_for_vm
(105),
1264 vm_config
=> $vm_configs->{105},
1271 name
=> '105_running_replicated_without_snapshot',
1276 runningmachine
=> 'pc-i440fx-5.0+pve0',
1283 'with-local-disks' => 1,
1285 target_volids
=> local_volids_for_vm
(105),
1287 %{$replicated_expected_calls_online},
1288 'block-dirty-bitmap-add-drive-scsi0' => 1,
1289 'block-dirty-bitmap-add-drive-ide0' => 1,
1292 source_volids
=> local_volids_for_vm
(105),
1293 target_volids
=> local_volids_for_vm
(105),
1294 vm_config
=> get_patched_config
(105, {
1299 runningmachine
=> 'pc-i440fx-5.0+pve0',
1304 name
=> '105_replicated_without_snapshot',
1316 target_volids
=> local_volids_for_vm
(105),
1317 expected_calls
=> $replicated_expected_calls_offline,
1319 source_volids
=> local_volids_for_vm
(105),
1320 target_volids
=> local_volids_for_vm
(105),
1321 vm_config
=> get_patched_config
(105, {
1330 name
=> '1033_running',
1335 runningmachine
=> 'pc-q35-5.0+pve0',
1340 expected_calls
=> $default_expected_calls_online,
1342 source_volids
=> {},
1343 target_volids
=> {},
1344 vm_config
=> $vm_configs->{1033},
1347 runningmachine
=> 'pc-q35-5.0+pve0',
1352 name
=> '149_locked',
1361 expected_calls
=> {},
1362 expect_die
=> "VM is locked",
1364 source_volids
=> local_volids_for_vm
(149),
1365 target_volids
=> {},
1366 vm_config
=> get_patched_config
(149, {
1375 name
=> '149_storage_not_available',
1381 expected_calls
=> {},
1382 expect_die
=> "storage 'local-lvm' is not available on node 'pve2'",
1384 source_volids
=> local_volids_for_vm
(149),
1385 target_volids
=> {},
1386 vm_config
=> $vm_configs->{149},
1393 name
=> '149_running',
1398 runningmachine
=> 'pc-q35-5.0+pve0',
1402 'with-local-disks' => 1,
1404 expected_calls
=> $default_expected_calls_online,
1406 source_volids
=> {},
1408 'local-lvm:vm-149-disk-10' => 1,
1409 'local-dir:149/vm-149-disk-11.qcow2' => 1,
1411 vm_config
=> get_patched_config
(149, {
1412 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
1413 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
1417 runningmachine
=> 'pc-q35-5.0+pve0',
1422 name
=> '149_running_drive_mirror_fail',
1427 runningmachine
=> 'pc-q35-5.0+pve0',
1431 'with-local-disks' => 1,
1433 expected_calls
=> {},
1434 expect_die
=> "qemu_drive_mirror 'scsi1' error",
1436 'qemu_drive_mirror' => 'scsi1',
1439 source_volids
=> local_volids_for_vm
(149),
1440 target_volids
=> {},
1441 vm_config
=> $vm_configs->{149},
1444 runningmachine
=> 'pc-q35-5.0+pve0',
1449 name
=> '149_running_unused_block_job_cancel_fail',
1454 runningmachine
=> 'pc-q35-5.0+pve0',
1458 'with-local-disks' => 1,
1462 unused0
=> 'local-dir:149/vm-149-disk-0.qcow2',
1464 expected_calls
=> {},
1465 expect_die
=> "qemu_drive_mirror_monitor 'cancel' error",
1466 # note that 'cancel' is also used to finish and that's what this test is about
1468 'qemu_drive_mirror_monitor' => 'cancel',
1471 source_volids
=> local_volids_for_vm
(149),
1472 target_volids
=> {},
1473 vm_config
=> get_patched_config
(149, {
1475 unused0
=> 'local-dir:149/vm-149-disk-0.qcow2',
1479 runningmachine
=> 'pc-q35-5.0+pve0',
1484 name
=> '149_offline',
1491 'with-local-disks' => 1,
1493 expected_calls
=> $default_expected_calls_offline,
1495 source_volids
=> {},
1496 target_volids
=> local_volids_for_vm
(149),
1497 vm_config
=> $vm_configs->{149},
1504 name
=> '149_storage_migrate_fail',
1511 'with-local-disks' => 1,
1514 'storage_migrate' => 'local-lvm:vm-149-disk-0',
1516 expected_calls
=> {},
1517 expect_die
=> "storage_migrate 'local-lvm:vm-149-disk-0' error",
1519 source_volids
=> local_volids_for_vm
(149),
1520 target_volids
=> {},
1521 vm_config
=> $vm_configs->{149},
1529 my $single_test_name = shift;
1531 if (defined($single_test_name) && $single_test_name eq 'DUMP_NAMES') {
1533 foreach my $test (@{$tests}) {
1534 $output .= $test->{name
} . ' ';
1540 mkdir $RUN_DIR_PATH;
1542 foreach my $test (@{$tests}) {
1543 my $name = $test->{name
};
1544 next if defined($single_test_name) && $name ne $single_test_name;
1546 my $run_dir = "${RUN_DIR_PATH}/${name}";
1549 file_set_contents
("${run_dir}/replication_config", to_json
($replication_config));
1550 file_set_contents
("${run_dir}/storage_config", to_json
($storage_config));
1551 file_set_contents
("${run_dir}/source_vdisks", to_json
($source_vdisks));
1553 my $expect_die = $test->{expect_die
};
1554 my $expected = $test->{expected
};
1556 my $source_volids = local_volids_for_vm
($test->{vmid
});
1557 my $target_volids = $test->{target_volids
} // {};
1559 my $config_patch = $test->{config_patch
};
1560 my $vm_config = get_patched_config
($test->{vmid
}, $test->{config_patch
});
1562 my $fail_config = $test->{fail_config
} // {};
1563 my $storage_migrate_map = $test->{storage_migrate_map
} // {};
1565 if (my $targetstorage = $test->{opts
}->{targetstorage
}) {
1566 $test->{opts
}->{storagemap
} = PVE
::JSONSchema
::parse_idmap
($targetstorage, 'pve-storage-id');
1569 my $migrate_params = {
1570 target
=> $test->{target
},
1571 vmid
=> $test->{vmid
},
1572 opts
=> $test->{opts
},
1575 file_set_contents
("${run_dir}/nbd_info", to_json
({}));
1576 file_set_contents
("${run_dir}/source_volids", to_json
($source_volids));
1577 file_set_contents
("${run_dir}/target_volids", to_json
($target_volids));
1578 file_set_contents
("${run_dir}/vm_config", to_json
($vm_config));
1579 file_set_contents
("${run_dir}/vm_status", to_json
($test->{vm_status
}));
1580 file_set_contents
("${run_dir}/expected_calls", to_json
($test->{expected_calls
}));
1581 file_set_contents
("${run_dir}/fail_config", to_json
($fail_config));
1582 file_set_contents
("${run_dir}/storage_migrate_map", to_json
($storage_migrate_map));
1583 file_set_contents
("${run_dir}/migrate_params", to_json
($migrate_params));
1585 $ENV{QM_LIB_PATH
} = $QM_LIB_PATH;
1586 $ENV{RUN_DIR_PATH
} = $run_dir;
1587 my $exitcode = run_command
([
1589 "-I${MIGRATE_LIB_PATH}",
1590 "-I${MIGRATE_LIB_PATH}/test",
1591 "${MIGRATE_LIB_PATH}/test/MigrationTest/QemuMigrateMock.pm",
1592 ], noerr
=> 1, errfunc
=> sub {print "#$name - $_[0]\n"} );
1594 if (defined($expect_die) && $exitcode) {
1595 my $log = file_get_contents
("${run_dir}/log");
1596 my @lines = split /\n/, $log;
1599 foreach my $line (@lines) {
1600 $matched = 1 if $line =~ m/^err:.*\Q${expect_die}\E/;
1601 $matched = 1 if $line =~ m/^warn:.*\Q${expect_die}\E/;
1605 note
("expected error message is not present in log");
1607 } elsif (defined($expect_die) && !$exitcode) {
1609 note
("mocked migrate call didn't fail, but it was expected to - check log");
1610 } elsif (!defined($expect_die) && $exitcode) {
1612 note
("mocked migrate call failed, but it was not expected - check log");
1615 my $expected_calls = decode_json
(file_get_contents
("${run_dir}/expected_calls"));
1616 foreach my $call (keys %{$expected_calls}) {
1618 note
("expected call '$call' was not made");
1621 if (!defined($expect_die)) {
1622 my $nbd_info = decode_json
(file_get_contents
("${run_dir}/nbd_info"));
1623 foreach my $drive (keys %{$nbd_info}) {
1625 note
("drive '$drive' was not mirrored");
1630 source_volids
=> decode_json
(file_get_contents
("${run_dir}/source_volids")),
1631 target_volids
=> decode_json
(file_get_contents
("${run_dir}/target_volids")),
1632 vm_config
=> decode_json
(file_get_contents
("${run_dir}/vm_config")),
1633 vm_status
=> decode_json
(file_get_contents
("${run_dir}/vm_status")),
1636 is_deeply
($actual, $expected, $name);