diff --git a/install.sh b/install.sh
index a9dee20015..b0d21b42ff 100755
--- a/install.sh
+++ b/install.sh
@@ -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"
diff --git a/share/install_novnc.sh b/share/install_novnc.sh
index 5dc90d6763..861fe78315 100755
--- a/share/install_novnc.sh
+++ b/share/install_novnc.sh
@@ -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"
\ No newline at end of file
diff --git a/src/cloud/occi/etc/occi-server.conf b/src/cloud/occi/etc/occi-server.conf
index 0084890209..7d42afbf3d 100644
--- a/src/cloud/occi/etc/occi-server.conf
+++ b/src/cloud/occi/etc/occi-server.conf
@@ -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:
diff --git a/src/cloud/occi/lib/OCCIServer.rb b/src/cloud/occi/lib/OCCIServer.rb
index 8a4f66cf33..f762fe1fbc 100755
--- a/src/cloud/occi/lib/OCCIServer.rb
+++ b/src/cloud/occi/lib/OCCIServer.rb
@@ -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
diff --git a/src/cloud/occi/lib/occi-server.rb b/src/cloud/occi/lib/occi-server.rb
index 470ec9e19a..bf7657fa91 100755
--- a/src/cloud/occi/lib/occi-server.rb
+++ b/src/cloud/occi/lib/occi-server.rb
@@ -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 = ""
+ config << " #{session[:lang]}"
+ config << " #{wss}"
+ config << " #{vnc}"
+ config << ""
+
+ 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
diff --git a/src/cloud/occi/lib/ui/public/js/locale.js b/src/cloud/occi/lib/ui/public/js/locale.js
index be816c7239..792772954f 100644
--- a/src/cloud/occi/lib/ui/public/js/locale.js
+++ b/src/cloud/occi/lib/ui/public/js/locale.js
@@ -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(){
diff --git a/src/cloud/occi/lib/ui/public/js/occi.js b/src/cloud/occi/lib/ui/public/js/occi.js
index 004938dc67..a818fe8008 100644
--- a/src/cloud/occi/lib/ui/public/js/occi.js
+++ b/src/cloud/occi/lib/ui/public/js/occi.js
@@ -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 = '';
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": {
diff --git a/src/cloud/occi/lib/ui/public/js/plugins/compute.js b/src/cloud/occi/lib/ui/public/js/plugins/compute.js
index 993faf93ab..5613a1b3a2 100644
--- a/src/cloud/occi/lib/ui/public/js/plugins/compute.js
+++ b/src/cloud/occi/lib/ui/public/js/plugins/compute.js
@@ -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 = '';
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){
'+tr("Memory")+' | \
'+vm_info.MEMORY+' | \
\
+ \
+ '+tr("Launch VNC session")+' | \
+ '+vncIcon(vm_info)+' | \
+
\
\
\
\
@@ -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 = '
';
+ gr_icon += '
';
+ }
+ else {
+ gr_icon = '

';
+ }
+ 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('
'+message+'
');
-}
+}*/
+
-*/
// 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);
diff --git a/src/cloud/occi/lib/ui/public/js/plugins/configuration.js b/src/cloud/occi/lib/ui/public/js/plugins/configuration.js
index c92844ac1e..900e21e32a 100644
--- a/src/cloud/occi/lib/ui/public/js/plugins/configuration.js
+++ b/src/cloud/occi/lib/ui/public/js/plugins/configuration.js
@@ -41,24 +41,46 @@ var config_tab_content =
\
';
+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);
});
\ No newline at end of file
diff --git a/src/sunstone/OpenNebulaVNC.rb b/src/sunstone/OpenNebulaVNC.rb
new file mode 100644
index 0000000000..2da2e57d34
--- /dev/null
+++ b/src/sunstone/OpenNebulaVNC.rb
@@ -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
diff --git a/src/sunstone/etc/sunstone-server.conf b/src/sunstone/etc/sunstone-server.conf
index 1927bfb949..bcc7e8225f 100644
--- a/src/sunstone/etc/sunstone-server.conf
+++ b/src/sunstone/etc/sunstone-server.conf
@@ -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
diff --git a/src/sunstone/models/SunstoneServer.rb b/src/sunstone/models/SunstoneServer.rb
index a8113bcf65..0c21f8440d 100644
--- a/src/sunstone/models/SunstoneServer.rb
+++ b/src/sunstone/models/SunstoneServer.rb
@@ -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)
diff --git a/src/sunstone/public/js/plugins/config-tab.js b/src/sunstone/public/js/plugins/config-tab.js
index 6f64a8bab4..303961fb60 100644
--- a/src/sunstone/public/js/plugins/config-tab.js
+++ b/src/sunstone/public/js/plugins/config-tab.js
@@ -33,6 +33,12 @@ var config_tab_content =
\
\
\
+
\
+ ' + tr("Secure websockets connection") + ' | \
+ \
+ \
+ | \
+
\
\
\
\
@@ -41,18 +47,74 @@ var config_tab_content =
\
';
+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);
});
\ No newline at end of file
diff --git a/src/sunstone/public/js/plugins/vms-tab.js b/src/sunstone/public/js/plugins/vms-tab.js
index fa69971dd6..cfb477c9c7 100644
--- a/src/sunstone/public/js/plugins/vms-tab.js
+++ b/src/sunstone/public/js/plugins/vms-tab.js
@@ -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,
diff --git a/src/sunstone/sunstone-server.rb b/src/sunstone/sunstone-server.rb
index 2ece360837..a2636ed929 100755
--- a/src/sunstone/sunstone-server.rb
+++ b/src/sunstone/sunstone-server.rb
@@ -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