X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FQemuServer.pm;h=a5576a6da78639ae99dfd8ce5a0796e94ce23ad9;hb=0cea6a01606674112f921b151bf2b636ff8b3b69;hp=d9896c18dbafd9effbc49a9466c55e0d12c826a7;hpb=590e698c07faa1e1f38ef2574d7743fde30f2667;p=qemu-server.git diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index d9896c1..a5576a6 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -234,7 +234,7 @@ my $confdesc = { optional => 1, type => 'string', description => "scsi controller model", - enum => [qw(lsi virtio-scsi-pci megasas)], + enum => [qw(lsi lsi53c810 virtio-scsi-pci megasas pvscsi)], default => 'lsi', }, description => { @@ -465,7 +465,7 @@ my $MAX_SERIAL_PORTS = 4; my $MAX_PARALLEL_PORTS = 3; my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio', - 'ne2k_isa', 'i82551', 'i82557b', 'i82559er']; + 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3']; my $nic_model_list_txt = join(' ', sort @$nic_model_list); my $netdesc = { @@ -505,7 +505,7 @@ my $drivename_hash; my $idedesc = { optional => 1, type => 'string', format => 'pve-qm-drive', - typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]', + typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]', description => "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").", }; PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc); @@ -513,7 +513,7 @@ PVE::JSONSchema::register_standard_option("pve-qm-ide", $idedesc); my $scsidesc = { optional => 1, type => 'string', format => 'pve-qm-drive', - typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]', + typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]', description => "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").", }; PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc); @@ -521,7 +521,7 @@ PVE::JSONSchema::register_standard_option("pve-qm-scsi", $scsidesc); my $satadesc = { optional => 1, type => 'string', format => 'pve-qm-drive', - typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]', + typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]', description => "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").", }; PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc); @@ -529,7 +529,7 @@ PVE::JSONSchema::register_standard_option("pve-qm-sata", $satadesc); my $virtiodesc = { optional => 1, type => 'string', format => 'pve-qm-drive', - typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]', + typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]', description => "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").", }; PVE::JSONSchema::register_standard_option("pve-qm-virtio", $virtiodesc); @@ -558,7 +558,7 @@ PVE::JSONSchema::register_standard_option("pve-qm-usb", $usbdesc); my $hostpcidesc = { optional => 1, type => 'string', format => 'pve-qm-hostpci', - typetext => "HOSTPCIDEVICE", + typetext => "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off]", description => <{werror} && $res->{werror} !~ m/^(enospc|ignore|report|stop)$/; return undef if $res->{backup} && $res->{backup} !~ m/^(yes|no)$/; return undef if $res->{aio} && $res->{aio} !~ m/^(native|threads)$/; - + return undef if $res->{discard} && $res->{discard} !~ m/^(ignore|on)$/; return undef if $res->{mbps_rd} && $res->{mbps}; return undef if $res->{mbps_wr} && $res->{mbps}; return undef if $res->{mbps} && $res->{mbps} !~ m/^\d+(\.\d+)?$/; + return undef if $res->{mbps_max} && $res->{mbps_max} !~ m/^\d+(\.\d+)?$/; return undef if $res->{mbps_rd} && $res->{mbps_rd} !~ m/^\d+(\.\d+)?$/; + return undef if $res->{mbps_rd_max} && $res->{mbps_rd_max} !~ m/^\d+(\.\d+)?$/; return undef if $res->{mbps_wr} && $res->{mbps_wr} !~ m/^\d+(\.\d+)?$/; + return undef if $res->{mbps_wr_max} && $res->{mbps_wr_max} !~ m/^\d+(\.\d+)?$/; return undef if $res->{iops_rd} && $res->{iops}; return undef if $res->{iops_wr} && $res->{iops}; + + return undef if $res->{iops} && $res->{iops} !~ m/^\d+$/; + return undef if $res->{iops_max} && $res->{iops_max} !~ m/^\d+$/; return undef if $res->{iops_rd} && $res->{iops_rd} !~ m/^\d+$/; + return undef if $res->{iops_rd_max} && $res->{iops_rd_max} !~ m/^\d+$/; return undef if $res->{iops_wr} && $res->{iops_wr} !~ m/^\d+$/; + return undef if $res->{iops_wr_max} && $res->{iops_wr_max} !~ m/^\d+$/; if ($res->{size}) { @@ -962,13 +974,13 @@ sub parse_drive { return $res; } -my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr); +my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max); sub print_drive { my ($vmid, $drive) = @_; my $opts = ''; - foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') { + foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup') { $opts .= ",$o=$drive->{$o}" if $drive->{$o}; } @@ -1050,7 +1062,7 @@ sub print_drivedevice_full { my $pciaddr = print_pci_addr("$drive->{interface}$drive->{index}", $bridges); $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr"; } elsif ($drive->{interface} eq 'scsi') { - $maxdev = ($conf->{scsihw} && $conf->{scsihw} ne 'lsi') ? 256 : 7; + $maxdev = ($conf->{scsihw} && ($conf->{scsihw} !~ m/^lsi/)) ? 256 : 7; my $controller = int($drive->{index} / $maxdev); my $unit = $drive->{index} % $maxdev; my $devicetype = 'hd'; @@ -1077,8 +1089,8 @@ sub print_drivedevice_full { } } - if (!$conf->{scsihw} || $conf->{scsihw} eq 'lsi'){ - $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}" if !$conf->{scsihw} || $conf->{scsihw} eq 'lsi'; + if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)){ + $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}"; } else { $device = "scsi-$devicetype,bus=scsihw$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}"; } @@ -1201,14 +1213,27 @@ sub parse_hostpci { return undef if !$value; + + my @list = split(/,/, $value); + my $found; + my $res = {}; + foreach my $kv (@list) { - if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) { - $res->{pciid} = $value; - } else { - return undef; + if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9])$/) { + $found = 1; + $res->{pciid} = $2; + } elsif ($kv =~ m/^driver=(kvm|vfio)$/) { + $res->{driver} = $1; + } elsif ($kv =~ m/^rombar=(on|off)$/) { + $res->{rombar} = $1; + } else { + warn "unknown hostpci setting '$kv'\n"; + } } + return undef if !$found; + return $res; } @@ -1220,7 +1245,7 @@ sub parse_net { foreach my $kvp (split(/,/, $data)) { - if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) { + if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) { my $model = lc($1); my $mac = defined($3) ? uc($3) : PVE::Tools::random_ether_addr(); $res->{model} = $model; @@ -1835,6 +1860,7 @@ sub check_local_resources { $loc_res = 1 if $conf->{hostpci}; # old syntax foreach my $k (keys %$conf) { + next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice'); $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/; } @@ -2324,7 +2350,8 @@ sub config_to_command { my $d = parse_hostpci($conf->{"hostpci$i"}); next if !$d; $pciaddr = print_pci_addr("hostpci$i", $bridges); - push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr"; + my $rombar = $d->{rombar} && $d->{rombar} eq 'off' ? ",rombar=0" : ""; + push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr$rombar"; } # usb devices @@ -2450,6 +2477,8 @@ sub config_to_command { my $cpu = $nokvm ? "qemu64" : "kvm64"; $cpu = $conf->{cpu} if $conf->{cpu}; + push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64'; + push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype} ne 'solaris'; push @$cpuFlags , '-x2apic' if $conf->{ostype} eq 'solaris'; @@ -2497,7 +2526,7 @@ sub config_to_command { my $pciaddr = print_pci_addr("spice", $bridges); - $spice_port = PVE::Tools::next_unused_port(61000, 61099); + $spice_port = PVE::Tools::next_spice_port(); push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on"; @@ -2548,7 +2577,7 @@ sub config_to_command { if ($drive->{interface} eq 'scsi') { - my $maxdev = ($scsihw ne 'lsi') ? 256 : 7; + my $maxdev = ($scsihw !~ m/^lsi/) ? 256 : 7; my $controller = int($drive->{index} / $maxdev); $pciaddr = print_pci_addr("scsihw$controller", $bridges); push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller}; @@ -2705,7 +2734,7 @@ sub vm_deviceplug { } if ($deviceid =~ m/^(scsi)(\d+)$/) { - return 1 if ($conf->{scsihw} && $conf->{scsihw} ne 'lsi'); #virtio-scsi not yet support hotplug + return 1 if ($conf->{scsihw} && ($conf->{scsihw} !~ m/^lsi/)); #virtio-scsi not yet support hotplug return undef if !qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device); return undef if !qemu_driveadd($storecfg, $vmid, $device); my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device); @@ -2850,7 +2879,7 @@ sub qemu_devicedelverify { sub qemu_findorcreatescsihw { my ($storecfg, $conf, $vmid, $device) = @_; - my $maxdev = ($conf->{scsihw} && $conf->{scsihw} ne 'lsi') ? 256 : 7; + my $maxdev = ($conf->{scsihw} && ($conf->{scsihw} !~ m/^lsi/)) ? 256 : 7; my $controller = int($device->{index} / $maxdev); my $scsihwid="scsihw$controller"; my $devices_list = vm_devices_list($vmid); @@ -4731,7 +4760,7 @@ sub qemu_img_convert { my $dst_path = PVE::Storage::path($storecfg, $dst_volid); my $cmd = []; - push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-C'; + push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n'; push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2"); push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path; @@ -4908,21 +4937,4 @@ sub get_current_qemu_machine { return $current || $default || 'pc'; } -sub read_x509_subject_spice { - my ($filename) = @_; - - # read x509 subject - my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); - my $x509 = Net::SSLeay::PEM_read_bio_X509($bio); - Net::SSLeay::BIO_free($bio); - my $nameobj = Net::SSLeay::X509_get_subject_name($x509); - my $subject = Net::SSLeay::X509_NAME_oneline($nameobj); - Net::SSLeay::X509_free($x509); - - # remote-viewer wants comma as seperator (not '/') - $subject =~ s!^/!!; - $subject =~ s!/(\w+=)!,$1!g; - - return $subject; -} 1;