}
}
+sub vga_conf_has_spice {
+ my ($vga) = @_;
+
+ return $vga && ($vga eq 'qxl');
+}
+
sub config_to_command {
my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
$tablet = $conf->{tablet};
} else {
$tablet = $defaults->{tablet};
- $tablet = 0 if $vga eq 'qxl'; # disable for spice because it is not needed
+ $tablet = 0 if vga_conf_has_spice($vga); # disable for spice because it is not needed
}
push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
}
- if ($vga eq 'qxl') {
+ my $spice_port;
+ if (vga_conf_has_spice($vga)) {
my $pciaddr = print_pci_addr("spice", $bridges);
-
- my $port = PVE::Tools::next_unused_port(61000, 61099);
- push @$cmd, '-spice', "tls-port=$port,addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA";
+ $spice_port = PVE::Tools::next_unused_port(61000, 61099);
+
+ 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";
push @$cmd, '-global', join(',', @$globalFlags)
if scalar(@$globalFlags);
- return wantarray ? ($cmd, $vollist) : $cmd;
+ return wantarray ? ($cmd, $vollist, $spice_port) : $cmd;
}
sub vnc_socket {
}
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;
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)
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;