+ $cmd = [@$remcmd, "/usr/sbin/qm", 'vncproxy', $vmid];
+
+ my $sock = IO::Socket::IP->new(
+ ReuseAddr => 1,
+ Listen => 1,
+ LocalPort => $port,
+ Proto => 'tcp',
+ GetAddrInfoFlags => 0,
+ ) or die "failed to create socket: $!\n";
+ # Inside the worker we shouldn't have any previous alarms
+ # running anyway...:
+ alarm(0);
+ local $SIG{ALRM} = sub { die "connection timed out\n" };
+ alarm $timeout;
+ accept(my $cli, $sock) or die "connection failed: $!\n";
+ alarm(0);
+ close($sock);
+ if (PVE::Tools::run_command($cmd,
+ output => '>&'.fileno($cli),
+ input => '<&'.fileno($cli),
+ noerr => 1) != 0)
+ {
+ die "Failed to run vncproxy.\n";
+ }
+ }
+
+ return;
+ };
+
+ my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $authuser, $realcmd, 1);
+
+ PVE::Tools::wait_for_vnc_port($port);
+
+ return {
+ user => $authuser,
+ ticket => $ticket,
+ port => $port,
+ upid => $upid,
+ cert => $sslcert,
+ };
+ }});
+
+__PACKAGE__->register_method({
+ name => 'termproxy',
+ path => '{vmid}/termproxy',
+ method => 'POST',
+ protected => 1,
+ permissions => {
+ check => ['perm', '/vms/{vmid}', [ 'VM.Console' ]],
+ },
+ description => "Creates a TCP proxy connections.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ vmid => get_standard_option('pve-vmid'),
+ serial=> {
+ optional => 1,
+ type => 'string',
+ enum => [qw(serial0 serial1 serial2 serial3)],
+ description => "opens a serial terminal (defaults to display)",
+ },
+ },
+ },
+ returns => {
+ additionalProperties => 0,
+ properties => {
+ user => { type => 'string' },
+ ticket => { type => 'string' },
+ port => { type => 'integer' },
+ upid => { type => 'string' },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+
+ my $authuser = $rpcenv->get_user();