[pve-devel] [PATCH v2 qemu-server 3/7] add new 'boot' property format and introduce legacy conversion helpers
Stefan Reiter
s.reiter at proxmox.com
Tue Oct 6 15:32:14 CEST 2020
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.reiter at 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
More information about the pve-devel
mailing list