mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-06 13:17:42 +03:00
Signed-off-by: Frederick Borges <fborges@opennebula.io> Co-authored-by: Tino Vázquez <cvazquez@opennebula.io>
This commit is contained in:
parent
1c3e4a795c
commit
4177637567
4
.gitignore
vendored
4
.gitignore
vendored
@ -48,6 +48,10 @@ src/sunstone/public/package-lock.json
|
||||
src/sunstone/guac/node_modules
|
||||
src/sunstone/guac/dist
|
||||
src/sunstone/guac/package-lock.json
|
||||
src/sunstone/vmrc/node_modules
|
||||
src/sunstone/vmrc/dist
|
||||
src/sunstone/vmrc/package-lock.json
|
||||
src/sunstone/vmrc/v8-compile-cache-0/
|
||||
.tx/config
|
||||
|
||||
src/fireedge/node_modules
|
||||
|
@ -900,6 +900,7 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \
|
||||
src/oca/ruby/opennebula.rb \
|
||||
src/sunstone/OpenNebulaVNC.rb \
|
||||
src/sunstone/OpenNebulaGuac.rb \
|
||||
src/sunstone/OpenNebulaVMRC.rb \
|
||||
src/sunstone/OpenNebulaAddons.rb \
|
||||
src/vmm_mad/remotes/vcenter/vcenter_driver.rb \
|
||||
src/vmm_mad/remotes/nsx/nsx_driver.rb \
|
||||
@ -2406,7 +2407,8 @@ SUNSTONE_MODELS_FILES="src/sunstone/models/OpenNebulaJSON.rb \
|
||||
src/sunstone/models/OpenNebula2FA/SunstoneWebAuthn.rb \
|
||||
src/sunstone/models/OpenNebula2FA/sunstone_qr_code.rb \
|
||||
src/sunstone/models/OpenNebula2FA/sunstone_optp.rb \
|
||||
src/sunstone/models/OpenNebula2FA/sunstone_2f_auth.rb "
|
||||
src/sunstone/models/OpenNebula2FA/sunstone_2f_auth.rb \
|
||||
src/sunstone/models/OpenNebulaValidateFireedge.rb"
|
||||
|
||||
SUNSTONE_MODELS_JSON_FILES="src/sunstone/models/OpenNebulaJSON/HostJSON.rb \
|
||||
src/sunstone/models/OpenNebulaJSON/ImageJSON.rb \
|
||||
@ -2432,6 +2434,7 @@ SUNSTONE_MODELS_JSON_FILES="src/sunstone/models/OpenNebulaJSON/HostJSON.rb \
|
||||
SUNSTONE_VIEWS_FILES="src/sunstone/views/index.erb \
|
||||
src/sunstone/views/login.erb \
|
||||
src/sunstone/views/vnc.erb \
|
||||
src/sunstone/views/vmrc.erb \
|
||||
src/sunstone/views/spice.erb \
|
||||
src/sunstone/views/_login_standard.erb \
|
||||
src/sunstone/views/_login_x509.erb"
|
||||
|
203
src/sunstone/OpenNebulaVMRC.rb
Normal file
203
src/sunstone/OpenNebulaVMRC.rb
Normal file
@ -0,0 +1,203 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
#----------------------------------------------------------------------------#
|
||||
# This class provides support for launching and stopping a vmrc proxy server #
|
||||
#----------------------------------------------------------------------------#
|
||||
|
||||
require 'rubygems'
|
||||
require 'json'
|
||||
require 'opennebula'
|
||||
require 'base64'
|
||||
require 'openssl'
|
||||
require 'vcenter_driver'
|
||||
require 'fileutils'
|
||||
|
||||
if !ONE_LOCATION
|
||||
VMRC_TICKETS = "/var/lib/one/sunstone_vnc_tokens/vmrc/"
|
||||
else
|
||||
VMRC_TICKETS = ONE_LOCATION + "/var/lib/one/sunstone_vnc_tokens/vmrc/"
|
||||
end
|
||||
|
||||
FileUtils.mkdir_p VMRC_TICKETS
|
||||
|
||||
VMRC_STATES = [
|
||||
#0, #LCM_INIT
|
||||
#1, #PROLOG
|
||||
#2, #BOOT
|
||||
"3", #RUNNING
|
||||
"4", #MIGRATE
|
||||
#5, #SAVE_STOP
|
||||
#6, #SAVE_SUSPEND
|
||||
#7, #SAVE_MIGRATE
|
||||
#8, #PROLOG_MIGRATE
|
||||
#9, #PROLOG_RESUME
|
||||
#10, #EPILOG_STOP
|
||||
#11, #EPILOG
|
||||
"12", #SHUTDOWN
|
||||
"13", #CANCEL
|
||||
#14, #FAILURE
|
||||
#15, #CLEANUP_RESUBMIT
|
||||
"16", #UNKNOWN
|
||||
"17", #HOTPLUG
|
||||
"18", #SHUTDOWN_POWEROFF
|
||||
#19, #BOOT_UNKNOWN
|
||||
#20, #BOOT_POWEROFF
|
||||
#21, #BOOT_SUSPENDED
|
||||
#22, #BOOT_STOPPED
|
||||
#23, #CLEANUP_DELETE
|
||||
"24", #HOTPLUG_SNAPSHOT
|
||||
"25", #HOTPLUG_NIC
|
||||
"26", #HOTPLUG_SAVEAS
|
||||
"27", #HOTPLUG_SAVEAS_POWEROFF
|
||||
"28", #HOTPLUG_SAVEAS_SUSPENDED
|
||||
"29", #SHUTDOWN_UNDEPLOY
|
||||
#30, #EPILOG_UNDEPLOY
|
||||
#31, #PROLOG_UNDEPLOY
|
||||
#32, #BOOT_UNDEPLOY
|
||||
#33, #HOTPLUG_PROLOG_POWEROFF
|
||||
#34, #HOTPLUG_EPILOG_POWEROFF
|
||||
#35, #BOOT_MIGRATE
|
||||
#36, #BOOT_FAILURE
|
||||
#37, #BOOT_MIGRATE_FAILURE
|
||||
#38, #PROLOG_MIGRATE_FAILURE
|
||||
#39, #PROLOG_FAILURE
|
||||
#40, #EPILOG_FAILURE
|
||||
#41, #EPILOG_STOP_FAILURE
|
||||
#42, #EPILOG_UNDEPLOY_FAILURE
|
||||
#43, #PROLOG_MIGRATE_POWEROFF
|
||||
#44, #PROLOG_MIGRATE_POWEROFF_FAILURE
|
||||
#45, #PROLOG_MIGRATE_SUSPEND
|
||||
#46, #PROLOG_MIGRATE_SUSPEND_FAILURE
|
||||
#47, #BOOT_UNDEPLOY_FAILURE
|
||||
#48, #BOOT_STOPPED_FAILURE
|
||||
#49, #PROLOG_RESUME_FAILURE
|
||||
#50, #PROLOG_UNDEPLOY_FAILURE
|
||||
#51, #DISK_SNAPSHOT_POWEROFF
|
||||
#52, #DISK_SNAPSHOT_REVERT_POWEROFF
|
||||
#53, #DISK_SNAPSHOT_DELETE_POWEROFF
|
||||
#54, #DISK_SNAPSHOT_SUSPENDED
|
||||
#55, #DISK_SNAPSHOT_REVERT_SUSPENDED
|
||||
#56, #DISK_SNAPSHOT_DELETE_SUSPENDED
|
||||
"57", #DISK_SNAPSHOT
|
||||
"58", #DISK_SNAPSHOT_REVERT
|
||||
#59, #DISK_SNAPSHOT_DELETE
|
||||
#60, #PROLOG_MIGRATE_UNKNOWN
|
||||
#61, #PROLOG_MIGRATE_UNKNOWN_FAILURE
|
||||
"62" #DISK_RESIZE
|
||||
#63, #DISK_RESIZE_POWEROFF
|
||||
#64 #DISK_RESIZE_UNDEPLOYED
|
||||
#65 #HOTPLUG_NIC_POWEROFF
|
||||
]
|
||||
|
||||
class OpenNebulaVMRC
|
||||
|
||||
attr_reader :proxy_port
|
||||
|
||||
def initialize(config, logger, options = {})
|
||||
opts={ :json_errors => true }.merge(options)
|
||||
|
||||
@options = opts
|
||||
@logger = logger
|
||||
end
|
||||
|
||||
def sanitize(ticket)
|
||||
# Bad as defined by wikipedia: https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
|
||||
# Also have to escape the backslash
|
||||
bad_chars = [ '/', '\\', '?', '%', '*', ':', '|', '"', '<', '>', '.', ' ' ]
|
||||
bad_chars.each do |bad_char|
|
||||
ticket.gsub!(bad_char, '_')
|
||||
end
|
||||
ticket
|
||||
end
|
||||
|
||||
def proxy(vm_resource)
|
||||
# Check configurations and VM attributes
|
||||
|
||||
unless is_running?
|
||||
return error(400, "Fireedge Server is not running, please contact your cloud administrator")
|
||||
end
|
||||
|
||||
# Check configurations and VM attributes
|
||||
unless VMRC_STATES.include?(vm_resource['LCM_STATE'])
|
||||
return error(400, "Wrong state (#{vm_resource['LCM_STATE']}) to open a VMRC session")
|
||||
end
|
||||
|
||||
if vm_resource['USER_TEMPLATE/HYPERVISOR'] == "vcenter"
|
||||
if vm_resource['MONITORING/VCENTER_ESX_HOST']
|
||||
hostname = vm_resource['MONITORING/VCENTER_ESX_HOST']
|
||||
else
|
||||
return error(400,"Could not determine the vCenter ESX host where the VM is running.
|
||||
Wait till the VCENTER_ESX_HOST attribute is retrieved once the host has been monitored")
|
||||
end
|
||||
else
|
||||
return error(400, "VMRC Connection is only for vcenter hipervisor")
|
||||
end
|
||||
|
||||
vm_id = vm_resource['ID']
|
||||
one_vm = VCenterDriver::VIHelper.one_item(OpenNebula::VirtualMachine, vm_id)
|
||||
vm_ref = one_vm['DEPLOY_ID']
|
||||
|
||||
host_id = one_vm['HISTORY_RECORDS/HISTORY[last()]/HID'].to_i
|
||||
|
||||
vi_client = VCenterDriver::VIClient.new_from_host(host_id)
|
||||
|
||||
vm = VCenterDriver::VirtualMachine.new(vi_client, vm_ref, vm_id)
|
||||
|
||||
parameters = vm.get_html_console_parameters
|
||||
|
||||
data = {
|
||||
:host => parameters[:host],
|
||||
:port => parameters[:port],
|
||||
:ticket => parameters[:ticket]
|
||||
}
|
||||
|
||||
File.open(VMRC_TICKETS + sanitize(data[:ticket]), 'w') { |file| file.write("https://" + data[:host] + ":" + data[:port].to_s ) }
|
||||
|
||||
[200, { :data => data }.to_json]
|
||||
end
|
||||
|
||||
def status
|
||||
if is_running?
|
||||
STDOUT.puts "VMRC server is running"
|
||||
true
|
||||
else
|
||||
STDOUT.puts "VMRC server is NOT running"
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def error(code, msg)
|
||||
if @options[:json_errors]
|
||||
[code, OpenNebula::Error.new(msg).to_json]
|
||||
else
|
||||
[code,msg]
|
||||
end
|
||||
end
|
||||
|
||||
def is_running?
|
||||
|
||||
if $conf[:fireedge_up]
|
||||
return true
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
alias_method :get_vmrc_pid, :is_running?
|
||||
|
||||
end
|
@ -161,6 +161,10 @@
|
||||
:guac_port: 29877
|
||||
:guacd_port: 4822
|
||||
|
||||
:vmrc_port: 2616
|
||||
:fireedge_server_endpoint: "http://localhost:2616"
|
||||
:max_waiting_tries: 5
|
||||
|
||||
# Login Session Length in seconds, defaults to 1 hour.
|
||||
#:session_expire_time: 3600
|
||||
|
||||
@ -264,4 +268,4 @@
|
||||
################################################################################
|
||||
|
||||
:zeromq_server: tcp://localhost:2101
|
||||
:autorefresh_ip: 127.0.0.1
|
||||
:autorefresh_ip: 127.0.0.1
|
||||
|
@ -419,6 +419,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -92,6 +92,7 @@ tabs:
|
||||
VM.lockU: true
|
||||
VM.unlock: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -418,6 +418,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -411,6 +411,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -419,6 +419,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -92,6 +92,7 @@ tabs:
|
||||
VM.lockU: true
|
||||
VM.unlock: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -418,6 +418,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -411,6 +411,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -417,6 +417,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -93,6 +93,7 @@ tabs:
|
||||
VM.lockU: true
|
||||
VM.unlock: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -418,6 +418,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
@ -411,6 +411,7 @@ tabs:
|
||||
VM.edit_labels: true
|
||||
VM.menu_labels: true
|
||||
VM.startvnc: true
|
||||
VM.startvmrc: true
|
||||
VM.startspice: true
|
||||
VM.vnc: true
|
||||
VM.ssh: true
|
||||
|
63
src/sunstone/models/OpenNebulaValidateFireedge.rb
Normal file
63
src/sunstone/models/OpenNebulaValidateFireedge.rb
Normal file
@ -0,0 +1,63 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# 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 'CloudServer'
|
||||
|
||||
|
||||
require 'net/http'
|
||||
|
||||
class ValidateFireedge < CloudServer
|
||||
|
||||
def initialize(config, logger)
|
||||
super(config, logger)
|
||||
@time = 1
|
||||
@max_tries = config[:max_waiting_tries]
|
||||
end
|
||||
|
||||
def send_request(url)
|
||||
response = nil
|
||||
uri = URI(url)
|
||||
|
||||
begin
|
||||
Net::HTTP.start(uri.host, uri.port) do |http|
|
||||
request = Net::HTTP::Get.new uri
|
||||
response = http.request request
|
||||
end
|
||||
|
||||
return response.kind_of? Net::HTTPSuccess
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def validate_fireedge_running
|
||||
fireedge_endpoint = $conf[:fireedge_server_endpoint]
|
||||
if (fireedge_endpoint)
|
||||
tries = 0
|
||||
while (!$conf[:fireedge_up] || tries <= max_tries) do
|
||||
if (!$conf[:fireedge_up] && send_request(fireedge_endpoint))
|
||||
$conf[:fireedge_up] = true;
|
||||
else
|
||||
sleep 1
|
||||
end
|
||||
tries = tries + 1
|
||||
end
|
||||
else
|
||||
$conf[:fireedge_up] = false;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -21,6 +21,7 @@ include OpenNebulaJSON
|
||||
|
||||
require 'OpenNebulaVNC'
|
||||
require 'OpenNebulaGuac'
|
||||
require 'OpenNebulaVMRC'
|
||||
require 'OpenNebulaAddons'
|
||||
require 'OpenNebulaJSON/JSONUtils'
|
||||
#include JSONUtils
|
||||
@ -330,6 +331,34 @@ class SunstoneServer < CloudServer
|
||||
return guac.proxy(resource, type_connection)
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# VMRC
|
||||
########################################################################
|
||||
def startvmrc(id, vmrc)
|
||||
resource = retrieve_resource("vm", id)
|
||||
if OpenNebula.is_error?(resource)
|
||||
return [404, resource.to_json]
|
||||
end
|
||||
|
||||
client = @client
|
||||
vm_pool = VirtualMachinePool.new(client, -1)
|
||||
user_pool = UserPool.new(client)
|
||||
|
||||
rc = user_pool.info
|
||||
if OpenNebula.is_error?(rc)
|
||||
puts rc.message
|
||||
exit -1
|
||||
end
|
||||
|
||||
rc = vm_pool.info
|
||||
if OpenNebula.is_error?(rc)
|
||||
puts rc.message
|
||||
exit -1
|
||||
end
|
||||
|
||||
return vmrc.proxy(resource)
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Accounting & Monitoring
|
||||
########################################################################
|
||||
|
@ -84,148 +84,16 @@ module.exports = function(grunt) {
|
||||
include: ["almond"],
|
||||
insertRequire: ["console/vnc"]
|
||||
},
|
||||
{
|
||||
name: "console/vmrc",
|
||||
include: ["almond"],
|
||||
insertRequire: ["console/vmrc"]
|
||||
},
|
||||
{
|
||||
name: "console/spice",
|
||||
include: ["almond"],
|
||||
insertRequire: ["console/spice"]
|
||||
}
|
||||
/*{
|
||||
name: 'main'
|
||||
excludeShallow: [
|
||||
'app'
|
||||
],
|
||||
include: [
|
||||
'jquery',
|
||||
'datatables',
|
||||
'foundation-datatables',
|
||||
'jgrowl',
|
||||
'foundation.core',
|
||||
'foundation.abide',
|
||||
'foundation.accordion',
|
||||
'foundation.alert',
|
||||
'foundation.clearing',
|
||||
'foundation.dropdown',
|
||||
'foundation.equalizer',
|
||||
'foundation.interchange',
|
||||
'foundation.joyride',
|
||||
'foundation.magellan',
|
||||
'foundation.offcanvas',
|
||||
'foundation.orbit',
|
||||
'foundation.reveal',
|
||||
'foundation.slider',
|
||||
'foundation.tab',
|
||||
'foundation.tooltip',
|
||||
'foundation.topbar',
|
||||
'hbs',
|
||||
'jquery.cookie',
|
||||
'fastclick',
|
||||
'modernizr',
|
||||
'placeholder',
|
||||
'resumable',
|
||||
'flot',
|
||||
'flot.stack',
|
||||
'flot.resize',
|
||||
'flot.time',
|
||||
'flot.tooltip',
|
||||
'nouislider',
|
||||
'vnc-util',
|
||||
'spice-main',
|
||||
'spice-spicearraybuffer',
|
||||
'spice-enums',
|
||||
'spice-atKeynames',
|
||||
'spice-utils',
|
||||
'spice-png',
|
||||
'spice-lz',
|
||||
'spice-quic',
|
||||
'spice-bitmap',
|
||||
'spice-spicedataview',
|
||||
'spice-spicetype',
|
||||
'spice-spicemsg',
|
||||
'spice-wire',
|
||||
'spice-spiceconn',
|
||||
'spice-display',
|
||||
'spice-inputs',
|
||||
'spice-webm',
|
||||
'spice-playback',
|
||||
'spice-simulatecursor',
|
||||
'spice-cursor',
|
||||
'spice-jsbn',
|
||||
'spice-rsa',
|
||||
'spice-prng4',
|
||||
'spice-rng',
|
||||
'spice-sha1',
|
||||
'spice-ticket',
|
||||
'spice-resize',
|
||||
'spice-filexfer'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'app',
|
||||
exclude: [
|
||||
'jquery',
|
||||
'datatables',
|
||||
'foundation-datatables',
|
||||
'jgrowl',
|
||||
'foundation.core',
|
||||
'foundation.abide',
|
||||
'foundation.accordion',
|
||||
'foundation.alert',
|
||||
'foundation.clearing',
|
||||
'foundation.dropdown',
|
||||
'foundation.equalizer',
|
||||
'foundation.interchange',
|
||||
'foundation.joyride',
|
||||
'foundation.magellan',
|
||||
'foundation.offcanvas',
|
||||
'foundation.orbit',
|
||||
'foundation.reveal',
|
||||
'foundation.slider',
|
||||
'foundation.tab',
|
||||
'foundation.tooltip',
|
||||
'foundation.topbar',
|
||||
'hbs',
|
||||
'jquery.cookie',
|
||||
'fastclick',
|
||||
'modernizr',
|
||||
'placeholder',
|
||||
'resumable',
|
||||
'flot',
|
||||
'flot.stack',
|
||||
'flot.resize',
|
||||
'flot.time',
|
||||
'flot.tooltip',
|
||||
'nouislider',
|
||||
'vnc-util',
|
||||
'spice-main',
|
||||
'spice-spicearraybuffer',
|
||||
'spice-enums',
|
||||
'spice-atKeynames',
|
||||
'spice-utils',
|
||||
'spice-png',
|
||||
'spice-lz',
|
||||
'spice-quic',
|
||||
'spice-bitmap',
|
||||
'spice-spicedataview',
|
||||
'spice-spicetype',
|
||||
'spice-spicemsg',
|
||||
'spice-wire',
|
||||
'spice-spiceconn',
|
||||
'spice-display',
|
||||
'spice-inputs',
|
||||
'spice-webm',
|
||||
'spice-playback',
|
||||
'spice-simulatecursor',
|
||||
'spice-cursor',
|
||||
'spice-jsbn',
|
||||
'spice-rsa',
|
||||
'spice-prng4',
|
||||
'spice-rng',
|
||||
'spice-sha1',
|
||||
'spice-ticket',
|
||||
'spice-resize',
|
||||
'spice-filexfer'
|
||||
]
|
||||
}*/
|
||||
]
|
||||
}
|
||||
}
|
||||
|
139
src/sunstone/public/app/console/vmrc.js
Normal file
139
src/sunstone/public/app/console/vmrc.js
Normal file
@ -0,0 +1,139 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2020, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require) {
|
||||
require("jquery");
|
||||
require("jquery-ui");
|
||||
var WMKS = require("wmks");
|
||||
var Config = require("sunstone-config");
|
||||
var _wmks;
|
||||
var _is_encrypted = "";
|
||||
|
||||
function setStatus(message="", status=""){
|
||||
$(".VMRC_message").text(message);
|
||||
$("#VMRC_status").text(status);
|
||||
}
|
||||
|
||||
function connected(){
|
||||
setStatus(null, "VMRC " + _wmks.connectionState + " (" + _is_encrypted + ") to: " + _wmks.vm_name);
|
||||
}
|
||||
|
||||
function disconnectedFromServer(e){
|
||||
if (e.detail.clean) {
|
||||
setStatus(null, "VMRC " + _wmks.connectionState + " (" + _is_encrypted + ") to: " + _wmks.vm_name);
|
||||
} else {
|
||||
setStatus("Something went wrong, connection is closed", "Failed");
|
||||
}
|
||||
}
|
||||
|
||||
function desktopNameChange(name) {
|
||||
if (e.detail.name) {
|
||||
setStatus(null, "VMRC " + _wmks.connectionState + " (" + _is_encrypted + ") to: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
function credentialsRequired(e) {
|
||||
setStatus("Something went wrong, more credentials must be given to continue", "Failed");
|
||||
}
|
||||
|
||||
function sendCtrlAltDel() {
|
||||
if (_wmks) { _wmks.sendCAD(); }
|
||||
}
|
||||
|
||||
function updateState(state, msg) {
|
||||
var s, sb, cad, level;
|
||||
s = document.querySelector("#VMRC_status");
|
||||
sb = document.querySelector("#VMRC_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;
|
||||
default: level = "warn"; break;
|
||||
}
|
||||
|
||||
if (state === "normal") {
|
||||
cad.disabled = false;
|
||||
} else {
|
||||
cad.disabled = true;
|
||||
xvpInit(0);
|
||||
}
|
||||
|
||||
if (typeof(msg) !== "undefined") {
|
||||
sb.setAttribute("class", "VMRC_status_" + level);
|
||||
s.innerHTML = msg;
|
||||
}
|
||||
}
|
||||
|
||||
function getQueryVariable(variable)
|
||||
{
|
||||
var query = window.location.search.substring(1);
|
||||
var vars = query.split("&");
|
||||
for (var i=0;i<vars.length;i++) {
|
||||
var pair = vars[i].split("=");
|
||||
if(pair[0] == variable){return pair[1];}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
var URL = "";
|
||||
var host = getQueryVariable("host");
|
||||
var port = getQueryVariable("port");
|
||||
var ticket = getQueryVariable("ticket");
|
||||
var vm_name = getQueryVariable("name");
|
||||
|
||||
if (window.location.protocol === "https:") {
|
||||
URL = "wss";
|
||||
_is_encrypted = "encrypted";
|
||||
} else {
|
||||
URL = "ws";
|
||||
_is_encrypted = "unencrypted";
|
||||
}
|
||||
URL += "://" + host;
|
||||
URL += ":" + port;
|
||||
URL += "/vmrc/" + ticket;
|
||||
|
||||
document.querySelector("#sendCtrlAltDelButton").style.display = "inline";
|
||||
document.querySelector("#sendCtrlAltDelButton").onclick = sendCtrlAltDel;
|
||||
|
||||
if ((!host) || (!port)) {
|
||||
updateState("failed",
|
||||
"Must specify host and port in URL");
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
_wmks = WMKS.createWMKS("wmksContainer", {})
|
||||
.register(WMKS.CONST.Events.CONNECTION_STATE_CHANGE,
|
||||
function (event, data) {
|
||||
if (typeof cons !== 'undefined' && data.state == cons.ConnectionState.CONNECTED) {
|
||||
console.log("connection state change : connected");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
_wmks.eventHandlers["connectionstatechange"].push(connected);
|
||||
_wmks.eventHandlers["disconnect"] = disconnectedFromServer;
|
||||
|
||||
_wmks.connect(URL);
|
||||
_wmks["vm_name"] = vm_name;
|
||||
}catch(err){
|
||||
setStatus("Something went wrong, connection is closed", "Failed");
|
||||
console.log("error start VMRC ", err);
|
||||
}
|
||||
});
|
@ -25,6 +25,8 @@ require.config({
|
||||
/* jQuery */
|
||||
"jquery": "../bower_components/jquery/dist/jquery",
|
||||
"jquery-ui": "../bower_components/jquery-ui/jquery-ui",
|
||||
/* WMKS */
|
||||
"wmks" : "../bower_components/wmks/wmks_AMD.min",
|
||||
|
||||
/** Wickedpicker */
|
||||
"wickedpicker": "../bower_components/wickedpicker/dist/wickedpicker.min",
|
||||
@ -36,29 +38,12 @@ require.config({
|
||||
"datatables.net": "../bower_components/datatables/media/js/jquery.dataTables",
|
||||
"datatables.foundation": "../bower_components/datatables/media/js/dataTables.foundation",
|
||||
|
||||
/* DataTables */
|
||||
/* jqrowl notfications */
|
||||
"jgrowl": "../bower_components/jgrowl/jquery.jgrowl",
|
||||
|
||||
/* Foundation */
|
||||
"foundation": "../bower_components/foundation-sites/dist/foundation",
|
||||
//'foundation.core': '../bower_components/foundation/js/foundation/foundation',
|
||||
//'foundation.abide': '../bower_components/foundation/js/foundation/foundation.abide',
|
||||
//'foundation.accordion': '../bower_components/foundation/js/foundation/foundation.accordion',
|
||||
//'foundation.alert': '../bower_components/foundation/js/foundation/foundation.alert',
|
||||
//'foundation.clearing': '../bower_components/foundation/js/foundation/foundation.clearing',
|
||||
//'foundation.dropdown': '../bower_components/foundation/js/foundation/foundation.dropdown',
|
||||
//'foundation.equalizer': '../bower_components/foundation/js/foundation/foundation.equalizer',
|
||||
//'foundation.interchange': '../bower_components/foundation/js/foundation/foundation.interchange',
|
||||
//'foundation.joyride': '../bower_components/foundation/js/foundation/foundation.joyride',
|
||||
//'foundation.magellan': '../bower_components/foundation/js/foundation/foundation.magellan',
|
||||
//'foundation.offcanvas': '../bower_components/foundation/js/foundation/foundation.offcanvas',
|
||||
//'foundation.orbit': '../bower_components/foundation/js/foundation/foundation.orbit',
|
||||
//'foundation.reveal': '../bower_components/foundation/js/foundation/foundation.reveal',
|
||||
//'foundation.slider': '../bower_components/foundation/js/foundation/foundation.slider',
|
||||
//'foundation.tab': '../bower_components/foundation/js/foundation/foundation.tab',
|
||||
//'foundation.tooltip': '../bower_components/foundation/js/foundation/foundation.tooltip',
|
||||
//'foundation.topbar': '../bower_components/foundation/js/foundation/foundation.topbar',
|
||||
|
||||
|
||||
/* Handlebars */
|
||||
"hbs": "../bower_components/require-handlebars-plugin/hbs",
|
||||
|
||||
@ -122,6 +107,8 @@ require.config({
|
||||
deps: [
|
||||
"jquery",
|
||||
"foundation",
|
||||
"jquery-ui",
|
||||
"wmks",
|
||||
"tabs/provision-tab",
|
||||
"tabs/dashboard-tab",
|
||||
"tabs/system-top-tab",
|
||||
@ -171,76 +158,23 @@ require.config({
|
||||
deps: ["jquery"]
|
||||
},
|
||||
|
||||
/* JQuery-UI */
|
||||
"jquery-ui": {
|
||||
deps: ["jquery"]
|
||||
},
|
||||
|
||||
/* Foundation */
|
||||
"foundation": {
|
||||
deps: ["jquery"]
|
||||
},
|
||||
//'foundation.core': {
|
||||
// deps: ['jquery', 'modernizr'],
|
||||
// exports: 'Foundation'
|
||||
//},
|
||||
//'foundation.abide': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.accordion': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.alert': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.clearing': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.dropdown': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.equalizer': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.interchange': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.joyride': {
|
||||
// deps: ['foundation.core', 'jquery.cookie']
|
||||
//},
|
||||
//'foundation.magellan': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.offcanvas': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.orbit': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.reveal': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.slider': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.tab': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.tooltip': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
//'foundation.topbar': {
|
||||
// deps: ['foundation.core']
|
||||
//},
|
||||
|
||||
/* Vendor Scripts */
|
||||
//'jquery.cookie': {
|
||||
// deps: ['jquery']
|
||||
//},
|
||||
//'fastclick': {
|
||||
// exports: 'FastClick'
|
||||
//},
|
||||
//'modernizr': {
|
||||
// exports: 'Modernizr'
|
||||
//},
|
||||
//'placeholder': {
|
||||
// exports: 'Placeholders'
|
||||
//},
|
||||
/* WMKS */
|
||||
"wmks": {
|
||||
deps: [
|
||||
"jquery",
|
||||
"jquery-ui"
|
||||
],
|
||||
exports: "WMKS"
|
||||
},
|
||||
|
||||
/* Flot Graphs */
|
||||
"flot": {
|
||||
|
@ -533,6 +533,26 @@ define(function(require) {
|
||||
}
|
||||
});
|
||||
},
|
||||
"vmrc" : function(params) {
|
||||
var callback = params.success;
|
||||
var callback_error = params.error;
|
||||
var id = params.data.id;
|
||||
var resource = RESOURCE;
|
||||
|
||||
var request = OpenNebulaHelper.request(resource, null, params.data);
|
||||
$.ajax({
|
||||
url: "vm/" + id + "/startvmrc",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
return callback ? callback(request, response) : null;
|
||||
},
|
||||
error: function(response) {
|
||||
return callback_error ?
|
||||
callback_error(request, OpenNebulaError(response)) : null;
|
||||
}
|
||||
});
|
||||
},
|
||||
"append": function(params) {
|
||||
var action_obj = {"template_raw" : params.data.extra_param, append : true};
|
||||
OpenNebulaAction.simple_action(params, RESOURCE, "update", action_obj);
|
||||
@ -688,6 +708,7 @@ define(function(require) {
|
||||
"isNICAttachSupported": isNICAttachSupported,
|
||||
"isVNCSupported": isVNCSupported,
|
||||
"isConnectionSupported": isConnectionSupported,
|
||||
"isVMRCSupported": isVMRCSupported,
|
||||
"isSPICESupported": isSPICESupported,
|
||||
"isWFileSupported": isWFileSupported,
|
||||
"hasConnection": hasConnection,
|
||||
@ -952,6 +973,14 @@ define(function(require) {
|
||||
? true : false;
|
||||
}
|
||||
|
||||
// returns true if the vmrc button should be enabled
|
||||
function isVMRCSupported(element) {
|
||||
var action_enabled = Config.isTabActionEnabled("vms-tab", "VM.startvmrc");
|
||||
var graphics = graphicSupported(element, "vmrc");
|
||||
return (action_enabled && graphics)
|
||||
? true : false;
|
||||
}
|
||||
|
||||
function isSPICESupported(element) {
|
||||
return (Config.isTabActionEnabled("vms-tab", "VM.startspice") && graphicSupported(element, "spice"))
|
||||
? true : false;
|
||||
|
@ -170,6 +170,7 @@ define(function(require) {
|
||||
"filterView": _config["view"]["filter-view"],
|
||||
"doCountAnimation": _config["view"]["do_count_animation"],
|
||||
"guacPort": _config["user_config"]["guac_port"],
|
||||
"vmrcPort": _config["user_config"]["vmrc_port"],
|
||||
|
||||
"allTabs": function() {
|
||||
return Object.keys(_config["view"]["tabs"]);
|
||||
|
@ -28,6 +28,8 @@
|
||||
<label class="hypervisor only_kvm not_lxd" for="radioSdlType{{uniqueId}}">SDL</label>
|
||||
<input type="radio" wizard_field="TYPE" name="graphics_type" ID="radioSpiceType{{uniqueId}}" value="SPICE" class="hypervisor only_kvm not_lxd" >
|
||||
<label class="hypervisor only_kvm not_lxd" for="radioSpiceType{{uniqueId}}">SPICE</label>
|
||||
<input type="radio" wizard_field="TYPE" name="graphics_type" ID="radioVMRCType{{uniqueId}}" value="VMRC" class="hypervisor only_vcenter" >
|
||||
<label class="hypervisor only_vcenter" for="radioVMRCType{{uniqueId}}">VMRC</label>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
|
@ -36,6 +36,7 @@ define(function(require) {
|
||||
require("./vms-tab/dialogs/snapshot"),
|
||||
require("./vms-tab/dialogs/revert"),
|
||||
require("./vms-tab/dialogs/vnc"),
|
||||
require("./vms-tab/dialogs/vmrc"),
|
||||
require("./vms-tab/dialogs/spice"),
|
||||
require("./vms-tab/dialogs/guac"),
|
||||
require("./vms-tab/dialogs/saveas-template")
|
||||
|
@ -22,6 +22,7 @@ define(function(require) {
|
||||
var OpenNebulaVM = require('opennebula/vm');
|
||||
var CommonActions = require('utils/common-actions');
|
||||
var Vnc = require('utils/vnc');
|
||||
var Vmrc = require('utils/vmrc');
|
||||
var Spice = require('utils/spice');
|
||||
var Files = require('utils/files');
|
||||
|
||||
@ -30,6 +31,7 @@ define(function(require) {
|
||||
var DEPLOY_DIALOG_ID = require('./dialogs/deploy/dialogId');
|
||||
var MIGRATE_DIALOG_ID = require('./dialogs/migrate/dialogId');
|
||||
var VNC_DIALOG_ID = require('./dialogs/vnc/dialogId');
|
||||
var VMRC_DIALOG_ID = require('./dialogs/vmrc/dialogId');
|
||||
var SPICE_DIALOG_ID = require('./dialogs/spice/dialogId');
|
||||
var GUAC_DIALOG_ID = require('./dialogs/guac/dialogId');
|
||||
var SAVE_AS_TEMPLATE_DIALOG_ID = require('./dialogs/saveas-template/dialogId');
|
||||
@ -283,6 +285,36 @@ define(function(require) {
|
||||
},
|
||||
notify: true
|
||||
},
|
||||
"VM.startvmrc" : {
|
||||
type: "custom",
|
||||
call: function() {
|
||||
$.each(Sunstone.getDataTable(TAB_ID).elements(), function(index, elem) {
|
||||
if (!Vmrc.lockStatus()) {
|
||||
Vmrc.lock();
|
||||
var vm_name = OpenNebulaVM.getName(elem);
|
||||
Sunstone.runAction("VM.startvmrc_action", elem, vm_name);
|
||||
} else {
|
||||
Notifier.notifyError(Locale.tr("VMRC Connection in progress"))
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
"VM.startvmrc_action" : {
|
||||
type: "single",
|
||||
call: OpenNebulaVM.vmrc,
|
||||
callback: function(request, response) {
|
||||
var dialog = Sunstone.getDialog(VMRC_DIALOG_ID);
|
||||
response["vm_name"] = request.request.data[0].extra_param;
|
||||
dialog.setElement(response);
|
||||
dialog.show();
|
||||
},
|
||||
error: function(req, resp) {
|
||||
Notifier.onError(req, resp);
|
||||
Vmrc.unlock();
|
||||
},
|
||||
notify: true
|
||||
},
|
||||
"VM.startspice" : {
|
||||
type: "custom",
|
||||
call: function() {
|
||||
|
@ -200,6 +200,12 @@ define(function(require) {
|
||||
layout: "vmsremote_buttons",
|
||||
custom_classes: "only-sunstone-info vnc-sunstone-info"
|
||||
},
|
||||
"VM.startvmrc" : {
|
||||
type: "action",
|
||||
text: Locale.tr("VMRC"),
|
||||
layout: "vmsremote_buttons",
|
||||
custom_classes: "only-sunstone-info vmrc-sunstone-info"
|
||||
},
|
||||
"VM.startspice" : {
|
||||
type: "action",
|
||||
text: Locale.tr("SPICE"),
|
||||
|
95
src/sunstone/public/app/tabs/vms-tab/dialogs/vmrc.js
Normal file
95
src/sunstone/public/app/tabs/vms-tab/dialogs/vmrc.js
Normal file
@ -0,0 +1,95 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2020, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require) {
|
||||
/*
|
||||
DEPENDENCIES
|
||||
*/
|
||||
|
||||
var BaseDialog = require('utils/dialogs/dialog');
|
||||
var TemplateHTML = require('hbs!./vmrc/html');
|
||||
var Sunstone = require('sunstone');
|
||||
var Vmrc = require('utils/vmrc');
|
||||
|
||||
/*
|
||||
CONSTANTS
|
||||
*/
|
||||
|
||||
var DIALOG_ID = require('./vmrc/dialogId');
|
||||
var TAB_ID = require('../tabId')
|
||||
|
||||
/*
|
||||
CONSTRUCTOR
|
||||
*/
|
||||
|
||||
function Dialog() {
|
||||
this.dialogId = DIALOG_ID;
|
||||
|
||||
BaseDialog.call(this);
|
||||
};
|
||||
|
||||
Dialog.DIALOG_ID = DIALOG_ID;
|
||||
Dialog.prototype = Object.create(BaseDialog.prototype);
|
||||
Dialog.prototype.constructor = Dialog;
|
||||
Dialog.prototype.html = _html;
|
||||
Dialog.prototype.onShow = _onShow;
|
||||
Dialog.prototype.onClose = _onClose;
|
||||
Dialog.prototype.setup = _setup;
|
||||
Dialog.prototype.setElement = _setElement;
|
||||
|
||||
return Dialog;
|
||||
|
||||
/*
|
||||
FUNCTION DEFINITIONS
|
||||
*/
|
||||
|
||||
function _html() {
|
||||
return TemplateHTML({
|
||||
'dialogId': this.dialogId
|
||||
});
|
||||
}
|
||||
|
||||
function _setup(context) {
|
||||
var that = this;
|
||||
|
||||
$("#open_in_a_new_window", context).on("click", function() {
|
||||
var dialog = Sunstone.getDialog(DIALOG_ID);
|
||||
dialog.hide();
|
||||
});
|
||||
|
||||
$('#sendCtrlAltDelButton', context).click(function() {
|
||||
Vmrc.sendCtrlAltDel();
|
||||
return false;
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function _onShow(context) {
|
||||
Vmrc.vmrcCallback(this.element);
|
||||
return false;
|
||||
}
|
||||
|
||||
function _onClose(context) {
|
||||
Vmrc.disconnect();
|
||||
Vmrc.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
function _setElement(element) {
|
||||
this.element = element
|
||||
}
|
||||
});
|
@ -0,0 +1,19 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2020, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require) {
|
||||
return 'vmrcVMDialog';
|
||||
});
|
39
src/sunstone/public/app/tabs/vms-tab/dialogs/vmrc/html.hbs
Normal file
39
src/sunstone/public/app/tabs/vms-tab/dialogs/vmrc/html.hbs
Normal file
@ -0,0 +1,39 @@
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
{{! Copyright 2002-2020, OpenNebula Project, OpenNebula Systems }}
|
||||
{{! }}
|
||||
{{! 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. }}
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
|
||||
<div id="{{dialogId}}" class="reveal full" data-reveal>
|
||||
<div class="row text-center">
|
||||
<div class="large-12 columns">
|
||||
<h5 class="subheader" id="vmrc_dialog">
|
||||
<span id="VMRC_status"></span>
|
||||
<span id="VMRC_buttons" class="right">
|
||||
<button class="button alert" value="Send CtrlAltDel"
|
||||
id="sendCtrlAltDelButton">{{tr "Send CtrlAltDel"}}</button>
|
||||
<a class="button" id="open_in_a_new_window" href="" target="_blank" title="{{tr "Open in a new window"}}">
|
||||
<i class="fas fa-external-link-alt detach-vmrc-icon" />
|
||||
</a>
|
||||
<button class="button secondary" data-close aria-label="{{tr "Close modal"}}" type="button"
|
||||
title="Close VMRC">
|
||||
<i class="fas fa-times-circle"></i>
|
||||
</button>
|
||||
</span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="reveal-body text-center" style="width:100%; overflow-x:auto">
|
||||
<div id="wmksContainer" style="position:absolute;width:100%;height:100%; left:0em"></div>
|
||||
</div>
|
||||
</div>
|
@ -45,7 +45,8 @@ define(function(require) {
|
||||
isSPICESupported = Boolean(OpenNebulaVM.isSPICESupported(element)),
|
||||
isWFileSupported = Boolean(OpenNebulaVM.isWFileSupported(element)),
|
||||
isRDPSupported = Boolean(OpenNebulaVM.isConnectionSupported(element, 'rdp')),
|
||||
isSSHSupported = Boolean(OpenNebulaVM.isConnectionSupported(element, 'ssh'));
|
||||
isSSHSupported = Boolean(OpenNebulaVM.isConnectionSupported(element, 'ssh')),
|
||||
isVMRCSupported = Boolean(OpenNebulaVM.isVMRCSupported(element));
|
||||
|
||||
// All remote buttons are disabled
|
||||
var allDisabled = (
|
||||
@ -53,21 +54,33 @@ define(function(require) {
|
||||
!isSPICESupported &&
|
||||
!isWFileSupported &&
|
||||
!isRDPSupported &&
|
||||
!isSSHSupported
|
||||
!isSSHSupported &&
|
||||
!isVMRCSupported
|
||||
);
|
||||
|
||||
$("#vmsremote_buttons").toggle(!allDisabled);
|
||||
|
||||
if (isVNCSupported) {
|
||||
$(".vnc-sunstone-info").show();
|
||||
$(".spice-sunstone-info").hide();
|
||||
$(".vmrc-sunstone-info").hide();
|
||||
|
||||
}
|
||||
else if (isSPICESupported) {
|
||||
$(".spice-sunstone-info").show();
|
||||
$(".vnc-sunstone-info").hide();
|
||||
$(".vmrc-sunstone-info").hide();
|
||||
|
||||
}
|
||||
else if (isVMRCSupported){
|
||||
$(".vmrc-sunstone-info").show();
|
||||
$(".vnc-sunstone-info").hide();
|
||||
$(".spice-sunstone-info").hide();
|
||||
}
|
||||
else {
|
||||
$(".spice-sunstone-info").hide();
|
||||
$(".vnc-sunstone-info").hide();
|
||||
$(".vmrc-sunstone-info").hide();
|
||||
}
|
||||
|
||||
// Show / hide virt-viewer button
|
||||
|
@ -171,6 +171,20 @@ define(function(require) {
|
||||
TemplateTable.setup(strippedTemplate, RESOURCE, this.element.ID, context, unshownValues, strippedTemplateVcenter);
|
||||
TemplateTableVcenter.setup(strippedTemplateVcenter, RESOURCE, this.element.ID, context, unshownValues, strippedTemplate);
|
||||
|
||||
if (config.system_config &&
|
||||
config.system_config.is_fireedge_up &&
|
||||
config.system_config.is_fireedge_up === "false"){
|
||||
$("a.vmrc-sunstone-info").attr("data-toggle",'tooltip');
|
||||
$("a.vmrc-sunstone-info").attr("title",'Fireedge Server is not running, please contact your cloud administrator');
|
||||
$("a.vmrc-sunstone-info").css("color",'gray');
|
||||
}
|
||||
else{
|
||||
$("a.vmrc-sunstone-info").removeAttr("data-toggle");
|
||||
$("a.vmrc-sunstone-info").removeAttr("title");
|
||||
$("a.vmrc-sunstone-info").css("color",'');
|
||||
}
|
||||
|
||||
|
||||
Websocket.subscribe(this.element.ID);
|
||||
|
||||
}
|
||||
|
149
src/sunstone/public/app/utils/vmrc.js
Normal file
149
src/sunstone/public/app/utils/vmrc.js
Normal file
@ -0,0 +1,149 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2020, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function (require) {
|
||||
var WMKS = require("wmks");
|
||||
var Config = require("sunstone-config");
|
||||
var _lock = false;
|
||||
var _wmks;
|
||||
var _is_encrypted = "";
|
||||
|
||||
return {
|
||||
"lockStatus": lockStatus,
|
||||
"lock": lock,
|
||||
"unlock": unlock,
|
||||
"vmrcCallback": vmrcCallback,
|
||||
"disconnect": disconnect,
|
||||
"sendCtrlAltDel": sendCtrlAltDel
|
||||
};
|
||||
|
||||
function lockStatus() {
|
||||
return _lock;
|
||||
}
|
||||
|
||||
function lock() {
|
||||
_lock = true;
|
||||
}
|
||||
|
||||
function unlock() {
|
||||
_lock = false;
|
||||
}
|
||||
|
||||
function setStatus(message = "", status = "") {
|
||||
$(".VMRC_message").text(message);
|
||||
$("#VMRC_status").text(status);
|
||||
}
|
||||
|
||||
function connected() {
|
||||
setStatus(null, "VMRC " + _wmks.connectionState + " (" + _is_encrypted + ") to: " + _wmks.vm_name);
|
||||
}
|
||||
|
||||
function disconnectedFromServer(e) {
|
||||
if (e.detail.clean) {
|
||||
setStatus(null, "VMRC " + _wmks.connectionState + " (" + _is_encrypted + ") to: " + _wmks.vm_name);
|
||||
} else {
|
||||
setStatus("Something went wrong, connection is closed", "Failed");
|
||||
}
|
||||
}
|
||||
|
||||
function desktopNameChange(e) {
|
||||
if (e.detail.name) {
|
||||
setStatus(null, "VMRC " + _wmks.connectionState + " (" + _is_encrypted + ") to: " /*+ e.detail.name*/);
|
||||
}
|
||||
}
|
||||
|
||||
function credentialsRequired(e) {
|
||||
setStatus("Something went wrong, more credentials must be given to continue", "Failed");
|
||||
}
|
||||
|
||||
function render(ticket, host_vmrc, port_vmrc, response){
|
||||
var URL = "";
|
||||
|
||||
var hostname = window.location.hostname;
|
||||
var port = window.location.port;
|
||||
var protocol = window.location.protocol;
|
||||
var vmrc_port = Config.vmrcPort;
|
||||
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
|
||||
// Content of response.data
|
||||
var ticket = ticket ? ticket : urlParams.get('ticket');
|
||||
var host_vmrc = host_vmrc ? host_vmrc : urlParams.get('host');
|
||||
var port_vmrc = port_vmrc ? port_vmrc : urlParams.get('port');
|
||||
|
||||
if (protocol === "https:") {
|
||||
URL = "wss";
|
||||
_is_encrypted ="encrypted";
|
||||
} else {
|
||||
URL = "ws";
|
||||
_is_encrypted ="unencrypted";
|
||||
}
|
||||
|
||||
URL += "://" + hostname;
|
||||
URL += ":" + vmrc_port + "/";
|
||||
|
||||
var re = new RegExp("^(ws|wss):\\/\\/[\\w\\D]*?\\/", "gi");
|
||||
var link = URL.replace(re, protocol + "//" + hostname + ":" + port + "/vmrc?");
|
||||
|
||||
URL += "vmrc/" + ticket;
|
||||
link += "host=" + hostname;
|
||||
link += "&port=" + vmrc_port;
|
||||
link += "&ticket=" + ticket;
|
||||
|
||||
try {
|
||||
_wmks = WMKS.createWMKS("wmksContainer", {})
|
||||
.register(WMKS.CONST.Events.CONNECTION_STATE_CHANGE,
|
||||
function (event, data) {
|
||||
if (typeof cons !== 'undefined' && data.state == cons.ConnectionState.CONNECTED) {
|
||||
console.log("connection state change : connected");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
_wmks.eventHandlers["connectionstatechange"].push(connected);
|
||||
_wmks.eventHandlers["disconnect"] = disconnectedFromServer;
|
||||
|
||||
_wmks.connect(URL);
|
||||
_wmks["vm_name"] = response.vm_name ? response.vm_name:"";
|
||||
link += "&name=" + _wmks["vm_name"];
|
||||
$("#VMRC_buttons #open_in_a_new_window").attr("href",link);
|
||||
} catch (err) {
|
||||
setStatus("Something went wrong, connection is closed", "Failed");
|
||||
console.log("error start VMRC ", err);
|
||||
}
|
||||
}
|
||||
|
||||
function vmrcCallback(response) {
|
||||
if (response.data){
|
||||
|
||||
render(response.data.ticket,
|
||||
response.data.host,
|
||||
response.data.port,
|
||||
response);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
if (_wmks) { _wmks.disconnect(); }
|
||||
}
|
||||
|
||||
function sendCtrlAltDel() {
|
||||
if (_wmks) { _wmks.sendCAD(); }
|
||||
}
|
||||
});
|
314
src/sunstone/public/app/utils/webmks/css/extended-keypad.css
Normal file
314
src/sunstone/public/app/utils/webmks/css/extended-keypad.css
Normal file
@ -0,0 +1,314 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2013 VMware, Inc. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* extended-keypad.css
|
||||
*
|
||||
* Defines style for the virtual keys on the control pane.
|
||||
*/
|
||||
|
||||
.ctrl-pane-wrapper {
|
||||
width: 290px !important; /* Needed as the default is a bit larger than this */
|
||||
border: 1px solid #333 !important;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
background: rgb(170,171,182); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* W3C */
|
||||
}
|
||||
|
||||
.fnKey-pane-wrapper {
|
||||
width: 427px;
|
||||
border: 1px solid #333;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
background: #c1c4d1; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #c1c4d1 0%,#b0b1bd 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #c1c4d1 0%,#b0b1bd 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #c1c4d1 0%,#b0b1bd 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #c1c4d1 0%, #b0b1bd 100%); /* W3C */
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
-moz-box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
-webkit-box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.fnKey-pane-wrapper-down {
|
||||
width: 427px;
|
||||
border: 1px solid #333;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
background: #6e6e77; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #6e6e77 0%,#656565 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #6e6e77 0%,#656565 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #6e6e77 0%,#656565 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #6e6e77 0%, #656565 100%); /* W3C */
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
-moz-box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
-webkit-box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
/* Hide jquery ui title bar. */
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar {
|
||||
border-top: 1px solid #ccc;
|
||||
border-left: 1px solid #aaa;
|
||||
border-right: 1px solid #aaa;
|
||||
border-bottom: 0;
|
||||
padding: .6em .8em 0 .8em;
|
||||
background: none !important;
|
||||
-moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -khtml-border-top-left-radius: 5px; border-top-left-radius: 5px;
|
||||
-moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -khtml-border-top-right-radius: 5px; border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
/* Replace jquery ui title bar close icon. */
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar-close {
|
||||
margin-top: -9px;
|
||||
border: 0 !important;
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
/* Background-image is defined along with touch-sprite in 1 place. */
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar-close .ui-icon {
|
||||
background-position: -9px -239px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar-close .ui-icon:active {
|
||||
background-position-x: -24px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* The grabber icon indicating the dialog could be moved around */
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar .ui-dialog-title {
|
||||
background-position: -10px -255px;
|
||||
background-repeat: no-repeat;
|
||||
width: 40px;
|
||||
height: 14px;
|
||||
margin: 0 0 0 42%;
|
||||
}
|
||||
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar .ui-dialog-title:active {
|
||||
background-position-x: -52px;
|
||||
}
|
||||
|
||||
.ctrl-pane-wrapper .ui-dialog-content {
|
||||
background: none !important;
|
||||
padding: 0 0;
|
||||
border-style: solid;
|
||||
border-color: #aaaaaa;
|
||||
border-width: 0 1px 1px 1px;
|
||||
-moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -khtml-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;
|
||||
-moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; -khtml-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
.fnKey-inner-border-helper {
|
||||
position: relative;
|
||||
background: none !important;
|
||||
border-style: solid;
|
||||
border-color: #d5d5d5;
|
||||
border-width: 1px;
|
||||
-moz-border-radius: 5px; -webkit-border-radius: 5px; -khtml-border-radius: 5px; border-radius: 5px;
|
||||
pointer-events:none;
|
||||
}
|
||||
|
||||
.ctrl-pane-wrapper .ctrl-pane {
|
||||
padding: 3px 0 3px 6px;
|
||||
height: 140px;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey {
|
||||
float: left;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
width: 57px;
|
||||
height: 57px;
|
||||
margin: 6px;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
font-family: "HelveticaNeue", "Helvetica Neue", "HelveticaNeue", "Helvetica Neue", 'TeXGyreHeros', "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
||||
font-size: 18px;
|
||||
text-shadow: 0 1px 1px #eeeeee;
|
||||
-moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, .7);
|
||||
-webkit-box-shadow: 0px 1px 3px rgba(0,0,0,.7);
|
||||
box-shadow: 0px 1px 3px rgba(0,0,0,.7);
|
||||
}
|
||||
|
||||
.ctrl-pane .ctrl-key-top-row {
|
||||
background: -webkit-linear-gradient(top, #fff 0%,#f3f5fb 2%,#d2d2d8 98%,#999 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #fff 0%,#f3f5fb 2%,#d2d2d8 98%,#999 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #fff 0%,#f3f5fb 2%,#d2d2d8 98%,#999 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #fff 0%,#f3f5fb 2%,#d2d2d8 98%,#999 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .ctrl-key-bottom-row {
|
||||
background: -webkit-linear-gradient(top, #fff 0%,#e1e1e3 2%,#d1d1d4 50%,#bebec3 98%,#838387 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #fff 0%,#e1e1e3 2%,#d1d1d4 50%,#bebec3 98%,#838387 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #fff 0%,#e1e1e3 2%,#d1d1d4 50%,#bebec3 98%,#838387 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #fff 0%,#e1e1e3 2%,#d1d1d4 50%,#bebec3 98%,#838387 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .up-position .fn-key-top-row {
|
||||
color:#333;
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#f7f7f7 2%,#dcdde3 96%,#999999 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#f7f7f7 2%,#dcdde3 96%,#999999 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#f7f7f7 2%,#dcdde3 96%,#999999 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #ffffff 0%,#f7f7f7 2%,#dcdde3 96%,#999999 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .up-position .fn-key-bottom-row {
|
||||
color:#333;
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#f3f5fb 2%,#d2d2d8 98%,#999999 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#f3f5fb 2%,#d2d2d8 98%,#999999 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#f3f5fb 2%,#d2d2d8 98%,#999999 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #ffffff 0%,#f3f5fb 2%,#d2d2d8 98%,#999999 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .down-position .fn-key-top-row {
|
||||
color:#333;
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#e1e1e3 4%,#d1d1d4 45%,#b7b8bd 98%,#838387 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#e1e1e3 4%,#d1d1d4 45%,#b7b8bd 98%,#838387 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#e1e1e3 4%,#d1d1d4 45%,#b7b8bd 98%,#838387 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #ffffff 0%,#e1e1e3 4%,#d1d1d4 45%,#b7b8bd 98%,#838387 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .down-position .fn-key-bottom-row {
|
||||
color:#333;
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#d9dadd 4%,#c8c8cd 45%,#b0b0b7 98%,#838387 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#d9dadd 4%,#c8c8cd 45%,#b0b0b7 98%,#838387 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#d9dadd 4%,#c8c8cd 45%,#b0b0b7 98%,#838387 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #ffffff 0%,#d9dadd 4%,#c8c8cd 45%,#b0b0b7 98%,#838387 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .fn-key-top-row {
|
||||
margin: 12px 6px 6px 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .border-key-top-left .fn-key-top-row {
|
||||
margin: 12px 6px 6px 12px;
|
||||
}
|
||||
|
||||
.ctrl-pane .border-key-top-right .fn-key-top-row {
|
||||
margin: 12px 12px 6px 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .fn-key-bottom-row {
|
||||
margin: 5px 6px 12px 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .border-key-bottom-left .fn-key-bottom-row {
|
||||
margin: 5px 6px 12px 12px;
|
||||
}
|
||||
|
||||
.ctrl-pane .border-key-bottom-right .fn-key-bottom-row {
|
||||
margin: 5px 12px 12px 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .ctrl-key-top-row:active, .ctrl-pane .fn-key-top-row:active,
|
||||
.ctrl-pane .ctrl-key-bottom-row:active, .ctrl-pane .fn-key-bottom-row:active {
|
||||
background: #bbbbbb;
|
||||
background: -webkit-linear-gradient(bottom, #888888 25%, #CCCCCC 68%);
|
||||
background: -ms-linear-gradient(bottom, #888888 25%, #CCCCCC 68%);
|
||||
background: -o-linear-gradient(bottom, #888888 25%, #CCCCCC 68%);
|
||||
background: linear-gradient(bottom, #888888 25%, #CCCCCC 68%);
|
||||
}
|
||||
|
||||
.ctrl-pane .ctrl-key-top-row div, .ctrl-pane .ctrl-key-bottom-row div,
|
||||
.ctrl-pane .fn-key-top-row div, .ctrl-pane .fn-key-bottom-row div {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding-top: 17px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Highlight selected modifier key */
|
||||
.ctrl-pane .ab-modifier-key-down {
|
||||
color: #4D8DFF;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey img { /* use .touch-sprite for image */
|
||||
background-repeat: no-repeat;
|
||||
width: 57px;
|
||||
height: 57px;
|
||||
border: 0;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .right-arrow {
|
||||
background-position: -242px -182px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .left-arrow {
|
||||
background-position: -126px -182px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .up-arrow {
|
||||
background-position: -299px -182px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .down-arrow {
|
||||
background-position: -183px -182px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .more-keys {
|
||||
background-position: -10px -182px;
|
||||
}
|
||||
|
||||
/* Ctrl - pane flip transition. */
|
||||
.ctrl-pane.flip-container {
|
||||
perspective: 1000;
|
||||
-webkit-perspective: 1000;
|
||||
-moz-perspective: 1000;
|
||||
-ms-perspective: 1000;
|
||||
}
|
||||
|
||||
/* flip the ctrl-pane when this class toggles. */
|
||||
.flip-container.perform-flip .flipper {
|
||||
transform: rotateY(180deg);
|
||||
-webkit-transform: rotateY(180deg);
|
||||
-moz-transform: rotateY(180deg);
|
||||
-ms-transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
/* flip speed goes here */
|
||||
.flip-container .flipper {
|
||||
transition: 0.6s;
|
||||
transform-style: preserve-3d;
|
||||
-webkit-transition: 0.6s;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
-moz-transition: 0.6s;
|
||||
-moz-transform-style: preserve-3d;
|
||||
-ms-transition: 0.6s;
|
||||
-ms-transform-style: preserve-3d;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* hide back of pane during swap */
|
||||
.flip-container .front, .flip-container .back {
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* front pane, placed above back */
|
||||
.flip-container .front {
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
/* back, initially hidden pane */
|
||||
.flip-container .back {
|
||||
transform: rotateY(180deg);
|
||||
-webkit-transform: rotateY(180deg);
|
||||
-moz-transform: rotateY(180deg);
|
||||
-ms-transform: rotateY(180deg);
|
||||
}
|
155
src/sunstone/public/app/utils/webmks/css/main-ui.css
Normal file
155
src/sunstone/public/app/utils/webmks/css/main-ui.css
Normal file
@ -0,0 +1,155 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2013 VMware, Inc. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* main-ui.css
|
||||
*
|
||||
* Defines style for the wmks ui widgets.
|
||||
*
|
||||
* Use CSS3 for touch devices as jquery effects break when browser handles
|
||||
* orientation changes, or page bouncing.
|
||||
*
|
||||
* TODO: Need to handle Retina mode for iPad.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jQuery UI Dialog 1.8.16
|
||||
*/
|
||||
.ui-dialog {
|
||||
padding: 0;
|
||||
box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: .8em .8em;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar-close {
|
||||
right: .4em;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
.ui-widget-content {
|
||||
border: 0;
|
||||
background: #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.ui-widget-header a {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
|
||||
/* Touch feedback indicator */
|
||||
.ui-touch-feedback-icon {
|
||||
background-image: url('../img/touch_sprite_feedback.png');
|
||||
width: 300px;
|
||||
height: 120px;
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
top: -9999px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.feedback-container {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.feedback-container.cursor-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -260px -15px no-repeat;
|
||||
width: 17px;
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
.feedback-container.tap-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -300px -15px no-repeat;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.feedback-container.drag-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -10px -10px no-repeat;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.feedback-container.pulse-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -111px -10px no-repeat;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.feedback-container.scroll-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -212px -10px no-repeat;
|
||||
width: 27px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
/* CSS3 feedback indicator animation. Keep it simple (uses lower cpu cycles)
|
||||
as there may be multiple animation requests made in quick successions. */
|
||||
.animate-feedback-indicator {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
animation-name: showfadeout;
|
||||
animation-duration: 350ms;
|
||||
-webkit-animation-name: showfadeout;
|
||||
-webkit-animation-duration: 350ms;
|
||||
-moz-animation-name: showfadeout;
|
||||
-moz-animation-duration: 350ms;
|
||||
-ms-animation-name: showfadeout;
|
||||
-ms-animation-duration: 350ms;
|
||||
}
|
||||
|
||||
@-webkit-keyframes showfadeout {
|
||||
0% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-moz-keyframes showfadeout {
|
||||
0% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-ms-keyframes showfadeout {
|
||||
0% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
.animate-double-feedback-indicator {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
animation-name: showdoublefadeout;
|
||||
animation-duration: 400ms;
|
||||
-webkit-animation-name: showdoublefadeout;
|
||||
-webkit-animation-duration: 400ms;
|
||||
-moz-animation-name: showdoublefadeout;
|
||||
-moz-animation-duration: 400ms;
|
||||
-ms-animation-name: showdoublefadeout;
|
||||
-ms-animation-duration: 400ms;
|
||||
}
|
||||
|
||||
@-webkit-keyframes showdoublefadeout {
|
||||
0% { opacity: 1; }
|
||||
40% { opacity: 0; }
|
||||
70% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-moz-keyframes showdoublefadeout {
|
||||
0% { opacity: 1; }
|
||||
40% { opacity: 0; }
|
||||
70% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-ms-keyframes showdoublefadeout {
|
||||
0% { opacity: 1; }
|
||||
40% { opacity: 0; }
|
||||
70% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
192
src/sunstone/public/app/utils/webmks/css/trackpad.css
Normal file
192
src/sunstone/public/app/utils/webmks/css/trackpad.css
Normal file
@ -0,0 +1,192 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2013 VMware, Inc. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* trackpad.css
|
||||
*
|
||||
* Defines style for the trackpad widget.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jQuery UI Dialog 1.8.16
|
||||
*/
|
||||
.ui-dialog {
|
||||
padding: 0;
|
||||
box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: .8em .8em;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar-close {
|
||||
right: .4em;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
.ui-widget-content {
|
||||
border: 0;
|
||||
background: #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.ui-widget-header a {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
/*
|
||||
* Touch sprite is loaded in a single class (as we have disabled caching images).
|
||||
* We do this for the iOS case, due to extreme limitations in terms of image size.
|
||||
* This form of grouped declaration forces all these definitions to load the same
|
||||
* sprite. (This is also loaded upfront for the navbar so its always visible).
|
||||
* For details see PR - 978390.
|
||||
*/
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close .ui-icon,
|
||||
.trackpad-wrapper .ui-dialog-titlebar .ui-dialog-title,
|
||||
.touch-sprite {
|
||||
background-image: url('../img/touch_sprite.png');
|
||||
}
|
||||
|
||||
/* Replace jquery ui title bar close icon. */
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close {
|
||||
margin-top: -9px;
|
||||
border: 0 !important;
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close {
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
/* Background-image is defined along with touch-sprite in 1 place. */
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close .ui-icon {
|
||||
background-position: -9px -239px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close .ui-icon:active {
|
||||
background-position-x: -24px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* The grabber icon indicating the dialog could be moved around */
|
||||
.trackpad-wrapper .ui-dialog-titlebar .ui-dialog-title {
|
||||
background-position: -10px -255px;
|
||||
background-repeat: no-repeat;
|
||||
width: 40px;
|
||||
height: 14px;
|
||||
margin: 0 0 0 42%;
|
||||
}
|
||||
.trackpad-wrapper .ui-dialog-titlebar .ui-dialog-title:active {
|
||||
background-position-x: -52px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper {
|
||||
width: 289px !important; /* As this is less than the default value */
|
||||
border: 1px solid #333 !important;
|
||||
background: none !important;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0px 4px 9px rgba(0,0,0,.6);
|
||||
}
|
||||
|
||||
.trackpad-wrapper .ui-dialog-titlebar {
|
||||
border-top: 1px solid #ccc;
|
||||
border-left: 1px solid #aaa;
|
||||
border-right: 1px solid #aaa;
|
||||
border-bottom: 0;
|
||||
padding: .5em .8em .4em .8em;
|
||||
background: rgb(175,176,187); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(175,176,187,.93) 0%,rgba(170,171,182,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(175,176,187,.93) 0%,rgba(170,171,182,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(175,176,187,.93) 0%,rgba(170,171,182,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(175,176,187,.93) 0%,rgba(170,171,182,.93) 100%); /* W3C */
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .trackpad-container {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .left-border {
|
||||
background: rgb(170,171,182); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* W3C */
|
||||
margin-top: -1px;
|
||||
float: left;
|
||||
width: 12px;
|
||||
height: 209px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .touch-area {
|
||||
background: rgba(255,255,255,0.8);
|
||||
background: -webkit-linear-gradient(-70deg, rgba(255,255,255,0.8) 0%, rgba(238,238,240,0.8) 22%, rgba(210,210,216,0.8) 71%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(-70deg, rgba(255,255,255,0.8) 0%, rgba(238,238,240,0.8) 22%, rgba(210,210,216,0.8) 71%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(-70deg, rgba(255,255,255,0.8) 0%, rgba(238,238,240,0.8) 22%, rgba(210,210,216,0.8) 71%); /* IE10+ */
|
||||
background: linear-gradient(110deg, rgba(255,255,255,0.8) 0%, rgba(238,238,240,0.8) 22%, rgba(210,210,216,0.8) 71%); /* W3C */
|
||||
border: 1px solid #555;
|
||||
box-shadow: 0 2px 6px 1px #888 inset;
|
||||
float: left;
|
||||
width: 263px;
|
||||
height: 206px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .right-border {
|
||||
background: rgb(170,171,182); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* W3C */
|
||||
margin-top: -1px;
|
||||
float: left;
|
||||
width: 12px;
|
||||
height: 209px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .bottom-border {
|
||||
background: rgb(123,123,133); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(123,123,133,.93) 0%,rgba(110,110,119,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(123,123,133,.93) 0%,rgba(110,110,119,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(123,123,133,.93) 0%,rgba(110,110,119,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(123,123,133,.93) 0%,rgba(110,110,119,.93) 100%); /* W3C */
|
||||
width: 289px;
|
||||
height: 73px;
|
||||
margin-top: 208px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .button-left, .trackpad-wrapper .button-right {
|
||||
background: rgb(255,255,255); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(255,255,255,.7) 0%,rgba(225,225,227,.7) 3%,rgba(204,204,204,.7) 45%,rgba(190,190,195,.7) 96%,rgba(131,131,135,.7) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(255,255,255,.7) 0%,rgba(225,225,227,.7) 3%,rgba(204,204,204,.7) 45%,rgba(190,190,195,.7) 96%,rgba(131,131,135,.7) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(255,255,255,.7) 0%,rgba(225,225,227,.7) 3%,rgba(204,204,204,.7) 45%,rgba(190,190,195,.7) 96%,rgba(131,131,135,.7) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(255,255,255,.7) 0%,rgba(225,225,227,.7) 3%,rgba(204,204,204,.7) 45%,rgba(190,190,195,.7) 96%,rgba(131,131,135,.7) 100%); /* W3C */
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 5px #333;
|
||||
float: left;
|
||||
width: 126px;
|
||||
height: 47px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .button-left {
|
||||
margin: 12px 0px auto 12px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .button-right {
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .button-left.button-highlight,
|
||||
.trackpad-wrapper .button-right.button-highlight {
|
||||
background: -webkit-linear-gradient(top, rgba(170,171,182,.7) 0%,rgba(123,123,133,.7) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(170,171,182,.7) 0%,rgba(123,123,133,.7) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(170,171,182,.7) 0%,rgba(123,123,133,.7) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(170,171,182,.7) 0%,rgba(123,123,133,.7) 100%); /* W3C */
|
||||
}
|
661
src/sunstone/public/app/utils/webmks/css/wmks-all.css
Normal file
661
src/sunstone/public/app/utils/webmks/css/wmks-all.css
Normal file
@ -0,0 +1,661 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2013 VMware, Inc. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* main-ui.css
|
||||
*
|
||||
* Defines style for the wmks ui widgets.
|
||||
*
|
||||
* Use CSS3 for touch devices as jquery effects break when browser handles
|
||||
* orientation changes, or page bouncing.
|
||||
*
|
||||
* TODO: Need to handle Retina mode for iPad.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jQuery UI Dialog 1.8.16
|
||||
*/
|
||||
.ui-dialog {
|
||||
padding: 0;
|
||||
box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: .8em .8em;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar-close {
|
||||
right: .4em;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
.ui-widget-content {
|
||||
border: 0;
|
||||
background: #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.ui-widget-header a {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
|
||||
/* Touch feedback indicator */
|
||||
.ui-touch-feedback-icon {
|
||||
background-image: url('../img/touch_sprite_feedback.png');
|
||||
width: 300px;
|
||||
height: 120px;
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
top: -9999px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.feedback-container {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.feedback-container.cursor-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -260px -15px no-repeat;
|
||||
width: 17px;
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
.feedback-container.tap-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -300px -15px no-repeat;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.feedback-container.drag-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -10px -10px no-repeat;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.feedback-container.pulse-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -111px -10px no-repeat;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.feedback-container.scroll-icon {
|
||||
background: url('../img/touch_sprite_feedback.png') -212px -10px no-repeat;
|
||||
width: 27px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
/* CSS3 feedback indicator animation. Keep it simple (uses lower cpu cycles)
|
||||
as there may be multiple animation requests made in quick successions. */
|
||||
.animate-feedback-indicator {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
animation-name: showfadeout;
|
||||
animation-duration: 350ms;
|
||||
-webkit-animation-name: showfadeout;
|
||||
-webkit-animation-duration: 350ms;
|
||||
-moz-animation-name: showfadeout;
|
||||
-moz-animation-duration: 350ms;
|
||||
-ms-animation-name: showfadeout;
|
||||
-ms-animation-duration: 350ms;
|
||||
}
|
||||
|
||||
@-webkit-keyframes showfadeout {
|
||||
0% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-moz-keyframes showfadeout {
|
||||
0% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-ms-keyframes showfadeout {
|
||||
0% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
.animate-double-feedback-indicator {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
animation-name: showdoublefadeout;
|
||||
animation-duration: 400ms;
|
||||
-webkit-animation-name: showdoublefadeout;
|
||||
-webkit-animation-duration: 400ms;
|
||||
-moz-animation-name: showdoublefadeout;
|
||||
-moz-animation-duration: 400ms;
|
||||
-ms-animation-name: showdoublefadeout;
|
||||
-ms-animation-duration: 400ms;
|
||||
}
|
||||
|
||||
@-webkit-keyframes showdoublefadeout {
|
||||
0% { opacity: 1; }
|
||||
40% { opacity: 0; }
|
||||
70% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-moz-keyframes showdoublefadeout {
|
||||
0% { opacity: 1; }
|
||||
40% { opacity: 0; }
|
||||
70% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-ms-keyframes showdoublefadeout {
|
||||
0% { opacity: 1; }
|
||||
40% { opacity: 0; }
|
||||
70% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright 2013 VMware, Inc. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* trackpad.css
|
||||
*
|
||||
* Defines style for the trackpad widget.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jQuery UI Dialog 1.8.16
|
||||
*/
|
||||
.ui-dialog {
|
||||
padding: 0;
|
||||
box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: .8em .8em;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar-close {
|
||||
right: .4em;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
.ui-widget-content {
|
||||
border: 0;
|
||||
background: #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.ui-widget-header a {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
/*
|
||||
* Touch sprite is loaded in a single class (as we have disabled caching images).
|
||||
* We do this for the iOS case, due to extreme limitations in terms of image size.
|
||||
* This form of grouped declaration forces all these definitions to load the same
|
||||
* sprite. (This is also loaded upfront for the navbar so its always visible).
|
||||
* For details see PR - 978390.
|
||||
*/
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close .ui-icon,
|
||||
.trackpad-wrapper .ui-dialog-titlebar .ui-dialog-title,
|
||||
.touch-sprite {
|
||||
background-image: url('../img/touch_sprite.png');
|
||||
}
|
||||
|
||||
/* Replace jquery ui title bar close icon. */
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close {
|
||||
margin-top: -9px;
|
||||
border: 0 !important;
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close {
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
/* Background-image is defined along with touch-sprite in 1 place. */
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close .ui-icon {
|
||||
background-position: -9px -239px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .ui-dialog-titlebar-close .ui-icon:active {
|
||||
background-position-x: -24px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* The grabber icon indicating the dialog could be moved around */
|
||||
.trackpad-wrapper .ui-dialog-titlebar .ui-dialog-title {
|
||||
background-position: -10px -255px;
|
||||
background-repeat: no-repeat;
|
||||
width: 40px;
|
||||
height: 14px;
|
||||
margin: 0 0 0 42%;
|
||||
}
|
||||
.trackpad-wrapper .ui-dialog-titlebar .ui-dialog-title:active {
|
||||
background-position-x: -52px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper {
|
||||
width: 289px !important; /* As this is less than the default value */
|
||||
border: 1px solid #333 !important;
|
||||
background: none !important;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0px 4px 9px rgba(0,0,0,.6);
|
||||
}
|
||||
|
||||
.trackpad-wrapper .ui-dialog-titlebar {
|
||||
border-top: 1px solid #ccc;
|
||||
border-left: 1px solid #aaa;
|
||||
border-right: 1px solid #aaa;
|
||||
border-bottom: 0;
|
||||
padding: .5em .8em .4em .8em;
|
||||
background: rgb(175,176,187); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(175,176,187,.93) 0%,rgba(170,171,182,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(175,176,187,.93) 0%,rgba(170,171,182,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(175,176,187,.93) 0%,rgba(170,171,182,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(175,176,187,.93) 0%,rgba(170,171,182,.93) 100%); /* W3C */
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .trackpad-container {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .left-border {
|
||||
background: rgb(170,171,182); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* W3C */
|
||||
margin-top: -1px;
|
||||
float: left;
|
||||
width: 12px;
|
||||
height: 209px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .touch-area {
|
||||
background: rgba(255,255,255,0.8);
|
||||
background: -webkit-linear-gradient(-70deg, rgba(255,255,255,0.8) 0%, rgba(238,238,240,0.8) 22%, rgba(210,210,216,0.8) 71%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(-70deg, rgba(255,255,255,0.8) 0%, rgba(238,238,240,0.8) 22%, rgba(210,210,216,0.8) 71%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(-70deg, rgba(255,255,255,0.8) 0%, rgba(238,238,240,0.8) 22%, rgba(210,210,216,0.8) 71%); /* IE10+ */
|
||||
background: linear-gradient(110deg, rgba(255,255,255,0.8) 0%, rgba(238,238,240,0.8) 22%, rgba(210,210,216,0.8) 71%); /* W3C */
|
||||
border: 1px solid #555;
|
||||
box-shadow: 0 2px 6px 1px #888 inset;
|
||||
float: left;
|
||||
width: 263px;
|
||||
height: 206px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .right-border {
|
||||
background: rgb(170,171,182); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* W3C */
|
||||
margin-top: -1px;
|
||||
float: left;
|
||||
width: 12px;
|
||||
height: 209px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .bottom-border {
|
||||
background: rgb(123,123,133); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(123,123,133,.93) 0%,rgba(110,110,119,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(123,123,133,.93) 0%,rgba(110,110,119,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(123,123,133,.93) 0%,rgba(110,110,119,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(123,123,133,.93) 0%,rgba(110,110,119,.93) 100%); /* W3C */
|
||||
width: 289px;
|
||||
height: 73px;
|
||||
margin-top: 208px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .button-left, .trackpad-wrapper .button-right {
|
||||
background: rgb(255,255,255); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(255,255,255,.7) 0%,rgba(225,225,227,.7) 3%,rgba(204,204,204,.7) 45%,rgba(190,190,195,.7) 96%,rgba(131,131,135,.7) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(255,255,255,.7) 0%,rgba(225,225,227,.7) 3%,rgba(204,204,204,.7) 45%,rgba(190,190,195,.7) 96%,rgba(131,131,135,.7) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(255,255,255,.7) 0%,rgba(225,225,227,.7) 3%,rgba(204,204,204,.7) 45%,rgba(190,190,195,.7) 96%,rgba(131,131,135,.7) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(255,255,255,.7) 0%,rgba(225,225,227,.7) 3%,rgba(204,204,204,.7) 45%,rgba(190,190,195,.7) 96%,rgba(131,131,135,.7) 100%); /* W3C */
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 5px #333;
|
||||
float: left;
|
||||
width: 126px;
|
||||
height: 47px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .button-left {
|
||||
margin: 12px 0px auto 12px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .button-right {
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.trackpad-wrapper .button-left.button-highlight,
|
||||
.trackpad-wrapper .button-right.button-highlight {
|
||||
background: -webkit-linear-gradient(top, rgba(170,171,182,.7) 0%,rgba(123,123,133,.7) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(170,171,182,.7) 0%,rgba(123,123,133,.7) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(170,171,182,.7) 0%,rgba(123,123,133,.7) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(170,171,182,.7) 0%,rgba(123,123,133,.7) 100%); /* W3C */
|
||||
}
|
||||
/******************************************************************************
|
||||
* Copyright 2013 VMware, Inc. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* extended-keypad.css
|
||||
*
|
||||
* Defines style for the virtual keys on the control pane.
|
||||
*/
|
||||
|
||||
.ctrl-pane-wrapper {
|
||||
width: 290px !important; /* Needed as the default is a bit larger than this */
|
||||
border: 1px solid #333 !important;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
background: rgb(170,171,182); /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(170,171,182,.93) 0%,rgba(123,123,133,.93) 100%); /* W3C */
|
||||
}
|
||||
|
||||
.fnKey-pane-wrapper {
|
||||
width: 427px;
|
||||
border: 1px solid #333;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
background: #c1c4d1; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #c1c4d1 0%,#b0b1bd 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #c1c4d1 0%,#b0b1bd 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #c1c4d1 0%,#b0b1bd 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #c1c4d1 0%, #b0b1bd 100%); /* W3C */
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
-moz-box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
-webkit-box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.fnKey-pane-wrapper-down {
|
||||
width: 427px;
|
||||
border: 1px solid #333;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
background: #6e6e77; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #6e6e77 0%,#656565 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #6e6e77 0%,#656565 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #6e6e77 0%,#656565 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #6e6e77 0%, #656565 100%); /* W3C */
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
-moz-box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
-webkit-box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
box-shadow: 0px 5px 7px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
/* Hide jquery ui title bar. */
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar {
|
||||
border-top: 1px solid #ccc;
|
||||
border-left: 1px solid #aaa;
|
||||
border-right: 1px solid #aaa;
|
||||
border-bottom: 0;
|
||||
padding: .6em .8em 0 .8em;
|
||||
background: none !important;
|
||||
-moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -khtml-border-top-left-radius: 5px; border-top-left-radius: 5px;
|
||||
-moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -khtml-border-top-right-radius: 5px; border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
/* Replace jquery ui title bar close icon. */
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar-close {
|
||||
margin-top: -9px;
|
||||
border: 0 !important;
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
/* Background-image is defined along with touch-sprite in 1 place. */
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar-close .ui-icon {
|
||||
background-position: -9px -239px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar-close .ui-icon:active {
|
||||
background-position-x: -24px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* The grabber icon indicating the dialog could be moved around */
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar .ui-dialog-title {
|
||||
background-position: -10px -255px;
|
||||
background-repeat: no-repeat;
|
||||
width: 40px;
|
||||
height: 14px;
|
||||
margin: 0 0 0 42%;
|
||||
}
|
||||
|
||||
.ctrl-pane-wrapper .ui-dialog-titlebar .ui-dialog-title:active {
|
||||
background-position-x: -52px;
|
||||
}
|
||||
|
||||
.ctrl-pane-wrapper .ui-dialog-content {
|
||||
background: none !important;
|
||||
padding: 0 0;
|
||||
border-style: solid;
|
||||
border-color: #aaaaaa;
|
||||
border-width: 0 1px 1px 1px;
|
||||
-moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -khtml-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;
|
||||
-moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; -khtml-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
.fnKey-inner-border-helper {
|
||||
position: relative;
|
||||
background: none !important;
|
||||
border-style: solid;
|
||||
border-color: #d5d5d5;
|
||||
border-width: 1px;
|
||||
-moz-border-radius: 5px; -webkit-border-radius: 5px; -khtml-border-radius: 5px; border-radius: 5px;
|
||||
pointer-events:none;
|
||||
}
|
||||
|
||||
.ctrl-pane-wrapper .ctrl-pane {
|
||||
padding: 3px 0 3px 6px;
|
||||
height: 140px;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey {
|
||||
float: left;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
width: 57px;
|
||||
height: 57px;
|
||||
margin: 6px;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
font-family: "HelveticaNeue", "Helvetica Neue", "HelveticaNeue", "Helvetica Neue", 'TeXGyreHeros', "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
||||
font-size: 18px;
|
||||
text-shadow: 0 1px 1px #eeeeee;
|
||||
-moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, .7);
|
||||
-webkit-box-shadow: 0px 1px 3px rgba(0,0,0,.7);
|
||||
box-shadow: 0px 1px 3px rgba(0,0,0,.7);
|
||||
}
|
||||
|
||||
.ctrl-pane .ctrl-key-top-row {
|
||||
background: -webkit-linear-gradient(top, #fff 0%,#f3f5fb 2%,#d2d2d8 98%,#999 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #fff 0%,#f3f5fb 2%,#d2d2d8 98%,#999 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #fff 0%,#f3f5fb 2%,#d2d2d8 98%,#999 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #fff 0%,#f3f5fb 2%,#d2d2d8 98%,#999 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .ctrl-key-bottom-row {
|
||||
background: -webkit-linear-gradient(top, #fff 0%,#e1e1e3 2%,#d1d1d4 50%,#bebec3 98%,#838387 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #fff 0%,#e1e1e3 2%,#d1d1d4 50%,#bebec3 98%,#838387 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #fff 0%,#e1e1e3 2%,#d1d1d4 50%,#bebec3 98%,#838387 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #fff 0%,#e1e1e3 2%,#d1d1d4 50%,#bebec3 98%,#838387 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .up-position .fn-key-top-row {
|
||||
color:#333;
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#f7f7f7 2%,#dcdde3 96%,#999999 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#f7f7f7 2%,#dcdde3 96%,#999999 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#f7f7f7 2%,#dcdde3 96%,#999999 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #ffffff 0%,#f7f7f7 2%,#dcdde3 96%,#999999 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .up-position .fn-key-bottom-row {
|
||||
color:#333;
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#f3f5fb 2%,#d2d2d8 98%,#999999 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#f3f5fb 2%,#d2d2d8 98%,#999999 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#f3f5fb 2%,#d2d2d8 98%,#999999 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #ffffff 0%,#f3f5fb 2%,#d2d2d8 98%,#999999 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .down-position .fn-key-top-row {
|
||||
color:#333;
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#e1e1e3 4%,#d1d1d4 45%,#b7b8bd 98%,#838387 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#e1e1e3 4%,#d1d1d4 45%,#b7b8bd 98%,#838387 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#e1e1e3 4%,#d1d1d4 45%,#b7b8bd 98%,#838387 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #ffffff 0%,#e1e1e3 4%,#d1d1d4 45%,#b7b8bd 98%,#838387 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .down-position .fn-key-bottom-row {
|
||||
color:#333;
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -webkit-linear-gradient(top, #ffffff 0%,#d9dadd 4%,#c8c8cd 45%,#b0b0b7 98%,#838387 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #ffffff 0%,#d9dadd 4%,#c8c8cd 45%,#b0b0b7 98%,#838387 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#d9dadd 4%,#c8c8cd 45%,#b0b0b7 98%,#838387 100%); /* IE10+ */
|
||||
background: linear-gradient(top, #ffffff 0%,#d9dadd 4%,#c8c8cd 45%,#b0b0b7 98%,#838387 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ctrl-pane .fn-key-top-row {
|
||||
margin: 12px 6px 6px 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .border-key-top-left .fn-key-top-row {
|
||||
margin: 12px 6px 6px 12px;
|
||||
}
|
||||
|
||||
.ctrl-pane .border-key-top-right .fn-key-top-row {
|
||||
margin: 12px 12px 6px 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .fn-key-bottom-row {
|
||||
margin: 5px 6px 12px 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .border-key-bottom-left .fn-key-bottom-row {
|
||||
margin: 5px 6px 12px 12px;
|
||||
}
|
||||
|
||||
.ctrl-pane .border-key-bottom-right .fn-key-bottom-row {
|
||||
margin: 5px 12px 12px 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .ctrl-key-top-row:active, .ctrl-pane .fn-key-top-row:active,
|
||||
.ctrl-pane .ctrl-key-bottom-row:active, .ctrl-pane .fn-key-bottom-row:active {
|
||||
background: #bbbbbb;
|
||||
background: -webkit-linear-gradient(bottom, #888888 25%, #CCCCCC 68%);
|
||||
background: -ms-linear-gradient(bottom, #888888 25%, #CCCCCC 68%);
|
||||
background: -o-linear-gradient(bottom, #888888 25%, #CCCCCC 68%);
|
||||
background: linear-gradient(bottom, #888888 25%, #CCCCCC 68%);
|
||||
}
|
||||
|
||||
.ctrl-pane .ctrl-key-top-row div, .ctrl-pane .ctrl-key-bottom-row div,
|
||||
.ctrl-pane .fn-key-top-row div, .ctrl-pane .fn-key-bottom-row div {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding-top: 17px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Highlight selected modifier key */
|
||||
.ctrl-pane .ab-modifier-key-down {
|
||||
color: #4D8DFF;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey img { /* use .touch-sprite for image */
|
||||
background-repeat: no-repeat;
|
||||
width: 57px;
|
||||
height: 57px;
|
||||
border: 0;
|
||||
-moz-border-radius: 6px; -webkit-border-radius: 6px; -khtml-border-radius: 6px; border-radius: 6px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .right-arrow {
|
||||
background-position: -242px -182px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .left-arrow {
|
||||
background-position: -126px -182px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .up-arrow {
|
||||
background-position: -299px -182px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .down-arrow {
|
||||
background-position: -183px -182px;
|
||||
}
|
||||
|
||||
.ctrl-pane .baseKey .more-keys {
|
||||
background-position: -10px -182px;
|
||||
}
|
||||
|
||||
/* Ctrl - pane flip transition. */
|
||||
.ctrl-pane.flip-container {
|
||||
perspective: 1000;
|
||||
-webkit-perspective: 1000;
|
||||
-moz-perspective: 1000;
|
||||
-ms-perspective: 1000;
|
||||
}
|
||||
|
||||
/* flip the ctrl-pane when this class toggles. */
|
||||
.flip-container.perform-flip .flipper {
|
||||
transform: rotateY(180deg);
|
||||
-webkit-transform: rotateY(180deg);
|
||||
-moz-transform: rotateY(180deg);
|
||||
-ms-transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
/* flip speed goes here */
|
||||
.flip-container .flipper {
|
||||
transition: 0.6s;
|
||||
transform-style: preserve-3d;
|
||||
-webkit-transition: 0.6s;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
-moz-transition: 0.6s;
|
||||
-moz-transform-style: preserve-3d;
|
||||
-ms-transition: 0.6s;
|
||||
-ms-transform-style: preserve-3d;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* hide back of pane during swap */
|
||||
.flip-container .front, .flip-container .back {
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* front pane, placed above back */
|
||||
.flip-container .front {
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
/* back, initially hidden pane */
|
||||
.flip-container .back {
|
||||
transform: rotateY(180deg);
|
||||
-webkit-transform: rotateY(180deg);
|
||||
-moz-transform: rotateY(180deg);
|
||||
-ms-transform: rotateY(180deg);
|
||||
}
|
BIN
src/sunstone/public/app/utils/webmks/img/touch_sprite.png
Normal file
BIN
src/sunstone/public/app/utils/webmks/img/touch_sprite.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
6
src/sunstone/public/app/utils/webmks/wmks.min.js
vendored
Normal file
6
src/sunstone/public/app/utils/webmks/wmks.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -20,7 +20,8 @@
|
||||
"jquery-ui": "~1.12.1",
|
||||
"wickedpicker": "https://github.com/OpenNebula/sunstone-deps.git#9398b3f",
|
||||
"guacamole-common-js": "https://github.com/OpenNebula/sunstone-deps.git#1633556e63",
|
||||
"webauthn-json": "https://registry.npmjs.org/@github/webauthn-json/-/webauthn-json-0.4.1.tgz"
|
||||
"webauthn-json": "https://registry.npmjs.org/@github/webauthn-json/-/webauthn-json-0.4.1.tgz",
|
||||
"wmks": "https://github.com/OpenNebula/sunstone-deps.git#cb0251c"
|
||||
},
|
||||
"authors": [
|
||||
"Daniel Molina <dmolina@opennebula.org>",
|
||||
|
@ -122,6 +122,7 @@ require "sunstone_2f_auth"
|
||||
require 'CloudAuth'
|
||||
require 'SunstoneServer'
|
||||
require 'SunstoneViews'
|
||||
require 'OpenNebulaValidateFireedge'
|
||||
|
||||
require 'sinatra-websocket'
|
||||
require 'eventmachine'
|
||||
@ -147,6 +148,8 @@ rescue Exception => e
|
||||
exit 1
|
||||
end
|
||||
|
||||
$conf[:fireedge_up] = false
|
||||
|
||||
if $conf[:one_xmlrpc_timeout]
|
||||
ENV['ONE_XMLRPC_TIMEOUT'] = $conf[:one_xmlrpc_timeout].to_s unless ENV['ONE_XMLRPC_TIMEOUT']
|
||||
end
|
||||
@ -227,6 +230,12 @@ use Rack::Deflater
|
||||
include CloudLogger
|
||||
logger=enable_logging(SUNSTONE_LOG, $conf[:debug_level].to_i)
|
||||
|
||||
@ValidateFireedge = ValidateFireedge.new($conf, logger)
|
||||
|
||||
Thread.new do
|
||||
@ValidateFireedge.validate_fireedge_running
|
||||
end
|
||||
|
||||
begin
|
||||
ENV["ONE_CIPHER_AUTH"] = SUNSTONE_AUTH
|
||||
$cloud_auth = CloudAuth.new($conf, logger)
|
||||
@ -263,9 +272,13 @@ $vnc = OpenNebulaVNC.new($conf, logger)
|
||||
#init Guacamole server
|
||||
$guac = OpenNebulaGuac.new($conf, logger)
|
||||
|
||||
#init VMRC server
|
||||
$vmrc = OpenNebulaVMRC.new($conf, logger)
|
||||
|
||||
configure do
|
||||
set :run, false
|
||||
set :vnc, $vnc
|
||||
set :vmrc, $vmrc
|
||||
set :erb, :trim => '-'
|
||||
end
|
||||
|
||||
@ -546,7 +559,7 @@ before do
|
||||
@request_body = request.body.read
|
||||
request.body.rewind
|
||||
|
||||
unless %w(/ /login /vnc /spice /version /webauthn_options_for_get /ws).include?(request.path)
|
||||
unless %w(/ /login /vnc /spice /version /webauthn_options_for_get /ws /vmrc).include?(request.path)
|
||||
halt [401, "csrftoken"] unless authorized? && valid_csrftoken?
|
||||
end
|
||||
|
||||
@ -744,6 +757,20 @@ get '/vnc' do
|
||||
end
|
||||
end
|
||||
|
||||
get '/vmrc' do
|
||||
content_type 'text/html', :charset => 'utf-8'
|
||||
if !authorized?
|
||||
erb :login
|
||||
else
|
||||
erb :vmrc, :locals => {
|
||||
:logos_conf => $conf[:locals][:logos_conf],
|
||||
:oned_conf => $conf[:locals][:oned_conf],
|
||||
:support => $conf[:locals][:support],
|
||||
:upgrade => $conf[:locals][:upgrade]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
get '/spice' do
|
||||
content_type 'text/html', :charset => 'utf-8'
|
||||
if !authorized?
|
||||
@ -1106,6 +1133,14 @@ post '/vm/:id/guac/:type' do
|
||||
@SunstoneServer.startguac(vm_id, type_connection, $guac)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Start VMRC Session for a target VM
|
||||
##############################################################################
|
||||
post '/vm/:id/startvmrc' do
|
||||
vm_id = params[:id]
|
||||
@SunstoneServer.startvmrc(vm_id, $vmrc)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Perform an action on a Resource
|
||||
##############################################################################
|
||||
|
@ -42,9 +42,10 @@
|
||||
'threshold_low' : '<%= $conf[:threshold_low] %>',
|
||||
'threshold_high' : '<%= $conf[:threshold_high] %>',
|
||||
'guac_port' : '<%= $conf[:guac_port] %>',
|
||||
'vmrc_port' : '<%= $conf[:vmrc_port] %>',
|
||||
},
|
||||
'system_config' : {
|
||||
'paginate': '<%= $conf[:paginate] %>',
|
||||
'paginate': '<%= $conf[:paginate] %>',
|
||||
'marketplace_url' : '<%= $conf[:marketplace_url] %>',
|
||||
'vnc_request_password' : <%= $conf[:vnc_request_password] || false %>,
|
||||
'vnc_proxy_port' : '<%= $vnc.proxy_port %>',
|
||||
@ -57,7 +58,7 @@
|
||||
'autorefresh_wss': '<%= session[:autorefresh_wss] %>',
|
||||
'autorefresh_ip': '<%= $conf[:autorefresh_ip] %>',
|
||||
'autorefresh_port': '<%= $conf[:port] %>',
|
||||
|
||||
'is_fireedge_up': '<%= $conf[:fireedge_up] %>',
|
||||
},
|
||||
'view' : view,
|
||||
'available_views' : available_views,
|
||||
@ -118,7 +119,6 @@
|
||||
<div class="large-12 columns" id="dialogs"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<% if $conf[:env] == 'dev' %>
|
||||
<script src="bower_components/requirejs/require.js" data-main="app/main"></script>
|
||||
<% else %>
|
||||
|
96
src/sunstone/views/vmrc.erb
Normal file
96
src/sunstone/views/vmrc.erb
Normal file
@ -0,0 +1,96 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><%= params['vm_name']%></title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<link rel="apple-touch-startup-image" href="images/screen_320x460.png" />
|
||||
<link rel="apple-touch-icon" href="images/screen_57x57.png">
|
||||
<!-- Stylesheets -->
|
||||
<link rel="stylesheet" type="text/css" href="css/novnc-custom.css" title="plain">
|
||||
<% view = $views_config.view(session[:user], session[:user_gname], session[:default_view]) %>
|
||||
<!-- JQuery -->
|
||||
<script src="bower_components/jquery/dist/jquery.min.js"></script>
|
||||
<script src="bower_components/jquery-ui/jquery-ui.min.js"></script>
|
||||
<!-- Scripts -->
|
||||
<script type="text/javascript">
|
||||
var csrftoken = '<%= session[:csrftoken] %>';
|
||||
var view = JSON.parse('<%= view.to_json %>')
|
||||
var available_views = JSON.parse('["<%=
|
||||
$views_config.available_views(session[:user], session[:user_gname]).join('","')
|
||||
%>"]')
|
||||
var all_labels = JSON.parse('["<%=
|
||||
$views_config.get_all_labels(session[:user_gname]).join('","')
|
||||
%>"]')
|
||||
var all_views = JSON.parse('["<%=
|
||||
$views_config.get_all_views.join('","')
|
||||
%>"]')
|
||||
if ('<%= $conf[:addons] %>'){
|
||||
var addons = JSON.parse('<%= $conf[:addons].to_json %>');
|
||||
}
|
||||
var config = {
|
||||
'user_config' : {
|
||||
'lang' : '<%= session[:lang] %>',
|
||||
'vnc_wss' : '<%= session[:vnc_wss] %>',
|
||||
'table_order' : '<%= session[:table_order] %>',
|
||||
'default_view' : '<%= session[:default_view] %>',
|
||||
'page_length' : '<%= session[:page_length] %>'
|
||||
},
|
||||
'system_config' : {
|
||||
'marketplace_url' : '<%= $conf[:marketplace_url] %>',
|
||||
'vnc_request_password' : <%= $conf[:vnc_request_password] || false %>,
|
||||
'vnc_proxy_port' : '<%= $vnc.proxy_port %>',
|
||||
'vnc_client_port' : '<%= $conf[:vnc_client_port] %>',
|
||||
'max_upload_file_size' : <%= $conf[:max_upload_file_size] ? $conf[:max_upload_file_size] : "undefined" %>
|
||||
},
|
||||
'view' : view,
|
||||
'available_views' : available_views,
|
||||
'all_labels' : all_labels,
|
||||
'all_views' : all_views,
|
||||
'user_id' : '<%= session[:user_id] %>',
|
||||
'user_gid' : '<%= session[:user_gid] %>',
|
||||
'display_name' : '<%= session[:display_name] %>',
|
||||
'zone_name' : '<%= session[:zone_name] %>',
|
||||
'zone_id' : '<%= session[:zone_id] %>',
|
||||
'federation_mode' : '<%= session[:federation_mode] %>',
|
||||
'vm_logos' : <%= logos_conf.to_json %>,
|
||||
'oned_conf' : <%= oned_conf.to_json %>,
|
||||
'support' : <%= support.to_json %>,
|
||||
'upgrade' : <%= upgrade.to_json %>,
|
||||
'mode' : '<%= session[:mode] %>'
|
||||
};
|
||||
</script>
|
||||
<script src="bower_components/wmks/wmks.min.js"></script>
|
||||
<script src="dist/console/vmrc.js?v=<%= OpenNebula::VERSION %>"></script>
|
||||
</head>
|
||||
<body style="margin: 0px;">
|
||||
<div id="VMRC_screen">
|
||||
<div style="background: #f7f7f7; border-bottom: 1px solid #dfdfdf; padding: 10px 0px 15px 0px">
|
||||
<div id="VMRC_status_bar" class="VMRC_status_bar" style="margin-top: 0px;">
|
||||
<table border="0" width="100%">
|
||||
<tr>
|
||||
<td width="1%" >
|
||||
<img src="images/one_small_logo.png" style="height:40px; vertical-align:top; margin-left: 30px"></td>
|
||||
<td>
|
||||
<div id="VMRC_status" style="position: relative; height: auto; color: #000; text-align:center;">Loading</div>
|
||||
</td>
|
||||
<td width="1%" >
|
||||
<div id="VMRC_buttons" style="margin-right: 30px">
|
||||
<input type=button value="Send CtrlAltDel"
|
||||
id="sendCtrlAltDelButton">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wmksContainer" style="position:absolute;width:100%;height:100%; left:0em"></div>
|
||||
<div id="VMRC_canvas" width="640px" height="20px">
|
||||
<div class="VMRC_message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user