1
0
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:
Hector Sanjuan 2012-07-19 18:15:44 +02:00 committed by Ruben S. Montero
parent b26aa52c2b
commit 7b184d6c43
14 changed files with 209 additions and 252 deletions

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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){

View File

@ -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){

View File

@ -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(){

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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);
}, },

View File

@ -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%">\

View File

@ -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){

View File

@ -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!