diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index 8a7e98c1..396879a5 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -2959,7 +2959,7 @@ __PACKAGE__->register_method({ my $newdrive = PVE::QemuServer::clone_disk($storecfg, $vmid, $running, $opt, $drive, $snapname, $newid, $storage, $format, $fullclone->{$opt}, $newvollist, - $jobs, $completion, $oldconf->{agent}, $clonelimit); + $jobs, $completion, $oldconf->{agent}, $clonelimit, $oldconf); $newconf->{$opt} = PVE::QemuServer::print_drive($newdrive); @@ -3146,7 +3146,7 @@ __PACKAGE__->register_method({ my $movelimit = PVE::Storage::get_bandwidth_limit('move', [$oldstoreid, $storeid], $bwlimit); my $newdrive = PVE::QemuServer::clone_disk($storecfg, $vmid, $running, $disk, $drive, undef, - $vmid, $storeid, $format, 1, $newvollist, undef, undef, undef, $movelimit); + $vmid, $storeid, $format, 1, $newvollist, undef, undef, undef, $movelimit, $conf); $conf->{$disk} = PVE::QemuServer::print_drive($newdrive); diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm index 64b4c0ec..80978b94 100644 --- a/PVE/QemuMigrate.pm +++ b/PVE/QemuMigrate.pm @@ -508,6 +508,12 @@ sub sync_disks { } }); + # we want to set the efidisk size in the config to the size of the + # real OVMF_VARS.fd image, else we can create a too big image, which does not work + if (defined($conf->{efidisk0})) { + PVE::QemuServer::update_efidisk_size($conf); + } + $self->log('info', "copying local disk images") if scalar(%$local_volumes); foreach my $volid (keys %$local_volumes) { diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 9c9debfd..611fb450 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -3051,8 +3051,14 @@ sub config_to_command { $format = 'raw'; } + my $size_str = ""; + + if ($format eq 'raw' && $version_guard->(4, 1, 2)) { + $size_str = ",size=" . (-s $ovmf_vars); + } + push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$ovmf_code"; - push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path"; + push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0$size_str,file=$path"; } # load q35 config @@ -6732,7 +6738,7 @@ sub qemu_blockjobs_cancel { sub clone_disk { my ($storecfg, $vmid, $running, $drivename, $drive, $snapname, - $newvmid, $storage, $format, $full, $newvollist, $jobs, $completion, $qga, $bwlimit) = @_; + $newvmid, $storage, $format, $full, $newvollist, $jobs, $completion, $qga, $bwlimit, $conf) = @_; my $newvolid; @@ -6755,6 +6761,8 @@ sub clone_disk { $name .= ".$dst_format" if $dst_format ne 'raw'; $snapname = undef; $size = PVE::QemuServer::Cloudinit::CLOUDINIT_DISK_SIZE; + } elsif ($drivename eq 'efidisk0') { + $size = get_efivars_size($conf); } $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $dst_format, $name, ($size/1024)); push @$newvollist, $newvolid; @@ -6768,7 +6776,16 @@ sub clone_disk { my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid); if (!$running || $snapname) { # TODO: handle bwlimits - qemu_img_convert($drive->{file}, $newvolid, $size, $snapname, $sparseinit); + if ($drivename eq 'efidisk0') { + # the relevant data on the efidisk may be smaller than the source + # e.g. on RBD/ZFS, so we use dd to copy only the amount + # that is given by the OVMF_VARS.fd + my $src_path = PVE::Storage::path($storecfg, $drive->{file}); + my $dst_path = PVE::Storage::path($storecfg, $newvolid); + run_command(['qemu-img', 'dd', '-n', '-O', $dst_format, "bs=1", "count=$size", "if=$src_path", "of=$dst_path"]); + } else { + qemu_img_convert($drive->{file}, $newvolid, $size, $snapname, $sparseinit); + } } else { my $kvmver = get_running_qemu_version ($vmid); @@ -6820,6 +6837,26 @@ sub qemu_use_old_bios_files { return ($use_old_bios_files, $machine_type); } +sub get_efivars_size { + my ($conf) = @_; + my $arch = get_vm_arch($conf); + my (undef, $ovmf_vars) = get_ovmf_files($arch); + die "uefi vars image '$ovmf_vars' not found\n" if ! -f $ovmf_vars; + return -s $ovmf_vars; +} + +sub update_efidisk_size { + my ($conf) = @_; + + return if !defined($conf->{efidisk0}); + + my $disk = PVE::QemuServer::parse_drive('efidisk0', $conf->{efidisk0}); + $disk->{size} = get_efivars_size($conf); + $conf->{efidisk0} = print_drive($disk); + + return; +} + sub create_efidisk($$$$$) { my ($storecfg, $storeid, $vmid, $fmt, $arch) = @_; diff --git a/test/cfg2cmd/efi-raw-old.conf b/test/cfg2cmd/efi-raw-old.conf new file mode 100644 index 00000000..549cd250 --- /dev/null +++ b/test/cfg2cmd/efi-raw-old.conf @@ -0,0 +1,5 @@ +# TEST: Test raw efidisk size parameter on old version +smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465 +bios: ovmf +machine: pc-i440fx-4.1+pve1 +efidisk0: local:100/vm-disk-100-0.raw diff --git a/test/cfg2cmd/efi-raw-old.conf.cmd b/test/cfg2cmd/efi-raw-old.conf.cmd new file mode 100644 index 00000000..5526a489 --- /dev/null +++ b/test/cfg2cmd/efi-raw-old.conf.cmd @@ -0,0 +1,26 @@ +/usr/bin/kvm \ + -id 8006 \ + -name vm8006 \ + -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server,nowait' \ + -mon 'chardev=qmp,mode=control' \ + -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect=5' \ + -mon 'chardev=qmp-event,mode=control' \ + -pidfile /var/run/qemu-server/8006.pid \ + -daemonize \ + -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \ + -drive 'if=pflash,unit=0,format=raw,readonly,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \ + -drive 'if=pflash,unit=1,format=raw,id=drive-efidisk0,file=/var/lib/vz/images/100/vm-disk-100-0.raw' \ + -smp '1,sockets=1,cores=1,maxcpus=1' \ + -nodefaults \ + -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \ + -vnc unix:/var/run/qemu-server/8006.vnc,password \ + -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \ + -m 512 \ + -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \ + -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \ + -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \ + -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \ + -device 'VGA,id=vga,bus=pci.0,addr=0x2' \ + -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3' \ + -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \ + -machine 'type=pc-i440fx-4.1+pve0' diff --git a/test/cfg2cmd/efi-raw.conf b/test/cfg2cmd/efi-raw.conf new file mode 100644 index 00000000..11e6a3e6 --- /dev/null +++ b/test/cfg2cmd/efi-raw.conf @@ -0,0 +1,4 @@ +# TEST: Test raw efidisk size parameter +smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465 +bios: ovmf +efidisk0: local:100/vm-disk-100-0.raw diff --git a/test/cfg2cmd/efi-raw.conf.cmd b/test/cfg2cmd/efi-raw.conf.cmd new file mode 100644 index 00000000..a3369327 --- /dev/null +++ b/test/cfg2cmd/efi-raw.conf.cmd @@ -0,0 +1,26 @@ +/usr/bin/kvm \ + -id 8006 \ + -name vm8006 \ + -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server,nowait' \ + -mon 'chardev=qmp,mode=control' \ + -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect=5' \ + -mon 'chardev=qmp-event,mode=control' \ + -pidfile /var/run/qemu-server/8006.pid \ + -daemonize \ + -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \ + -drive 'if=pflash,unit=0,format=raw,readonly,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \ + -drive 'if=pflash,unit=1,format=raw,id=drive-efidisk0,size=131072,file=/var/lib/vz/images/100/vm-disk-100-0.raw' \ + -smp '1,sockets=1,cores=1,maxcpus=1' \ + -nodefaults \ + -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \ + -vnc unix:/var/run/qemu-server/8006.vnc,password \ + -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \ + -m 512 \ + -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \ + -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \ + -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \ + -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \ + -device 'VGA,id=vga,bus=pci.0,addr=0x2' \ + -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3' \ + -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \ + -machine 'type=pc+pve0'