]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer.pm
add some comments for legacy 2MB OVMF image builds
[qemu-server.git] / PVE / QemuServer.pm
index 052835624c48c522f4cbe3e1dca70bc0140c97e5..9811eba19106f570ba28aac8d40d4b2e8f6d58b9 100644 (file)
@@ -49,15 +49,16 @@ use PVE::Tools qw(run_command file_read_firstline file_get_contents dir_glob_for
 
 use PVE::QMPClient;
 use PVE::QemuConfig;
-use PVE::QemuServer::Helpers qw(min_version config_aware_timeout windows_version);
+use PVE::QemuServer::Helpers qw(config_aware_timeout min_version windows_version);
 use PVE::QemuServer::Cloudinit;
 use PVE::QemuServer::CGroup;
 use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options);
 use PVE::QemuServer::Drive qw(is_valid_drivename drive_is_cloudinit drive_is_cdrom drive_is_read_only parse_drive print_drive);
 use PVE::QemuServer::Machine;
-use PVE::QemuServer::Memory;
+use PVE::QemuServer::Memory qw(get_current_memory);
 use PVE::QemuServer::Monitor qw(mon_cmd);
 use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port parse_hostpci);
+use PVE::QemuServer::QMPHelpers qw(qemu_deviceadd qemu_devicedel qemu_objectadd qemu_objectdel);
 use PVE::QemuServer::USB;
 
 my $have_sdn;
@@ -85,6 +86,9 @@ my $OVMF = {
            "$EDK2_FW_BASE/OVMF_CODE_4M.secboot.fd",
            "$EDK2_FW_BASE/OVMF_VARS_4M.ms.fd",
        ],
+       # FIXME: These are legacy 2MB-sized images that modern OVMF doesn't supports to build
+       # anymore. how can we deperacate this sanely without breaking existing instances, or using
+       # older backups and snapshot?
        default => [
            "$EDK2_FW_BASE/OVMF_CODE.fd",
            "$EDK2_FW_BASE/OVMF_VARS.fd",
@@ -349,11 +353,9 @@ my $confdesc = {
     },
     memory => {
        optional => 1,
-       type => 'integer',
-       description => "Amount of RAM for the VM in MiB. This is the maximum available memory when"
-           ." you use the balloon device.",
-       minimum => 16,
-       default => 512,
+       type => 'string',
+       description => "Memory properties.",
+       format => $PVE::QemuServer::Memory::memory_fmt
     },
     balloon => {
        optional => 1,
@@ -842,44 +844,9 @@ while (my ($k, $v) = each %$confdesc) {
 my $MAX_NETS = 32;
 my $MAX_SERIAL_PORTS = 4;
 my $MAX_PARALLEL_PORTS = 3;
-my $MAX_NUMA = 8;
-
-my $numa_fmt = {
-    cpus => {
-       type => "string",
-       pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
-       description => "CPUs accessing this NUMA node.",
-       format_description => "id[-id];...",
-    },
-    memory => {
-       type => "number",
-       description => "Amount of memory this NUMA node provides.",
-       optional => 1,
-    },
-    hostnodes => {
-       type => "string",
-       pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
-       description => "Host NUMA nodes to use.",
-       format_description => "id[-id];...",
-       optional => 1,
-    },
-    policy => {
-       type => 'string',
-       enum => [qw(preferred bind interleave)],
-       description => "NUMA allocation policy.",
-       optional => 1,
-    },
-};
-PVE::JSONSchema::register_format('pve-qm-numanode', $numa_fmt);
-my $numadesc = {
-    optional => 1,
-    type => 'string', format => $numa_fmt,
-    description => "NUMA topology.",
-};
-PVE::JSONSchema::register_standard_option("pve-qm-numanode", $numadesc);
 
-for (my $i = 0; $i < $MAX_NUMA; $i++)  {
-    $confdesc->{"numa$i"} = $numadesc;
+for (my $i = 0; $i < $PVE::QemuServer::Memory::MAX_NUMA; $i++)  {
+    $confdesc->{"numa$i"} = $PVE::QemuServer::Memory::numadesc;
 }
 
 my $nic_model_list = [
@@ -1930,29 +1897,6 @@ sub print_vga_device {
     return "$type,id=${vgaid}${memory}${max_outputs}${pciaddr}${edidoff}";
 }
 
-sub parse_number_sets {
-    my ($set) = @_;
-    my $res = [];
-    foreach my $part (split(/;/, $set)) {
-       if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
-           die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
-           push @$res, [ $1, $2 ];
-       } else {
-           die "invalid range: $part\n";
-       }
-    }
-    return $res;
-}
-
-sub parse_numa {
-    my ($data) = @_;
-
-    my $res = parse_property_string($numa_fmt, $data);
-    $res->{cpus} = parse_number_sets($res->{cpus}) if defined($res->{cpus});
-    $res->{hostnodes} = parse_number_sets($res->{hostnodes}) if defined($res->{hostnodes});
-    return $res;
-}
-
 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
 sub parse_net {
     my ($data, $disable_mac_autogen) = @_;
@@ -2960,8 +2904,7 @@ sub vmstatus {
        $d->{cpus} = $conf->{vcpus} if $conf->{vcpus};
 
        $d->{name} = $conf->{name} || "VM $vmid";
-       $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024)
-           : $defaults->{memory}*(1024*1024);
+       $d->{maxmem} = get_current_memory($conf->{memory})*(1024*1024);
 
        if ($conf->{balloon}) {
            $d->{balloon_min} = $conf->{balloon}*(1024*1024);
@@ -3403,9 +3346,13 @@ sub get_ovmf_files($$$) {
        or die "no OVMF images known for architecture '$arch'\n";
 
     my $type = 'default';
-    if ($arch ne "aarch64" && defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
-       $type = $smm ? "4m" : "4m-no-smm";
-       $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
+    if ($arch eq 'x86_64') {
+       if (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
+           $type = $smm ? "4m" : "4m-no-smm";
+           $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
+       } else {
+           # TODO: log_warn about use of legacy images for x86_64 with Promxox VE 9
+       }
     }
 
     my ($ovmf_code, $ovmf_vars) = $types->{$type}->@*;
@@ -3906,7 +3853,7 @@ sub config_to_command {
     }
 
     PVE::QemuServer::Memory::config(
-       $conf, $vmid, $sockets, $cores, $defaults, $hotplug_features->{memory}, $cmd);
+       $conf, $vmid, $sockets, $cores, $hotplug_features->{memory}, $cmd);
 
     push @$cmd, '-S' if $conf->{freeze};
 
@@ -4435,21 +4382,6 @@ sub qemu_spice_usbredir_chardev_add {
     ));
 }
 
-sub qemu_deviceadd {
-    my ($vmid, $devicefull) = @_;
-
-    $devicefull = "driver=".$devicefull;
-    my %options =  split(/[=,]/, $devicefull);
-
-    mon_cmd($vmid, "device_add" , %options);
-}
-
-sub qemu_devicedel {
-    my ($vmid, $deviceid) = @_;
-
-    my $ret = mon_cmd($vmid, "device_del", id => $deviceid);
-}
-
 sub qemu_iothread_add {
     my ($vmid, $deviceid, $device) = @_;
 
@@ -4468,22 +4400,6 @@ sub qemu_iothread_del {
     }
 }
 
-sub qemu_objectadd {
-    my ($vmid, $objectid, $qomtype) = @_;
-
-    mon_cmd($vmid, "object-add", id => $objectid, "qom-type" => $qomtype);
-
-    return 1;
-}
-
-sub qemu_objectdel {
-    my ($vmid, $objectid) = @_;
-
-    mon_cmd($vmid, "object-del", id => $objectid);
-
-    return 1;
-}
-
 sub qemu_driveadd {
     my ($storecfg, $vmid, $device) = @_;
 
@@ -5052,7 +4968,7 @@ sub vmconfig_hotplug_pending {
        my $force = $pending_delete_hash->{$opt}->{force};
        eval {
            if ($opt eq 'hotplug') {
-               die "skip\n" if ($conf->{hotplug} =~ /memory/);
+               die "skip\n" if ($conf->{hotplug} =~ /(cpu|memory)/);
            } elsif ($opt eq 'tablet') {
                die "skip\n" if !$hotplug_features->{usb};
                if ($defaults->{tablet}) {
@@ -5075,7 +4991,7 @@ sub vmconfig_hotplug_pending {
                # enable balloon device is not hotpluggable
                die "skip\n" if defined($conf->{balloon}) && $conf->{balloon} == 0;
                # here we reset the ballooning value to memory
-               my $balloon = $conf->{memory} || $defaults->{memory};
+               my $balloon = get_current_memory($conf->{memory});
                mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
            } elsif ($fast_plug_option->{$opt}) {
                # do nothing
@@ -5088,7 +5004,7 @@ sub vmconfig_hotplug_pending {
                vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
            } elsif ($opt =~ m/^memory$/) {
                die "skip\n" if !$hotplug_features->{memory};
-               PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults);
+               PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf);
            } elsif ($opt eq 'cpuunits') {
                $cgroup->change_cpu_shares(undef);
            } elsif ($opt eq 'cpulimit') {
@@ -5113,6 +5029,7 @@ sub vmconfig_hotplug_pending {
        eval {
            if ($opt eq 'hotplug') {
                die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
+               die "skip\n" if ($value =~ /cpu/) || ($value !~ /cpu/ && $conf->{hotplug} =~ /cpu/);
            } elsif ($opt eq 'tablet') {
                die "skip\n" if !$hotplug_features->{usb};
                if ($value == 1) {
@@ -5143,7 +5060,8 @@ sub vmconfig_hotplug_pending {
 
                # allow manual ballooning if shares is set to zero
                if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
-                   my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
+                   my $memory = get_current_memory($conf->{memory});
+                   my $balloon = $conf->{pending}->{balloon} || $memory;
                    mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
                }
            } elsif ($opt =~ m/^net(\d+)$/) {
@@ -5163,7 +5081,7 @@ sub vmconfig_hotplug_pending {
                                     $vmid, $opt, $value, $arch, $machine_type);
            } elsif ($opt =~ m/^memory$/) { #dimms
                die "skip\n" if !$hotplug_features->{memory};
-               $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $value);
+               $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $value);
            } elsif ($opt eq 'cpuunits') {
                my $new_cpuunits = PVE::CGroup::clamp_cpu_shares($conf->{pending}->{$opt}); #clamp
                $cgroup->change_cpu_shares($new_cpuunits);
@@ -5828,7 +5746,8 @@ sub vm_start_nolock {
        push @$cmd, '-S';
     }
 
-    my $start_timeout = $params->{timeout} // config_aware_timeout($conf, $resume);
+    my $memory = get_current_memory($conf->{memory});
+    my $start_timeout = $params->{timeout} // config_aware_timeout($conf, $memory, $resume);
 
     my $pci_reserve_list = [];
     for my $device (values $pci_devices->%*) {
@@ -7366,9 +7285,6 @@ sub restore_vma_archive {
 
     $add_pipe->(['vma', 'extract', '-v', '-r', $mapfifo, $readfrom, $tmpdir]);
 
-    my $oldtimeout;
-    my $timeout = 5;
-
     my $devinfo = {}; # info about drives included in backup
     my $virtdev_hash = {}; # info about allocated drives
 
@@ -7462,6 +7378,8 @@ sub restore_vma_archive {
        $fh->close();
     };
 
+    my $oldtimeout;
+
     eval {
        # enable interrupts
        local $SIG{INT} =
@@ -7471,7 +7389,7 @@ sub restore_vma_archive {
            local $SIG{PIPE} = sub { die "interrupted by signal\n"; };
        local $SIG{ALRM} = sub { die "got timeout\n"; };
 
-       $oldtimeout = alarm($timeout);
+       $oldtimeout = alarm(5); # for reading the VMA header - might hang with a corrupted one
 
        my $parser = sub {
            my $line = shift;
@@ -8357,7 +8275,7 @@ sub generate_smbios1_uuid {
 sub nbd_stop {
     my ($vmid) = @_;
 
-    mon_cmd($vmid, 'nbd-server-stop');
+    mon_cmd($vmid, 'nbd-server-stop', timeout => 25);
 }
 
 sub create_reboot_request {
@@ -8587,13 +8505,17 @@ sub complete_migration_storage {
 }
 
 sub vm_is_paused {
-    my ($vmid) = @_;
+    my ($vmid, $include_suspended) = @_;
     my $qmpstatus = eval {
        PVE::QemuConfig::assert_config_exists_on_node($vmid);
        mon_cmd($vmid, "query-status");
     };
     warn "$@\n" if $@;
-    return $qmpstatus && $qmpstatus->{status} eq "paused";
+    return $qmpstatus && (
+       $qmpstatus->{status} eq "paused" ||
+       $qmpstatus->{status} eq "prelaunch" ||
+       ($include_suspended && $qmpstatus->{status} eq "suspended")
+    );
 }
 
 sub check_volume_storage_type {
@@ -8631,9 +8553,9 @@ sub add_nets_bridge_fdb {
            next;
        }
        if ($have_sdn) {
-           PVE::Network::SDN::Zones::add_bridge_fdb($iface, $mac, $bridge, $net->{firewall});
+           PVE::Network::SDN::Zones::add_bridge_fdb($iface, $mac, $bridge);
        } elsif (-d "/sys/class/net/$bridge/bridge") { # avoid fdb management with OVS for now
-           PVE::Network::add_bridge_fdb($iface, $mac, $net->{firewall});
+           PVE::Network::add_bridge_fdb($iface, $mac);
        }
     }
 }
@@ -8650,9 +8572,9 @@ sub del_nets_bridge_fdb {
 
        my $bridge = $net->{bridge};
        if ($have_sdn) {
-           PVE::Network::SDN::Zones::del_bridge_fdb($iface, $mac, $bridge, $net->{firewall});
+           PVE::Network::SDN::Zones::del_bridge_fdb($iface, $mac, $bridge);
        } elsif (-d "/sys/class/net/$bridge/bridge") { # avoid fdb management with OVS for now
-           PVE::Network::del_bridge_fdb($iface, $mac, $net->{firewall});
+           PVE::Network::del_bridge_fdb($iface, $mac);
        }
     }
 }