mirror of
https://git.proxmox.com/git/qemu-server
synced 2025-10-04 17:01:46 +00:00
fix efidisks on storages with minimum sizes bigger than OVMF_VARS.fd
on storages where the minimum size of images is bigger than the real OVMF_VARS.fd file, they get padded to their minimum size when using such an image, qemu maps it fully to the vm, but the efi does not find the vars region and creates a file on the first efi partition it finds this breaks some settings in the ovmf, such as resolution to fix this, we have to specify the size for the pflash, so that qemu only maps the first n bytes in the vm (this only works for raw files, not for qcow2) we also have to use the correct size when converting between storages in 'clone_disk' (used for move disk and cloning vms) and when live migrating to different storages when we now expect that the source image is always correctly used/created (e.g. raw with size=x in pflash argument) then we always create the target correctly when encountering users which have a non-valid image (e.g. a efidisk moved from zfs to qcow2 before this patch), we have to tell them to recreate the efidisk and the settings on it we have to version_guard it to 4.1+pve2 (since we haven't bumped yet since the change to pve2) also add 2 tests, one for the old version and one for the new Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> Tested-by: Stefan Reiter <s.reiter@proxmox.com> Reviewed-by: Stefan Reiter <s.reiter@proxmox.com> [ Thomas: rebased to master ] Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
5c50a84f23
commit
818ce80ec1
@ -2959,7 +2959,7 @@ __PACKAGE__->register_method({
|
|||||||
|
|
||||||
my $newdrive = PVE::QemuServer::clone_disk($storecfg, $vmid, $running, $opt, $drive, $snapname,
|
my $newdrive = PVE::QemuServer::clone_disk($storecfg, $vmid, $running, $opt, $drive, $snapname,
|
||||||
$newid, $storage, $format, $fullclone->{$opt}, $newvollist,
|
$newid, $storage, $format, $fullclone->{$opt}, $newvollist,
|
||||||
$jobs, $completion, $oldconf->{agent}, $clonelimit);
|
$jobs, $completion, $oldconf->{agent}, $clonelimit, $oldconf);
|
||||||
|
|
||||||
$newconf->{$opt} = PVE::QemuServer::print_drive($newdrive);
|
$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 $movelimit = PVE::Storage::get_bandwidth_limit('move', [$oldstoreid, $storeid], $bwlimit);
|
||||||
|
|
||||||
my $newdrive = PVE::QemuServer::clone_disk($storecfg, $vmid, $running, $disk, $drive, undef,
|
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);
|
$conf->{$disk} = PVE::QemuServer::print_drive($newdrive);
|
||||||
|
|
||||||
|
@ -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);
|
$self->log('info', "copying local disk images") if scalar(%$local_volumes);
|
||||||
|
|
||||||
foreach my $volid (keys %$local_volumes) {
|
foreach my $volid (keys %$local_volumes) {
|
||||||
|
@ -3051,8 +3051,14 @@ sub config_to_command {
|
|||||||
$format = 'raw';
|
$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=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
|
# load q35 config
|
||||||
@ -6732,7 +6738,7 @@ sub qemu_blockjobs_cancel {
|
|||||||
|
|
||||||
sub clone_disk {
|
sub clone_disk {
|
||||||
my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
|
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;
|
my $newvolid;
|
||||||
|
|
||||||
@ -6755,6 +6761,8 @@ sub clone_disk {
|
|||||||
$name .= ".$dst_format" if $dst_format ne 'raw';
|
$name .= ".$dst_format" if $dst_format ne 'raw';
|
||||||
$snapname = undef;
|
$snapname = undef;
|
||||||
$size = PVE::QemuServer::Cloudinit::CLOUDINIT_DISK_SIZE;
|
$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));
|
$newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $dst_format, $name, ($size/1024));
|
||||||
push @$newvollist, $newvolid;
|
push @$newvollist, $newvolid;
|
||||||
@ -6768,7 +6776,16 @@ sub clone_disk {
|
|||||||
my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
|
my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
|
||||||
if (!$running || $snapname) {
|
if (!$running || $snapname) {
|
||||||
# TODO: handle bwlimits
|
# 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 {
|
} else {
|
||||||
|
|
||||||
my $kvmver = get_running_qemu_version ($vmid);
|
my $kvmver = get_running_qemu_version ($vmid);
|
||||||
@ -6820,6 +6837,26 @@ sub qemu_use_old_bios_files {
|
|||||||
return ($use_old_bios_files, $machine_type);
|
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($$$$$) {
|
sub create_efidisk($$$$$) {
|
||||||
my ($storecfg, $storeid, $vmid, $fmt, $arch) = @_;
|
my ($storecfg, $storeid, $vmid, $fmt, $arch) = @_;
|
||||||
|
|
||||||
|
5
test/cfg2cmd/efi-raw-old.conf
Normal file
5
test/cfg2cmd/efi-raw-old.conf
Normal file
@ -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
|
26
test/cfg2cmd/efi-raw-old.conf.cmd
Normal file
26
test/cfg2cmd/efi-raw-old.conf.cmd
Normal file
@ -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'
|
4
test/cfg2cmd/efi-raw.conf
Normal file
4
test/cfg2cmd/efi-raw.conf
Normal file
@ -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
|
26
test/cfg2cmd/efi-raw.conf.cmd
Normal file
26
test/cfg2cmd/efi-raw.conf.cmd
Normal file
@ -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'
|
Loading…
Reference in New Issue
Block a user