X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FQemuServer.pm;h=81f05843efdbbf681bb4be474d445bb5bc92269f;hb=1f720e28c739bcb0fa8ce8c61a066d7d49edbee6;hp=4906f2c52c9a9842408e8a4e5da653626a43c3d1;hpb=b62532e4e89f1a1d23ea8c6b7d4158f28b962cbe;p=qemu-server.git diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 4906f2c5..81f05843 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -373,7 +373,7 @@ EODESCR machine => { description => "Specific the Qemu machine type.", type => 'string', - pattern => '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)', + pattern => '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)', maxLength => 40, optional => 1, }, @@ -481,7 +481,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] [,discard=ignore|on]', + 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] [,serial=serial][,model=model]', 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); @@ -489,7 +489,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] [,discard=ignore|on] [,iothread=on] [,queues=]', + 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] [,iothread=on] [,queues=] [,serial=serial]', 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); @@ -497,7 +497,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] [,discard=ignore|on]', + 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] [,serial=serial]', 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); @@ -505,7 +505,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] [,discard=ignore|on] [,iothread=on]', + 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] [,iothread=on] [,serial=serial]', 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 @@ my $serialdesc = { description => <{iops_wr} && $res->{iops_wr} !~ m/^\d+$/; return undef if $res->{iops_wr_max} && $res->{iops_wr_max} !~ m/^\d+$/; - if ($res->{size}) { return undef if !defined($res->{size} = &$parse_size($res->{size})); } @@ -976,7 +976,7 @@ sub parse_drive { return $res; } -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); +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 serial); sub print_drive { my ($vmid, $drive) = @_; @@ -990,6 +990,10 @@ sub print_drive { $opts .= ",size=" . &$format_size($drive->{size}); } + if (my $model = $drive->{model}) { + $opts .= ",model=$model"; + } + return "$drive->{file}$opts"; } @@ -1122,6 +1126,9 @@ sub print_drivedevice_full { my $devicetype = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd"; $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}"; + if ($devicetype eq 'hd' && (my $model = $drive->{model})) { + $device .= ",model=$model"; + } } elsif ($drive->{interface} eq 'sata'){ my $controller = int($drive->{index} / $MAX_SATA_DISKS); my $unit = $drive->{index} % $MAX_SATA_DISKS; @@ -1212,7 +1219,7 @@ sub print_drive_full { } sub print_netdevice_full { - my ($vmid, $conf, $net, $netid, $bridges) = @_; + my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_; my $bootorder = $conf->{boot} || $confdesc->{boot}->{default}; @@ -1229,11 +1236,28 @@ sub print_netdevice_full { $tmpstr .= ",vectors=$vectors,mq=on"; } $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex} ; + + if ($use_old_bios_files) { + my $romfile; + if ($device eq 'virtio-net-pci') { + $romfile = 'pxe-virtio.rom'; + } elsif ($device eq 'e1000') { + $romfile = 'pxe-e1000.rom'; + } elsif ($device eq 'ne2k') { + $romfile = 'pxe-ne2k_pci.rom'; + } elsif ($device eq 'pcnet') { + $romfile = 'pxe-pcnet.rom'; + } elsif ($device eq 'rtl8139') { + $romfile = 'pxe-rtl8139.rom'; + } + $tmpstr .= ",romfile=$romfile" if $romfile; + } + return $tmpstr; } sub print_netdev_full { - my ($vmid, $conf, $net, $netid) = @_; + my ($vmid, $conf, $net, $netid, $hotplug) = @_; my $i = ''; if ($netid =~ m/^net(\d+)$/) { @@ -1254,9 +1278,10 @@ sub print_netdev_full { my $vmname = $conf->{name} || "vm$vmid"; my $netdev = ""; + my $script = $hotplug ? "pve-bridge-hotplug" : "pve-bridge"; if ($net->{bridge}) { - $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam"; + $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam"; } else { $netdev = "type=user,id=$netid,hostname=$vmname"; } @@ -2133,6 +2158,8 @@ sub check_local_resources { foreach my $k (keys %$conf) { next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice'); + # sockets are safe: they will recreated be on the target side post-migrate + next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket'); $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/; } @@ -2619,6 +2646,8 @@ sub config_to_command { my $q35 = machine_type_is_q35($conf); my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1'); my $machine_type = $forcemachine || $conf->{machine}; + my $use_old_bios_files = undef; + ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type); my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits} : $defaults->{cpuunits}; @@ -2627,6 +2656,9 @@ sub config_to_command { push @$cmd, '--scope'; push @$cmd, '--slice', "qemu"; push @$cmd, '--unit', $vmid; + # set KillMode=none, so that systemd don't kill those scopes + # at shutdown (pve-manager service should stop the VMs instead) + push @$cmd, '-p', "KillMode=none"; push @$cmd, '-p', "CPUShares=$cpuunits"; if ($conf->{cpulimit}) { my $cpulimit = int($conf->{cpulimit} * 100); @@ -3145,7 +3177,7 @@ sub config_to_command { my $netdevfull = print_netdev_full($vmid,$conf,$d,"net$i"); push @$devices, '-netdev', $netdevfull; - my $netdevicefull = print_netdevice_full($vmid,$conf,$d,"net$i",$bridges); + my $netdevicefull = print_netdevice_full($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files); push @$devices, '-device', $netdevicefull; } @@ -3310,7 +3342,12 @@ sub vm_deviceplug { } elsif ($deviceid =~ m/^(net)(\d+)$/) { return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid); - my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid); + + my $machine_type = PVE::QemuServer::qemu_machine_pxe($vmid, $conf); + my $use_old_bios_files = undef; + ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type); + + my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files); qemu_deviceadd($vmid, $netdevicefull); eval { qemu_deviceaddverify($vmid, $deviceid); }; if (my $err = $@) { @@ -3567,7 +3604,7 @@ sub qemu_set_link_status { sub qemu_netdevadd { my ($vmid, $conf, $device, $deviceid) = @_; - my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid); + my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1); my %options = split(/[=,]/, $netdev); vm_mon_cmd($vmid, "netdev_add", %options); @@ -4266,7 +4303,8 @@ sub vmconfig_update_disk { } sub vm_start { - my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_; + my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, + $forcemachine, $spice_ticket) = @_; lock_config($vmid, sub { my $conf = load_config($vmid, $migratedfrom); @@ -4298,10 +4336,11 @@ sub vm_start { my $nodename = PVE::INotify::nodename(); if ($datacenterconf->{migration_unsecure}) { $localip = PVE::Cluster::remote_node_ip($nodename, 1); + $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip); } my $pfamily = PVE::Tools::get_host_address_family($nodename); $migrate_port = PVE::Tools::next_migrate_port($pfamily); - $migrate_uri = "tcp:[${localip}]:${migrate_port}"; + $migrate_uri = "tcp:${localip}:${migrate_port}"; push @$cmd, '-incoming', $migrate_uri; push @$cmd, '-S'; } else { @@ -4607,15 +4646,21 @@ sub vm_suspend { } sub vm_resume { - my ($vmid, $skiplock) = @_; + my ($vmid, $skiplock, $nocheck) = @_; lock_config($vmid, sub { - my $conf = load_config($vmid); + if (!$nocheck) { - check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup')); + my $conf = load_config($vmid); - vm_mon_cmd($vmid, "cont"); + check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup')); + + vm_mon_cmd($vmid, "cont"); + + } else { + vm_mon_cmd_nocheck($vmid, "cont"); + } }); } @@ -6114,6 +6159,9 @@ sub qemu_img_convert { my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1); if ($src_storeid && $dst_storeid) { + + PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname); + my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid); my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid); @@ -6318,6 +6366,43 @@ sub qemu_machine_feature_enabled { } +sub qemu_machine_pxe { + my ($vmid, $conf, $machine) = @_; + + $machine = PVE::QemuServer::get_current_qemu_machine($vmid) if !$machine; + + foreach my $opt (keys %$conf) { + next if $opt !~ m/^net(\d+)$/; + my $net = PVE::QemuServer::parse_net($conf->{$opt}); + next if !$net; + my $romfile = PVE::QemuServer::vm_mon_cmd_nocheck($vmid, 'qom-get', path => $opt, property => 'romfile'); + return $machine.".pxe" if $romfile =~ m/pxe/; + last; + } + +} + +sub qemu_use_old_bios_files { + my ($machine_type) = @_; + + return if !$machine_type; + + my $use_old_bios_files = undef; + + if ($machine_type =~ m/^(\S+)\.pxe$/) { + $machine_type = $1; + $use_old_bios_files = 1; + } else { + # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we + # load new efi bios files on migration. So this hack is required to allow + # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when + # updrading from proxmox-ve-3.X to proxmox-ve 4.0 + $use_old_bios_files = !qemu_machine_feature_enabled ($machine_type, undef, 2, 4); + } + + return ($use_old_bios_files, $machine_type); +} + sub lspci { my $devices = {}; @@ -6429,6 +6514,7 @@ sub complete_storage { my $res = []; foreach my $sid (keys %$ids) { next if !PVE::Storage::storage_check_enabled($cfg, $sid, undef, 1); + next if !$ids->{$sid}->{content}->{images}; push @$res, $sid; }