package PVE::QemuServer;
use strict;
+use warnings;
use POSIX;
use IO::Handle;
use IO::Select;
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 => {
ostype => {
optional => 1,
type => 'string',
- enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26)],
+ enum => [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
description => <<EODESC,
Used to enable special optimization/features for specific
operating systems:
win8 => Microsoft Windows 8/2012
l24 => Linux 2.4 Kernel
l26 => Linux 2.6/3.X Kernel
+solaris => solaris/opensolaris/openindiania kernel
-other|l24|l26 ... no special behaviour
+other|l24|l26|solaris ... no special behaviour
wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
EODESC
},
vga => {
optional => 1,
type => 'string',
- description => "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever.",
- enum => [qw(std cirrus vmware qxl)],
+ description => "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
+ enum => [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
},
watchdog => {
optional => 1,
optional => 1,
type => 'boolean',
default => 1,
- description => "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning. Else the mouse runs out of sync with normal vnc clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches.",
+ description => "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
},
migrate_speed => {
optional => 1,
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 = {
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);
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);
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);
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);
my $hostpcidesc = {
optional => 1,
type => 'string', format => 'pve-qm-hostpci',
- typetext => "HOSTPCIDEVICE",
+ typetext => "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off]",
description => <<EODESCR,
Map host pci devices. HOSTPCIDEVICE syntax is:
You can us the 'lspci' command to list existing pci devices.
+The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
+
+The 'driver' option is currently ignored.
+
Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
Experimental: user reported problems with this option.
my $serialdesc = {
optional => 1,
type => 'string',
- pattern => '/dev/ttyS\d+',
+ pattern => '(/dev/ttyS\d+|socket)',
description => <<EODESCR,
-Map host serial devices (n is 0 to 3).
+Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device, or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
my $paralleldesc= {
optional => 1,
type => 'string',
- pattern => '/dev/parport\d+',
+ pattern => '/dev/parport\d+|/dev/usb/lp\d+',
description => <<EODESCR,
Map host parallel devices (n is 0 to 2).
# ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
# [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
# [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
-# [,aio=native|threads]
+# [,aio=native|threads][,discard=ignore|on]
sub parse_drive {
my ($key, $data) = @_;
foreach my $p (split (/,/, $data)) {
next if $p =~ m/^\s*$/;
- if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|bps_rd|mbps_rd|bps_wr|mbps_wr|iops|iops_rd|iops_wr|size)=(.+)$/) {
+ if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard)=(.+)$/) {
my ($k, $v) = ($1, $2);
$k = 'file' if $k eq 'volume';
return undef if $res->{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}) {
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};
}
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';
}
}
- 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}";
}
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;
}
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;
$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+$/;
}
}
}
+sub vga_conf_has_spice {
+ my ($vga) = @_;
+
+ return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
+
+ return $1 || 1;
+}
+
sub config_to_command {
my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
# include usb device config
push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
+ my $vga = $conf->{vga};
+
+ my $qxlnum = vga_conf_has_spice($vga);
+ $vga = 'qxl' if $qxlnum;
+
+ if (!$vga) {
+ if ($conf->{ostype} && ($conf->{ostype} eq 'win8' ||
+ $conf->{ostype} eq 'win7' ||
+ $conf->{ostype} eq 'w2k8')) {
+ $vga = 'std';
+ } else {
+ $vga = 'cirrus';
+ }
+ }
+
# enable absolute mouse coordinates (needed by vnc)
- my $tablet = defined($conf->{tablet}) ? $conf->{tablet} : $defaults->{tablet};
+ my $tablet;
+ if (defined($conf->{tablet})) {
+ $tablet = $conf->{tablet};
+ } else {
+ $tablet = $defaults->{tablet};
+ $tablet = 0 if $qxlnum; # disable for spice because it is not needed
+ $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
+ }
+
push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
# host pci devices
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
# serial devices
for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
if (my $path = $conf->{"serial$i"}) {
- die "no such serial device\n" if ! -c $path;
- push @$devices, '-chardev', "tty,id=serial$i,path=$path";
- push @$devices, '-device', "isa-serial,chardev=serial$i";
+ if ($path eq 'socket') {
+ my $socket = "/var/run/qemu-server/${vmid}.serial$i";
+ push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
+ push @$devices, '-device', "isa-serial,chardev=serial$i";
+ } else {
+ die "no such serial device\n" if ! -c $path;
+ push @$devices, '-chardev', "tty,id=serial$i,path=$path";
+ push @$devices, '-device', "isa-serial,chardev=serial$i";
+ }
}
}
for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
if (my $path = $conf->{"parallel$i"}) {
die "no such parallel device\n" if ! -c $path;
- push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
+ my $devtype = $path =~ m!^/dev/usb/lp! ? 'tty' : 'parport';
+ push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
push @$devices, '-device', "isa-parallel,chardev=parallel$i";
}
}
push @$cmd, '-no-reboot' if defined($conf->{reboot}) && $conf->{reboot} == 0;
- my $vga = $conf->{vga};
- if (!$vga) {
- if ($conf->{ostype} && ($conf->{ostype} eq 'win8' || $conf->{ostype} eq 'win7' || $conf->{ostype} eq 'w2k8')) {
- $vga = 'std';
- } else {
- $vga = 'cirrus';
- }
- }
-
- push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
+ push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
# time drift fix
my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
my $useLocaltime = $conf->{localtime};
if (my $ost = $conf->{ostype}) {
- # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
+ # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
if ($ost =~ m/^w/) { # windows
$useLocaltime = 1 if !defined($conf->{localtime});
my $cpu = $nokvm ? "qemu64" : "kvm64";
$cpu = $conf->{cpu} if $conf->{cpu};
- push @$cpuFlags , '+x2apic' if !$nokvm;
+ 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';
push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
}
- if ($vga eq 'qxl') {
- my $pciaddr = print_pci_addr("spice", $bridges);
+ my $spice_port;
- my $x509 = "x509-key-file=/etc/pve/local/pve-ssl.key" .
- ",x509-cert-file=/etc/pve/local/pve-ssl.pem" .
- ",x509-cacert-file=/etc/pve/pve-root-ca.pem";
-
- my $port = PVE::Tools::next_unused_port(61000, 61099);
+ if ($qxlnum) {
+ if ($qxlnum > 1) {
+ if ($conf->{ostype} && $conf->{ostype} =~ m/^w/){
+ for(my $i = 1; $i < $qxlnum; $i++){
+ my $pciaddr = print_pci_addr("vga$i", $bridges);
+ push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
+ }
+ } else {
+ # assume other OS works like Linux
+ push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
+ push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
+ }
+ }
- push @$cmd, '-spice', "tls-port=$port,addr=127.0.0.1,$x509,tls-ciphers=DES-CBC3-SHA";
+ my $pciaddr = print_pci_addr("spice", $bridges);
+
+ $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";
push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
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};
push @$cmd, '-global', join(',', @$globalFlags)
if scalar(@$globalFlags);
- return wantarray ? ($cmd, $vollist) : $cmd;
+ return wantarray ? ($cmd, $vollist, $spice_port) : $cmd;
}
sub vnc_socket {
}
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);
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);
}
sub vm_start {
- my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine) = @_;
+ my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
lock_config($vmid, sub {
my $conf = load_config($vmid, $migratedfrom);
# set environment variable useful inside network script
$ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
- my ($cmd, $vollist) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
+ my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
my $migrate_port = 0;
-
+ my $migrate_uri;
if ($statefile) {
if ($statefile eq 'tcp') {
+ my $localip = "localhost";
+ my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
+ if ($datacenterconf->{migration_unsecure}) {
+ my $nodename = PVE::INotify::nodename();
+ $localip = PVE::Cluster::remote_node_ip($nodename, 1);
+ }
$migrate_port = PVE::Tools::next_migrate_port();
- my $migrate_uri = "tcp:localhost:${migrate_port}";
+ $migrate_uri = "tcp:${localip}:${migrate_port}";
push @$cmd, '-incoming', $migrate_uri;
push @$cmd, '-S';
} else {
my $err = $@;
die "start failed: $err" if $err;
- print "migration listens on port $migrate_port\n" if $migrate_port;
+ print "migration listens on $migrate_uri\n" if $migrate_uri;
if ($statefile && $statefile ne 'tcp') {
eval { vm_mon_cmd_nocheck($vmid, "cont"); };
warn $@ if $@;
}
- if($migratedfrom) {
+ if ($migratedfrom) {
my $capabilities = {};
$capabilities->{capability} = "xbzrle";
$capabilities->{state} = JSON::true;
eval { vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => [$capabilities]); };
- }
- else{
+ warn $@ if $@;
+
+ if ($spice_port) {
+ print "spice listens on port $spice_port\n";
+ if ($spice_ticket) {
+ PVE::QemuServer::vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice', password => $spice_ticket);
+ PVE::QemuServer::vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice', time => "+30");
+ }
+ }
+
+ } else {
if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
net3 => { bus => 0, addr => 21 },
net4 => { bus => 0, addr => 22 },
net5 => { bus => 0, addr => 23 },
+ vga1 => { bus => 0, addr => 24 },
+ vga2 => { bus => 0, addr => 25 },
+ vga3 => { bus => 0, addr => 26 },
#addr29 : usb-host (pve-usb.cfg)
'pci.1' => { bus => 0, addr => 30 },
'pci.2' => { bus => 0, addr => 31 },
my $write_zeros = 1;
# fixme: what other storages types initialize volumes with zero?
- if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs' ||
+ if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs' || $scfg->{type} eq 'glusterfs' ||
$scfg->{type} eq 'sheepdog' || $scfg->{type} eq 'rbd') {
$write_zeros = 0;
}
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;