The format is unused in this commit, but will replace the current string-based format of the 'boot' property. It is included since the parameter of bootorder_from_legacy follows it.
Two helper methods are introduced: * bootorder_from_legacy: Parses the legacy format into a hash closer to what the new format represents * get_default_bootdevices: Encapsulates the legacy default behaviour if nothing is specified in the boot order resolve_first_disk is simplified and gets a new $cdrom parameter to control the behaviour of excluding CD-ROMs or instead searching for only them. Signed-off-by: Stefan Reiter <s.rei...@proxmox.com> --- PVE/QemuServer.pm | 130 ++++++++++++++++++++++++++++++++++++++++ PVE/QemuServer/Drive.pm | 11 ++-- 2 files changed, 135 insertions(+), 6 deletions(-) diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index bd59616..cfac03a 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -1091,6 +1091,68 @@ for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) { $confdesc->{"usb$i"} = $usbdesc; } +my $boot_fmt = { + legacy => { + optional => 1, + default_key => 1, + type => 'string', + description => "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)." + . " Deprecated, use 'order=' instead.", + pattern => '[acdn]{1,4}', + format_description => "[acdn]{1,4}", + + # note: this is also the fallback if boot: is not given at all + default => 'cdn', + }, + order => { + optional => 1, + type => 'string', + format => 'pve-qm-bootdev-list', + format_description => "device[;device...]", + description => <<EODESC, +The guest will attempt to boot from devices in the order they appear here. + +Disks, optical drives and passed-through storage USB devices will be directly +booted from, NICs will load PXE, and PCIe devices will either behave like disks +(e.g. NVMe) or load an option ROM (e.g. RAID controller, hardware NIC). + +Note that only devices in this list will be marked as bootable and thus loaded +by the guest firmware (BIOS/UEFI). If you require multiple disks for booting +(e.g. software-raid), you need to specify all of them here. + +Overrides the deprecated 'legacy=[acdn]*' value when given. +EODESC + }, +}; +PVE::JSONSchema::register_format('pve-qm-boot', $boot_fmt); + +PVE::JSONSchema::register_format('pve-qm-bootdev', \&verify_bootdev); +sub verify_bootdev { + my ($dev, $noerr) = @_; + + return $dev if PVE::QemuServer::Drive::is_valid_drivename($dev) && $dev !~ m/^efidisk/; + + my $check = sub { + my ($base) = @_; + return 0 if $dev !~ m/^$base\d+$/; + return 0 if !$confdesc->{$dev}; + return 1; + }; + + return $dev if $check->("net"); + return $dev if $check->("usb"); + return $dev if $check->("hostpci"); + + return undef if $noerr; + die "invalid boot device '$dev'\n"; +} + +sub print_bootorder { + my ($devs) = @_; + my $data = { order => join(';', @$devs) }; + return PVE::JSONSchema::print_property_string($data, $boot_fmt); +} + my $kvm_api_version = 0; sub kvm_version { @@ -7152,6 +7214,74 @@ sub clear_reboot_request { return $res; } +sub bootorder_from_legacy { + my ($conf, $bootcfg) = @_; + + my $boot = $bootcfg->{legacy} || $boot_fmt->{legacy}->{default}; + my $bootindex_hash = {}; + my $i = 1; + foreach my $o (split(//, $boot)) { + $bootindex_hash->{$o} = $i*100; + $i++; + } + + my $bootorder = {}; + + PVE::QemuConfig->foreach_volume($conf, sub { + my ($ds, $drive) = @_; + + if (drive_is_cdrom ($drive, 1)) { + if ($bootindex_hash->{d}) { + $bootorder->{$ds} = $bootindex_hash->{d}; + $bootindex_hash->{d} += 1; + } + } elsif ($bootindex_hash->{c}) { + $bootorder->{$ds} = $bootindex_hash->{c} + if $conf->{bootdisk} && $conf->{bootdisk} eq $ds; + $bootindex_hash->{c} += 1; + } + }); + + if ($bootindex_hash->{n}) { + for (my $i = 0; $i < $MAX_NETS; $i++) { + my $netname = "net$i"; + next if !$conf->{$netname}; + $bootorder->{$netname} = $bootindex_hash->{n}; + $bootindex_hash->{n} += 1; + } + } + + return $bootorder; +} + +# Generate default device list for 'boot: order=' property. Matches legacy +# default boot order, but with explicit device names. This is important, since +# the fallback for when neither 'order' nor the old format is specified relies +# on 'bootorder_from_legacy' above, and it would be confusing if this diverges. +sub get_default_bootdevices { + my ($conf) = @_; + + my @ret = (); + + # harddisk + my $first = PVE::QemuServer::Drive::resolve_first_disk($conf, 0); + push @ret, $first if $first; + + # cdrom + $first = PVE::QemuServer::Drive::resolve_first_disk($conf, 1); + push @ret, $first if $first; + + # network + for (my $i = 0; $i < $MAX_NETS; $i++) { + my $netname = "net$i"; + next if !$conf->{$netname}; + push @ret, $netname; + last; + } + + return \@ret; +} + # bash completion helper sub complete_backup_archives { diff --git a/PVE/QemuServer/Drive.pm b/PVE/QemuServer/Drive.pm index 91c33f8..b71fc93 100644 --- a/PVE/QemuServer/Drive.pm +++ b/PVE/QemuServer/Drive.pm @@ -584,16 +584,15 @@ sub is_volume_in_use { } sub resolve_first_disk { - my $conf = shift; + my ($conf, $cdrom) = @_; my @disks = valid_drive_names(); - my $firstdisk; - foreach my $ds (reverse @disks) { + foreach my $ds (@disks) { next if !$conf->{$ds}; my $disk = parse_drive($ds, $conf->{$ds}); - next if drive_is_cdrom($disk); - $firstdisk = $ds; + next if drive_is_cdrom($disk) xor $cdrom; + return $ds; } - return $firstdisk; + return undef; } 1; -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel