X-Git-Url: https://git.proxmox.com/?p=qemu-server.git;a=blobdiff_plain;f=PVE%2FQemuServer.pm;h=28e630d30b21891a6c8203c3809c4f436985fc2e;hp=dc0f9c7a33a8bd168a94c36a0c9801e3d9f211d2;hb=HEAD;hpb=eb06e486572b4408ea14afce57ab6b50fe9a8c7e diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index dc0f9c7..5df0c96 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -124,14 +124,6 @@ PVE::JSONSchema::register_standard_option('pve-qm-stateuri', { optional => 1, }); -PVE::JSONSchema::register_standard_option('pve-qemu-machine', { - description => "Specifies the QEMU machine type.", - type => 'string', - pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)', - maxLength => 40, - optional => 1, -}); - # FIXME: remove in favor of just using the INotify one, it's cached there exactly the same way my $nodename_cache; sub nodename { @@ -429,7 +421,7 @@ wvista;; Microsoft Windows Vista win7;; Microsoft Windows 7 win8;; Microsoft Windows 8/2012/2012r2 win10;; Microsoft Windows 10/2016/2019 -win11;; Microsoft Windows 11/2022 +win11;; Microsoft Windows 11/2022/2025 l24;; Linux 2.4 Kernel l26;; Linux 2.6 - 6.X Kernel solaris;; Solaris/OpenSolaris/OpenIndiania kernel @@ -598,7 +590,10 @@ EODESCR migrate_downtime => { optional => 1, type => 'number', - description => "Set maximum tolerated downtime (in seconds) for migrations.", + description => "Set maximum tolerated downtime (in seconds) for migrations. Should the" + ." migration not be able to converge in the very end, because too much newly dirtied" + ." RAM needs to be transferred, the limit will be increased automatically step-by-step" + ." until migration can converge.", minimum => 0, default => 0.1, }, @@ -1413,24 +1408,24 @@ sub print_drivedevice_full { my $unit = $drive->{index} % $maxdev; my $machine_version = extract_version($machine_type, kvm_user_version()); - my $devicetype = PVE::QemuServer::Drive::get_scsi_devicetype( + my $device_type = PVE::QemuServer::Drive::get_scsi_device_type( $drive, $storecfg, $machine_version); if (!$conf->{scsihw} || $conf->{scsihw} =~ m/^lsi/ || $conf->{scsihw} eq 'pvscsi') { - $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit"; + $device = "scsi-$device_type,bus=$controller_prefix$controller.0,scsi-id=$unit"; } else { - $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0" + $device = "scsi-$device_type,bus=$controller_prefix$controller.0,channel=0,scsi-id=0" .",lun=$drive->{index}"; } $device .= ",drive=drive-$drive_id,id=$drive_id"; - if ($drive->{ssd} && ($devicetype eq 'block' || $devicetype eq 'hd')) { + if ($drive->{ssd} && ($device_type eq 'block' || $device_type eq 'hd')) { $device .= ",rotation_rate=1"; } $device .= ",wwn=$drive->{wwn}" if $drive->{wwn}; # only scsi-hd and scsi-cd support passing vendor and product information - if ($devicetype eq 'hd' || $devicetype eq 'cd') { + if ($device_type eq 'hd' || $device_type eq 'cd') { if (my $vendor = $drive->{vendor}) { $device .= ",vendor=$vendor"; } @@ -1454,9 +1449,9 @@ sub print_drivedevice_full { $unit = 0; } - my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd"; + my $device_type = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd"; - $device = "ide-$devicetype"; + $device = "ide-$device_type"; if ($drive->{interface} eq 'ide') { $device .= ",bus=ide.$controller,unit=$unit"; } else { @@ -1464,7 +1459,7 @@ sub print_drivedevice_full { } $device .= ",drive=drive-$drive_id,id=$drive_id"; - if ($devicetype eq 'hd') { + if ($device_type eq 'hd') { if (my $model = $drive->{model}) { $model = URI::Escape::uri_unescape($model); $device .= ",model=$model"; @@ -1804,7 +1799,7 @@ sub print_vga_device { } } - die "no devicetype for $vga->{type}\n" if !$type; + die "no device-type for $vga->{type}\n" if !$type; my $memory = ""; if ($vgamem_mb) { @@ -2102,8 +2097,9 @@ sub qemu_created_version_fixups { # check if we need to apply some handling for VMs that always use the latest machine version but # had a machine version transition happen that affected HW such that, e.g., an OS config change # would be required (we do not want to pin machine version for non-windows OS type) + my $machine_conf = PVE::QemuServer::Machine::parse_machine($conf->{machine}); if ( - (!defined($conf->{machine}) || $conf->{machine} =~ m/^(?:pc|q35|virt)$/) # non-versioned machine + (!defined($machine_conf->{type}) || $machine_conf->{type} =~ m/^(?:pc|q35|virt)$/) # non-versioned machine && (!defined($meta->{'creation-qemu'}) || !min_version($meta->{'creation-qemu'}, 6, 1)) # created before 6.1 && (!$forced_vers || min_version($forced_vers, 6, 1)) # handle snapshot-rollback/migrations && min_version($kvmver, 6, 1) # only need to apply the change since 6.1 @@ -2597,7 +2593,7 @@ sub check_local_resources { foreach my $k (keys %$conf) { if ($k =~ m/^usb/) { my $entry = parse_property_string('pve-qm-usb', $conf->{$k}); - next if $entry->{host} =~ m/^spice$/i; + next if $entry->{host} && $entry->{host} =~ m/^spice$/i; if ($entry->{mapping}) { $add_missing_mapping->('usb', $k, $entry->{mapping}); push @$mapped_res, $k; @@ -3259,7 +3255,8 @@ sub windows_get_pinned_machine_version { sub get_vm_machine { my ($conf, $forcemachine, $arch, $add_pve_version, $kvmversion) = @_; - my $machine = $forcemachine || $conf->{machine}; + my $machine_conf = PVE::QemuServer::Machine::parse_machine($conf->{machine}); + my $machine = $forcemachine || $machine_conf->{type}; if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) { $kvmversion //= kvm_user_version(); @@ -3508,6 +3505,8 @@ sub config_to_command { my $kvm = $conf->{kvm}; my $nodename = nodename(); + my $machine_conf = PVE::QemuServer::Machine::parse_machine($conf->{machine}); + my $arch = get_vm_arch($conf); my $kvm_binary = get_command_for_arch($arch); my $kvmver = kvm_user_version($kvm_binary); @@ -4084,6 +4083,17 @@ sub config_to_command { } push @$machineFlags, "type=${machine_type_min}"; + PVE::QemuServer::Machine::assert_valid_machine_property($conf, $machine_conf); + + if (my $viommu = $machine_conf->{viommu}) { + if ($viommu eq 'intel') { + unshift @$devices, '-device', 'intel-iommu,intremap=on,caching-mode=on'; + push @$machineFlags, 'kernel-irqchip=split'; + } elsif ($viommu eq 'virtio') { + push @$devices, '-device', 'virtio-iommu-pci'; + } + } + push @$cmd, @$devices; push @$cmd, '-rtc', join(',', @$rtcFlags) if scalar(@$rtcFlags); push @$cmd, '-machine', join(',', @$machineFlags) if scalar(@$machineFlags); @@ -6396,7 +6406,8 @@ sub vm_suspend { if ($err) { # cleanup, but leave suspending lock, to indicate something went wrong eval { - mon_cmd($vmid, "savevm-end"); + eval { mon_cmd($vmid, "savevm-end"); }; + warn $@ if $@; PVE::Storage::deactivate_volumes($storecfg, [$vmstate]); PVE::Storage::vdisk_free($storecfg, $vmstate); delete $conf->@{qw(vmstate runningmachine runningcpu)}; @@ -7298,9 +7309,6 @@ sub pbs_live_restore { sub live_import_from_files { my ($mapping, $vmid, $conf, $restore_options) = @_; - die "only live-restore is implemented for restirng from files\n" - if !$restore_options->{live}; - my $live_restore_backing = {}; for my $dev (keys %$mapping) { die "disk not support for live-restoring: '$dev'\n" @@ -8150,7 +8158,8 @@ sub clone_disk { my ($newvmid, $dst_drivename, $efisize) = $dest->@{qw(vmid drivename efisize)}; my ($storage, $format) = $dest->@{qw(storage format)}; - my $use_drive_mirror = $full && $running && $src_drivename && !$snapname; + my $unused = defined($src_drivename) && $src_drivename =~ /^unused/; + my $use_drive_mirror = $full && $running && $src_drivename && !$snapname && !$unused; if ($src_drivename && $dst_drivename && $src_drivename ne $dst_drivename) { die "cloning from/to EFI disk requires EFI disk\n" @@ -8256,7 +8265,7 @@ no_data_clone: my $disk = dclone($drive); delete $disk->{format}; $disk->{file} = $newvolid; - $disk->{size} = $size if defined($size); + $disk->{size} = $size if defined($size) && !$unused; return $disk; }