class OodCore::BatchConnect::Templates::VNC
A batch connect template that starts up a VNC
server within a batch job
Public Class Methods
@param context [#to_h] the context used to render the template @option context [#to_sym, Array<#to_sym>] :conn_params ([]) A list of
connection parameters added to the connection file (`:host`, `:port`, `:password`, `:spassword`, `:display` and `:websocket` will always exist)
@option context [#to_s] :websockify_cmd
("${WEBSOCKIFY_CMD:-/opt/websockify/run}") the path to the websockify script (assumes you don't modify `:after_script`)
@option context [#to_s] :vnc_log (“vnc.log”) path to vnc server log
file (assumes you don't modify `:before_script` or `:after_script`)
@option context [#to_s] :vnc_passwd (“vnc.passwd”) path to the file
generated that contains the encrypted vnc password (assumes you don't modify `:before_script`)
@option context [#to_s] :vnc_args arguments used when starting up the
vnc server (overrides any specific vnc argument) (assumes you don't modify `:before_script`)
@option context [#to_s] :name (“”) name of the vnc server session
(not set if blank or `:vnc_args` is set) (assumes you don't modify `:before_script`)
@option context [#to_s] :geometry (“”) resolution of vnc display (not
set if blank or `:vnc_args` is set) (assumes you don't modify `:before_script`)
@option context [#to_s] :dpi (“”) dpi of vnc display (not set if
blank or `:vnc_args` is set) (assumes you don't modify `:before_script`)
@option context [#to_s] :fonts (“”) command delimited list of fonts
available in vnc display (not set if blank or `:vnc_args` is set) (assumes you don't modify `:before_script`)
@option context [#to_s] :idle (“”) timeout vnc server if no
connection in this amount of time in seconds (not set if blank or `:vnc_args` is set) (assumes you don't modify `:before_script`)
@option context [#to_s] :extra_args (“”) any extra arguments used
when initializing the vnc server process (not set if blank or `:vnc_args` is set) (assumes you don't modify `:before_script`)
@option context [#to_s] :vnc_clean (“…”) script used to clean up
any active vnc sessions (assumes you don't modify `:before_script` or `:clean_script`)
@see Template
OodCore::BatchConnect::Template::new
# File lib/ood_core/batch_connect/templates/vnc.rb, line 57 def initialize(context = {}) super end
Private Instance Methods
After startup the main script, scan the VNC
server log file for successful connections so that the password can be reset
# File lib/ood_core/batch_connect/templates/vnc.rb, line 126 def after_script websockify_cmd = context.fetch(:websockify_cmd, "${WEBSOCKIFY_CMD:-/opt/websockify/run}").to_s <<-EOT.gsub(/^ {14}/, "") #{super} # Launch websockify websocket server echo "Starting websocket server..." websocket=$(find_port) #{websockify_cmd} -D ${websocket} localhost:${port} # Set up background process that scans the log file for successful # connections by users, and change the password after every # connection echo "Scanning VNC log file for user authentications..." while read -r line; do if [[ ${line} =~ "Full-control authentication enabled for" ]]; then change_passwd create_yml fi done < <(tail -f --pid=${SCRIPT_PID} "#{vnc_log}") & EOT end
Before running the main script, start up a VNC
server and record the connection information
# File lib/ood_core/batch_connect/templates/vnc.rb, line 69 def before_script <<-EOT.gsub(/^ {14}/, "") # Setup one-time use passwords and initialize the VNC password function change_passwd () { echo "Setting VNC password..." password=$(create_passwd "#{password_size}") spassword=${spassword:-$(create_passwd "#{password_size}")} ( umask 077 echo -ne "${password}\\n${spassword}" | vncpasswd -f > "#{vnc_passwd}" ) } change_passwd # Start up vnc server (if at first you don't succeed, try, try again) echo "Starting VNC server..." for i in $(seq 1 10); do # Clean up any old VNC sessions that weren't cleaned before #{vnc_clean} # Attempt to start VNC server VNC_OUT=$(vncserver -log "#{vnc_log}" -rfbauth "#{vnc_passwd}" -nohttpd -noxstartup #{vnc_args} 2>&1) VNC_PID=$(pgrep -s 0 Xvnc) # the script above will daemonize the Xvnc process echo "${VNC_OUT}" # Sometimes Xvnc hangs if it fails to find working disaply, we # should kill it and try again kill -0 ${VNC_PID} 2>/dev/null && [[ "${VNC_OUT}" =~ "Fatal server error" ]] && kill -TERM ${VNC_PID} # Check that Xvnc process is running, if not assume it died and # wait some random period of time before restarting kill -0 ${VNC_PID} 2>/dev/null || sleep 0.$(random_number 1 9)s # If running, then all is well and break out of loop kill -0 ${VNC_PID} 2>/dev/null && break done # If we fail to start it after so many tries, then just give up kill -0 ${VNC_PID} 2>/dev/null || clean_up 1 # Parse output for ports used display=$(echo "${VNC_OUT}" | awk -F':' '/^Desktop/{print $NF}') port=$((5900+display)) echo "Successfully started VNC server on ${host}:${port}..." #{super} EOT end
We need to know the VNC
and websockify connection information
OodCore::BatchConnect::Template#conn_params
# File lib/ood_core/batch_connect/templates/vnc.rb, line 63 def conn_params (super + [:display, :websocket, :spassword]).uniq end
Run the script under the VNC
server's display
# File lib/ood_core/batch_connect/templates/vnc.rb, line 120 def run_script %(DISPLAY=:${display} #{super}) end
Arguments sent to `vncserver` command
# File lib/ood_core/batch_connect/templates/vnc.rb, line 171 def vnc_args context.fetch(:vnc_args) do name = context.fetch(:name, "").to_s geometry = context.fetch(:geometry, "").to_s dpi = context.fetch(:dpi, "").to_s fonts = context.fetch(:fonts, "").to_s idle = context.fetch(:idle, "").to_s extra_args = context.fetch(:extra_args, "").to_s args = [] args << "-name #{name}" unless name.empty? args << "-geometry #{geometry}" unless geometry.empty? args << "-dpi #{dpi}" unless dpi.empty? args << "-fp #{fonts}" unless fonts.empty? args << "-idletimeout #{idle}" unless idle.empty? args << extra_args args.join(" ") end.to_s end
Clean up any stale VNC
sessions
# File lib/ood_core/batch_connect/templates/vnc.rb, line 193 def vnc_clean context.fetch(:vnc_clean) do %(vncserver -list | awk '/^:/{system("kill -0 "$2" 2>/dev/null || vncserver -kill "$1)}') end.to_s end
Log file for VNC
server
# File lib/ood_core/batch_connect/templates/vnc.rb, line 161 def vnc_log context.fetch(:vnc_log, "vnc.log").to_s end
Password file for VNC
server
# File lib/ood_core/batch_connect/templates/vnc.rb, line 166 def vnc_passwd context.fetch(:vnc_passwd, "vnc.passwd").to_s end