mirror of
https://git.proxmox.com/git/qemu-server
synced 2025-05-29 07:10:36 +00:00
add spice proxy API
This is experimental code, spice connections are not encryped and thus insecure. We use ticket passwords for spice auth, and do direct spice connections to the nodes instead of using a tunnel.
This commit is contained in:
parent
1011b57090
commit
288eeea8ae
113
PVE/API2/Qemu.pm
113
PVE/API2/Qemu.pm
@ -497,6 +497,7 @@ __PACKAGE__->register_method({
|
||||
{ subdir => 'rrddata' },
|
||||
{ subdir => 'monitor' },
|
||||
{ subdir => 'snapshot' },
|
||||
{ subdir => 'spiceproxy' },
|
||||
];
|
||||
|
||||
return $res;
|
||||
@ -1321,6 +1322,118 @@ __PACKAGE__->register_method({
|
||||
};
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method({
|
||||
name => 'spiceproxy',
|
||||
path => '{vmid}/spiceproxy',
|
||||
method => 'GET', # fixme: should be POST, but howto handle that in the HTML client
|
||||
protected => 1,
|
||||
proxyto => 'node', # fixme: use direct connections or ssh tunnel?
|
||||
permissions => {
|
||||
check => ['perm', '/vms/{vmid}', [ 'VM.Console' ]],
|
||||
},
|
||||
description => "Returns a SPICE configuration to connect to the VM.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {
|
||||
node => get_standard_option('pve-node'),
|
||||
vmid => get_standard_option('pve-vmid'),
|
||||
},
|
||||
},
|
||||
returns => {
|
||||
additionalProperties => 1,
|
||||
properties => {
|
||||
type => { type => 'string' },
|
||||
password => { type => 'string' },
|
||||
host => { type => 'string' },
|
||||
port => { type => 'integer' },
|
||||
},
|
||||
},
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
my $rpcenv = PVE::RPCEnvironment::get();
|
||||
|
||||
my $authuser = $rpcenv->get_user();
|
||||
|
||||
my $vmid = $param->{vmid};
|
||||
my $node = $param->{node};
|
||||
|
||||
my $port = PVE::Tools::next_vnc_port();
|
||||
|
||||
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 $authpath = "/vms/$vmid";
|
||||
|
||||
my $ticket = PVE::AccessControl::assemble_spice_ticket($authuser, $authpath);
|
||||
|
||||
my $timeout = 10;
|
||||
|
||||
# Note: this only works if VM is on local node
|
||||
PVE::QemuServer::vm_mon_cmd($vmid, "set_password", protocol => 'spice', password => $ticket);
|
||||
PVE::QemuServer::vm_mon_cmd($vmid, "expire_password", protocol => 'spice', time => "+30");
|
||||
|
||||
my $remcmd = []; #fixme
|
||||
|
||||
my $realcmd = sub {
|
||||
my $upid = shift;
|
||||
|
||||
syslog('info', "starting spice proxy $upid\n");
|
||||
|
||||
my $socket = PVE::QemuServer::spice_socket($vmid);
|
||||
|
||||
my $cmd = ['/usr/bin/socat', '-d', '-d',
|
||||
"TCP-LISTEN:$port,reuseaddr,fork" ];
|
||||
|
||||
if ($remip) {
|
||||
push @$cmd, "EXEC:'ssh root@$remip socat STDIO UNIX-CONNECT:$socket";
|
||||
} else {
|
||||
push @$cmd, "UNIX-CONNECT:$socket";
|
||||
}
|
||||
|
||||
my $conn_count = 0;
|
||||
|
||||
my $parser = sub {
|
||||
my $line = shift;
|
||||
print "$line\n";
|
||||
if ($line =~ /successfully connected from/) {
|
||||
$conn_count++;
|
||||
} elsif ($line =~ /exiting with status/) {
|
||||
$conn_count--;
|
||||
# Note: counting connections seems unreliable here
|
||||
die "client exit\n"; # if $conn_count <= 0;
|
||||
}
|
||||
};
|
||||
|
||||
eval { PVE::Tools::run_command($cmd, errfunc => $parser, outfunc => sub{}); };
|
||||
if (my $err = $@) {
|
||||
die $err if $err !~ m/client exit$/;
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
my $upid = $rpcenv->fork_worker('spiceproxy', $vmid, $authuser, $realcmd);
|
||||
|
||||
PVE::Tools::wait_for_vnc_port($port);
|
||||
|
||||
# fimxe: ??
|
||||
my $host = `hostname -f` || PVE::INotify::nodename();
|
||||
chomp $host;
|
||||
|
||||
return {
|
||||
type => 'spice',
|
||||
host => $host,
|
||||
port => $port,
|
||||
password => $ticket,
|
||||
upid => $upid,
|
||||
};
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method({
|
||||
name => 'vmcmdidx',
|
||||
path => '{vmid}/status',
|
||||
|
@ -2424,7 +2424,7 @@ sub config_to_command {
|
||||
|
||||
my $socket = spice_socket($vmid);
|
||||
|
||||
push @$cmd, '-spice', "disable-ticketing,unix=$socket";
|
||||
push @$cmd, '-spice', "unix=$socket";
|
||||
push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
|
||||
push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
|
||||
push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
|
||||
|
Loading…
Reference in New Issue
Block a user