mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
Merge branch 'feature-1069'
This commit is contained in:
commit
b66ebf5982
@ -1013,7 +1013,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"
|
||||
|
||||
@ -1077,7 +1078,8 @@ ETC_CLIENT_FILES="src/cli/etc/group.default"
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
SUNSTONE_FILES="src/sunstone/config.ru \
|
||||
src/sunstone/sunstone-server.rb"
|
||||
src/sunstone/sunstone-server.rb \
|
||||
src/sunstone/OpenNebulaVNC.rb"
|
||||
|
||||
SUNSTONE_BIN_FILES="src/sunstone/bin/sunstone-server"
|
||||
|
||||
|
@ -1,40 +1,56 @@
|
||||
#!/bin/bash
|
||||
|
||||
NOVNC_TMP=/tmp/one/novnc-$(date "+%Y%m%d%H%M%S")
|
||||
PROXY_PATH=noVNC/utils/websockify
|
||||
|
||||
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%^\(:novnc_path: \).*$%\1$ONE_SHARE/noVNC%" $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"
|
@ -52,5 +52,26 @@
|
||||
:cpu: 8
|
||||
:memory: 8192
|
||||
|
||||
# Default language setting for Self-Service UI
|
||||
#############################################################
|
||||
# OCCI UI Settings (SelfService)
|
||||
#############################################################
|
||||
|
||||
# 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:
|
||||
|
@ -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, :status=>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,32 @@ class OCCIServer < CloudServer
|
||||
|
||||
return to_occi_xml(user, :status=>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
|
||||
|
@ -306,10 +306,25 @@ get '/user/:id' do
|
||||
end
|
||||
|
||||
##############################################
|
||||
## UI
|
||||
## OCCI UI (Self-Service)
|
||||
##############################################
|
||||
|
||||
post '/config' do
|
||||
get '/ui/config' do
|
||||
wss = settings.config[:vnc_proxy_support_wss]
|
||||
wss = (wss == true || wss == "yes" || wss == "only" ? "yes" : "no")
|
||||
|
||||
vnc = settings.config[:vnc_enable] ? "yes" : "no"
|
||||
|
||||
config = "<UI_CONFIGURARION>"
|
||||
config << " <LANG>#{session[:lang]}</LANG>"
|
||||
config << " <WSS>#{wss}</WSS>"
|
||||
config << " <VNC>#{vnc}</VNC>"
|
||||
config << "</UI_CONFIGURARION>"
|
||||
|
||||
return [200, config]
|
||||
end
|
||||
|
||||
post '/ui/config' do
|
||||
begin
|
||||
body = JSON.parse(request.body.read)
|
||||
rescue
|
||||
@ -321,6 +336,8 @@ post '/config' do
|
||||
when "lang" then session[:lang]=value
|
||||
end
|
||||
end
|
||||
|
||||
return 200
|
||||
end
|
||||
|
||||
get '/ui/login' do
|
||||
@ -355,3 +372,55 @@ 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)
|
||||
|
||||
rc = [200, info.to_json]
|
||||
end
|
||||
|
||||
return rc
|
||||
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
|
||||
|
@ -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(){
|
||||
|
@ -342,6 +342,31 @@ var OCCI = {
|
||||
}
|
||||
},
|
||||
|
||||
"Config": {
|
||||
"resource": "CONFIG",
|
||||
|
||||
"list": function(params){
|
||||
var callback = params.success;
|
||||
var callback_error = params.error;
|
||||
|
||||
var resource = OCCI.Config.resource;
|
||||
var request = OCCI.Helper.request(resource,"list");
|
||||
|
||||
$.ajax({
|
||||
url: "ui/config",
|
||||
type: "GET",
|
||||
dataType: "xml ONEjson",
|
||||
success: function(response){
|
||||
return callback ? callback(request, response) : null;
|
||||
},
|
||||
error: function(response){
|
||||
return callback_error ?
|
||||
callback_error(request, OCCI.Error(response)) : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
"Network": {
|
||||
"resource": "NETWORK",
|
||||
|
||||
@ -413,7 +438,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 +448,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 +465,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": {
|
||||
|
@ -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);
|
||||
|
@ -41,24 +41,46 @@ var config_tab_content =
|
||||
</tr>\
|
||||
</table></form>';
|
||||
|
||||
var config_actions = {
|
||||
"Config.list" : {
|
||||
type : 'list',
|
||||
call : OCCI.Config.list,
|
||||
callback : updateConfig,
|
||||
error : onError
|
||||
},
|
||||
};
|
||||
|
||||
var config_tab = {
|
||||
title: tr("Configuration"),
|
||||
content: config_tab_content
|
||||
}
|
||||
|
||||
Sunstone.addActions(config_actions);
|
||||
Sunstone.addMainTab('config_tab',config_tab);
|
||||
|
||||
function updateConfig(request, response){
|
||||
var config = 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;
|
||||
};
|
||||
|
||||
$(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());
|
||||
});
|
||||
Sunstone.runAction('Config.list');
|
||||
|
||||
$('#li_config_tab').click(function(){
|
||||
hideDialog();
|
||||
});
|
||||
|
||||
$('div#logo img').attr('src',logo_small);
|
||||
//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);
|
||||
});
|
103
src/sunstone/OpenNebulaVNC.rb
Normal file
103
src/sunstone/OpenNebulaVNC.rb
Normal file
@ -0,0 +1,103 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'json'
|
||||
require 'OpenNebula'
|
||||
|
||||
#
|
||||
# This class provides support for launching and stopping a websockify proxy
|
||||
#
|
||||
class OpenNebulaVNC
|
||||
def initialize(config, opt={:json_errors => true})
|
||||
@proxy_path = config[:vnc_proxy_path]
|
||||
@proxy_base_port = config[:vnc_proxy_base_port].to_i
|
||||
|
||||
@wss = config[:vnc_proxy_support_wss]
|
||||
|
||||
if (@wss == "yes") || (@wss == "only") || (@wss == true)
|
||||
@enable_wss = true
|
||||
@cert = config[:vnc_proxy_cert]
|
||||
@key = config[:vnc_proxy_key]
|
||||
else
|
||||
@enable_wss = false
|
||||
end
|
||||
|
||||
@options = opt
|
||||
end
|
||||
|
||||
# Start a VNC proxy
|
||||
def start(vm_resource)
|
||||
# Check configurations and VM attributes
|
||||
|
||||
if @proxy_path == nil || @proxy_path.empty?
|
||||
return error(403,"VNC proxy not configured")
|
||||
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 = ""
|
||||
|
||||
if @enable_wss
|
||||
proxy_options << " --cert #{@cert}"
|
||||
proxy_options << " --key #{@key}" if @key && @key.size > 0
|
||||
proxy_options << " --ssl-only" if @wss == "only"
|
||||
end
|
||||
|
||||
cmd ="#{@proxy_path} #{proxy_options} #{proxy_port} #{host}:#{vnc_port}"
|
||||
|
||||
begin
|
||||
$stderr.puts("Starting vnc proxy: #{proxy_cmd}")
|
||||
pipe = IO.popen(cmd)
|
||||
rescue Exception => e
|
||||
return [500, OpenNebula::Error.new(e.message).to_json]
|
||||
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
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def error(code, msg)
|
||||
if @options[:json_errors]
|
||||
return [code,OpenNebula::Error.new(msg).to_json]
|
||||
else
|
||||
return [code,msg]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
@ -16,8 +16,20 @@
|
||||
:core_auth: cipher
|
||||
|
||||
# VNC Configuration
|
||||
# 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. For yes and only, provide path to
|
||||
# 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_base_port: 29876
|
||||
:novnc_path:
|
||||
:vnc_proxy_path:
|
||||
:vnc_proxy_support_wss: no
|
||||
:vnc_proxy_cert:
|
||||
:vnc_proxy_key:
|
||||
|
||||
|
||||
# Default language setting
|
||||
:lang: en_US
|
||||
|
@ -18,6 +18,7 @@ require 'OpenNebulaJSON'
|
||||
include OpenNebulaJSON
|
||||
|
||||
require 'acct/watch_client'
|
||||
require 'OpenNebulaVNC'
|
||||
|
||||
class SunstoneServer
|
||||
# FLAG that will filter the elements retrieved from the Pools
|
||||
@ -146,37 +147,6 @@ class SunstoneServer
|
||||
end
|
||||
end
|
||||
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
def get_configuration(user_id)
|
||||
if user_id != "0"
|
||||
return [401, ""]
|
||||
end
|
||||
|
||||
one_config = VAR_LOCATION + "/config"
|
||||
config = Hash.new
|
||||
|
||||
begin
|
||||
cfg = File.read(one_config)
|
||||
rescue Exception => e
|
||||
error = Error.new("Error reading config: #{e.inspect}")
|
||||
return [500, error.to_json]
|
||||
end
|
||||
|
||||
cfg.lines do |line|
|
||||
m=line.match(/^([^=]+)=(.*)$/)
|
||||
|
||||
if m
|
||||
name=m[1].strip.upcase
|
||||
value=m[2].strip
|
||||
config[name]=value
|
||||
end
|
||||
end
|
||||
|
||||
return [200, config.to_json]
|
||||
end
|
||||
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
@ -201,7 +171,6 @@ class SunstoneServer
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
########################################################################
|
||||
# VNC
|
||||
########################################################################
|
||||
@ -211,50 +180,16 @@ class SunstoneServer
|
||||
return [404, resource.to_json]
|
||||
end
|
||||
|
||||
if resource['LCM_STATE'] != "3"
|
||||
error = OpenNebula::Error.new("VM is not running")
|
||||
return [403, error.to_json]
|
||||
end
|
||||
|
||||
if resource['TEMPLATE/GRAPHICS/TYPE'] != "vnc"
|
||||
error = OpenNebula::Error.new("VM has no VNC configured")
|
||||
return [403, error.to_json]
|
||||
end
|
||||
|
||||
# The VM host and its VNC port
|
||||
host = resource['/VM/HISTORY_RECORDS/HISTORY[last()]/HOSTNAME']
|
||||
vnc_port = resource['TEMPLATE/GRAPHICS/PORT']
|
||||
# The noVNC proxy_port
|
||||
proxy_port = config[:vnc_proxy_base_port].to_i + vnc_port.to_i
|
||||
|
||||
begin
|
||||
novnc_cmd = "#{config[:novnc_path]}/utils/wsproxy.py"
|
||||
novnc_exec = "#{novnc_cmd} #{proxy_port} #{host}:#{vnc_port}"
|
||||
$stderr.puts("Starting vnc proxy: #{novnc_exec}")
|
||||
pipe = IO.popen(novnc_exec)
|
||||
rescue Exception => e
|
||||
error = Error.new(e.message)
|
||||
return [500, error.to_json]
|
||||
end
|
||||
|
||||
vnc_pw = resource['TEMPLATE/GRAPHICS/PASSWD']
|
||||
|
||||
info = {:pipe => pipe, :port => proxy_port, :password => vnc_pw}
|
||||
return [200, info]
|
||||
vnc_proxy = OpenNebulaVNC.new(config)
|
||||
return vnc_proxy.start(resource)
|
||||
end
|
||||
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
def stopvnc(id,pipe)
|
||||
resource = retrieve_resource("vm", id)
|
||||
if OpenNebula.is_error?(resource)
|
||||
return [404, resource.to_json]
|
||||
end
|
||||
|
||||
def stopvnc(pipe)
|
||||
begin
|
||||
Process.kill('KILL',pipe.pid)
|
||||
pipe.close
|
||||
OpenNebulaVNC.stop(pipe)
|
||||
rescue Exception => e
|
||||
error = Error.new(e.message)
|
||||
return [500, error.to_json]
|
||||
@ -266,7 +201,6 @@ class SunstoneServer
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
|
||||
def get_monitoring(id, resource, monitor_resources, gid)
|
||||
watch_client = case resource
|
||||
when "vm","VM"
|
||||
@ -295,18 +229,11 @@ class SunstoneServer
|
||||
return [200, rc.to_json]
|
||||
end
|
||||
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
|
||||
|
||||
|
||||
private
|
||||
|
||||
############################################################################
|
||||
#
|
||||
############################################################################
|
||||
def retrieve_resource(kind, id)
|
||||
resource = case kind
|
||||
when "group" then GroupJSON.new_with_id(id, @client)
|
||||
|
@ -33,6 +33,12 @@ var config_tab_content =
|
||||
</select>\
|
||||
</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("Secure websockets connection") + '</td>\
|
||||
<td class="value_td">\
|
||||
<input id="wss_checkbox" type="checkbox" value="yes" />\
|
||||
</td>\
|
||||
</tr>\
|
||||
</table>\
|
||||
\
|
||||
</div>\
|
||||
@ -41,18 +47,74 @@ var config_tab_content =
|
||||
</tr>\
|
||||
</table></form>';
|
||||
|
||||
var config_actions = {
|
||||
"Config.list" : {
|
||||
type: "list",
|
||||
call: OpenNebula.Config.list,
|
||||
callback: updateConfig,
|
||||
error: onError
|
||||
},
|
||||
};
|
||||
|
||||
var config_tab = {
|
||||
title: tr("Configuration"),
|
||||
content: config_tab_content
|
||||
}
|
||||
|
||||
Sunstone.addActions(config_actions);
|
||||
Sunstone.addMainTab('config_tab',config_tab);
|
||||
|
||||
|
||||
function updateConfig(request,response){
|
||||
var config = response['user_config'];
|
||||
|
||||
//Set wss checkbox to correct value
|
||||
if (config["wss"] == "yes"){
|
||||
$('table#config_table input#wss_checkbox').attr('checked','checked');
|
||||
};
|
||||
};
|
||||
|
||||
function updateWss(){
|
||||
var user_info_req = {
|
||||
data : {
|
||||
id: uid,
|
||||
},
|
||||
success: function(req,user_json) {
|
||||
var template = user_json.USER.TEMPLATE;
|
||||
var template_str="";
|
||||
template['VNC_WSS']=
|
||||
$('#config_table #wss_checkbox').is(':checked') ? "yes" : "no";
|
||||
//convert json to ONE template format - simple conversion
|
||||
$.each(template,function(key,value){
|
||||
template_str += (key + '=' + '"' + value + '"\n');
|
||||
});
|
||||
|
||||
var request = {
|
||||
data: {
|
||||
id: uid,
|
||||
extra_param: template_str
|
||||
},
|
||||
error: onError
|
||||
};
|
||||
OpenNebula.User.update(request);
|
||||
},
|
||||
};
|
||||
OpenNebula.User.show(user_info_req);
|
||||
$.post('config',JSON.stringify({wss : ($('#config_table #wss_checkbox').is(':checked') ? "yes" : "no")}));
|
||||
};
|
||||
|
||||
$(document).ready(function(){
|
||||
Sunstone.runAction('Config.list');
|
||||
|
||||
//Set the language select to correct value
|
||||
if (lang)
|
||||
$('table#config_table #lang_sel option[value="'+lang+'"]').attr('selected','selected');
|
||||
|
||||
//Listener to change language
|
||||
$('table#config_table #lang_sel').change(function(){
|
||||
setLang($(this).val());
|
||||
});
|
||||
|
||||
//Listener to wss change
|
||||
$('table#config_table #wss_checkbox').change(updateWss);
|
||||
});
|
@ -1227,7 +1227,7 @@ function setupVNC(){
|
||||
|
||||
function vncCallback(request,response){
|
||||
rfb = new RFB({'target': $D('VNC_canvas'),
|
||||
'encrypt': false,
|
||||
'encrypt': $('#config_table #wss_checkbox').is(':checked'),
|
||||
'true_color': true,
|
||||
'local_cursor': true,
|
||||
'shared': true,
|
||||
|
@ -39,6 +39,7 @@ SUNSTONE_ROOT_DIR = File.dirname(__FILE__)
|
||||
|
||||
$: << RUBY_LIB_LOCATION
|
||||
$: << RUBY_LIB_LOCATION+'/cloud'
|
||||
$: << SUNSTONE_ROOT_DIR
|
||||
$: << SUNSTONE_ROOT_DIR+'/models'
|
||||
|
||||
##############################################################################
|
||||
@ -115,12 +116,28 @@ helpers do
|
||||
session[:ip] = request.ip
|
||||
session[:remember] = params[:remember]
|
||||
|
||||
#User IU options initialization
|
||||
#Load options either from user settings or default config.
|
||||
# - LANG
|
||||
# - WSS CONECTION
|
||||
|
||||
if user['TEMPLATE/LANG']
|
||||
session[:lang] = user['TEMPLATE/LANG']
|
||||
else
|
||||
session[:lang] = settings.config[:lang]
|
||||
end
|
||||
|
||||
if user['TEMPLATE/VNC_WSS']
|
||||
session[:wss] = user['TEMPLATE/VNC_WSS']
|
||||
else
|
||||
wss = settings.config[:vnc_proxy_support_wss]
|
||||
#limit to yes,no options
|
||||
session[:wss] = (wss == true || wss == "yes" || wss == "only" ?
|
||||
"yes" : "no")
|
||||
end
|
||||
|
||||
#end user options
|
||||
|
||||
if params[:remember]
|
||||
env['rack.session.options'][:expire_after] = 30*60*60*24
|
||||
end
|
||||
@ -210,10 +227,18 @@ post '/logout' do
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Config and Logs
|
||||
# User configuration and VM logs
|
||||
##############################################################################
|
||||
|
||||
get '/config' do
|
||||
@SunstoneServer.get_configuration(session[:user_id])
|
||||
uconf = {
|
||||
:user_config => {
|
||||
:lang => session[:lang],
|
||||
:wss => session[:wss]
|
||||
}
|
||||
}
|
||||
|
||||
[200, uconf.to_json]
|
||||
end
|
||||
|
||||
post '/config' do
|
||||
@ -225,7 +250,8 @@ post '/config' do
|
||||
|
||||
body.each do | key,value |
|
||||
case key
|
||||
when "lang" then session[:lang]=value
|
||||
when "lang" then session[:lang]= value
|
||||
when "wss" then session[:wss] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -301,7 +327,8 @@ post '/vm/:id/stopvnc' do
|
||||
return [403, OpenNebula::Error.new(msg).to_json]
|
||||
end
|
||||
|
||||
rc = @SunstoneServer.stopvnc(vm_id, vnc_hash[vm_id][:pipe])
|
||||
rc = @SunstoneServer.stopvnc(vnc_hash[vm_id][:pipe])
|
||||
|
||||
if rc[0] == 200
|
||||
session['vnc'].delete(vm_id)
|
||||
end
|
||||
@ -327,7 +354,8 @@ post '/vm/:id/startvnc' do
|
||||
return [200, info.to_json]
|
||||
end
|
||||
|
||||
rc = @SunstoneServer.startvnc(vm_id, settings.config)
|
||||
rc = @SunstoneServer.startvnc(vm_id,settings.config)
|
||||
|
||||
if rc[0] == 200
|
||||
info = rc[1]
|
||||
session['vnc'][vm_id] = info.clone
|
||||
|
Loading…
x
Reference in New Issue
Block a user