diff --git a/src/cloud/occi/etc/occi-server.conf b/src/cloud/occi/etc/occi-server.conf index 90ea4df134..7d42afbf3d 100644 --- a/src/cloud/occi/etc/occi-server.conf +++ b/src/cloud/occi/etc/occi-server.conf @@ -52,9 +52,8 @@ :cpu: 8 :memory: 8192 - ############################################################# -### SelfService UI Settings +# OCCI UI Settings (SelfService) ############################################################# # Default language setting @@ -70,6 +69,7 @@ # 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 diff --git a/src/cloud/occi/lib/ImageOCCI.rb b/src/cloud/occi/lib/ImageOCCI.rb index 777876fdcd..f95f4f65bc 100755 --- a/src/cloud/occi/lib/ImageOCCI.rb +++ b/src/cloud/occi/lib/ImageOCCI.rb @@ -84,7 +84,7 @@ class ImageOCCI < Image end # Creates the OCCI representation of an Image - def to_occi(base_url) + def to_occi(base_url, verbose=false) begin occi_im = ERB.new(OCCI_IMAGE) occi_im_text = occi_im.result(binding) diff --git a/src/cloud/occi/lib/ImagePoolOCCI.rb b/src/cloud/occi/lib/ImagePoolOCCI.rb index ee38636867..db1d89d306 100755 --- a/src/cloud/occi/lib/ImagePoolOCCI.rb +++ b/src/cloud/occi/lib/ImagePoolOCCI.rb @@ -30,7 +30,7 @@ class ImagePoolOCCI < ImagePool } # Creates the OCCI representation of a Virtual Machine Pool - def to_occi(base_url) + def to_occi(base_url, verbose=false) begin occi = ERB.new(OCCI_IMAGE_POOL) occi_text = occi.result(binding) diff --git a/src/cloud/occi/lib/OCCIServer.rb b/src/cloud/occi/lib/OCCIServer.rb index 12035fe18a..f762fe1fbc 100755 --- a/src/cloud/occi/lib/OCCIServer.rb +++ b/src/cloud/occi/lib/OCCIServer.rb @@ -512,15 +512,13 @@ class OCCIServer < CloudServer ############################################################################ def startvnc(id,config) - vm = VirtualMachineOCCI.new( - VirtualMachine.build_xml(id), - @client) - + 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] + error = "Error starting VNC session, " + error << "could not retrieve Virtual Machine" + return [404, error] end vnc_proxy = OpenNebulaVNC.new(config,{:json_errors => false}) @@ -533,6 +531,7 @@ class OCCIServer < CloudServer rescue Exception => e return [500, e.message] end + return [200,nil] end end diff --git a/src/cloud/occi/lib/UserOCCI.rb b/src/cloud/occi/lib/UserOCCI.rb index fa8a960ef2..ecb71deb37 100644 --- a/src/cloud/occi/lib/UserOCCI.rb +++ b/src/cloud/occi/lib/UserOCCI.rb @@ -51,7 +51,7 @@ class UserOCCI < User end # Creates the OCCI representation of a User - def to_occi(base_url) + def to_occi(base_url, verbose=false) quota = Quota.new user_usage = quota.get_usage(self.id, nil, FORCE_USAGE) user_usage.delete(:uid) diff --git a/src/cloud/occi/lib/UserPoolOCCI.rb b/src/cloud/occi/lib/UserPoolOCCI.rb index 2745020dc7..6455a2c3b8 100644 --- a/src/cloud/occi/lib/UserPoolOCCI.rb +++ b/src/cloud/occi/lib/UserPoolOCCI.rb @@ -30,7 +30,7 @@ class UserPoolOCCI < UserPool } # Creates the OCCI representation of a User Pool - def to_occi(base_url) + def to_occi(base_url, verbose=false) begin occi = ERB.new(OCCI_USER_POOL) occi_text = occi.result(binding) diff --git a/src/cloud/occi/lib/VirtualMachineOCCI.rb b/src/cloud/occi/lib/VirtualMachineOCCI.rb index 4cb8754653..3a190e571a 100755 --- a/src/cloud/occi/lib/VirtualMachineOCCI.rb +++ b/src/cloud/occi/lib/VirtualMachineOCCI.rb @@ -122,7 +122,7 @@ class VirtualMachineOCCI < VirtualMachine end # Creates the VMI representation of a Virtual Machine - def to_occi(base_url) + def to_occi(base_url, verbose=false) begin occi_vm = ERB.new(OCCI_VM) occi_vm_text = occi_vm.result(binding) diff --git a/src/cloud/occi/lib/VirtualNetworkOCCI.rb b/src/cloud/occi/lib/VirtualNetworkOCCI.rb index 68edb59c7f..6efe071bba 100755 --- a/src/cloud/occi/lib/VirtualNetworkOCCI.rb +++ b/src/cloud/occi/lib/VirtualNetworkOCCI.rb @@ -54,7 +54,7 @@ class VirtualNetworkOCCI < VirtualNetwork end # Creates the OCCI representation of a Virtual Network - def to_occi(base_url) + def to_occi(base_url, verbose=false) network_address = nil network_size = nil diff --git a/src/cloud/occi/lib/VirtualNetworkPoolOCCI.rb b/src/cloud/occi/lib/VirtualNetworkPoolOCCI.rb index 3de2469ae9..a88fdf6d0c 100755 --- a/src/cloud/occi/lib/VirtualNetworkPoolOCCI.rb +++ b/src/cloud/occi/lib/VirtualNetworkPoolOCCI.rb @@ -31,7 +31,8 @@ class VirtualNetworkPoolOCCI < VirtualNetworkPool # Creates the OCCI representation of a Virtual Machine Pool - def to_occi(base_url)begin + def to_occi(base_url, verbose=false) + begin occi = ERB.new(OCCI_NETWORK_POOL) occi_text = occi.result(binding) rescue Exception => e diff --git a/src/cloud/occi/lib/occi-server.rb b/src/cloud/occi/lib/occi-server.rb index b64016525d..ad51901120 100755 --- a/src/cloud/occi/lib/occi-server.rb +++ b/src/cloud/occi/lib/occi-server.rb @@ -306,19 +306,22 @@ get '/user/:id' do end ############################################## -## UI +## OCCI UI (Self-Service) ############################################## -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 +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 @@ -333,6 +336,7 @@ post '/ui/config' do when "lang" then session[:lang]=value end end + return 200 end @@ -363,9 +367,12 @@ end post '/ui/upload' do file = Tempfile.new('uploaded_image') - FileUtils.cp(request.env['rack.input'].path,file.path) - request.params['file'] = file.path #so we can re-use occi post_storage() + FileUtils.cp(request.env['rack.input'].path, file.path) + + #so we can re-use occi post_storage() + request.params['file'] = {:tempfile => file} result,rc = @occi_server.post_storage(request) + treat_response(result,rc) end @@ -374,12 +381,11 @@ post '/ui/startvnc/:id' do return [403, "VNC sessions are disabled"] end - vm_id = params[:id] - + vm_id = params[:id] vnc_hash = session['vnc'] if !vnc_hash - session['vnc']= {} + session['vnc'] = {} elsif vnc_hash[vm_id] #return existing information info = vnc_hash[vm_id].clone @@ -395,10 +401,10 @@ post '/ui/startvnc/:id' do session['vnc'][vm_id] = info.clone info.delete(:pipe) - [200, info.to_json] - else - rc + rc = [200, info.to_json] end + + return rc end post '/ui/stopvnc/:id' do @@ -406,12 +412,11 @@ post '/ui/stopvnc/:id' do return [403, "VNC sessions are disabled"] end - vm_id = params[:id] + 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] + return [403, "It seems there is no VNC proxy running for this machine"] end rc = @occi_server.stopvnc(vnc_hash[vm_id][:pipe]) @@ -420,5 +425,5 @@ post '/ui/stopvnc/:id' do session['vnc'].delete(vm_id) end - rc + return rc end diff --git a/src/cloud/occi/lib/ui/public/js/occi.js b/src/cloud/occi/lib/ui/public/js/occi.js index 569a75e527..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", 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 de32d3e084..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,14 +41,33 @@ 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(){ + Sunstone.runAction('Config.list'); + $('#li_config_tab').click(function(){ hideDialog(); }); @@ -64,14 +83,4 @@ $(document).ready(function(){ //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 diff --git a/src/sunstone/OpenNebulaVNC.rb b/src/sunstone/OpenNebulaVNC.rb index e2e3ac3fde..71c92b6fe2 100644 --- a/src/sunstone/OpenNebulaVNC.rb +++ b/src/sunstone/OpenNebulaVNC.rb @@ -14,22 +14,83 @@ # limitations under the License. # #--------------------------------------------------------------------------- # - -#This file provides support for launching and stopping a websockify proxy - 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] + 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] - @enable_wss = (@wss == "yes") || (@wss == "only") || (@wss == true) - @cert = @enable_wss? config[:vnc_proxy_cert] : nil - @key = @enable_wss? config[:vnc_proxy_key] : nil - @options=opt + + 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: #{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] @@ -38,52 +99,5 @@ class OpenNebulaVNC end end - def start(vm_resource) - 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 - - # The VM host and its VNC port - host = vm_resource['/VM/HISTORY_RECORDS/HISTORY[last()]/HOSTNAME'] - vnc_port = vm_resource['TEMPLATE/GRAPHICS/PORT'] - # The port on which the proxy will listen - proxy_port = @proxy_base_port + vnc_port.to_i - - if !@proxy_path || @proxy_path.size == 0 - return error(403,"VNC proxy not configured") - end - - 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 - - proxy_cmd = "#{@proxy_path} #{proxy_options} #{proxy_port} #{host}:#{vnc_port}" - - begin - $stderr.puts("Starting vnc proxy: #{proxy_cmd}") - pipe = IO.popen(proxy_cmd) - rescue Exception => e - error = Error.new(e.message) - return [500, error.to_json] - end - - vnc_pw = vm_resource['TEMPLATE/GRAPHICS/PASSWD'] - - info = {:pipe => pipe, :port => proxy_port, :password => vnc_pw} - return [200, info] - end - - #handle exceptions outside - def self.stop(pipe) - Process.kill('KILL',pipe.pid) - pipe.close - end end diff --git a/src/sunstone/models/SunstoneServer.rb b/src/sunstone/models/SunstoneServer.rb index 359a24267e..c4049404e6 100644 --- a/src/sunstone/models/SunstoneServer.rb +++ b/src/sunstone/models/SunstoneServer.rb @@ -150,37 +150,6 @@ class SunstoneServer ############################################################################ # Unused ############################################################################ - # 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 - - ############################################################################ - # - ############################################################################ def get_vm_log(id) resource = retrieve_resource("vm", id) if OpenNebula.is_error?(resource) @@ -202,7 +171,6 @@ class SunstoneServer end end - ######################################################################## # VNC ######################################################################## @@ -233,7 +201,6 @@ class SunstoneServer ############################################################################ # ############################################################################ - def get_monitoring(id, resource, monitor_resources, gid) watch_client = case resource when "vm","VM" @@ -262,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 f342e91665..303961fb60 100644 --- a/src/sunstone/public/js/plugins/config-tab.js +++ b/src/sunstone/public/js/plugins/config-tab.js @@ -47,13 +47,33 @@ 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 : { @@ -84,16 +104,17 @@ function updateWss(){ }; $(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); - - $.get('config/wss',function(response){ - if (response != "no") - $('table#config_table input#wss_checkbox').attr('checked','checked'); - }); }); \ No newline at end of file diff --git a/src/sunstone/sunstone-server.rb b/src/sunstone/sunstone-server.rb index bb9bdeba03..a2636ed929 100755 --- a/src/sunstone/sunstone-server.rb +++ b/src/sunstone/sunstone-server.rb @@ -132,7 +132,7 @@ helpers do else wss = settings.config[:vnc_proxy_support_wss] #limit to yes,no options - session[:wss] = (wss == true || wss == "yes" || wss == "only" ? + session[:wss] = (wss == true || wss == "yes" || wss == "only" ? "yes" : "no") end @@ -227,18 +227,18 @@ post '/logout' do end ############################################################################## -# Config and Logs +# User configuration and VM logs ############################################################################## -#get '/config' do -# @SunstoneServer.get_configuration(session[:user_id]) -#end -get '/config/:opt' do - case params[:opt] - when "lang" then session[:lang] - when "wss" then session[:wss] - else "unknown" - end +get '/config' do + uconf = { + :user_config => { + :lang => session[:lang], + :wss => session[:wss] + } + } + + [200, uconf.to_json] end post '/config' do @@ -250,8 +250,8 @@ post '/config' do body.each do | key,value | case key - when "lang" then session[:lang]=value - when "wss" then session[:wss]=value + when "lang" then session[:lang]= value + when "wss" then session[:wss] = value end end end