mirror of
https://git.proxmox.com/git/pve-manager
synced 2026-02-01 19:49:18 +00:00
include spiceterm
This commit is contained in:
parent
e1bae24c4c
commit
2d802f8c3b
11
PVE/API2.pm
11
PVE/API2.pm
@ -83,7 +83,7 @@ __PACKAGE__->register_method ({
|
||||
path => 'version',
|
||||
method => 'GET',
|
||||
permissions => { user => 'all' },
|
||||
description => "API version details",
|
||||
description => "API version details. The result also includes the global datacenter confguration.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {},
|
||||
@ -99,6 +99,13 @@ __PACKAGE__->register_method ({
|
||||
code => sub {
|
||||
my ($resp, $param) = @_;
|
||||
|
||||
return PVE::pvecfg::version_info();
|
||||
my $res = PVE::Cluster::cfs_read_file('datacenter.cfg');
|
||||
|
||||
my $vi = PVE::pvecfg::version_info();
|
||||
foreach my $k (qw(version release repoid)) {
|
||||
$res->{$k} = $vi->{$k};
|
||||
}
|
||||
|
||||
return $res;
|
||||
}});
|
||||
1;
|
||||
|
||||
@ -119,6 +119,7 @@ __PACKAGE__->register_method ({
|
||||
{ name => 'rrd' }, # fixme: remove?
|
||||
{ name => 'rrddata' },# fixme: remove?
|
||||
{ name => 'vncshell' },
|
||||
{ name => 'spiceshell' },
|
||||
{ name => 'time' },
|
||||
{ name => 'dns' },
|
||||
{ name => 'services' },
|
||||
@ -767,6 +768,137 @@ __PACKAGE__->register_method ({
|
||||
};
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'spiceshell',
|
||||
path => 'spiceshell',
|
||||
method => 'POST',
|
||||
protected => 1,
|
||||
proxyto => 'node',
|
||||
permissions => {
|
||||
description => "Restricted to users on realm 'pam'",
|
||||
check => ['perm', '/nodes/{node}', [ 'Sys.Console' ]],
|
||||
},
|
||||
description => "Creates a spice shell.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {
|
||||
node => get_standard_option('pve-node'),
|
||||
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,
|
||||
},
|
||||
upgrade => {
|
||||
type => 'boolean',
|
||||
description => "Run 'apt-get dist-upgrade' instead of normal shell.",
|
||||
optional => 1,
|
||||
default => 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
returns => {
|
||||
description => "Returned values can be directly passed to the 'remote-viewer' application.",
|
||||
additionalProperties => 1,
|
||||
properties => {
|
||||
type => { type => 'string' },
|
||||
password => { type => 'string' },
|
||||
proxy => { type => 'string' },
|
||||
host => { type => 'string' },
|
||||
'tls-port' => { type => 'integer' },
|
||||
},
|
||||
},
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
my $rpcenv = PVE::RPCEnvironment::get();
|
||||
my $authuser = $rpcenv->get_user();
|
||||
|
||||
my ($user, undef, $realm) = PVE::AccessControl::verify_username($authuser);
|
||||
|
||||
raise_perm_exc("realm != pam") if $realm ne 'pam';
|
||||
|
||||
raise_perm_exc('user != root@pam') if $param->{upgrade} && $user ne 'root@pam';
|
||||
|
||||
my $node = $param->{node};
|
||||
my $proxy = $param->{proxy};
|
||||
if (!$proxy) {
|
||||
my $host = `hostname -f` || PVE::INotify::nodename();
|
||||
chomp $host;
|
||||
$proxy = $host;
|
||||
}
|
||||
|
||||
my $authpath = "/nodes/$node";
|
||||
|
||||
my ($ticket, $proxyticket) = PVE::AccessControl::assemble_spice_ticket($authuser, 0, $node);
|
||||
|
||||
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;
|
||||
|
||||
my $port = PVE::Tools::next_spice_port();
|
||||
|
||||
my $shcmd;
|
||||
|
||||
if ($user eq 'root@pam') {
|
||||
if ($param->{upgrade}) {
|
||||
my $upgradecmd = "pveupgrade --shell";
|
||||
$shcmd = [ '/bin/bash', '-c', $upgradecmd ];
|
||||
} else {
|
||||
$shcmd = [ '/bin/bash', '-l' ];
|
||||
}
|
||||
} else {
|
||||
$shcmd = [ '/bin/login' ];
|
||||
}
|
||||
|
||||
my $timeout = 10;
|
||||
|
||||
my $cmd = ['/usr/bin/spiceterm', '--port', $port, '--addr', '127.0.0.1',
|
||||
'--timeout', $timeout, '--authpath', $authpath,
|
||||
'--permissions', 'Sys.Console', '--', @$shcmd];
|
||||
|
||||
my $realcmd = sub {
|
||||
my $upid = shift;
|
||||
|
||||
syslog ('info', "starting spiceterm $upid\n");
|
||||
|
||||
my $cmdstr = join (' ', @$cmd);
|
||||
syslog ('info', "launch command: $cmdstr");
|
||||
|
||||
eval {
|
||||
foreach my $k (keys %ENV) {
|
||||
next if $k eq 'PATH' || $k eq 'TERM' || $k eq 'USER' || $k eq 'HOME';
|
||||
delete $ENV{$k};
|
||||
}
|
||||
$ENV{PWD} = '/';
|
||||
$ENV{SPICE_TICKET} = $ticket;
|
||||
PVE::Tools::run_command($cmd, errmsg => "spiceterm failed");
|
||||
};
|
||||
if (my $err = $@) {
|
||||
syslog ('err', $err);
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
my $upid = $rpcenv->fork_worker('spiceshell', "", $user, $realcmd);
|
||||
|
||||
PVE::Tools::wait_for_vnc_port($port);
|
||||
|
||||
return {
|
||||
type => 'spice',
|
||||
title => "Shell on '$node'",
|
||||
host => $proxyticket, # this break tls hostname verification, so we need to use 'host-subject'
|
||||
proxy => "http://$proxy:3128",
|
||||
'tls-port' => $port,
|
||||
'host-subject' => $subject,
|
||||
ca => $cacert,
|
||||
password => $ticket,
|
||||
'delete-this-file' => 1,
|
||||
};
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method({
|
||||
name => 'dns',
|
||||
path => 'dns',
|
||||
|
||||
2
debian/control.in
vendored
2
debian/control.in
vendored
@ -3,7 +3,7 @@ Version: @VERSION@-@PACKAGERELEASE@
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
Depends: perl (>= 5.10.0-19), libtimedate-perl, libauthen-pam-perl, libintl-perl, rsync, libjson-perl, liblockfile-simple-perl, vncterm, qemu-server (>= 1.1-1), libwww-perl (>= 6.04-1), libnet-http-perl (>= 6.06-1), libhttp-daemon-perl, wget, libnet-dns-perl, vlan, ifenslave-2.6 (>= 1.1.0-10), liblinux-inotify2-perl, debconf (>= 0.5) | debconf-2.0, netcat-traditional, pve-cluster (>= 1.0-29), libpve-common-perl, libpve-storage-perl, libterm-readline-gnu-perl, libpve-access-control (>= 3.0-2), libio-socket-ssl-perl, libfilesys-df-perl, libfile-readbackwards-perl, libfile-sync-perl, redhat-cluster-pve, resource-agents-pve, fence-agents-pve, cstream, postfix | mail-transport-agent, libxml-parser-perl, lzop, dtach, libanyevent-perl, liburi-perl, logrotate, libanyevent-http-perl, apt-transport-https, libapt-pkg-perl, libcrypt-ssleay-perl, liblwp-protocol-https-perl
|
||||
Depends: perl (>= 5.10.0-19), libtimedate-perl, libauthen-pam-perl, libintl-perl, rsync, libjson-perl, liblockfile-simple-perl, vncterm, qemu-server (>= 1.1-1), libwww-perl (>= 6.04-1), libnet-http-perl (>= 6.06-1), libhttp-daemon-perl, wget, libnet-dns-perl, vlan, ifenslave-2.6 (>= 1.1.0-10), liblinux-inotify2-perl, debconf (>= 0.5) | debconf-2.0, netcat-traditional, pve-cluster (>= 1.0-29), libpve-common-perl, libpve-storage-perl, libterm-readline-gnu-perl, libpve-access-control (>= 3.0-2), libio-socket-ssl-perl, libfilesys-df-perl, libfile-readbackwards-perl, libfile-sync-perl, redhat-cluster-pve, resource-agents-pve, fence-agents-pve, cstream, postfix | mail-transport-agent, libxml-parser-perl, lzop, dtach, libanyevent-perl, liburi-perl, logrotate, libanyevent-http-perl, apt-transport-https, libapt-pkg-perl, libcrypt-ssleay-perl, liblwp-protocol-https-perl, spiceterm
|
||||
Conflicts: netcat-openbsd, vzdump
|
||||
Replaces: vzdump
|
||||
Provides: vzdump
|
||||
|
||||
@ -250,6 +250,18 @@ Ext.define('PVE.Utils', { statics: {
|
||||
return data;
|
||||
},
|
||||
|
||||
render_console_viewer: function(value) {
|
||||
if (!value) {
|
||||
return PVE.Utils.defaultText + ' (Java VNC Applet)';
|
||||
} else if (value === 'applet') {
|
||||
return 'Java VNC Applet';
|
||||
} else if (value === 'vv') {
|
||||
return 'SPICE (remote-viewer)';
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
language_map: {
|
||||
zh_CN: 'Chinese',
|
||||
ca: 'Catalan',
|
||||
@ -507,6 +519,7 @@ Ext.define('PVE.Utils', { statics: {
|
||||
vncproxy: [ 'VM/CT', gettext('Console') ],
|
||||
spiceproxy: [ 'VM/CT', gettext('Console') + ' (Spice)' ],
|
||||
vncshell: [ '', gettext('Shell') ],
|
||||
spiceshell: [ '', gettext('Shell') + ' (Spice)' ],
|
||||
qmsnapshot: [ 'VM', gettext('Snapshot') ],
|
||||
qmrollback: [ 'VM', gettext('Rollback') ],
|
||||
qmdelsnapshot: [ 'VM', gettext('Delete Snapshot') ],
|
||||
@ -911,6 +924,31 @@ Ext.define('PVE.Utils', { statics: {
|
||||
nw.focus();
|
||||
},
|
||||
|
||||
defaultViewer: function(){
|
||||
return PVE.VersionInfo.console || 'applet';
|
||||
},
|
||||
|
||||
openSpiceViewer: function(url, params){
|
||||
PVE.Utils.API2Request({
|
||||
url: url,
|
||||
params: params,
|
||||
method: 'POST',
|
||||
failure: function(response, opts){
|
||||
Ext.Msg.alert('Error', response.htmlStatus);
|
||||
},
|
||||
success: function(response, opts){
|
||||
var raw = "[virt-viewer]\n";
|
||||
Ext.Object.each(response.result.data, function(k, v) {
|
||||
raw += k + "=" + v + "\n";
|
||||
});
|
||||
var url = 'data:application/x-virt-viewer;charset=UTF-8,' +
|
||||
encodeURIComponent(raw);
|
||||
|
||||
window.open(url, "_top");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// comp.setLoading() is buggy in ExtJS 4.0.7, so we
|
||||
// use el.mask() instead
|
||||
setErrorMask: function(comp, msg) {
|
||||
|
||||
@ -45,6 +45,35 @@ Ext.define('PVE.dc.KeyboardEdit', {
|
||||
}
|
||||
});
|
||||
|
||||
Ext.define('PVE.dc.ConsoleViewerEdit', {
|
||||
extend: 'PVE.window.Edit',
|
||||
|
||||
initComponent : function() {
|
||||
var me = this;
|
||||
|
||||
var data = [];
|
||||
|
||||
Ext.Array.each(['', 'applet', 'vv'], function(value) {
|
||||
data.push([value, PVE.Utils.render_console_viewer(value)]);
|
||||
});
|
||||
|
||||
Ext.applyIf(me, {
|
||||
subject: gettext('Console Viewer'),
|
||||
items: {
|
||||
xtype: 'pveKVComboBox',
|
||||
name: 'console',
|
||||
data: data,
|
||||
value: '',
|
||||
fieldLabel: gettext('Console Viewer')
|
||||
}
|
||||
});
|
||||
|
||||
me.callParent();
|
||||
|
||||
me.load();
|
||||
}
|
||||
});
|
||||
|
||||
Ext.define('PVE.dc.OptionView', {
|
||||
extend: 'PVE.grid.ObjectGrid',
|
||||
alias: ['widget.pveDcOptionView'],
|
||||
@ -75,6 +104,12 @@ Ext.define('PVE.dc.OptionView', {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
console: {
|
||||
header: gettext('Console Viewer'),
|
||||
editor: 'PVE.dc.ConsoleViewerEdit',
|
||||
required: true,
|
||||
renderer: PVE.Utils.render_console_viewer
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -51,13 +51,12 @@ Ext.define('PVE.node.Config', {
|
||||
text: gettext('Shell'),
|
||||
disabled: !caps.nodes['Sys.Console'],
|
||||
handler: function() {
|
||||
var url = Ext.urlEncode({
|
||||
console: 'shell',
|
||||
node: nodename
|
||||
});
|
||||
var nw = window.open("?" + url, '_blank',
|
||||
"innerWidth=745,innerheight=427");
|
||||
nw.focus();
|
||||
if (PVE.Utils.defaultViewer() === 'vv') {
|
||||
var params = { proxy: window.location.hostname };
|
||||
PVE.Utils.openSpiceViewer('/nodes/' + nodename + '/spiceshell', params);
|
||||
} else {
|
||||
PVE.Utils.openConoleWindow('shell', undefined, nodename);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -145,10 +145,10 @@ Ext.define('PVE.qemu.Config', {
|
||||
text: gettext('Console'),
|
||||
disabled: !caps.vms['VM.Console'],
|
||||
handler: function() {
|
||||
if (spice) {
|
||||
openSpiceConsole(vmid, nodename, vmname);
|
||||
} else {
|
||||
if (PVE.VersionInfo.console === 'applet' || !spice) {
|
||||
PVE.Utils.openConoleWindow('kvm', vmid, nodename, vmname);
|
||||
} else {
|
||||
openSpiceConsole(vmid, nodename, vmname);
|
||||
}
|
||||
},
|
||||
menu: new Ext.menu.Menu({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user