]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/API2/Qemu.pm
bump version to 3.0-29
[qemu-server.git] / PVE / API2 / Qemu.pm
index dede2e4ad279058e6380b721c7dea660c8fb0988..9450b16d36c96f916cfcfdde5133014b45409ccd 100644 (file)
@@ -3,6 +3,7 @@ package PVE::API2::Qemu;
 use strict;
 use warnings;
 use Cwd 'abs_path';
+use Net::SSLeay;
 
 use PVE::Cluster qw (cfs_read_file cfs_write_file);;
 use PVE::SafeSyslog;
@@ -1272,6 +1273,8 @@ __PACKAGE__->register_method({
        my $vmid = $param->{vmid};
        my $node = $param->{node};
 
+       my $conf = PVE::QemuServer::load_config($vmid, $node); # check if VM exists
+
        my $authpath = "/vms/$vmid";
 
        my $ticket = PVE::AccessControl::assemble_vnc_ticket($authuser, $authpath);
@@ -1282,14 +1285,14 @@ __PACKAGE__->register_method({
        my $port = PVE::Tools::next_vnc_port();
 
        my $remip;
+       my $remcmd = [];
 
        if ($node ne 'localhost' && $node ne PVE::INotify::nodename()) {
            $remip = PVE::Cluster::remote_node_ip($node);
+           # NOTE: kvm VNC traffic is already TLS encrypted
+           $remcmd = ['/usr/bin/ssh', '-T', '-o', 'BatchMode=yes', $remip];
        }
 
-       # NOTE: kvm VNC traffic is already TLS encrypted
-       my $remcmd = $remip ? ['/usr/bin/ssh', '-T', '-o', 'BatchMode=yes', $remip] : [];
-
        my $timeout = 10;
 
        my $realcmd = sub {
@@ -1297,12 +1300,24 @@ __PACKAGE__->register_method({
 
            syslog('info', "starting vnc proxy $upid\n");
 
-           my $qmcmd = [@$remcmd, "/usr/sbin/qm", 'vncproxy', $vmid];
+           my $cmd;
+
+           if ($conf->{vga} =~ m/^serial\d+$/) {
+
+               my $termcmd = [ '/usr/sbin/qm', 'terminal', $vmid, '-iface', $conf->{vga} ];
+               #my $termcmd = "/usr/bin/qm terminal -iface $conf->{vga}";
+               $cmd = ['/usr/bin/vncterm', '-rfbport', $port,
+                       '-timeout', $timeout, '-authpath', $authpath, 
+                       '-perm', 'Sys.Console', '-c', @$remcmd, @$termcmd];
+           } else {
+
+               my $qmcmd = [@$remcmd, "/usr/sbin/qm", 'vncproxy', $vmid];
 
-           my $qmstr = join(' ', @$qmcmd);
+               my $qmstr = join(' ', @$qmcmd);
 
-           # also redirect stderr (else we get RFB protocol errors)
-           my $cmd = ['/bin/nc', '-l', '-p', $port, '-w', $timeout, '-c', "$qmstr 2>/dev/null"];
+               # also redirect stderr (else we get RFB protocol errors)
+               $cmd = ['/bin/nc', '-l', '-p', $port, '-w', $timeout, '-c', "$qmstr 2>/dev/null"];
+           }
 
            PVE::Tools::run_command($cmd);
 
@@ -1337,9 +1352,15 @@ __PACKAGE__->register_method({
        properties => {
            node => get_standard_option('pve-node'),
            vmid => get_standard_option('pve-vmid'),
+           proxy => {
+               description => "This can be used by the client to specify the proxy server. All nodes in a cluster runs 'spiceproxy', so it is up to the client to choose one. By default, we return the node where the VM is currently running. As resonable setting is to use same node you use to connect to the API (This is window.location.hostname for the JS GUI).",
+               type => 'string', format => 'dns-name',
+               optional => 1,
+           },
        },
     },
     returns => {
+       description => "Returned values can be directly passed to the 'remote-viewer' application.",
        additionalProperties => 1,
        properties => {
            type => { type => 'string' },
@@ -1358,28 +1379,24 @@ __PACKAGE__->register_method({
 
        my $vmid = $param->{vmid};
        my $node = $param->{node};
-
-        my $remip;
-
-       # Note: we currectly use "proxyto => 'node'", so this code will never trigger
-        if ($node ne 'localhost' && $node ne PVE::INotify::nodename()) {
-            $remip = PVE::Cluster::remote_node_ip($node);
-        }
+       my $proxy = $param->{proxy};
 
        my ($ticket, $proxyticket) = PVE::AccessControl::assemble_spice_ticket($authuser, $vmid, $node);
 
        my $timeout = 10;
 
-       # Note: this only works if VM is on local node
        my $port = PVE::QemuServer::spice_port($vmid);
        PVE::QemuServer::vm_mon_cmd($vmid, "set_password", protocol => 'spice', password => $ticket);
        PVE::QemuServer::vm_mon_cmd($vmid, "expire_password", protocol => 'spice', time => "+30");
 
-       # fimxe: ??
-       my $host = `hostname -f` || PVE::INotify::nodename();
-       chomp $host;
+       if (!$proxy) {
+           my $host = `hostname -f` || PVE::INotify::nodename();
+           chomp $host;
+           $proxy = $host;
+       }
 
-       my $subject = "OU=PVE Cluster Node, O=Proxmox Virtual Environment, CN=$host";
+       my $filename = "/etc/pve/local/pve-ssl.pem";
+       my $subject = PVE::QemuServer::read_x509_subject_spice($filename);
 
        my $cacert = PVE::Tools::file_get_contents("/etc/pve/pve-root-ca.pem", 8192);
        $cacert =~ s/\n/\\n/g;
@@ -1388,7 +1405,7 @@ __PACKAGE__->register_method({
            type => 'spice',
            title => "VM $vmid",
            host => $proxyticket, # this break tls hostname verification, so we need to use 'host-subject'
-           proxy => "http://$host:3128",
+           proxy => "http://$proxy:3128",
            'tls-port' => $port,
            'host-subject' => $subject,
            ca => $cacert,
@@ -1477,9 +1494,7 @@ __PACKAGE__->register_method({
 
        $status->{ha} = &$vm_is_ha_managed($param->{vmid});
 
-       if ($conf->{vga} && ($conf->{vga} eq 'qxl')) {
-           $status->{spice} = 1;
-       }
+       $status->{spice} = 1 if PVE::QemuServer::vga_conf_has_spice($conf->{vga});
 
        return $status;
     }});
@@ -1533,6 +1548,14 @@ __PACKAGE__->register_method({
        raise_param_exc({ migratedfrom => "Only root may use this option." })
            if $migratedfrom && $authuser ne 'root@pam';
 
+       # read spice ticket from STDIN
+       my $spice_ticket;
+       if ($stateuri && ($stateuri eq 'tcp') && $migratedfrom && ($rpcenv->{type} eq 'cli')) {
+           my $line = <>;
+           chomp $line;
+           $spice_ticket = $line if $line;
+       }
+
        my $storecfg = PVE::Storage::config();
 
        if (&$vm_is_ha_managed($vmid) && !$stateuri &&
@@ -1561,7 +1584,8 @@ __PACKAGE__->register_method({
 
                syslog('info', "start VM $vmid: $upid\n");
 
-               PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef, $machine);
+               PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef, 
+                                         $machine, $spice_ticket);
 
                return;
            };