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

Feature #1076: Add VNC support in SelfService.

When enabled in the occi server configuration file, UI users will be able to click the VNC icon that appears in the VM information.

Then the websockets proxy will be set up, provided that the machine has been configured with the appropiate GRAPHICS section etc. This must be done in the OCCI templates, and cannot be done by the UI user.

Wss sessions can be configured in the occi server configuration file. Unlike Sunstone, here they are transparent to the user and whenever they are enabled VNC sessions will be launched using wss:// automaticly. As such, it is not up to the user to choose the type of connection, and it fully depends on the server configuration.

Additionally the install_novnc.sh script has been updated and improved. The install.sh has been updated too.
This commit is contained in:
Hector Sanjuan 2012-02-13 15:55:11 +01:00
parent 6bb9cb74a2
commit 4ccaf9704a
9 changed files with 205 additions and 31 deletions

View File

@ -1012,7 +1012,8 @@ OCCI_LIB_FILES="src/cloud/occi/lib/OCCIServer.rb \
src/cloud/occi/lib/UserOCCI.rb \
src/cloud/occi/lib/UserPoolOCCI.rb \
src/cloud/occi/lib/ImageOCCI.rb \
src/cloud/occi/lib/ImagePoolOCCI.rb"
src/cloud/occi/lib/ImagePoolOCCI.rb \
src/sunstone/OpenNebulaVNC.rb"
OCCI_LIB_CLIENT_FILES="src/cloud/occi/lib/OCCIClient.rb"

View File

@ -7,35 +7,50 @@ if [ -z "$ONE_LOCATION" ]; then
ONE_SHARE=/usr/share/one
ONE_PUBLIC_SUNSTONE=/usr/lib/one/sunstone/public
SUNSTONE_CONF=/etc/one/sunstone-server.conf
ONE_PUBLIC_SELFSERVICE=/usr/lib/one/ruby/cloud/occi/ui/public
SELFSERVICE_CONF=/etc/one/occi-server.conf
else
ONE_SHARE=$ONE_LOCATION/share
ONE_PUBLIC_SUNSTONE=$ONE_LOCATION/lib/sunstone/public
SUNSTONE_CONF=$ONE_LOCATION/etc/sunstone-server.conf
ONE_PUBLIC_SELFSERVICE=$ONE_LOCATION/lib/ruby/cloud/occi/ui/public
SELFSERVICE_CONF=$ONE_LOCATION/etc/occi-server.conf
fi
echo "Downloading noVNC latest version..."
mkdir -p $NOVNC_TMP
wget -P $NOVNC_TMP --no-check-certificate http://github.com/kanaka/noVNC/tarball/master
cd $NOVNC_TMP
curl -O -# -L http://github.com/kanaka/noVNC/tarball/master
if [ $? -ne 0 ]; then
echo "Error downloading noVNC"
echo "\nError downloading noVNC"
exit 1
fi
echo "Extracting files to temporary folder..."
tar=`ls -rt $NOVNC_TMP|tail -n1`
tar -C $ONE_SHARE -mxvzf $NOVNC_TMP/$tar
tar -C $ONE_SHARE -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..."
mkdir -p $ONE_PUBLIC_SUNSTONE/vendor/noVNC
mv $ONE_SHARE/noVNC/include/ $ONE_PUBLIC_SUNSTONE/vendor/noVNC/
cp -r $ONE_SHARE/noVNC/include/ $ONE_PUBLIC_SUNSTONE/vendor/noVNC/
sed -i.bck "s%^\(:vnc_proxy_path: \).*$%\1$ONE_SHARE/$PROXY_PATH%" $SUNSTONE_CONF
echo "Installing SelfService client libraries in $ONE_PUBLIC_SELFSERVICE..."
mkdir -p $ONE_PUBLIC_SELFSERVICE/vendor/noVNC
cp -r $ONE_SHARE/noVNC/include/ $ONE_PUBLIC_SELFSERVICE/vendor/noVNC/
#Update file permissions
chmod +x $ONE_SHARE/noVNC/utils/launch.sh
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
echo "Backing up and updating $SELFSERVICE_CONF with new VNC proxy path..."
sed -i.bck "s%^\(:vnc_proxy_path:\).*$%\1 $ONE_SHARE/$PROXY_PATH%" $SELFSERVICE_CONF
echo "Installation successful"

View File

@ -52,5 +52,26 @@
:cpu: 8
:memory: 8192
# Default language setting for Self-Service UI
#############################################################
### SelfService UI Settings
#############################################################
# Default language setting
:lang: en_US
# 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_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.
# vnc_proxy_cert: Certificate to encrypt wss connections.
# vnc_proxy_key: Key for wss connections. Only necessary if not included in cert.
:vnc_enable: no
:vnc_proxy_base_port: 33876
:vnc_proxy_path:
:vnc_proxy_support_wss: no
:vnc_proxy_cert:
:vnc_proxy_key:

View File

@ -30,6 +30,8 @@ require 'ImagePoolOCCI'
require 'UserOCCI'
require 'UserPoolOCCI'
require 'OpenNebulaVNC'
require 'pp'
@ -236,7 +238,6 @@ class OCCIServer < CloudServer
return to_occi_xml(vm, 200)
end
# Deletes a COMPUTE resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Delete confirmation msg or error,
@ -505,4 +506,33 @@ class OCCIServer < CloudServer
return to_occi_xml(user, 200)
end
############################################################################
# VNC Methods
############################################################################
def startvnc(id,config)
vm = VirtualMachineOCCI.new(
VirtualMachine.build_xml(id),
@client)
rc = vm.info
if OpenNebula.is_error?(rc)
error = "Error starting VNC session, "
error += "could not retrieve Virtual Machine"
return [404,error]
end
vnc_proxy = OpenNebulaVNC.new(config,{:json_errors => false})
return vnc_proxy.start(vm)
end
def stopvnc(pipe)
begin
OpenNebulaVNC.stop(pipe)
rescue Exception => e
return [500, e.message]
end
return [200,nil]
end
end

View File

@ -309,7 +309,19 @@ end
## UI
##############################################
post '/config' do
get '/ui/config/:opt' do
case params[:opt]
when "lang" then session[:lang]
when "wss"
wss = settings.config[:vnc_proxy_support_wss]
wss = (wss == true || wss == "yes" || wss == "only" ? "yes" : "no")
return wss
when "vnc" then settings.config[:vnc_enable] ? "yes" : "no"
else [404, "Unknown configuration option"]
end
end
post '/ui/config' do
begin
body = JSON.parse(request.body.read)
rescue
@ -321,6 +333,7 @@ post '/config' do
when "lang" then session[:lang]=value
end
end
return 200
end
get '/ui/login' do
@ -355,3 +368,57 @@ post '/ui/upload' do
result,rc = @occi_server.post_storage(request)
treat_response(result,rc)
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)
[200, info.to_json]
else
rc
end
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]
msg = "It seems there is no VNC proxy running for this machine"
return [403, msg]
end
rc = @occi_server.stopvnc(vnc_hash[vm_id][:pipe])
if rc[0] == 200
session['vnc'].delete(vm_id)
end
rc
end

View File

@ -45,7 +45,7 @@ function setLang(lang_str){
if (('localStorage' in window) && (window['localStorage'] !== null)){
localStorage['lang']=lang_str;
};
$.post('config',JSON.stringify({lang:lang_str}),function(){window.location.href = "./ui"});
$.post('ui/config',JSON.stringify({lang:lang_str}),function(){window.location.href = "./ui"});
};
$(document).ready(function(){

View File

@ -413,7 +413,7 @@ var OCCI = {
params.data.body = '<DISK id="'+disk_id+'"><SAVE_AS name="'+im_name+'" /></DISK>';
OCCI.Action.update(params,OCCI.VM.resource,"saveas");
},
/* "vnc" : function(params,startstop){
"vnc" : function(params,startstop){
var callback = params.success;
var callback_error = params.error;
var id = params.data.id;
@ -423,7 +423,7 @@ var OCCI = {
var action = OCCI.Helper.action(method);
var request = OCCI.Helper.request(resource,method, id);
$.ajax({
url: "vm/" + id + "/" + method,
url: "ui/" + method + "/" + id,
type: "POST",
dataType: "json",
success: function(response){
@ -440,13 +440,16 @@ var OCCI = {
},
"stopvnc" : function(params){
OCCI.VM.vnc(params,"stopvnc");
},
/*
"monitor" : function(params){
OCCI.Action.monitor(params,OCCI.VM.resource,false);
},
"monitor_all" : function(params){
OCCI.Action.monitor(params,OCCI.VM.resource,true);
}*/
}
*/
},
"Image": {

View File

@ -15,16 +15,19 @@
/* -------------------------------------------------------------------------- */
/*Virtual Machines tab plugin*/
//var INCLUDE_URI = "vendor/noVNC/include/";
var INCLUDE_URI = "vendor/noVNC/include/";
//var VM_HISTORY_LENGTH = 40;
/*
function loadVNC(){
var script = '<script src="vendor/noVNC/include/vnc.js"></script>';
document.write(script);
}
loadVNC();
var vnc_enable=false;
var use_wss=false;
/*
var vm_graphs = [
{ title : tr("CPU"),
monitor_resources : "cpu_usage",
@ -264,7 +267,6 @@ var vm_actions = {
error: onError
},
/*
"VM.startvnc" : {
type: "single",
call: OCCI.VM.startvnc,
@ -280,6 +282,7 @@ var vm_actions = {
notify: true
},
/*
"VM.monitor" : {
type: "monitor",
call : OCCI.VM.monitor,
@ -540,6 +543,10 @@ function updateVMInfo(request,vm){
<td class="key_td">'+tr("Memory")+'</td>\
<td class="value_td">'+vm_info.MEMORY+'</td>\
</tr>\
<tr>\
<td class="key_td">'+tr("Launch VNC session")+'</td>\
<td class="value_td">'+vncIcon(vm_info)+'</td>\
</tr>\
</tbody>\
</table>\
<div class="form_buttons">\
@ -940,7 +947,7 @@ function setVMAutorefresh(){
},INTERVAL+someTime());
}
/*
function updateVNCState(rfb, state, oldstate, msg) {
var s, sb, cad, klass;
s = $D('VNC_status');
@ -1016,7 +1023,7 @@ function setupVNC(){
Sunstone.runAction("VM.stopvnc",id);
});
$('.vnc',main_tabs_context).live("click",function(){
$('.vnc').live("click",function(){
//Which VM is it?
var id = $(this).attr('vm_id');
//Set attribute to dialog
@ -1029,7 +1036,7 @@ function setupVNC(){
function vncCallback(request,response){
rfb = new RFB({'target': $D('VNC_canvas'),
'encrypt': false,
'encrypt': use_wss,
'true_color': true,
'local_cursor': true,
'shared': true,
@ -1049,6 +1056,20 @@ function vncCallback(request,response){
}
function vncIcon(vm){
var gr_icon;
if (vnc_enable){
gr_icon = '<a class="vnc" href="#" vm_id="'+vm.ID+'">';
gr_icon += '<img src="images/vnc_on.png" alt=\"'+tr("Open VNC Session")+'\" /></a>';
}
else {
gr_icon = '<img src="images/vnc_off.png" alt=\"'+tr("VNC Disabled")+'\" />';
}
return gr_icon;
}
/*
function vncIcon(vm){
var graphics = vm.TEMPLATE.GRAPHICS;
var state = vm.STATE;
@ -1063,6 +1084,9 @@ function vncIcon(vm){
return gr_icon;
}
*/
/*
function vmMonitorError(req,error_json){
var message = error_json.error.message;
var info = req.request.data[0].monitor;
@ -1070,9 +1094,9 @@ function vmMonitorError(req,error_json){
var id_suffix = labels.replace(/,/g,'_');
var id = '#vm_monitor_'+id_suffix;
$('#vm_monitoring_tab '+id).html('<div style="padding-left:20px;">'+message+'</div>');
}
}*/
*/
// At this point the DOM is ready and the sunstone.js ready() has been run.
$(document).ready(function(){
@ -1102,7 +1126,7 @@ $(document).ready(function(){
//setupCreateVMDialog();
setupSaveasDialog();
setVMAutorefresh();
//setupVNC();
setupVNC();
initCheckAllBoxes(dataTable_vMachines);
tableCheckboxesListener(dataTable_vMachines);

View File

@ -49,16 +49,29 @@ var config_tab = {
Sunstone.addMainTab('config_tab',config_tab);
$(document).ready(function(){
if (lang)
$('table#config_table #lang_sel option[value="'+lang+'"]').attr('selected','selected');
$('table#config_table #lang_sel').change(function(){
setLang($(this).val());
});
$('#li_config_tab').click(function(){
hideDialog();
});
//Set lang to the right value
if (lang)
$('table#config_table #lang_sel option[value="'+lang+'"]').attr('selected','selected');
//Listen to changes in language
$('table#config_table #lang_sel').change(function(){
setLang($(this).val());
});
//Vendor customization, change small logo
$('div#logo img').attr('src',logo_small);
$.get('ui/config/vnc',function(response){
if (response == "true" || response == "yes")
vnc_enable=true; //defined in compute.js
});
$.get('ui/config/wss', function(response){
if (response == "true" || response == "yes")
use_wss=true; //defined in compute.js
});
});