]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer.pm
use machine version in vga default type selection
[qemu-server.git] / PVE / QemuServer.pm
index 0b866cdda406a48ebdbe46a7de5bced74ebdd662..c09168534661b898450d7785f7db5066745a6ab5 100644 (file)
@@ -56,12 +56,6 @@ cfs_register_file('/qemu-server/',
                  \&parse_vm_config,
                  \&write_vm_config);
 
-PVE::JSONSchema::register_standard_option('skiplock', {
-    description => "Ignore locks - only root is allowed to use this option.",
-    type => 'boolean',
-    optional => 1,
-});
-
 PVE::JSONSchema::register_standard_option('pve-qm-stateuri', {
     description => "Some command save/restore state from this location.",
     type => 'string',
@@ -124,6 +118,7 @@ my $cpu_vendor_list = {
     'Haswell-noTSX' => 'GenuineIntel',
     Broadwell => 'GenuineIntel',
     'Broadwell-noTSX' => 'GenuineIntel',
+    'Skylake-Client' => 'GenuineIntel',
     
     # AMD CPUs
     athlon => 'AuthenticAMD',
@@ -752,6 +747,12 @@ my %drivedesc_base = (
        description => "Whether the drive should be included when making backups.",
        optional => 1,
     },
+    rerror => {
+       type => 'string',
+       enum => [qw(ignore report stop)],
+       description => 'Read error action.',
+       optional => 1,
+    },
     werror => {
        type => 'string',
        enum => [qw(enospc ignore report stop)],
@@ -785,15 +786,6 @@ my %drivedesc_base = (
     }
 );
 
-my %rerror_fmt = (
-    rerror => {
-       type => 'string',
-       enum => [qw(ignore report stop)],
-       description => 'Read error action.',
-       optional => 1,
-    },
-);
-
 my %iothread_fmt = ( iothread => {
        type => 'boolean',
        description => "Whether to use iothreads for this drive",
@@ -820,6 +812,15 @@ my %queues_fmt = (
     }
 );
 
+my %scsiblock_fmt = (
+    scsiblock => {
+       type => 'boolean',
+       description => "whether to use scsi-block for full passthrough of host block device\n\nWARNING: can lead to I/O errors in combination with low memory or high memory fragmentation on host",
+       optional => 1,
+       default => 0,
+    },
+);
+
 my $add_throttle_desc = sub {
     my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
     my $d = {
@@ -860,7 +861,6 @@ $add_throttle_desc->('iops_wr_length',  'integer', 'length of write I/O bursts',
 
 my $ide_fmt = {
     %drivedesc_base,
-    %rerror_fmt,
     %model_fmt,
 };
 PVE::JSONSchema::register_format("pve-qm-ide", $ide_fmt);
@@ -876,6 +876,7 @@ my $scsi_fmt = {
     %drivedesc_base,
     %iothread_fmt,
     %queues_fmt,
+    %scsiblock_fmt,
 };
 my $scsidesc = {
     optional => 1,
@@ -886,7 +887,6 @@ PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc);
 
 my $sata_fmt = {
     %drivedesc_base,
-    %rerror_fmt,
 };
 my $satadesc = {
     optional => 1,
@@ -898,7 +898,6 @@ PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc);
 my $virtio_fmt = {
     %drivedesc_base,
     %iothread_fmt,
-    %rerror_fmt,
 };
 my $virtiodesc = {
     optional => 1,
@@ -909,10 +908,10 @@ PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc);
 
 my $alldrive_fmt = {
     %drivedesc_base,
-    %rerror_fmt,
     %iothread_fmt,
     %model_fmt,
     %queues_fmt,
+    %scsiblock_fmt,
 };
 
 my $efidisk_fmt = {
@@ -999,6 +998,13 @@ EODESCR
        optional => 1,
        default => 1,
     },
+    romfile => {
+        type => 'string',
+        pattern => '[^,;]+',
+        format_description => 'string',
+        description => "Custom pci device rom filename (must be located in /usr/share/kvm/).",
+        optional => 1,
+    },
     pcie => {
        type => 'boolean',
         description =>  "Choose the PCI-express bus (needs the 'q35' machine model).",
@@ -1486,7 +1492,7 @@ sub print_drivedevice_full {
            if ($drive->{file} =~ m|^/|) {
                $path = $drive->{file};
                if (my $info = path_is_scsi($path)) {
-                   if ($info->{type} == 0) {
+                   if ($info->{type} == 0 && $drive->{scsiblock}) {
                        $devicetype = 'block';
                    } elsif ($info->{type} == 1) { # tape
                        $devicetype = 'generic';
@@ -1707,12 +1713,10 @@ sub print_cpu_device {
        $cpu = $cpuconf->{cputype};
     }
 
-    my $sockets = 1;
-    $sockets = $conf->{sockets} if  $conf->{sockets};
     my $cores = $conf->{cores} || 1;
 
     my $current_core = ($id - 1) % $cores;
-    my $current_socket = int(($id - $current_core)/$cores);
+    my $current_socket = int(($id - 1 - $current_core)/$cores);
 
     return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
 }
@@ -2876,7 +2880,11 @@ sub config_to_command {
     $vga = 'qxl' if $qxlnum;
 
     if (!$vga) {
-       $vga = $winversion >= 6 ? 'std' : 'cirrus';
+       if (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 9)) {
+           $vga = (!$winversion || $winversion >= 6) ? 'std' : 'cirrus';
+       } else {
+           $vga = ($winversion >= 6) ? 'std' : 'cirrus';
+       }
     }
 
     # enable absolute mouse coordinates (needed by vnc)
@@ -2908,6 +2916,8 @@ sub config_to_command {
        }
 
        my $rombar = defined($d->{rombar}) && !$d->{rombar} ? ',rombar=0' : '';
+       my $romfile = $d->{romfile};
+
        my $xvga = '';
        if ($d->{'x-vga'}) {
            $xvga = ',x-vga=on';
@@ -2934,6 +2944,7 @@ sub config_to_command {
            if($j == 0){
                $devicestr .= "$rombar$xvga";
                $devicestr .= ",multifunction=on" if $multifunction;
+               $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
            }
 
            push @$devices, '-device', $devicestr;
@@ -3144,9 +3155,12 @@ sub config_to_command {
 
        my $nodename = PVE::INotify::nodename();
        my $pfamily = PVE::Tools::get_host_address_family($nodename);
-       $spice_port = PVE::Tools::next_spice_port($pfamily);
+       my @nodeaddrs = PVE::Tools::getaddrinfo_all('localhost', family => $pfamily);
+       die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
+       my $localhost = PVE::Network::addr_to_ip($nodeaddrs[0]->{addr});
+       $spice_port = PVE::Tools::next_spice_port($pfamily, $localhost);
 
-       push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
+       push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
 
        push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
        push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
@@ -3970,7 +3984,7 @@ sub qemu_block_resize {
 
     my $running = check_running($vmid);
 
-    return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
+    $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
 
     return if !$running;
 
@@ -5919,24 +5933,23 @@ sub qemu_drive_mirror {
        $format = "nbd";
        my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
        $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
-       my $cmd = ['socat', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=1"];
+       my $cmd = ['socat', '-T30', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=5"];
 
        my $pid = fork();
        if (!defined($pid)) {
-           die "forking socat tunnel failed";
+           die "forking socat tunnel failed\n";
        } elsif ($pid == 0) {
            exec(@$cmd);
-           exit(-1);
-       } else {
-           $jobs->{"drive-$drive"}->{pid} = $pid;
+           warn "exec failed: $!\n";
+           POSIX::_exit(-1);
+       }
+       $jobs->{"drive-$drive"}->{pid} = $pid;
 
-           my $timeout = 0;
-           while (1) {
-               last if -S $unixsocket; 
-               die if $timeout > 5;
-               $timeout++;
-               sleep 1;
-           }
+       my $timeout = 0;
+       while (!-S $unixsocket) {
+           die "nbd connection helper timed out\n"
+               if $timeout++ > 5;
+           sleep 1;
        }
     } else {
        my $storecfg = PVE::Storage::config();
@@ -5993,7 +6006,7 @@ sub qemu_drive_mirror_monitor {
                    next;
                }
 
-               die "$job: mirroring has been cancelled. Maybe do you have bad sectors?" if !defined($running_mirror_jobs->{$job});
+               die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
 
                my $busy = $running_mirror_jobs->{$job}->{busy};
                my $ready = $running_mirror_jobs->{$job}->{ready};
@@ -6039,14 +6052,14 @@ sub qemu_drive_mirror_monitor {
 
                    foreach my $job (keys %$jobs) {
                        # try to switch the disk if source and destination are on the same guest
-                       print "$job : Try to complete block job\n";
+                       print "$job: Completing block job...\n";
 
                        eval { vm_mon_cmd($vmid, "block-job-complete", device => $job) };
                        if ($@ =~ m/cannot be completed/) {
-                           print "$job : block job cannot be complete. Try again \n";
+                           print "$job: Block job cannot be completed, try again.\n";
                            $err_complete++;
                        }else {
-                           print "$job : complete ok : flushing pending writes\n";
+                           print "$job: Completed successfully.\n";
                            $jobs->{$job}->{complete} = 1;
                            eval { qemu_blockjobs_finish_tunnel($vmid, $job, $jobs->{$job}->{pid}) } ;
                        }
@@ -6069,7 +6082,7 @@ sub qemu_blockjobs_cancel {
     my ($vmid, $jobs) = @_;
 
     foreach my $job (keys %$jobs) {
-       print "$job: try to cancel block job\n";
+       print "$job: Cancelling block job\n";
        eval { vm_mon_cmd($vmid, "block-job-cancel", device => $job); };
        $jobs->{$job}->{cancel} = 1;
     }
@@ -6084,8 +6097,8 @@ sub qemu_blockjobs_cancel {
 
        foreach my $job (keys %$jobs) {
 
-           if(defined($jobs->{$job}->{cancel}) && !defined($running_jobs->{$job})) {
-               print "$job : finished\n";
+           if (defined($jobs->{$job}->{cancel}) && !defined($running_jobs->{$job})) {
+               print "$job: Done.\n";
                eval { qemu_blockjobs_finish_tunnel($vmid, $job, $jobs->{$job}->{pid}) } ;
                delete $jobs->{$job};
            }
@@ -6269,6 +6282,12 @@ sub lspci {
            push @{$devices->{$id}}, $res;
     });
 
+    # Entries should be sorted by functions.
+    foreach my $id (keys %$devices) {
+       my $dev = $devices->{$id};
+       $devices->{$id} = [ sort { $a->{function} <=> $b->{function} } @$dev ];
+    }
+
     return $devices;
 }
 
@@ -6290,7 +6309,7 @@ sub scsihw_infos {
 
     my $maxdev = 0;
 
-    if ($conf->{scsihw} && ($conf->{scsihw} =~ m/^lsi/)) {
+    if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)) {
         $maxdev = 7;
     } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
         $maxdev = 1;