mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-25 06:03:36 +03:00
Feature #1209: Single VNC proxy for all connections
Taking advantage of latest developments contributed to websockify, we can now make use of multiples targets validated by a system of file-based tokens. The stopvnc actions dissapear as we only have to close the connection. The proxy is launched at the start of Sunstone and shutdown and the end. The tokens which allow to set up the proxied connections expire after 4 seconds. Necessary modifications have been made in Sunstone and SelfService. novnc install script has been modified to fetch the websockify proxy files from the original project. Also, only the strictly necessary files for novnc+websockify to run are now installed. (cherry picked from commit 89631ebdb4c8a5368924cc04ddea0ebf955d75c5)
This commit is contained in:
parent
b26aa52c2b
commit
7b184d6c43
@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
NOVNC_TMP=/tmp/one/novnc-$(date "+%Y%m%d%H%M%S")
|
NOVNC_TMP=/tmp/one/novnc-$(date "+%Y%m%d%H%M%S")
|
||||||
PROXY_PATH=noVNC/utils/websockify
|
PROXY_PATH=websockify/websockify
|
||||||
|
|
||||||
if [ -z "$ONE_LOCATION" ]; then
|
if [ -z "$ONE_LOCATION" ]; then
|
||||||
ONE_SHARE=/usr/share/one
|
ONE_SHARE=/usr/share/one
|
||||||
@ -28,25 +28,40 @@ fi
|
|||||||
|
|
||||||
echo "Extracting files to temporary folder..."
|
echo "Extracting files to temporary folder..."
|
||||||
tar=`ls -rt $NOVNC_TMP|tail -n1`
|
tar=`ls -rt $NOVNC_TMP|tail -n1`
|
||||||
tar -C $ONE_SHARE -mxzf $NOVNC_TMP/$tar
|
tar -mxzf $NOVNC_TMP/$tar
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Error untaring noVNC"
|
echo "Error untaring noVNC"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Moving files to OpenNebula $ONE_SHARE folder..."
|
|
||||||
rm -rf $ONE_SHARE/noVNC
|
|
||||||
dir=`ls -rt $ONE_SHARE|tail -n1`
|
|
||||||
mv $ONE_SHARE/$dir $ONE_SHARE/noVNC
|
|
||||||
|
|
||||||
echo "Installing Sunstone client libraries in $ONE_PUBLIC_SUNSTONE..."
|
echo "Installing Sunstone client libraries in $ONE_PUBLIC_SUNSTONE..."
|
||||||
|
rm -rf $ONE_PUBLIC_SUNSTONE/vendor/noVNC/
|
||||||
mkdir -p $ONE_PUBLIC_SUNSTONE/vendor/noVNC
|
mkdir -p $ONE_PUBLIC_SUNSTONE/vendor/noVNC
|
||||||
cp -r $ONE_SHARE/noVNC/include/ $ONE_PUBLIC_SUNSTONE/vendor/noVNC/
|
cp -r $NOVNC_TMP/*noVNC*/include/ $ONE_PUBLIC_SUNSTONE/vendor/noVNC/
|
||||||
|
|
||||||
echo "Installing SelfService client libraries in $ONE_PUBLIC_SELFSERVICE..."
|
echo "Installing SelfService client libraries in $ONE_PUBLIC_SELFSERVICE..."
|
||||||
|
rm -rf $ONE_PUBLIC_SELFSERVICE/vendor/noVNC/
|
||||||
mkdir -p $ONE_PUBLIC_SELFSERVICE/vendor/noVNC
|
mkdir -p $ONE_PUBLIC_SELFSERVICE/vendor/noVNC
|
||||||
cp -r $ONE_SHARE/noVNC/include/ $ONE_PUBLIC_SELFSERVICE/vendor/noVNC/
|
cp -r $NOVNC_TMP/*noVNC*/include/ $ONE_PUBLIC_SELFSERVICE/vendor/noVNC/
|
||||||
|
|
||||||
|
cd $ONE_SHARE
|
||||||
|
rm -rf $NOVNC_TMP
|
||||||
|
|
||||||
|
echo "Downloading Websockify VNC proxy files"
|
||||||
|
rm -rf $ONE_SHARE/websockify
|
||||||
|
mkdir -p $ONE_SHARE/websockify
|
||||||
|
cd $ONE_SHARE/websockify
|
||||||
|
curl -O -# -L https://raw.github.com/kanaka/websockify/master/websockify
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "\nError downloading websockify"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
curl -O -# -L https://raw.github.com/kanaka/websockify/master/websocket.py
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "\nError downloading websocket.py"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Backing up and updating $SUNSTONE_CONF with new VNC proxy path..."
|
echo "Backing up and updating $SUNSTONE_CONF with new VNC proxy path..."
|
||||||
sed -i.bck "s%^\(:vnc_proxy_path:\).*$%\1 $ONE_SHARE/$PROXY_PATH%" $SUNSTONE_CONF
|
sed -i.bck "s%^\(:vnc_proxy_path:\).*$%\1 $ONE_SHARE/$PROXY_PATH%" $SUNSTONE_CONF
|
||||||
|
@ -88,8 +88,7 @@
|
|||||||
|
|
||||||
# VNC Configuration
|
# VNC Configuration
|
||||||
# vnc_enable: yes | no. Allow users to launch vnc sessions.
|
# vnc_enable: yes | no. Allow users to launch vnc sessions.
|
||||||
# base_port: base_port + vnc_port of the VM is the port where the
|
# vnc_proxy_port: port where the VNC proxy will listen
|
||||||
# proxy will listen for VNC session connections to that VM.
|
|
||||||
# vnc_proxy_path: path to the websockets proxy (set by install_novnc.sh)
|
# vnc_proxy_path: path to the websockets proxy (set by install_novnc.sh)
|
||||||
# support_wss: no | yes | only. If yes or only provide path to cert and key.
|
# support_wss: no | yes | only. If yes or only provide path to cert and key.
|
||||||
# "yes" means the proxy will accept both ws and wss connections.
|
# "yes" means the proxy will accept both ws and wss connections.
|
||||||
@ -97,7 +96,7 @@
|
|||||||
# vnc_proxy_key: Key for wss connections. Only necessary if not included in cert.
|
# vnc_proxy_key: Key for wss connections. Only necessary if not included in cert.
|
||||||
:vnc_enable: no
|
:vnc_enable: no
|
||||||
|
|
||||||
:vnc_proxy_base_port: 33876
|
:vnc_proxy_port: 33876
|
||||||
:vnc_proxy_path:
|
:vnc_proxy_path:
|
||||||
:vnc_proxy_support_wss: no
|
:vnc_proxy_support_wss: no
|
||||||
:vnc_proxy_cert:
|
:vnc_proxy_cert:
|
||||||
|
@ -558,7 +558,7 @@ class OCCIServer < CloudServer
|
|||||||
# VNC Methods
|
# VNC Methods
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
def startvnc(id,config)
|
def startvnc(id,vnc)
|
||||||
vm = VirtualMachineOCCI.new(VirtualMachine.build_xml(id), @client)
|
vm = VirtualMachineOCCI.new(VirtualMachine.build_xml(id), @client)
|
||||||
rc = vm.info
|
rc = vm.info
|
||||||
|
|
||||||
@ -568,18 +568,6 @@ class OCCIServer < CloudServer
|
|||||||
return [404, error]
|
return [404, error]
|
||||||
end
|
end
|
||||||
|
|
||||||
vnc_proxy = OpenNebulaVNC.new(config, logger, {:json_errors => false})
|
return vnc.proxy(vm)
|
||||||
return vnc_proxy.start(vm)
|
|
||||||
end
|
|
||||||
|
|
||||||
def stopvnc(pipe)
|
|
||||||
begin
|
|
||||||
OpenNebulaVNC.stop(pipe)
|
|
||||||
rescue Exception => e
|
|
||||||
logger.error {e.message}
|
|
||||||
return [500, "Error stopping VNC. Please check server logs."]
|
|
||||||
end
|
|
||||||
|
|
||||||
return [200,nil]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -124,6 +124,26 @@ end
|
|||||||
|
|
||||||
set :cloud_auth, cloud_auth
|
set :cloud_auth, cloud_auth
|
||||||
|
|
||||||
|
#start VNC proxy
|
||||||
|
|
||||||
|
configure do
|
||||||
|
set :run, false
|
||||||
|
|
||||||
|
if settings.config[:vnc_enable]
|
||||||
|
opts = {
|
||||||
|
:json_errors => false,
|
||||||
|
:token_folder_name => 'selfservice_vnc_tokens'
|
||||||
|
}
|
||||||
|
set :vnc, OpenNebulaVNC.new(settings.config,
|
||||||
|
settings.logger,
|
||||||
|
opts)
|
||||||
|
settings.vnc.start()
|
||||||
|
Kernel.at_exit do
|
||||||
|
settings.vnc.stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Helpers
|
# Helpers
|
||||||
##############################################################################
|
##############################################################################
|
||||||
@ -359,6 +379,9 @@ get '/ui/config' do
|
|||||||
config << " <LANG>#{session[:lang]}</LANG>"
|
config << " <LANG>#{session[:lang]}</LANG>"
|
||||||
config << " <WSS>#{wss}</WSS>"
|
config << " <WSS>#{wss}</WSS>"
|
||||||
config << " <VNC>#{vnc}</VNC>"
|
config << " <VNC>#{vnc}</VNC>"
|
||||||
|
if vnc == "yes"
|
||||||
|
config << " <VNC_PROXY_PORT>#{settings.vnc.proxy_port}</VNC_PROXY_PORT>"
|
||||||
|
end
|
||||||
config << "</UI_CONFIGURARION>"
|
config << "</UI_CONFIGURARION>"
|
||||||
|
|
||||||
return [200, config]
|
return [200, config]
|
||||||
@ -416,53 +439,8 @@ post '/ui/upload' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
post '/ui/startvnc/:id' do
|
post '/ui/startvnc/:id' do
|
||||||
if !settings.config[:vnc_enable]
|
|
||||||
return [403, "VNC sessions are disabled"]
|
|
||||||
end
|
|
||||||
|
|
||||||
vm_id = params[:id]
|
vm_id = params[:id]
|
||||||
vnc_hash = session['vnc']
|
@occi_server.startvnc(vm_id, settings.vnc)
|
||||||
|
|
||||||
if !vnc_hash
|
|
||||||
session['vnc'] = {}
|
|
||||||
elsif vnc_hash[vm_id]
|
|
||||||
#return existing information
|
|
||||||
info = vnc_hash[vm_id].clone
|
|
||||||
info.delete(:pipe)
|
|
||||||
|
|
||||||
return [200, info.to_json]
|
|
||||||
end
|
|
||||||
|
|
||||||
rc = @occi_server.startvnc(vm_id, settings.config)
|
|
||||||
|
|
||||||
if rc[0] == 200
|
|
||||||
info = rc[1]
|
|
||||||
session['vnc'][vm_id] = info.clone
|
|
||||||
info.delete(:pipe)
|
|
||||||
|
|
||||||
rc = [200, info.to_json]
|
|
||||||
end
|
|
||||||
|
|
||||||
return rc
|
|
||||||
end
|
end
|
||||||
|
|
||||||
post '/ui/stopvnc/:id' do
|
Sinatra::Application.run!
|
||||||
if !settings.config[:vnc_enable]
|
|
||||||
return [403, "VNC sessions are disabled"]
|
|
||||||
end
|
|
||||||
|
|
||||||
vm_id = params[:id]
|
|
||||||
vnc_hash = session['vnc']
|
|
||||||
|
|
||||||
if !vnc_hash || !vnc_hash[vm_id]
|
|
||||||
return [403, "It seems there is no VNC proxy running for this machine"]
|
|
||||||
end
|
|
||||||
|
|
||||||
rc = @occi_server.stopvnc(vnc_hash[vm_id][:pipe])
|
|
||||||
|
|
||||||
if rc[0] == 200
|
|
||||||
session['vnc'].delete(vm_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
return rc
|
|
||||||
end
|
|
||||||
|
@ -477,10 +477,6 @@ var OCCI = {
|
|||||||
},
|
},
|
||||||
"startvnc" : function(params){
|
"startvnc" : function(params){
|
||||||
OCCI.VM.vnc(params,"startvnc");
|
OCCI.VM.vnc(params,"startvnc");
|
||||||
},
|
|
||||||
"stopvnc" : function(params){
|
|
||||||
OCCI.VM.vnc(params,"stopvnc");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
"monitor" : function(params){
|
"monitor" : function(params){
|
||||||
|
@ -286,13 +286,6 @@ var vm_actions = {
|
|||||||
callback: vncCallback,
|
callback: vncCallback,
|
||||||
error: onError,
|
error: onError,
|
||||||
notify: true
|
notify: true
|
||||||
},
|
|
||||||
|
|
||||||
"VM.stopvnc" : {
|
|
||||||
type: "single",
|
|
||||||
call: OCCI.VM.stopvnc,
|
|
||||||
error: onError,
|
|
||||||
notify: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1035,17 +1028,13 @@ function setupVNC(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
dialog.bind( "dialogclose", function(event, ui) {
|
dialog.bind( "dialogclose", function(event, ui) {
|
||||||
var id = $vnc_dialog.attr('vm_id');
|
|
||||||
rfb.disconnect();
|
rfb.disconnect();
|
||||||
Sunstone.runAction("VM.stopvnc",id);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.vnc').live("click",function(){
|
$('.vnc').live("click",function(){
|
||||||
//Which VM is it?
|
//Which VM is it?
|
||||||
var id = $(this).attr('vm_id');
|
var id = $(this).attr('vm_id');
|
||||||
//Set attribute to dialog
|
//Ask server for connection params
|
||||||
$vnc_dialog.attr('vm_id',id);
|
|
||||||
//Request proxy server start
|
|
||||||
Sunstone.runAction("VM.startvnc",id);
|
Sunstone.runAction("VM.startvnc",id);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@ -1058,19 +1047,14 @@ function vncCallback(request,response){
|
|||||||
'local_cursor': true,
|
'local_cursor': true,
|
||||||
'shared': true,
|
'shared': true,
|
||||||
'updateState': updateVNCState});
|
'updateState': updateVNCState});
|
||||||
//fetch things from clicked element host - port - password
|
|
||||||
vnc_port = response["port"];
|
|
||||||
|
|
||||||
//Hopefully this is returning sunstone server address, where
|
var proxy_host = window.location.hostname;
|
||||||
//the proxy is running
|
var proxy_port = config_response["VNC_PROXY_PORT"];
|
||||||
vnc_host = window.location.hostname;
|
var pw = response["password"];
|
||||||
vnc_pw = response["password"];
|
var token = response["token"];
|
||||||
|
var path = '?token='+token;
|
||||||
setTimeout(function(){
|
rfb.connect(proxy_host, proxy_port, pw, path);
|
||||||
rfb.connect(vnc_host, vnc_port, vnc_pw);
|
|
||||||
$vnc_dialog.dialog('open');
|
$vnc_dialog.dialog('open');
|
||||||
},4000);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function vncIcon(vm){
|
function vncIcon(vm){
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
/* limitations under the License. */
|
/* limitations under the License. */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
var config_response = {}
|
||||||
var config_tab_content =
|
var config_tab_content =
|
||||||
'<form>\
|
'<form>\
|
||||||
<table id="config_table" style="width:100%">\
|
<table id="config_table" style="width:100%">\
|
||||||
@ -68,10 +69,12 @@ Sunstone.addActions(config_actions);
|
|||||||
Sunstone.addMainTab('config_tab',config_tab);
|
Sunstone.addMainTab('config_tab',config_tab);
|
||||||
|
|
||||||
function updateConfig(request, response){
|
function updateConfig(request, response){
|
||||||
var config = response;
|
config_response = response;
|
||||||
//These two variables defined in compute.js
|
//These two variables defined in compute.js
|
||||||
vnc_enable = config['VNC'] == 'true' || config['VNC'] == 'yes' ? true : false;
|
vnc_enable = config_response['VNC'] == 'true' ||
|
||||||
use_wss = config['WSS'] == 'true' || config['WSS'] == 'yes'? true : false;
|
config_response['VNC'] == 'yes' ? true : false;
|
||||||
|
use_wss = config_response['WSS'] == 'true' ||
|
||||||
|
config_response['WSS'] == 'yes'? true : false;
|
||||||
};
|
};
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
|
@ -14,16 +14,27 @@
|
|||||||
# limitations under the License. #
|
# limitations under the License. #
|
||||||
#--------------------------------------------------------------------------- #
|
#--------------------------------------------------------------------------- #
|
||||||
|
|
||||||
require 'json'
|
|
||||||
require 'OpenNebula'
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# This class provides support for launching and stopping a websockify proxy
|
# This class provides support for launching and stopping a websockify proxy
|
||||||
#
|
#
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
require 'OpenNebula'
|
||||||
|
|
||||||
|
TOKEN_EXPIRE_SECONDS = 4
|
||||||
|
|
||||||
class OpenNebulaVNC
|
class OpenNebulaVNC
|
||||||
def initialize(config, logger, opt={:json_errors => true})
|
|
||||||
|
attr_reader :proxy_port
|
||||||
|
|
||||||
|
def initialize(config, logger, opts={
|
||||||
|
:json_errors => true,
|
||||||
|
:token_folder_name => 'sunstone_vnc_tokens'})
|
||||||
|
@pipe = nil
|
||||||
|
@token_folder = File.join(VAR_LOCATION, opts[:token_folder_name])
|
||||||
@proxy_path = config[:vnc_proxy_path]
|
@proxy_path = config[:vnc_proxy_path]
|
||||||
@proxy_base_port = config[:vnc_proxy_base_port].to_i
|
@proxy_port = config[:vnc_proxy_port] ||
|
||||||
|
config[:vnc_proxy_base_port] #deprecated
|
||||||
|
|
||||||
@wss = config[:vnc_proxy_support_wss]
|
@wss = config[:vnc_proxy_support_wss]
|
||||||
|
|
||||||
@ -34,34 +45,25 @@ class OpenNebulaVNC
|
|||||||
else
|
else
|
||||||
@enable_wss = false
|
@enable_wss = false
|
||||||
end
|
end
|
||||||
|
@options = opts
|
||||||
@options = opt
|
|
||||||
@logger = logger
|
@logger = logger
|
||||||
|
|
||||||
|
begin
|
||||||
|
Dir.mkdir(@token_folder)
|
||||||
|
rescue Exception => e
|
||||||
|
@logger.error "Cannot create token folder"
|
||||||
|
@logger.error e.message
|
||||||
end
|
end
|
||||||
|
|
||||||
# Start a VNC proxy
|
end
|
||||||
def start(vm_resource)
|
|
||||||
# Check configurations and VM attributes
|
|
||||||
|
|
||||||
|
def start
|
||||||
if @proxy_path == nil || @proxy_path.empty?
|
if @proxy_path == nil || @proxy_path.empty?
|
||||||
return error(403,"VNC proxy not configured")
|
@logger.info "VNC proxy not configured"
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if vm_resource['LCM_STATE'] != "3"
|
proxy_options = "--target-config=#{@token_folder} "
|
||||||
return error(403,"VM is not running")
|
|
||||||
end
|
|
||||||
|
|
||||||
if vm_resource['TEMPLATE/GRAPHICS/TYPE'] != "vnc"
|
|
||||||
return error(403,"VM has no VNC configured")
|
|
||||||
end
|
|
||||||
|
|
||||||
# Proxy data
|
|
||||||
host = vm_resource['/VM/HISTORY_RECORDS/HISTORY[last()]/HOSTNAME']
|
|
||||||
vnc_port = vm_resource['TEMPLATE/GRAPHICS/PORT']
|
|
||||||
|
|
||||||
proxy_port = @proxy_base_port + vnc_port.to_i
|
|
||||||
|
|
||||||
proxy_options = ""
|
|
||||||
|
|
||||||
if @enable_wss
|
if @enable_wss
|
||||||
proxy_options << " --cert #{@cert}"
|
proxy_options << " --cert #{@cert}"
|
||||||
@ -69,25 +71,86 @@ class OpenNebulaVNC
|
|||||||
proxy_options << " --ssl-only" if @wss == "only"
|
proxy_options << " --ssl-only" if @wss == "only"
|
||||||
end
|
end
|
||||||
|
|
||||||
cmd ="#{@proxy_path} #{proxy_options} #{proxy_port} #{host}:#{vnc_port}"
|
cmd ="python #{@proxy_path} #{proxy_options} #{@proxy_port}"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@logger.info { "Starting vnc proxy: #{cmd}" }
|
@logger.info { "Starting VNC proxy: #{cmd}" }
|
||||||
pipe = IO.popen(cmd)
|
@pipe = IO.popen(cmd,'r')
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
return [500, OpenNebula::Error.new(e.message).to_json]
|
@logger.error e.message
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def proxy(vm_resource)
|
||||||
|
# Check configurations and VM attributes
|
||||||
|
if !@pipe
|
||||||
|
return error(400, "VNC Proxy is not running")
|
||||||
|
end
|
||||||
|
|
||||||
|
if vm_resource['LCM_STATE'] != "3"
|
||||||
|
return error(400,"VM is not running")
|
||||||
|
end
|
||||||
|
|
||||||
|
if vm_resource['TEMPLATE/GRAPHICS/TYPE'] != "vnc"
|
||||||
|
return error(400,"VM has no VNC configured")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Proxy data
|
||||||
|
host = vm_resource['/VM/HISTORY_RECORDS/HISTORY[last()]/HOSTNAME']
|
||||||
|
vnc_port = vm_resource['TEMPLATE/GRAPHICS/PORT']
|
||||||
vnc_pw = vm_resource['TEMPLATE/GRAPHICS/PASSWD']
|
vnc_pw = vm_resource['TEMPLATE/GRAPHICS/PASSWD']
|
||||||
info = {:pipe => pipe, :port => proxy_port, :password => vnc_pw}
|
|
||||||
|
|
||||||
return [200, info]
|
# Generate token random_str: host:port
|
||||||
|
random_str = rand(36**20).to_s(36) #random string a-z0-9 length 20
|
||||||
|
token = "#{random_str}: #{host}:#{vnc_port}"
|
||||||
|
token_file = 'one-'+vm_resource['ID']
|
||||||
|
|
||||||
|
# Create token file
|
||||||
|
begin
|
||||||
|
f = File.open(File.join(@token_folder, token_file), 'w')
|
||||||
|
f.write(token)
|
||||||
|
f.close
|
||||||
|
rescue Exception => e
|
||||||
|
@logger.error e.message
|
||||||
|
return error(500, "Cannot create VNC proxy token")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Stop a VNC proxy handle exceptions outside
|
info = {
|
||||||
def self.stop(pipe)
|
:password => vnc_pw,
|
||||||
Process.kill('KILL',pipe.pid)
|
:token => random_str,
|
||||||
pipe.close
|
}
|
||||||
|
|
||||||
|
# Delete token soon after
|
||||||
|
Thread.new do
|
||||||
|
sleep TOKEN_EXPIRE_SECONDS
|
||||||
|
delete_token(token_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
return [200, info.to_json]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Delete proxy token file
|
||||||
|
def delete_token(filename)
|
||||||
|
begin
|
||||||
|
File.delete(File.join(@token_folder, filename))
|
||||||
|
rescue => e
|
||||||
|
@logger.error "Error deleting token file for VM #{vm_id}"
|
||||||
|
@logger.error e.message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
if !@pipe then return end
|
||||||
|
@logger.info "Killing VNC proxy"
|
||||||
|
Process.kill('TERM',@pipe.pid)
|
||||||
|
@pipe.close
|
||||||
|
begin
|
||||||
|
Dir.rmdir(@token_folder)
|
||||||
|
rescue => e
|
||||||
|
@logger.error "Error deleting token folder"
|
||||||
|
@logger.error e.message
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -100,5 +163,4 @@ class OpenNebulaVNC
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -62,16 +62,14 @@
|
|||||||
# UI Settings
|
# UI Settings
|
||||||
################################################################################
|
################################################################################
|
||||||
# :vnc_proxy_
|
# :vnc_proxy_
|
||||||
# base_port: base_port + vnc_port of the VM is the port where the
|
# port: port where the vnc proxy will listen
|
||||||
# proxy will listen for VNC session connections to that VM.
|
|
||||||
# path: path to the websockets proxy (set by install_novnc.sh)
|
# path: path to the websockets proxy (set by install_novnc.sh)
|
||||||
# support_wss: no | yes | only. For yes and only, provide path to
|
# support_wss: no | yes | only. For yes and only, provide path to
|
||||||
# cert and key. "yes" means both ws and wss connections will
|
# cert and key. "yes" means both ws and wss connections will be
|
||||||
# be supported.
|
# supported.
|
||||||
# cert: Certificate to encrypt wss connections.
|
# vnc_proxy_cert: Certificate to encrypt wss connections.
|
||||||
# key: Key for wss connections. Only if not included in cert.
|
# vnc_proxy_key: Key for wss connections. Only necessary if not included in cert.
|
||||||
#
|
:vnc_proxy_port: 29876
|
||||||
:vnc_proxy_base_port: 29876
|
|
||||||
:vnc_proxy_path:
|
:vnc_proxy_path:
|
||||||
:vnc_proxy_support_wss: no
|
:vnc_proxy_support_wss: no
|
||||||
:vnc_proxy_cert:
|
:vnc_proxy_cert:
|
||||||
|
@ -228,34 +228,18 @@ class SunstoneServer < CloudServer
|
|||||||
########################################################################
|
########################################################################
|
||||||
# VNC
|
# VNC
|
||||||
########################################################################
|
########################################################################
|
||||||
def startvnc(id, config)
|
def startvnc(id, vnc)
|
||||||
resource = retrieve_resource("vm", id)
|
resource = retrieve_resource("vm", id)
|
||||||
if OpenNebula.is_error?(resource)
|
if OpenNebula.is_error?(resource)
|
||||||
return [404, resource.to_json]
|
return [404, resource.to_json]
|
||||||
end
|
end
|
||||||
|
|
||||||
vnc_proxy = OpenNebulaVNC.new(config, logger)
|
return vnc.proxy(resource)
|
||||||
return vnc_proxy.start(resource)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
############################################################################
|
########################################################################
|
||||||
#
|
#
|
||||||
############################################################################
|
########################################################################
|
||||||
def stopvnc(pipe)
|
|
||||||
begin
|
|
||||||
OpenNebulaVNC.stop(pipe)
|
|
||||||
rescue Exception => e
|
|
||||||
logger.error {e.message}
|
|
||||||
error = Error.new("Error stopping VNC. Please check server logs.")
|
|
||||||
return [500, error.to_json]
|
|
||||||
end
|
|
||||||
|
|
||||||
return [200, nil]
|
|
||||||
end
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
#
|
|
||||||
############################################################################
|
|
||||||
def get_pool_monitoring(resource, meters)
|
def get_pool_monitoring(resource, meters)
|
||||||
#pool_element
|
#pool_element
|
||||||
pool = case resource
|
pool = case resource
|
||||||
|
@ -678,9 +678,6 @@ var OpenNebula = {
|
|||||||
"startvnc" : function(params){
|
"startvnc" : function(params){
|
||||||
OpenNebula.VM.vnc(params,"startvnc");
|
OpenNebula.VM.vnc(params,"startvnc");
|
||||||
},
|
},
|
||||||
"stopvnc" : function(params){
|
|
||||||
OpenNebula.VM.vnc(params,"stopvnc");
|
|
||||||
},
|
|
||||||
"monitor" : function(params){
|
"monitor" : function(params){
|
||||||
OpenNebula.Action.monitor(params,OpenNebula.VM.resource,false);
|
OpenNebula.Action.monitor(params,OpenNebula.VM.resource,false);
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
/* limitations under the License. */
|
/* limitations under the License. */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
var config_response;
|
var config_response = {};
|
||||||
var config_tab_content =
|
var config_tab_content =
|
||||||
'<form>\
|
'<form>\
|
||||||
<table id="config_table" style="width:100%">\
|
<table id="config_table" style="width:100%">\
|
||||||
|
@ -411,13 +411,6 @@ var vm_actions = {
|
|||||||
notify: true
|
notify: true
|
||||||
},
|
},
|
||||||
|
|
||||||
"VM.stopvnc" : {
|
|
||||||
type: "single",
|
|
||||||
call: OpenNebula.VM.stopvnc,
|
|
||||||
error: onError,
|
|
||||||
notify: true
|
|
||||||
},
|
|
||||||
|
|
||||||
"VM.monitor" : {
|
"VM.monitor" : {
|
||||||
type: "monitor",
|
type: "monitor",
|
||||||
call : OpenNebula.VM.monitor,
|
call : OpenNebula.VM.monitor,
|
||||||
@ -1538,17 +1531,13 @@ function setupVNC(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
dialog.bind( "dialogclose", function(event, ui) {
|
dialog.bind( "dialogclose", function(event, ui) {
|
||||||
var id = $vnc_dialog.attr('vm_id');
|
|
||||||
rfb.disconnect();
|
rfb.disconnect();
|
||||||
Sunstone.runAction("VM.stopvnc",id);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.vnc').live("click",function(){
|
$('.vnc').live("click",function(){
|
||||||
//Which VM is it?
|
|
||||||
var id = $(this).attr('vm_id');
|
var id = $(this).attr('vm_id');
|
||||||
//Set attribute to dialog
|
|
||||||
$vnc_dialog.attr('vm_id',id);
|
//Ask server for connection params
|
||||||
//Request proxy server start
|
|
||||||
Sunstone.runAction("VM.startvnc",id);
|
Sunstone.runAction("VM.startvnc",id);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@ -1561,19 +1550,14 @@ function vncCallback(request,response){
|
|||||||
'local_cursor': true,
|
'local_cursor': true,
|
||||||
'shared': true,
|
'shared': true,
|
||||||
'updateState': updateVNCState});
|
'updateState': updateVNCState});
|
||||||
//fetch things from clicked element host - port - password
|
|
||||||
vnc_port = response["port"];
|
|
||||||
|
|
||||||
//Hopefully this is returning sunstone server address, where
|
var proxy_host = window.location.hostname;
|
||||||
//the proxy is running
|
var proxy_port = config_response['system_config']['vnc_proxy_port'];
|
||||||
vnc_host = window.location.hostname;
|
var pw = response["password"];
|
||||||
vnc_pw = response["password"];
|
var token = response["token"];
|
||||||
|
var path = '?token='+token;
|
||||||
setTimeout(function(){
|
rfb.connect(proxy_host, proxy_port, pw, path);
|
||||||
rfb.connect(vnc_host, vnc_port, vnc_pw);
|
|
||||||
$vnc_dialog.dialog('open');
|
$vnc_dialog.dialog('open');
|
||||||
},4000);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function vncIcon(vm){
|
function vncIcon(vm){
|
||||||
|
@ -97,6 +97,17 @@ end
|
|||||||
|
|
||||||
set :cloud_auth, cloud_auth
|
set :cloud_auth, cloud_auth
|
||||||
|
|
||||||
|
#start VNC proxy
|
||||||
|
|
||||||
|
configure do
|
||||||
|
set :run, false
|
||||||
|
set :vnc, OpenNebulaVNC.new(conf, settings.logger)
|
||||||
|
settings.vnc.start()
|
||||||
|
Kernel.at_exit do
|
||||||
|
settings.vnc.stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Helpers
|
# Helpers
|
||||||
##############################################################################
|
##############################################################################
|
||||||
@ -256,10 +267,10 @@ get '/config' do
|
|||||||
:user_config => {
|
:user_config => {
|
||||||
:lang => session[:lang],
|
:lang => session[:lang],
|
||||||
:wss => session[:wss],
|
:wss => session[:wss],
|
||||||
:marketplace_url => settings.config[:marketplace_url]
|
|
||||||
},
|
},
|
||||||
:system_config => {
|
:system_config => {
|
||||||
:marketplace_url => settings.config[:marketplace_url]
|
:marketplace_url => settings.config[:marketplace_url],
|
||||||
|
:vnc_proxy_port => settings.vnc.proxy_port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,55 +368,11 @@ post '/:pool' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Stop the VNC Session of a target VM
|
# Start VNC Session for a target VM
|
||||||
##############################################################################
|
|
||||||
post '/vm/:id/stopvnc' do
|
|
||||||
vm_id = params[:id]
|
|
||||||
vnc_hash = session['vnc']
|
|
||||||
|
|
||||||
if !vnc_hash || !vnc_hash[vm_id]
|
|
||||||
msg = "It seems there is no VNC proxy running for this machine"
|
|
||||||
return [403, OpenNebula::Error.new(msg).to_json]
|
|
||||||
end
|
|
||||||
|
|
||||||
rc = @SunstoneServer.stopvnc(vnc_hash[vm_id][:pipe])
|
|
||||||
|
|
||||||
if rc[0] == 200
|
|
||||||
session['vnc'].delete(vm_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
rc
|
|
||||||
end
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# Start a VNC Session for a target VM
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
post '/vm/:id/startvnc' do
|
post '/vm/:id/startvnc' do
|
||||||
vm_id = params[:id]
|
vm_id = params[:id]
|
||||||
|
@SunstoneServer.startvnc(vm_id, settings.vnc)
|
||||||
vnc_hash = session['vnc']
|
|
||||||
|
|
||||||
if !vnc_hash
|
|
||||||
session['vnc']= {}
|
|
||||||
elsif vnc_hash[vm_id]
|
|
||||||
#return existing information
|
|
||||||
info = vnc_hash[vm_id].clone
|
|
||||||
info.delete(:pipe)
|
|
||||||
|
|
||||||
return [200, info.to_json]
|
|
||||||
end
|
|
||||||
|
|
||||||
rc = @SunstoneServer.startvnc(vm_id,settings.config)
|
|
||||||
|
|
||||||
if rc[0] == 200
|
|
||||||
info = rc[1]
|
|
||||||
session['vnc'][vm_id] = info.clone
|
|
||||||
info.delete(:pipe)
|
|
||||||
|
|
||||||
[200, info.to_json]
|
|
||||||
else
|
|
||||||
rc
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
@ -416,3 +383,5 @@ post '/:resource/:id/action' do
|
|||||||
params[:id],
|
params[:id],
|
||||||
request.body.read)
|
request.body.read)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Sinatra::Application.run!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user