diff --git a/install.sh b/install.sh index 9c10727ba6..d5ce330bcb 100755 --- a/install.sh +++ b/install.sh @@ -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" diff --git a/share/install_novnc.sh b/share/install_novnc.sh index 52dbf373ef..861fe78315 100755 --- a/share/install_novnc.sh +++ b/share/install_novnc.sh @@ -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" \ 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..90ea4df134 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 + +############################################################# +### 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: diff --git a/src/cloud/occi/lib/OCCIServer.rb b/src/cloud/occi/lib/OCCIServer.rb index fbe3d210a9..d6c8691b96 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, 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 diff --git a/src/cloud/occi/lib/occi-server.rb b/src/cloud/occi/lib/occi-server.rb index 470ec9e19a..b64016525d 100755 --- a/src/cloud/occi/lib/occi-server.rb +++ b/src/cloud/occi/lib/occi-server.rb @@ -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 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..569a75e527 100644 --- a/src/cloud/occi/lib/ui/public/js/occi.js +++ b/src/cloud/occi/lib/ui/public/js/occi.js @@ -413,7 +413,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 +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": { 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..de32d3e084 100644 --- a/src/cloud/occi/lib/ui/public/js/plugins/configuration.js +++ b/src/cloud/occi/lib/ui/public/js/plugins/configuration.js @@ -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 + }); }); \ No newline at end of file