diff --git a/src/sunstone/public/app/console/vnc.js b/src/sunstone/public/app/console/vnc.js index b0e385a697..c40278913f 100644 --- a/src/sunstone/public/app/console/vnc.js +++ b/src/sunstone/public/app/console/vnc.js @@ -15,45 +15,23 @@ /* -------------------------------------------------------------------------- */ define(function(require) { - require('vnc-util'); - require('vnc-webutil'); - require('vnc-base64'); - require('vnc-websock'); - require('vnc-des'); - require('vnc-keysymdef'); - require('vnc-keyboard'); - require('vnc-input'); - require('vnc-display'); - require('vnc-jsunzip'); - require('vnc-rfb'); - require('vnc-keysym'); - + var RFB = require("vnc-rfb").default; + var Config = require("sunstone-config"); var rfb; - var encrypt = WebUtil.getQueryVar('encrypt', (window.location.protocol === "https:")); - var repeaterID = WebUtil.getQueryVar('repeaterID', ''); - var true_color = WebUtil.getQueryVar('true_color', true); - var local_cursor = WebUtil.getQueryVar('cursor', true); - var shared = WebUtil.getQueryVar('shared', true); - var view_only = WebUtil.getQueryVar('view_only', false); - var host = WebUtil.getQueryVar('host', window.location.hostname); - var port = WebUtil.getQueryVar('port', window.location.port); - var token = WebUtil.getQueryVar('token', null); - var password = WebUtil.getQueryVar('password', null); - var path = WebUtil.getQueryVar('path', 'websockify'); function passwordRequired(rfb) { var msg; - msg = '
"; + msg += "Password Required: "; + msg += ""; + msg += "<\/form>"; + document.querySelector("#noVNC_status_bar").setAttribute("class", "noVNC_status_warn"); + document.querySelector("#noVNC_status").innerHTML = msg; + document.querySelector("#setPasswordForm").addEventListener("submit", setPassword); } function setPassword(event) { - rfb.sendPassword($D('password_input').value); + rfb.sendPassword(document.querySelector("#password_input").value); event.preventDefault(); return false; } @@ -75,15 +53,15 @@ define(function(require) { } function updateState(rfb, state, oldstate, msg) { var s, sb, cad, level; - s = $D('noVNC_status'); - sb = $D('noVNC_status_bar'); - cad = $D('sendCtrlAltDelButton'); + s = document.querySelector("#noVNC_status"); + sb = document.querySelector("#noVNC_status_bar"); + cad = document.querySelector("#sendCtrlAltDelButton"); switch (state) { - case 'failed': level = "error"; break; - case 'fatal': level = "error"; break; - case 'normal': level = "normal"; break; - case 'disconnected': level = "normal"; break; - case 'loaded': level = "normal"; break; + case "failed": level = "error"; break; + case "fatal": level = "error"; break; + case "normal": level = "normal"; break; + case "disconnected": level = "normal"; break; + case "loaded": level = "normal"; break; default: level = "warn"; break; } @@ -94,7 +72,7 @@ define(function(require) { xvpInit(0); } - if (typeof(msg) !== 'undefined') { + if (typeof(msg) !== "undefined") { sb.setAttribute("class", "noVNC_status_" + level); s.innerHTML = msg; } @@ -102,62 +80,59 @@ define(function(require) { function xvpInit(ver) { var xvpbuttons; - xvpbuttons = $D('noVNC_xvp_buttons'); + xvpbuttons = document.querySelector("#noVNC_xvp_buttons"); if (ver >= 1) { - xvpbuttons.style.display = 'inline'; + xvpbuttons.style.display = "inline"; } else { - xvpbuttons.style.display = 'none'; + xvpbuttons.style.display = "none"; } } - var host, port, password, path, token; + function getQueryVariable(variable) + { + var query = window.location.search.substring(1); + var vars = query.split("&"); + for (var i=0;i ",element); var graphics = element.TEMPLATE.GRAPHICS; var state = parseInt(element.LCM_STATE); diff --git a/src/sunstone/public/app/tabs/vms-tab/dialogs/vnc/html.hbs b/src/sunstone/public/app/tabs/vms-tab/dialogs/vnc/html.hbs index 3c71a0a800..d14f4313fa 100644 --- a/src/sunstone/public/app/tabs/vms-tab/dialogs/vnc/html.hbs +++ b/src/sunstone/public/app/tabs/vms-tab/dialogs/vnc/html.hbs @@ -19,7 +19,7 @@
{{tr "VNC"}} - {{tr "Loading"}} + @@ -33,7 +33,9 @@
- {{tr "Canvas not supported."}} +
+
+
\ No newline at end of file diff --git a/src/sunstone/public/app/utils/vnc.js b/src/sunstone/public/app/utils/vnc.js index bcb75343d9..e74ab733a1 100644 --- a/src/sunstone/public/app/utils/vnc.js +++ b/src/sunstone/public/app/utils/vnc.js @@ -15,33 +15,21 @@ /* -------------------------------------------------------------------------- */ define(function(require) { - INCLUDE_URI = "bower_components/no-vnc/include/"; - require('vnc-util'); - require('vnc-webutil'); - require('vnc-base64'); - require('vnc-websock'); - require('vnc-des'); - require('vnc-keysymdef'); - require('vnc-keyboard'); - require('vnc-input'); - require('vnc-display'); - require('vnc-jsunzip'); - require('vnc-rfb'); - require('vnc-keysym'); - - var Config = require('sunstone-config'); - + var RFB = require("vnc-rfb").default; + var Config = require("sunstone-config"); var _lock = false; var _rfb; + var _message = ""; + var _status = "Loading"; return { - 'lockStatus': lockStatus, - 'lock': lock, - 'unlock': unlock, - 'vncCallback': vncCallback, - 'disconnect': disconnect, - 'sendCtrlAltDel': sendCtrlAltDel - } + "lockStatus": lockStatus, + "lock": lock, + "unlock": unlock, + "vncCallback": vncCallback, + "disconnect": disconnect, + "sendCtrlAltDel": sendCtrlAltDel + }; function lockStatus() { return _lock; @@ -55,34 +43,64 @@ define(function(require) { _lock = false; } - function vncCallback(response) { - _rfb = new RFB({'target': $D('VNC_canvas'), - 'encrypt': Config.vncWSS == "yes", - 'true_color': true, - 'local_cursor': true, - 'shared': true, - 'onUpdateState': updateVNCState}); + function connected(){ + status("","Loaded"); + } + function status(message="", status=""){ + _message = message; + _status = status; + $(".NOVNC_message").text(_message); + $("#VNC_status").text(_status); + } + + function disconnectedFromServer(e){ + if (e.detail.clean) { + status("", "Loaded"); + } else { + status("Something went wrong, connection is closed", "Failed"); + } + } + + function vncCallback(response) { + var URL = ""; var proxy_host = window.location.hostname; var proxy_port = Config.vncProxyPort; var pw = response["password"]; var token = response["token"]; var vm_name = response["vm_name"]; - var path = '?token=' + token; - - var url = "vnc?"; - url += "host=" + proxy_host; - url += "&port=" + proxy_port; - url += "&token=" + token; - url += "&encrypt=" + Config.vncWSS; - url += "&title=" + vm_name; + var protocol = window.location.protocol; + var hostname = window.location.hostname; + var port = window.location.port; + if (protocol === "https:") { + URL = "wss"; + } else { + URL = "ws"; + } + URL += "://" + hostname; + URL += ":" + proxy_port; + URL += "?host=" + proxy_host; + URL += "&port=" + proxy_port; + URL += "&token=" + token; + URL += "&encrypt=" + Config.vncWSS; + URL += "&title=" + vm_name; if (!Config.requestVNCPassword) { - url += "&password=" + pw; + URL += "&password=" + pw; + } + var re = new RegExp("^(ws|wss):\\/\\/[\\w\\D]*?\\?", "gi"); + var link = URL.replace(re, protocol + "//" + hostname + ":" + port + "/vnc?"); + + try{ + _rfb = new RFB(document.querySelector("#VNC_canvas"), URL); + _rfb.addEventListener("connect", connected); + _rfb.addEventListener("disconnect", disconnectedFromServer); + }catch(err){ + status("Something went wrong, connection is closed", "Failed"); + console.log("error start NOVNC ", err); } - $("#open_in_a_new_window").attr('href', url); - _rfb.connect(proxy_host, proxy_port, pw, path); + $("#open_in_a_new_window").attr("href", link); } function disconnect() { @@ -92,31 +110,4 @@ define(function(require) { function sendCtrlAltDel() { if (_rfb) { _rfb.sendCtrlAltDel(); } } - - //This is taken from noVNC examples - function updateVNCState(rfb, state, oldstate, msg) { - var s, sb, cad, klass; - s = $D('VNC_status'); - sb = $D('VNC_status_bar'); - cad = $D('sendCtrlAltDelButton'); - switch (state) { - case 'failed': level = "error"; break; - case 'fatal': level = "error"; break; - case 'normal': level = "normal"; break; - case 'disconnected': level = "normal"; break; - case 'loaded': level = "normal"; break; - default: level = "warn"; break; - } - - if (state === "normal") { - cad.disabled = false; - } else { - cad.disabled = true; - } - - if (typeof(msg) !== 'undefined') { - sb.setAttribute("class", "noVNC_status_" + level); - s.innerHTML = msg; - } - } }); diff --git a/src/sunstone/public/bower.json b/src/sunstone/public/bower.json index 5077753f9b..e491924823 100644 --- a/src/sunstone/public/bower.json +++ b/src/sunstone/public/bower.json @@ -5,7 +5,7 @@ "jgrowl": "1.4.2", "fontawesome": "5.0.7", "flot.tooltip": "0.8.4", - "no-vnc": "0.5.1", + "no-vnc": "1.1.0", "resumablejs": "git://github.com/23/resumable.js.git#420cd351c5", "spice-html5": "git://anongit.freedesktop.org/spice/spice-html5#spice-html5-0.1.6", "require-handlebars-plugin": "0.11.2", diff --git a/src/sunstone/public/build.sh b/src/sunstone/public/build.sh index ac8f038a3e..58f7ff94ea 100755 --- a/src/sunstone/public/build.sh +++ b/src/sunstone/public/build.sh @@ -31,6 +31,8 @@ install_patch() { bower install --force --allow-root --config.interactive=false + (cd bower_components/no-vnc/ && npm install && ./utils/use_require.js --clean --as amd && sed -i -e "s/'\.\//'\.\.\/bower_components\/no-vnc\/lib\//g" lib/rfb.js ) + PATCH_DIR="./patches/" for i in `ls ${PATCH_DIR}` ; do diff --git a/src/sunstone/public/css/novnc-custom.css b/src/sunstone/public/css/novnc-custom.css index eb6887559a..bf4ebff61d 100644 --- a/src/sunstone/public/css/novnc-custom.css +++ b/src/sunstone/public/css/novnc-custom.css @@ -115,10 +115,13 @@ html { } #noVNC_screen { text-align: center; - display: table; - width:100%; - height:100%; - /*border-top-left-radius: 800px 600px;*/ + width: 100%; + display: inline-flex; + height: 100%; + flex-direction: column; +} +#noVNC_screen > #VNC_canvas{ + flex-grow: 1; } #noVNC_container, #noVNC_canvas { diff --git a/src/sunstone/public/patches/bug4304-novnc.patch b/src/sunstone/public/patches/bug4304-novnc.patch deleted file mode 100644 index 6f305287f3..0000000000 --- a/src/sunstone/public/patches/bug4304-novnc.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff -ru public.old/bower_components/no-vnc/include/keyboard.js public.new/bower_components/no-vnc/include/keyboard.js ---- public.old/bower_components/no-vnc/include/keyboard.js 2014-11-29 10:46:27.000000000 +0100 -+++ public.new/bower_components/no-vnc/include/keyboard.js 2017-05-25 17:02:59.184008613 +0200 -@@ -407,12 +407,6 @@ - case 'keydown': - // is the next element a keypress? Then we should merge the two - if (queue.length !== 0 && queue[0].type === 'keypress') { -- // Firefox sends keypress even when no char is generated. -- // so, if keypress keysym is the same as we'd have guessed from keydown, -- // the modifier didn't have any effect, and should not be escaped -- if (queue[0].escape && (!cur.keysym || cur.keysym.keysym !== queue[0].keysym.keysym)) { -- cur.escape = queue[0].escape; -- } - cur.keysym = queue[0].keysym; - queue = queue.splice(1); - } diff --git a/src/sunstone/sunstone-server.rb b/src/sunstone/sunstone-server.rb index 54736bfa31..47ee23fc2b 100755 --- a/src/sunstone/sunstone-server.rb +++ b/src/sunstone/sunstone-server.rb @@ -251,6 +251,46 @@ helpers do session[:ip] && session[:ip] == request.ip end + def build_conf_locals + logos_conf = nil + begin + logos_conf = YAML.load_file(LOGOS_CONFIGURATION_FILE) + rescue Exception => e + logger.error { "Error parsing config file #{LOGOS_CONFIGURATION_FILE}: #{e.message}" } + error 500, "" + end + serveradmin_client = $cloud_auth.client(nil, session[:active_zone_endpoint]) + rc = OpenNebula::System.new(serveradmin_client).get_configuration + if OpenNebula.is_error?(rc) + logger.error { rc.message } + error 500, "" + end + oned_conf_template = rc.to_hash()['TEMPLATE'] + oned_conf = {} + ONED_CONF_OPTS['ALLOWED_KEYS'].each do |key| + value = oned_conf_template[key] + if key == 'DEFAULT_COST' + if value + oned_conf[key] = value + else + oned_conf[key] = ONED_CONF_OPTS['DEFAULT_COST'] + end + else + if ONED_CONF_OPTS['ARRAY_KEYS'].include?(key) && !value.is_a?(Array) + oned_conf[key] = [value] + else + oned_conf[key] = value + end + end + end + $conf[:locals] = { + :logos_conf => logos_conf, + :oned_conf => oned_conf, + :support => SUPPORT, + :upgrade => UPGRADE + } + end + def build_session begin result = $cloud_auth.auth(request.env, params) @@ -474,51 +514,16 @@ get '/' do return erb :login end - logos_conf = nil - - begin - logos_conf = YAML.load_file(LOGOS_CONFIGURATION_FILE) - rescue Exception => e - logger.error { "Error parsing config file #{LOGOS_CONFIGURATION_FILE}: #{e.message}" } - error 500, "" - end - - serveradmin_client = $cloud_auth.client(nil, session[:active_zone_endpoint]) - - rc = OpenNebula::System.new(serveradmin_client).get_configuration - - if OpenNebula.is_error?(rc) - logger.error { rc.message } - error 500, "" - end - - oned_conf_template = rc.to_hash()['TEMPLATE'] - - oned_conf = {} - ONED_CONF_OPTS['ALLOWED_KEYS'].each do |key| - value = oned_conf_template[key] - if key == 'DEFAULT_COST' - if value - oned_conf[key] = value - else - oned_conf[key] = ONED_CONF_OPTS['DEFAULT_COST'] - end - else - if ONED_CONF_OPTS['ARRAY_KEYS'].include?(key) && !value.is_a?(Array) - oned_conf[key] = [value] - else - oned_conf[key] = value - end - end + if $conf[:locals].nil? + build_conf_locals end response.set_cookie("one-user", :value=>"#{session[:user]}") - - erb :index, :locals => { - :logos_conf => logos_conf, - :oned_conf => oned_conf, - :support => SUPPORT, - :upgrade => UPGRADE + erb :index, :locals => { + :logos_conf => $conf[:locals][:logos_conf], + :oned_conf => $conf[:locals][:oned_conf], + :support => $conf[:locals][:support], + :upgrade => $conf[:locals][:upgrade] } end @@ -536,7 +541,12 @@ get '/vnc' do if !authorized? erb :login else - erb :vnc + erb :vnc, :locals => { + :logos_conf => $conf[:locals][:logos_conf], + :oned_conf => $conf[:locals][:oned_conf], + :support => $conf[:locals][:support], + :upgrade => $conf[:locals][:upgrade] + } end end diff --git a/src/sunstone/views/vnc.erb b/src/sunstone/views/vnc.erb index 22cdb38ffb..f96a1a3f79 100644 --- a/src/sunstone/views/vnc.erb +++ b/src/sunstone/views/vnc.erb @@ -1,71 +1,97 @@ - - - - - <%= params['vm_name']%> - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - - - - -
- -
Loading
-
-
- - - - - -
-
+ + + <%= params['vm_name']%> + + + + + + + + + + <% view = $views_config.view(session[:user], session[:user_gname], session[:default_view]) %> + + + + +
+
+
+ + + + + + +
+ +
Loading
+
+
+ + + + + +
+
+
+
+
+
+
-
- Canvas not supported. -
- - \ No newline at end of file + + \ No newline at end of file