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 += '\"'+tr("Open'; + } + else { + gr_icon = '\"'+tr("VNC'; + } + 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