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',
134 'bootdisk' => 'scsi0',
136 'ide0' => 'local-lvm:vm-111-disk-0,size=4096M',
137 'ide2' => 'none,media=cdrom',
139 'name' => 'pending-test',
140 'net0' => 'virtio=4A:A3:E4:4C:CF:F0,bridge=vmbr0,firewall=1',
144 'scsi0' => 'local-zfs:vm-111-disk-0,size=103M',
146 'scsihw' => 'virtio-scsi-pci',
148 'smbios1' => 'uuid=5ad71d4d-8f73-4377-853e-2d22c10c96a5',
150 'vmgenid' => '2c00c030-0b5b-4988-a371-6ab259893f22',
154 'bootdisk' => 'scsi0',
156 'hotplug' => 'disk,network,usb,memory,cpu',
157 'ide2' => 'none,media=cdrom',
160 'net0' => 'virtio=52:5D:7E:62:85:97,bridge=vmbr1',
163 'scsi0' => 'local-lvm:vm-149-disk-0,format=raw,size=4G',
164 'scsi1' => 'local-dir:149/vm-149-disk-0.qcow2,format=qcow2,size=1G',
165 'scsihw' => 'virtio-scsi-pci',
167 'smbios1' => 'uuid=e980bd43-a405-42e2-b5f4-31efe6517460',
169 'startup' => 'order=2',
170 'vmgenid' => '36c6c50c-6ef5-4adc-9b6f-6ba9c8071db0',
174 'bootdisk' => 'scsi0',
176 'efidisk0' => 'local-lvm:vm-341-disk-0',
177 'ide2' => 'none,media=cdrom',
178 'ipconfig0' => 'ip=103.214.69.10/25,gw=103.214.69.1',
181 'net0' => 'virtio=4E:F1:82:6D:D7:4B,bridge=vmbr0,firewall=1,rate=10',
184 'scsi0' => 'rbd-store:vm-341-disk-0,size=1G',
185 'scsihw' => 'virtio-scsi-pci',
187 'smbios1' => 'uuid=e01e4c73-46f1-47c8-af79-288fdf6b7462',
189 'vmgenid' => 'af47c000-eb0c-48e8-8991-ca4593cd6916',
192 'bootdisk' => 'scsi0',
194 'ide0' => 'rbd-store:vm-1033-cloudinit,media=cdrom,size=4M',
195 'ide2' => 'none,media=cdrom',
196 'ipconfig0' => 'ip=103.214.69.10/25,gw=103.214.69.1',
199 'net0' => 'virtio=4E:F1:82:6D:D7:4B,bridge=vmbr0,firewall=1,rate=10',
202 'scsi0' => 'rbd-store:vm-1033-disk-1,size=1G',
203 'scsihw' => 'virtio-scsi-pci',
205 'smbios1' => 'uuid=e01e4c73-46f1-47c8-af79-288fdf6b7462',
207 'vmgenid' => 'af47c000-eb0c-48e8-8991-ca4593cd6916',
210 'bootdisk' => 'scsi0',
212 'ide2' => 'none,media=cdrom',
215 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
220 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
221 'scsihw' => 'virtio-scsi-pci',
222 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
225 'bootdisk' => 'scsi0',
227 'ide2' => 'none,media=cdrom',
230 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
233 'runningcpu' => 'kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep',
234 'runningmachine' => 'pc-i440fx-5.0+pve0',
235 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
236 'scsihw' => 'virtio-scsi-pci',
237 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
238 'snaptime' => 1595928799,
240 'startup' => 'order=2',
241 'vmgenid' => '932b227a-8a39-4ede-955a-dbd4bc4385ed',
242 'vmstate' => 'local-dir:4567/vm-4567-state-snap1.raw',
245 'bootdisk' => 'scsi0',
247 'ide2' => 'none,media=cdrom',
250 'net0' => 'virtio=A6:D1:F1:EB:7B:C2,bridge=vmbr0,firewall=1',
254 'runningcpu' => 'kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep',
255 'runningmachine' => 'pc-i440fx-5.0+pve0',
256 'scsi0' => 'local-dir:4567/vm-4567-disk-0.qcow2,size=4G',
257 'scsi1' => 'local-zfs:vm-4567-disk-0,size=1G',
258 'scsihw' => 'virtio-scsi-pci',
259 'smbios1' => 'uuid=2925fdec-a066-4228-b46b-eef8662f5e74',
260 'snaptime' => 1595928871,
262 'startup' => 'order=2',
263 'vmgenid' => '932b227a-8a39-4ede-955a-dbd4bc4385ed',
264 'vmstate' => 'local-dir:4567/vm-4567-state-snap2.raw',
268 'startup' => 'order=2',
269 'unused0' => 'local-zfs:vm-4567-disk-0',
270 'vmgenid' => 'e698e60c-9278-4dd9-941f-416075383f2a',
274 my $source_vdisks = {
277 'ctime' => 1589439681,
280 'size' => 1073741824,
283 'volid' => 'local-dir:149/vm-149-disk-0.qcow2',
286 'ctime' => 1595928898,
289 'size' => 4294967296,
290 'used' => 1811664896,
292 'volid' => 'local-dir:4567/vm-4567-disk-0.qcow2',
295 'ctime' => 1595928800,
301 'volid' => 'local-dir:4567/vm-4567-state-snap1.raw',
304 'ctime' => 1595928872,
310 'volid' => 'local-dir:4567/vm-4567-state-snap2.raw',
315 'ctime' => '1589277334',
317 'size' => 4294967296,
319 'volid' => 'local-lvm:vm-149-disk-0',
322 'ctime' => '1589277334',
326 'volid' => 'local-lvm:vm-341-disk-0',
329 'ctime' => '1589277334',
331 'size' => 4294967296,
333 'volid' => 'local-lvm:vm-111-disk-0',
338 'ctime' => '1589277334',
340 'size' => 4294967296,
342 'volid' => 'local-zfs:vm-105-disk-0',
345 'ctime' => '1589277334',
349 'volid' => 'local-zfs:vm-105-disk-1',
352 'ctime' => '1589277334',
356 'volid' => 'local-zfs:vm-111-disk-0',
360 'name' => 'vm-4567-disk-0',
362 'size' => 1073741824,
364 'volid' => 'local-zfs:vm-4567-disk-0',
369 'ctime' => '1589277334',
371 'size' => 1073741824,
373 'volid' => 'rbd-store:vm-1033-disk-1',
376 'ctime' => '1589277334',
378 'size' => 1073741824,
380 'volid' => 'rbd-store:vm-1033-cloudinit',
385 my $default_expected_calls_online = {
386 move_config_to_node
=> 1,
391 my $default_expected_calls_offline = {
392 move_config_to_node
=> 1,
395 my $replicated_expected_calls_online = {
396 %{$default_expected_calls_online},
397 transfer_replication_state
=> 1,
398 switch_replication_job_target
=> 1,
401 my $replicated_expected_calls_offline = {
402 %{$default_expected_calls_offline},
403 transfer_replication_state
=> 1,
404 switch_replication_job_target
=> 1,
409 sub get_patched_config
{
410 my ($vmid, $patch) = @_;
412 my $new_config = { %{$vm_configs->{$vmid}} };
413 patch_config
($new_config, $patch) if defined($patch);
419 my ($config, $patch) = @_;
421 foreach my $key (keys %{$patch}) {
422 if ($key eq 'snapshots' && defined($patch->{$key})) {
423 my $new_snapshot_configs = {};
424 foreach my $snap (keys %{$patch->{snapshots
}}) {
425 my $new_snapshot_config = { %{$config->{snapshots
}->{$snap}} };
426 patch_config
($new_snapshot_config, $patch->{snapshots
}->{$snap});
427 $new_snapshot_configs->{$snap} = $new_snapshot_config;
429 $config->{snapshots
} = $new_snapshot_configs;
430 } elsif (defined($patch->{$key})) {
431 $config->{$key} = $patch->{$key};
432 } else { # use undef value for deletion
433 delete $config->{$key};
438 sub local_volids_for_vm
{
442 foreach my $storeid (keys %{$source_vdisks}) {
443 next if $storage_config->{ids
}->{$storeid}->{shared
};
446 map { $_->{vmid
} eq $vmid ?
($_->{volid
} => 1) : () } @{$source_vdisks->{$storeid}}
453 # each test consists of the following:
454 # name - unique name for the test which also serves as a dir name.
455 # NOTE: gets passed to make, so don't use whitespace or slash
456 # and adapt buildsys (regex) on code structure changes
457 # target - hostname of target node
458 # vmid - ID of the VM to migrate
459 # opts - options for the migrate() call
460 # target_volids - hash of volids on the target at the beginning
461 # vm_status - hash with running, runningmachine and optionally runningcpu
462 # expected_calls - hash whose keys are calls which are required
463 # to be made if the migration gets far enough
464 # expect_die - expect the migration call to fail, and an error message
465 # matching the specified text in the log
466 # expected - hash consisting of:
467 # source_volids - hash of volids expected on the source
468 # target_volids - hash of volids expected on the target
469 # vm_config - vm configuration hash
470 # vm_status - hash with running, runningmachine and optionally runningcpu
472 # NOTE get_efivars_size is mocked and returns 128K
473 name
=> '341_running_efidisk_targetstorage_dir',
478 runningmachine
=> 'pc-q35-5.0+pve0',
482 'with-local-disks' => 1,
483 targetstorage
=> 'local-dir',
485 expected_calls
=> $default_expected_calls_online,
489 'local-dir:341/vm-341-disk-10.raw' => 1,
491 vm_config
=> get_patched_config
(341, {
492 efidisk0
=> 'local-dir:341/vm-341-disk-10.raw,format=raw,size=128K',
496 runningmachine
=> 'pc-q35-5.0+pve0',
501 # NOTE get_efivars_size is mocked and returns 128K
502 name
=> '341_running_efidisk',
507 runningmachine
=> 'pc-q35-5.0+pve0',
511 'with-local-disks' => 1,
513 expected_calls
=> $default_expected_calls_online,
517 'local-lvm:vm-341-disk-10' => 1,
519 vm_config
=> get_patched_config
(341, {
520 efidisk0
=> 'local-lvm:vm-341-disk-10,format=raw,size=128K',
524 runningmachine
=> 'pc-q35-5.0+pve0',
529 name
=> '149_running_vdisk_alloc_and_pvesm_free_fail',
534 runningmachine
=> 'pc-q35-5.0+pve0',
538 'with-local-disks' => 1,
541 vdisk_alloc
=> 'local-dir:149/vm-149-disk-11.qcow2',
542 pvesm_free
=> 'local-lvm:vm-149-disk-10',
544 expected_calls
=> {},
545 expect_die
=> "remote command failed with exit code",
547 source_volids
=> local_volids_for_vm
(149),
549 'local-lvm:vm-149-disk-10' => 1,
551 vm_config
=> $vm_configs->{149},
554 runningmachine
=> 'pc-q35-5.0+pve0',
559 name
=> '149_running_vdisk_alloc_fail',
564 runningmachine
=> 'pc-q35-5.0+pve0',
568 'with-local-disks' => 1,
571 vdisk_alloc
=> 'local-lvm:vm-149-disk-10',
573 expected_calls
=> {},
574 expect_die
=> "remote command failed with exit code",
576 source_volids
=> local_volids_for_vm
(149),
578 vm_config
=> $vm_configs->{149},
581 runningmachine
=> 'pc-q35-5.0+pve0',
586 name
=> '149_vdisk_free_fail',
593 'with-local-disks' => 1,
596 'vdisk_free' => 'local-lvm:vm-149-disk-0',
598 expected_calls
=> $default_expected_calls_offline,
599 expect_die
=> "vdisk_free 'local-lvm:vm-149-disk-0' error",
602 'local-lvm:vm-149-disk-0' => 1,
604 target_volids
=> local_volids_for_vm
(149),
605 vm_config
=> $vm_configs->{149},
612 name
=> '105_replicated_run_replication_fail',
618 target_volids
=> local_volids_for_vm
(105),
620 run_replication
=> 1,
622 expected_calls
=> {},
623 expect_die
=> 'run_replication error',
625 source_volids
=> local_volids_for_vm
(105),
626 target_volids
=> local_volids_for_vm
(105),
627 vm_config
=> $vm_configs->{105},
634 name
=> '1033_running_query_migrate_fail',
639 runningmachine
=> 'pc-q35-5.0+pve0',
645 'query-migrate' => 1,
647 expected_calls
=> {},
648 expect_die
=> 'online migrate failure - aborting',
652 vm_config
=> $vm_configs->{1033},
655 runningmachine
=> 'pc-q35-5.0+pve0',
660 name
=> '4567_targetstorage_dirotherdir',
667 targetstorage
=> 'local-dir:other-dir,local-zfs:local-zfs',
669 storage_migrate_map
=> {
670 'local-dir:4567/vm-4567-disk-0.qcow2' => '4567/vm-4567-disk-0.qcow2',
671 'local-dir:4567/vm-4567-state-snap1.raw' => '4567/vm-4567-state-snap1.raw',
672 'local-dir:4567/vm-4567-state-snap2.raw' => '4567/vm-4567-state-snap2.raw',
674 expected_calls
=> $default_expected_calls_offline,
678 'other-dir:4567/vm-4567-disk-0.qcow2' => 1,
679 'other-dir:4567/vm-4567-state-snap1.raw' => 1,
680 'other-dir:4567/vm-4567-state-snap2.raw' => 1,
681 'local-zfs:vm-4567-disk-0' => 1,
683 vm_config
=> get_patched_config
(4567, {
684 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
687 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
688 'vmstate' => 'other-dir:4567/vm-4567-state-snap1.raw',
691 'scsi0' => 'other-dir:4567/vm-4567-disk-0.qcow2,size=4G',
692 'scsi1' => 'local-zfs:vm-4567-disk-0,size=1G',
693 'vmstate' => 'other-dir:4567/vm-4567-state-snap2.raw',
703 name
=> '4567_running',
708 runningmachine
=> 'pc-i440fx-5.0+pve0',
712 'with-local-disks' => 1,
714 expected_calls
=> {},
715 expect_die
=> 'online storage migration not possible if non-replicated snapshot exists',
717 source_volids
=> local_volids_for_vm
(4567),
719 vm_config
=> $vm_configs->{4567},
722 runningmachine
=> 'pc-i440fx-5.0+pve0',
727 name
=> '4567_offline',
733 expected_calls
=> $default_expected_calls_offline,
736 target_volids
=> local_volids_for_vm
(4567),
737 vm_config
=> $vm_configs->{4567},
744 name
=> '149_running_orphaned_disk_targetstorage_zfs',
749 runningmachine
=> 'pc-q35-5.0+pve0',
753 'with-local-disks' => 1,
754 targetstorage
=> 'local-zfs',
759 storage_migrate_map
=> {
760 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
762 expected_calls
=> $default_expected_calls_online,
765 'local-dir:149/vm-149-disk-0.qcow2' => 1,
768 'local-zfs:vm-149-disk-10' => 1,
770 vm_config
=> get_patched_config
(149, {
771 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
776 runningmachine
=> 'pc-q35-5.0+pve0',
781 name
=> '149_running_orphaned_disk',
786 runningmachine
=> 'pc-q35-5.0+pve0',
790 'with-local-disks' => 1,
795 storage_migrate_map
=> {
796 'local-dir:149/vm-149-disk-0.qcow2' => '149/vm-149-disk-0.qcow2',
798 expected_calls
=> $default_expected_calls_online,
801 'local-dir:149/vm-149-disk-0.qcow2' => 1,
804 'local-lvm:vm-149-disk-10' => 1,
806 vm_config
=> get_patched_config
(149, {
807 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
812 runningmachine
=> 'pc-q35-5.0+pve0',
817 # FIXME: This test is not (yet) a realistic situation, because
818 # storage_migrate currently never changes the format (AFAICT)
819 # But if such migrations become possible, we need to either update
820 # the 'format' property or simply remove it for drives migrated
821 # with storage_migrate (the property is optional, so it shouldn't be a problem)
822 name
=> '149_targetstorage_map_lvmzfs_defaultlvm',
829 targetstorage
=> 'local-lvm:local-zfs,local-lvm',
831 storage_migrate_map
=> {
832 'local-lvm:vm-149-disk-0' => 'vm-149-disk-0',
833 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
835 expected_calls
=> $default_expected_calls_offline,
839 'local-zfs:vm-149-disk-0' => 1,
840 'local-lvm:vm-149-disk-0' => 1,
842 vm_config
=> get_patched_config
(149, {
843 scsi0
=> 'local-zfs:vm-149-disk-0,format=raw,size=4G',
844 scsi1
=> 'local-lvm:vm-149-disk-0,format=qcow2,size=1G',
852 # FIXME same as for the previous test
853 name
=> '149_targetstorage_map_dirzfs_lvmdir',
861 'with-local-disks' => 1,
862 targetstorage
=> 'local-dir:local-zfs,local-lvm:local-dir',
864 storage_migrate_map
=> {
865 'local-lvm:vm-149-disk-0' => '149/vm-149-disk-0.raw',
866 'local-dir:149/vm-149-disk-0.qcow2' => 'vm-149-disk-0',
868 expected_calls
=> $default_expected_calls_offline,
872 'local-dir:149/vm-149-disk-0.raw' => 1,
873 'local-zfs:vm-149-disk-0' => 1,
875 vm_config
=> get_patched_config
(149, {
876 scsi0
=> 'local-dir:149/vm-149-disk-0.raw,format=raw,size=4G',
877 scsi1
=> 'local-zfs:vm-149-disk-0,format=qcow2,size=1G',
885 name
=> '149_running_targetstorage_map_lvmzfs_defaultlvm',
890 runningmachine
=> 'pc-q35-5.0+pve0',
894 'with-local-disks' => 1,
895 targetstorage
=> 'local-lvm:local-zfs,local-lvm',
897 expected_calls
=> $default_expected_calls_online,
901 'local-zfs:vm-149-disk-10' => 1,
902 'local-lvm:vm-149-disk-11' => 1,
904 vm_config
=> get_patched_config
(149, {
905 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
906 scsi1
=> 'local-lvm:vm-149-disk-11,format=raw,size=1G',
910 runningmachine
=> 'pc-q35-5.0+pve0',
915 name
=> '149_running_targetstorage_map_lvmzfs_dirdir',
920 runningmachine
=> 'pc-q35-5.0+pve0',
924 'with-local-disks' => 1,
925 targetstorage
=> 'local-lvm:local-zfs,local-dir:local-dir',
927 expected_calls
=> $default_expected_calls_online,
931 'local-zfs:vm-149-disk-10' => 1,
932 'local-dir:149/vm-149-disk-11.qcow2' => 1,
934 vm_config
=> get_patched_config
(149, {
935 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
936 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
940 runningmachine
=> 'pc-q35-5.0+pve0',
945 name
=> '149_running_targetstorage_zfs',
950 runningmachine
=> 'pc-q35-5.0+pve0',
954 'with-local-disks' => 1,
955 targetstorage
=> 'local-zfs',
957 expected_calls
=> $default_expected_calls_online,
961 'local-zfs:vm-149-disk-10' => 1,
962 'local-zfs:vm-149-disk-11' => 1,
964 vm_config
=> get_patched_config
(149, {
965 scsi0
=> 'local-zfs:vm-149-disk-10,format=raw,size=4G',
966 scsi1
=> 'local-zfs:vm-149-disk-11,format=raw,size=1G',
970 runningmachine
=> 'pc-q35-5.0+pve0',
975 name
=> '149_running_wrong_size',
980 runningmachine
=> 'pc-q35-5.0+pve0',
984 'with-local-disks' => 1,
987 scsi0
=> 'local-lvm:vm-149-disk-0,size=123T',
989 expected_calls
=> $default_expected_calls_online,
993 'local-lvm:vm-149-disk-10' => 1,
994 'local-dir:149/vm-149-disk-11.qcow2' => 1,
996 vm_config
=> get_patched_config
(149, {
997 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
998 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
1002 runningmachine
=> 'pc-q35-5.0+pve0',
1007 name
=> '149_running_missing_size',
1012 runningmachine
=> 'pc-q35-5.0+pve0',
1016 'with-local-disks' => 1,
1019 scsi0
=> 'local-lvm:vm-149-disk-0',
1021 expected_calls
=> $default_expected_calls_online,
1023 source_volids
=> {},
1025 'local-lvm:vm-149-disk-10' => 1,
1026 'local-dir:149/vm-149-disk-11.qcow2' => 1,
1028 vm_config
=> get_patched_config
(149, {
1029 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
1030 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
1034 runningmachine
=> 'pc-q35-5.0+pve0',
1039 name
=> '105_local_device_shared',
1046 ide2
=> '/dev/sde,shared=1',
1048 expected_calls
=> $default_expected_calls_offline,
1050 source_volids
=> {},
1051 target_volids
=> local_volids_for_vm
(105),
1052 vm_config
=> get_patched_config
(105, {
1053 ide2
=> '/dev/sde,shared=1',
1061 name
=> '105_local_device_in_snapshot',
1074 expected_calls
=> {},
1075 expect_die
=> "can't migrate local disk '/dev/sde': local file/device",
1077 source_volids
=> local_volids_for_vm
(105),
1078 target_volids
=> {},
1079 vm_config
=> get_patched_config
(105, {
1092 name
=> '105_local_device',
1101 expected_calls
=> {},
1102 expect_die
=> "can't migrate local disk '/dev/sde': local file/device",
1104 source_volids
=> local_volids_for_vm
(105),
1105 target_volids
=> {},
1106 vm_config
=> get_patched_config
(105, {
1115 name
=> '105_cdrom_in_snapshot',
1124 ide2
=> 'cdrom,media=cdrom',
1128 expected_calls
=> {},
1129 expect_die
=> "can't migrate local cdrom drive (referenced in snapshot - ohsnap",
1131 source_volids
=> local_volids_for_vm
(105),
1132 target_volids
=> {},
1133 vm_config
=> get_patched_config
(105, {
1136 ide2
=> 'cdrom,media=cdrom',
1146 name
=> '105_cdrom',
1153 ide2
=> 'cdrom,media=cdrom',
1155 expected_calls
=> {},
1156 expect_die
=> "can't migrate local cdrom drive",
1158 source_volids
=> local_volids_for_vm
(105),
1159 target_volids
=> {},
1160 vm_config
=> get_patched_config
(105, {
1161 ide2
=> 'cdrom,media=cdrom',
1169 name
=> '149_running_missing_option_withlocaldisks',
1174 runningmachine
=> 'pc-q35-5.0+pve0',
1179 expected_calls
=> {},
1180 expect_die
=> "can't live migrate attached local disks without with-local-disks option",
1182 source_volids
=> local_volids_for_vm
(149),
1183 target_volids
=> {},
1184 vm_config
=> $vm_configs->{149},
1187 runningmachine
=> 'pc-q35-5.0+pve0',
1192 name
=> '149_running_missing_option_online',
1197 runningmachine
=> 'pc-q35-5.0+pve0',
1200 'with-local-disks' => 1,
1202 expected_calls
=> {},
1203 expect_die
=> "can't migrate running VM without --online",
1205 source_volids
=> local_volids_for_vm
(149),
1206 target_volids
=> {},
1207 vm_config
=> $vm_configs->{149},
1210 runningmachine
=> 'pc-q35-5.0+pve0',
1215 name
=> '1033_running_customcpu',
1220 runningmachine
=> 'pc-q35-5.0+pve0',
1221 runningcpu
=> 'host,+kvm_pv_eoi,+kvm_pv_unhalt',
1227 cpu
=> 'custom-mycpu',
1229 expected_calls
=> $default_expected_calls_online,
1231 source_volids
=> {},
1232 target_volids
=> {},
1233 vm_config
=> get_patched_config
(1033, {
1234 cpu
=> 'custom-mycpu',
1238 runningmachine
=> 'pc-q35-5.0+pve0',
1239 runningcpu
=> 'host,+kvm_pv_eoi,+kvm_pv_unhalt',
1244 name
=> '105_replicated_to_non_replication_target',
1250 target_volids
=> {},
1251 expected_calls
=> $replicated_expected_calls_offline,
1253 source_volids
=> {},
1254 target_volids
=> local_volids_for_vm
(105),
1255 vm_config
=> $vm_configs->{105},
1262 name
=> '105_running_replicated',
1267 runningmachine
=> 'pc-i440fx-5.0+pve0',
1271 'with-local-disks' => 1,
1273 target_volids
=> local_volids_for_vm
(105),
1275 %{$replicated_expected_calls_online},
1276 'block-dirty-bitmap-add-drive-scsi0' => 1,
1277 'block-dirty-bitmap-add-drive-ide0' => 1,
1280 source_volids
=> local_volids_for_vm
(105),
1281 target_volids
=> local_volids_for_vm
(105),
1282 vm_config
=> $vm_configs->{105},
1285 runningmachine
=> 'pc-i440fx-5.0+pve0',
1290 name
=> '105_replicated',
1296 target_volids
=> local_volids_for_vm
(105),
1297 expected_calls
=> $replicated_expected_calls_offline,
1299 source_volids
=> local_volids_for_vm
(105),
1300 target_volids
=> local_volids_for_vm
(105),
1301 vm_config
=> $vm_configs->{105},
1308 name
=> '105_running_replicated_without_snapshot',
1313 runningmachine
=> 'pc-i440fx-5.0+pve0',
1320 'with-local-disks' => 1,
1322 target_volids
=> local_volids_for_vm
(105),
1324 %{$replicated_expected_calls_online},
1325 'block-dirty-bitmap-add-drive-scsi0' => 1,
1326 'block-dirty-bitmap-add-drive-ide0' => 1,
1329 source_volids
=> local_volids_for_vm
(105),
1330 target_volids
=> local_volids_for_vm
(105),
1331 vm_config
=> get_patched_config
(105, {
1336 runningmachine
=> 'pc-i440fx-5.0+pve0',
1341 name
=> '105_replicated_without_snapshot',
1353 target_volids
=> local_volids_for_vm
(105),
1354 expected_calls
=> $replicated_expected_calls_offline,
1356 source_volids
=> local_volids_for_vm
(105),
1357 target_volids
=> local_volids_for_vm
(105),
1358 vm_config
=> get_patched_config
(105, {
1367 name
=> '1033_running',
1372 runningmachine
=> 'pc-q35-5.0+pve0',
1377 expected_calls
=> $default_expected_calls_online,
1379 source_volids
=> {},
1380 target_volids
=> {},
1381 vm_config
=> $vm_configs->{1033},
1384 runningmachine
=> 'pc-q35-5.0+pve0',
1389 name
=> '149_locked',
1398 expected_calls
=> {},
1399 expect_die
=> "VM is locked",
1401 source_volids
=> local_volids_for_vm
(149),
1402 target_volids
=> {},
1403 vm_config
=> get_patched_config
(149, {
1412 name
=> '149_storage_not_available',
1418 expected_calls
=> {},
1419 expect_die
=> "storage 'local-lvm' is not available on node 'pve2'",
1421 source_volids
=> local_volids_for_vm
(149),
1422 target_volids
=> {},
1423 vm_config
=> $vm_configs->{149},
1430 name
=> '149_running',
1435 runningmachine
=> 'pc-q35-5.0+pve0',
1439 'with-local-disks' => 1,
1441 expected_calls
=> $default_expected_calls_online,
1443 source_volids
=> {},
1445 'local-lvm:vm-149-disk-10' => 1,
1446 'local-dir:149/vm-149-disk-11.qcow2' => 1,
1448 vm_config
=> get_patched_config
(149, {
1449 scsi0
=> 'local-lvm:vm-149-disk-10,format=raw,size=4G',
1450 scsi1
=> 'local-dir:149/vm-149-disk-11.qcow2,format=qcow2,size=1G',
1454 runningmachine
=> 'pc-q35-5.0+pve0',
1459 name
=> '149_running_drive_mirror_fail',
1464 runningmachine
=> 'pc-q35-5.0+pve0',
1468 'with-local-disks' => 1,
1470 expected_calls
=> {},
1471 expect_die
=> "qemu_drive_mirror 'scsi1' error",
1473 'qemu_drive_mirror' => 'scsi1',
1476 source_volids
=> local_volids_for_vm
(149),
1477 target_volids
=> {},
1478 vm_config
=> $vm_configs->{149},
1481 runningmachine
=> 'pc-q35-5.0+pve0',
1486 name
=> '149_running_unused_block_job_cancel_fail',
1491 runningmachine
=> 'pc-q35-5.0+pve0',
1495 'with-local-disks' => 1,
1499 unused0
=> 'local-dir:149/vm-149-disk-0.qcow2',
1501 expected_calls
=> {},
1502 expect_die
=> "qemu_drive_mirror_monitor 'cancel' error",
1503 # note that 'cancel' is also used to finish and that's what this test is about
1505 'qemu_drive_mirror_monitor' => 'cancel',
1508 source_volids
=> local_volids_for_vm
(149),
1509 target_volids
=> {},
1510 vm_config
=> get_patched_config
(149, {
1512 unused0
=> 'local-dir:149/vm-149-disk-0.qcow2',
1516 runningmachine
=> 'pc-q35-5.0+pve0',
1521 name
=> '149_offline',
1528 'with-local-disks' => 1,
1530 expected_calls
=> $default_expected_calls_offline,
1532 source_volids
=> {},
1533 target_volids
=> local_volids_for_vm
(149),
1534 vm_config
=> $vm_configs->{149},
1541 name
=> '149_storage_migrate_fail',
1548 'with-local-disks' => 1,
1551 'storage_migrate' => 'local-lvm:vm-149-disk-0',
1553 expected_calls
=> {},
1554 expect_die
=> "storage_migrate 'local-lvm:vm-149-disk-0' error",
1556 source_volids
=> local_volids_for_vm
(149),
1557 target_volids
=> {},
1558 vm_config
=> $vm_configs->{149},
1565 name
=> '111_running_pending',
1570 runningmachine
=> 'pc-q35-5.0+pve0',
1574 'with-local-disks' => 1,
1576 expected_calls
=> $default_expected_calls_online,
1578 source_volids
=> {},
1580 'local-zfs:vm-111-disk-0' => 1,
1581 'local-lvm:vm-111-disk-10' => 1,
1583 vm_config
=> get_patched_config
(111, {
1584 ide0
=> 'local-lvm:vm-111-disk-10,format=raw,size=4G',
1586 scsi0
=> 'local-zfs:vm-111-disk-0,size=103M',
1591 runningmachine
=> 'pc-q35-5.0+pve0',
1597 my $single_test_name = shift;
1599 mkdir $RUN_DIR_PATH;
1601 foreach my $test (@{$tests}) {
1602 my $name = $test->{name
};
1603 next if defined($single_test_name) && $name ne $single_test_name;
1605 my $run_dir = "${RUN_DIR_PATH}/${name}";
1608 file_set_contents
("${run_dir}/replication_config", to_json
($replication_config));
1609 file_set_contents
("${run_dir}/storage_config", to_json
($storage_config));
1610 file_set_contents
("${run_dir}/source_vdisks", to_json
($source_vdisks));
1612 my $expect_die = $test->{expect_die
};
1613 my $expected = $test->{expected
};
1615 my $source_volids = local_volids_for_vm
($test->{vmid
});
1616 my $target_volids = $test->{target_volids
} // {};
1618 my $config_patch = $test->{config_patch
};
1619 my $vm_config = get_patched_config
($test->{vmid
}, $test->{config_patch
});
1621 my $fail_config = $test->{fail_config
} // {};
1622 my $storage_migrate_map = $test->{storage_migrate_map
} // {};
1624 if (my $targetstorage = $test->{opts
}->{targetstorage
}) {
1625 $test->{opts
}->{storagemap
} = PVE
::JSONSchema
::parse_idmap
($targetstorage, 'pve-storage-id');
1628 my $migrate_params = {
1629 target
=> $test->{target
},
1630 vmid
=> $test->{vmid
},
1631 opts
=> $test->{opts
},
1634 file_set_contents
("${run_dir}/nbd_info", to_json
({}));
1635 file_set_contents
("${run_dir}/source_volids", to_json
($source_volids));
1636 file_set_contents
("${run_dir}/target_volids", to_json
($target_volids));
1637 file_set_contents
("${run_dir}/vm_config", to_json
($vm_config));
1638 file_set_contents
("${run_dir}/vm_status", to_json
($test->{vm_status
}));
1639 file_set_contents
("${run_dir}/expected_calls", to_json
($test->{expected_calls
}));
1640 file_set_contents
("${run_dir}/fail_config", to_json
($fail_config));
1641 file_set_contents
("${run_dir}/storage_migrate_map", to_json
($storage_migrate_map));
1642 file_set_contents
("${run_dir}/migrate_params", to_json
($migrate_params));
1644 $ENV{QM_LIB_PATH
} = $QM_LIB_PATH;
1645 $ENV{RUN_DIR_PATH
} = $run_dir;
1646 my $exitcode = run_command
([
1648 "-I${MIGRATE_LIB_PATH}",
1649 "-I${MIGRATE_LIB_PATH}/test",
1650 "${MIGRATE_LIB_PATH}/test/MigrationTest/QemuMigrateMock.pm",
1651 ], noerr
=> 1, errfunc
=> sub {print "#$name - $_[0]\n"} );
1653 if (defined($expect_die) && $exitcode) {
1654 my $log = file_get_contents
("${run_dir}/log");
1655 my @lines = split /\n/, $log;
1658 foreach my $line (@lines) {
1659 $matched = 1 if $line =~ m/^err:.*\Q${expect_die}\E/;
1660 $matched = 1 if $line =~ m/^warn:.*\Q${expect_die}\E/;
1664 note
("expected error message is not present in log");
1666 } elsif (defined($expect_die) && !$exitcode) {
1668 note
("mocked migrate call didn't fail, but it was expected to - check log");
1669 } elsif (!defined($expect_die) && $exitcode) {
1671 note
("mocked migrate call failed, but it was not expected - check log");
1674 my $expected_calls = decode_json
(file_get_contents
("${run_dir}/expected_calls"));
1675 foreach my $call (keys %{$expected_calls}) {
1677 note
("expected call '$call' was not made");
1680 if (!defined($expect_die)) {
1681 my $nbd_info = decode_json
(file_get_contents
("${run_dir}/nbd_info"));
1682 foreach my $drive (keys %{$nbd_info}) {
1684 note
("drive '$drive' was not mirrored");
1689 source_volids
=> decode_json
(file_get_contents
("${run_dir}/source_volids")),
1690 target_volids
=> decode_json
(file_get_contents
("${run_dir}/target_volids")),
1691 vm_config
=> decode_json
(file_get_contents
("${run_dir}/vm_config")),
1692 vm_status
=> decode_json
(file_get_contents
("${run_dir}/vm_status")),
1695 is_deeply
($actual, $expected, $name);