1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-27 10:50:10 +03:00

Merge branch 'master' of git.opennebula.org:one

This commit is contained in:
Tino Vazquez 2012-07-23 17:22:27 +02:00
commit 4891a5c1e5
16 changed files with 213 additions and 265 deletions

@ -1,7 +1,7 @@
#!/bin/bash
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
ONE_SHARE=/usr/share/one
@ -28,25 +28,40 @@ fi
echo "Extracting files to temporary folder..."
tar=`ls -rt $NOVNC_TMP|tail -n1`
tar -C $ONE_SHARE -mxzf $NOVNC_TMP/$tar
tar -mxzf $NOVNC_TMP/$tar
if [ $? -ne 0 ]; then
echo "Error untaring noVNC"
exit 1
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..."
rm -rf $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..."
rm -rf $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..."
sed -i.bck "s%^\(:vnc_proxy_path:\).*$%\1 $ONE_SHARE/$PROXY_PATH%" $SUNSTONE_CONF

@ -88,8 +88,7 @@
# VNC Configuration
# vnc_enable: yes | no. Allow users to launch vnc sessions.
# base_port: base_port + vnc_port of the VM is the port where the
# proxy will listen for VNC session connections to that VM.
# vnc_proxy_port: port where the VNC proxy will listen
# 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.
# "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_enable: no
:vnc_proxy_base_port: 33876
:vnc_proxy_port: 33876
:vnc_proxy_path:
:vnc_proxy_support_wss: no
:vnc_proxy_cert:

@ -558,7 +558,7 @@ class OCCIServer < CloudServer
# VNC Methods
############################################################################
def startvnc(id,config)
def startvnc(id,vnc)
vm = VirtualMachineOCCI.new(VirtualMachine.build_xml(id), @client)
rc = vm.info
@ -568,18 +568,6 @@ class OCCIServer < CloudServer
return [404, error]
end
vnc_proxy = OpenNebulaVNC.new(config, logger, {:json_errors => false})
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]
return vnc.proxy(vm)
end
end

@ -124,6 +124,26 @@ end
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
##############################################################################
@ -359,6 +379,9 @@ get '/ui/config' do
config << " <LANG>#{session[:lang]}</LANG>"
config << " <WSS>#{wss}</WSS>"
config << " <VNC>#{vnc}</VNC>"
if vnc == "yes"
config << " <VNC_PROXY_PORT>#{settings.vnc.proxy_port}</VNC_PROXY_PORT>"
end
config << "</UI_CONFIGURARION>"
return [200, config]
@ -416,53 +439,8 @@ post '/ui/upload' do
end
post '/ui/startvnc/:id' do
if !settings.config[:vnc_enable]
return [403, "VNC sessions are disabled"]
end
vm_id = params[:id]
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 = @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
@occi_server.startvnc(vm_id, settings.vnc)
end
post '/ui/stopvnc/:id' do
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
Sinatra::Application.run!

@ -477,10 +477,6 @@ var OCCI = {
},
"startvnc" : function(params){
OCCI.VM.vnc(params,"startvnc");
},
"stopvnc" : function(params){
OCCI.VM.vnc(params,"stopvnc");
}
/*
"monitor" : function(params){

@ -286,13 +286,6 @@ var vm_actions = {
callback: vncCallback,
error: onError,
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) {
var id = $vnc_dialog.attr('vm_id');
rfb.disconnect();
Sunstone.runAction("VM.stopvnc",id);
});
$('.vnc').live("click",function(){
//Which VM is it?
var id = $(this).attr('vm_id');
//Set attribute to dialog
$vnc_dialog.attr('vm_id',id);
//Request proxy server start
var id = $(this).attr('vm_id');
//Ask server for connection params
Sunstone.runAction("VM.startvnc",id);
return false;
});
@ -1058,19 +1047,14 @@ function vncCallback(request,response){
'local_cursor': true,
'shared': true,
'updateState': updateVNCState});
//fetch things from clicked element host - port - password
vnc_port = response["port"];
//Hopefully this is returning sunstone server address, where
//the proxy is running
vnc_host = window.location.hostname;
vnc_pw = response["password"];
setTimeout(function(){
rfb.connect(vnc_host, vnc_port, vnc_pw);
$vnc_dialog.dialog('open');
},4000);
var proxy_host = window.location.hostname;
var proxy_port = config_response["VNC_PROXY_PORT"];
var pw = response["password"];
var token = response["token"];
var path = '?token='+token;
rfb.connect(proxy_host, proxy_port, pw, path);
$vnc_dialog.dialog('open');
}
function vncIcon(vm){

@ -14,6 +14,7 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
var config_response = {}
var config_tab_content =
'<form>\
<table id="config_table" style="width:100%">\
@ -68,10 +69,12 @@ Sunstone.addActions(config_actions);
Sunstone.addMainTab('config_tab',config_tab);
function updateConfig(request, response){
var config = response;
config_response = response;
//These two variables defined in compute.js
vnc_enable = config['VNC'] == 'true' || config['VNC'] == 'yes' ? true : false;
use_wss = config['WSS'] == 'true' || config['WSS'] == 'yes'? true : false;
vnc_enable = config_response['VNC'] == 'true' ||
config_response['VNC'] == 'yes' ? true : false;
use_wss = config_response['WSS'] == 'true' ||
config_response['WSS'] == 'yes'? true : false;
};
$(document).ready(function(){

@ -415,6 +415,9 @@ int ImageManager::delete_image(int iid, const string& ds_data)
else
{
imd->rm(img->get_oid(), *drv_msg);
img->set_state(Image::DELETE);
ipool->update(img);
}
img->unlock();
@ -436,6 +439,7 @@ int ImageManager::delete_image(int iid, const string& ds_data)
{
release_cloning_image(cloning_id);
}
return 0;
}

@ -126,7 +126,6 @@ static void cp_action(istringstream& is,
int id,
const string& result)
{
int cloning_id;
string source;
string info;
@ -180,22 +179,10 @@ static void cp_action(istringstream& is,
ipool->update(image);
cloning_id = image->get_cloning_id();
image->clear_cloning_id();
image->unlock();
NebulaLog::log("ImM", Log::INFO, "Image copied and ready to use.");
if ( cloning_id != -1 ) // An Image clone operation finished
{
Nebula& nd = Nebula::instance();
ImageManager * im = nd.get_imagem();
im ->release_cloning_image(cloning_id);
}
return;
error:

@ -14,16 +14,27 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'json'
require 'OpenNebula'
#
# This class provides support for launching and stopping a websockify proxy
#
require 'json'
require 'OpenNebula'
TOKEN_EXPIRE_SECONDS = 4
class OpenNebulaVNC
def initialize(config, logger, opt={:json_errors => true})
@proxy_path = config[:vnc_proxy_path]
@proxy_base_port = config[:vnc_proxy_base_port].to_i
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_port = config[:vnc_proxy_port] ||
config[:vnc_proxy_base_port] #deprecated
@wss = config[:vnc_proxy_support_wss]
@ -34,34 +45,25 @@ class OpenNebulaVNC
else
@enable_wss = false
end
@options = opt
@options = opts
@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
def start(vm_resource)
# Check configurations and VM attributes
def start
if @proxy_path == nil || @proxy_path.empty?
return error(403,"VNC proxy not configured")
@logger.info "VNC proxy not configured"
return
end
if vm_resource['LCM_STATE'] != "3"
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 = ""
proxy_options = "--target-config=#{@token_folder} "
if @enable_wss
proxy_options << " --cert #{@cert}"
@ -69,25 +71,86 @@ class OpenNebulaVNC
proxy_options << " --ssl-only" if @wss == "only"
end
cmd ="#{@proxy_path} #{proxy_options} #{proxy_port} #{host}:#{vnc_port}"
cmd ="python #{@proxy_path} #{proxy_options} #{@proxy_port}"
begin
@logger.info { "Starting vnc proxy: #{cmd}" }
pipe = IO.popen(cmd)
@logger.info { "Starting VNC proxy: #{cmd}" }
@pipe = IO.popen(cmd,'r')
rescue Exception => e
return [500, OpenNebula::Error.new(e.message).to_json]
@logger.error e.message
return
end
vnc_pw = vm_resource['TEMPLATE/GRAPHICS/PASSWD']
info = {:pipe => pipe, :port => proxy_port, :password => vnc_pw}
return [200, info]
end
# Stop a VNC proxy handle exceptions outside
def self.stop(pipe)
Process.kill('KILL',pipe.pid)
pipe.close
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']
# 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
info = {
:password => vnc_pw,
:token => random_str,
}
# 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
private
@ -100,5 +163,4 @@ class OpenNebulaVNC
end
end
end

@ -62,16 +62,14 @@
# UI Settings
################################################################################
# :vnc_proxy_
# base_port: base_port + vnc_port of the VM is the port where the
# proxy will listen for VNC session connections to that VM.
# port: port where the vnc proxy will listen
# path: path to the websockets proxy (set by install_novnc.sh)
# support_wss: no | yes | only. For yes and only, provide path to
# cert and key. "yes" means both ws and wss connections will
# be supported.
# cert: Certificate to encrypt wss connections.
# key: Key for wss connections. Only if not included in cert.
#
:vnc_proxy_base_port: 29876
# cert and key. "yes" means both ws and wss connections will be
# supported.
# vnc_proxy_cert: Certificate to encrypt wss connections.
# vnc_proxy_key: Key for wss connections. Only necessary if not included in cert.
:vnc_proxy_port: 29876
:vnc_proxy_path:
:vnc_proxy_support_wss: no
:vnc_proxy_cert:

@ -228,34 +228,18 @@ class SunstoneServer < CloudServer
########################################################################
# VNC
########################################################################
def startvnc(id, config)
def startvnc(id, vnc)
resource = retrieve_resource("vm", id)
if OpenNebula.is_error?(resource)
return [404, resource.to_json]
end
vnc_proxy = OpenNebulaVNC.new(config, logger)
return vnc_proxy.start(resource)
return vnc.proxy(resource)
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)
#pool_element
pool = case resource

@ -678,9 +678,6 @@ var OpenNebula = {
"startvnc" : function(params){
OpenNebula.VM.vnc(params,"startvnc");
},
"stopvnc" : function(params){
OpenNebula.VM.vnc(params,"stopvnc");
},
"monitor" : function(params){
OpenNebula.Action.monitor(params,OpenNebula.VM.resource,false);
},

@ -14,7 +14,7 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
var config_response;
var config_response = {};
var config_tab_content =
'<form>\
<table id="config_table" style="width:100%">\

@ -411,13 +411,6 @@ var vm_actions = {
notify: true
},
"VM.stopvnc" : {
type: "single",
call: OpenNebula.VM.stopvnc,
error: onError,
notify: true
},
"VM.monitor" : {
type: "monitor",
call : OpenNebula.VM.monitor,
@ -1538,17 +1531,13 @@ function setupVNC(){
});
dialog.bind( "dialogclose", function(event, ui) {
var id = $vnc_dialog.attr('vm_id');
rfb.disconnect();
Sunstone.runAction("VM.stopvnc",id);
});
$('.vnc').live("click",function(){
//Which VM is it?
var id = $(this).attr('vm_id');
//Set attribute to dialog
$vnc_dialog.attr('vm_id',id);
//Request proxy server start
//Ask server for connection params
Sunstone.runAction("VM.startvnc",id);
return false;
});
@ -1561,19 +1550,14 @@ function vncCallback(request,response){
'local_cursor': true,
'shared': true,
'updateState': updateVNCState});
//fetch things from clicked element host - port - password
vnc_port = response["port"];
//Hopefully this is returning sunstone server address, where
//the proxy is running
vnc_host = window.location.hostname;
vnc_pw = response["password"];
setTimeout(function(){
rfb.connect(vnc_host, vnc_port, vnc_pw);
$vnc_dialog.dialog('open');
},4000);
var proxy_host = window.location.hostname;
var proxy_port = config_response['system_config']['vnc_proxy_port'];
var pw = response["password"];
var token = response["token"];
var path = '?token='+token;
rfb.connect(proxy_host, proxy_port, pw, path);
$vnc_dialog.dialog('open');
}
function vncIcon(vm){

@ -97,6 +97,17 @@ end
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
##############################################################################
@ -256,10 +267,10 @@ get '/config' do
:user_config => {
:lang => session[:lang],
:wss => session[:wss],
:marketplace_url => settings.config[:marketplace_url]
},
: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
##############################################################################
# Stop the VNC Session of 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
# Start VNC Session for a target VM
##############################################################################
post '/vm/:id/startvnc' do
vm_id = params[:id]
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
@SunstoneServer.startvnc(vm_id, settings.vnc)
end
##############################################################################
@ -416,3 +383,5 @@ post '/:resource/:id/action' do
params[:id],
request.body.read)
end
Sinatra::Application.run!