osc-vnc 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +169 -0
  6. data/Rakefile +1 -0
  7. data/config/script.yml +35 -0
  8. data/examples/desktop/xstartup +5 -0
  9. data/examples/paraview/fvwm/fvwmrc +80 -0
  10. data/examples/paraview/fvwm/winxp/images/close-activedown.xpm +237 -0
  11. data/examples/paraview/fvwm/winxp/images/close-activeup.xpm +286 -0
  12. data/examples/paraview/fvwm/winxp/images/close-inactive.xpm +88 -0
  13. data/examples/paraview/fvwm/winxp/images/maximize-activedown.xpm +190 -0
  14. data/examples/paraview/fvwm/winxp/images/maximize-activeup.xpm +257 -0
  15. data/examples/paraview/fvwm/winxp/images/maximize-inactive.xpm +66 -0
  16. data/examples/paraview/fvwm/winxp/images/title-active.xpm +58 -0
  17. data/examples/paraview/fvwm/winxp/images/title-inactive.xpm +58 -0
  18. data/examples/paraview/xstartup +17 -0
  19. data/examples/totalsim-desktop/config/menus/applications.menu +84 -0
  20. data/examples/totalsim-desktop/config/menus/settings.menu +20 -0
  21. data/examples/totalsim-desktop/images/TS_LOGO.jpg +0 -0
  22. data/examples/totalsim-desktop/xlogout +8 -0
  23. data/examples/totalsim-desktop/xstartup +20 -0
  24. data/lib/osc/vnc/connview.rb +95 -0
  25. data/lib/osc/vnc/error.rb +6 -0
  26. data/lib/osc/vnc/listenable.rb +45 -0
  27. data/lib/osc/vnc/scriptview.rb +63 -0
  28. data/lib/osc/vnc/session.rb +116 -0
  29. data/lib/osc/vnc/version.rb +6 -0
  30. data/lib/osc/vnc.rb +23 -0
  31. data/osc-vnc.gemspec +26 -0
  32. data/templates/conn/awesim.mustache +1 -0
  33. data/templates/conn/jnlp.mustache +49 -0
  34. data/templates/conn/novnc.mustache +1 -0
  35. data/templates/conn/osxvnc.mustache +1 -0
  36. data/templates/conn/terminal.mustache +1 -0
  37. data/templates/conn/txt.mustache +4 -0
  38. data/templates/conn/vnc.mustache +1 -0
  39. data/templates/conn/yaml.mustache +6 -0
  40. data/templates/script/_port_helpers.mustache +28 -0
  41. data/templates/script/_setup_env.mustache +7 -0
  42. data/templates/script/_ssh_tunnel.mustache +28 -0
  43. data/templates/script/_start_vncserver.mustache +38 -0
  44. data/templates/script/_tcp_server.mustache +6 -0
  45. data/templates/script/server.mustache +46 -0
  46. data/templates/script/vnc.mustache +86 -0
  47. metadata +153 -0
@@ -0,0 +1,45 @@
1
+ require 'socket'
2
+
3
+
4
+ module OSC
5
+ module VNC
6
+ # Mixin that adds the ability to create and read from a TCP server.
7
+ module Listenable
8
+ # Generate a TCP server that listens on a random port.
9
+ #
10
+ # @return [TCPServer] ruby TCPServer object listening on random port
11
+ def create_listen
12
+ listen_host = Socket.gethostname
13
+ listen_port = _get_port
14
+ begin
15
+ server = TCPServer.new(listen_host, listen_port)
16
+ rescue Errno::EADDRINUSE
17
+ listen_port = _get_port
18
+ retry
19
+ end
20
+ server
21
+ end
22
+
23
+ # Read the data received by the TCP server.
24
+ #
25
+ # @param [Hash] args the arguments to read data received by TCP server with
26
+ # @option args [TCPServer] :server the TCP server that is currently listening
27
+ # @return [String] the contents of the data received by the server
28
+ def read_listen(args)
29
+ server = args[:server]
30
+ client = server.accept # wait for connection
31
+ client.read # read complete response
32
+ end
33
+
34
+
35
+ private
36
+
37
+ # Get random number form 40,000 to 50,000.
38
+ #
39
+ # @return [Fixnum] a random number from 40,000 to 50,000
40
+ def _get_port
41
+ rand(40000..50000)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,63 @@
1
+ require 'fileutils'
2
+ require 'mustache'
3
+ require 'yaml'
4
+
5
+ module OSC
6
+ module VNC
7
+ # Provides a view for the PBS batch script configured as a mustache
8
+ # template in templates/script/vnc.mustache. Extra options can be passed to
9
+ # this view and accessed directly in the mustache template.
10
+ class ScriptView < Mustache
11
+ self.template_path = SCRIPT_TEMPLATE_PATH
12
+
13
+ # @param type [Symbol] The script type defined in config/script.yml (:vnc or :server).
14
+ # @param cluster [String] The cluster the job will run on defined in config/script.yml.
15
+ # @param opts [Hash] The options used to construct PBS batch script view.
16
+ # @option opts [Symbol] :subtype The subtype (i.e., :default or :shared) outlined in config/script.yml.
17
+ def initialize(type, cluster, opts = {})
18
+ self.template_name = type
19
+
20
+ # Read in pre-configured options
21
+ script_cfg = YAML.load_file("#{CONFIG_PATH}/script.yml").fetch(type.to_s, {})
22
+ subtype_opts = script_cfg[opts[:subtype].to_s] || script_cfg['default']
23
+ cluster_opts = subtype_opts.fetch('cluster', {}).fetch(cluster, {})
24
+ context = subtype_opts.merge cluster_opts
25
+
26
+ @view_context = {}
27
+ context.each do |key, value|
28
+ @view_context[key.to_sym] = value
29
+ end
30
+ @view_context.merge! opts
31
+ @view_context[:cluster] = cluster
32
+ end
33
+
34
+ # Determine whether the script is valid or not
35
+ #
36
+ # @return [Boolean] Whether this is a valid script.
37
+ # @raise [InvalidPath] if { #xstartup } or { #outdir } do not correspond to actual file system locations
38
+ def valid?
39
+ raise InvalidPath, "xstartup script is not found" unless File.file?(xstartup)
40
+ raise InvalidPath, "output directory is a file" if File.file?(outdir)
41
+ FileUtils.mkdir_p(outdir)
42
+ end
43
+
44
+ # See if the method call exists as a key in @view_context.
45
+ #
46
+ # @param method_name the method name called
47
+ # @param arguments the arguments to the call
48
+ # @param block an optional block for the call
49
+ def method_missing(method_name, *arguments, &block)
50
+ @view_context.fetch(method_name) { super }
51
+ end
52
+
53
+ # Checks if the method responds to an instance method, or is able to
54
+ # proxy it to @view_context.
55
+ #
56
+ # @param method_name the method name to check
57
+ # @return [Boolean]
58
+ def respond_to_missing?(method_name, include_private = false)
59
+ @view_context.include?(method_name) || super
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,116 @@
1
+ require 'osc/vnc/listenable'
2
+
3
+ module OSC
4
+ module VNC
5
+ # Provides a way for developers to create and submit VNC sessions to the
6
+ # OSC batch systems. Also, developers are now able to submit any server
7
+ # session to the batch systems whether it is VNC or not following the same
8
+ # principles as a VNC session.
9
+ class Session
10
+ include OSC::VNC::Listenable
11
+
12
+ # @return [PBS::Job] The job object used.
13
+ attr_reader :job
14
+
15
+ # @return [ScriptView] The batch script used.
16
+ attr_reader :script
17
+
18
+ # @param job [PBS::Job] The job object used.
19
+ # @param script [ScriptView] The batch script used.
20
+ # @param opts [Hash] The options used to construct a session.
21
+ def initialize(job, script, opts = {})
22
+ @job = job
23
+ @script = script
24
+ end
25
+
26
+ # Submit the VNC job to the defined batch server.
27
+ #
28
+ # @param opts [Hash] The options used in job submission.
29
+ # @option opts [Hash] :headers The headers for the PBS job.
30
+ # @option opts [Hash] :resources The resources for the PBS job.
31
+ # @option opts [Hash] :envvars The environment variables for the PBS job.
32
+ # @return [Session] the session object
33
+ def submit(opts = {})
34
+ script.valid? # check if script is valid (can raise errors here)
35
+
36
+ h = opts.fetch(:headers, {})
37
+ r = opts.fetch(:resources, {})
38
+ e = opts.fetch(:envvars, {})
39
+
40
+ # Create tcp listen server if requested
41
+ listen_server = _create_listen_server(e) if script.tcp_server?
42
+
43
+ job.submit(
44
+ string: script.render,
45
+ headers: _get_headers(h),
46
+ resources: _get_resources(r),
47
+ envvars: _get_envvars(e),
48
+ qsub: true
49
+ )
50
+
51
+ _write_listen_conn_info(listen_server) if script.tcp_server?
52
+
53
+ self
54
+ end
55
+
56
+ # The connection information file.
57
+ #
58
+ # @return [String] path to connection information file for this session
59
+ def conn_file
60
+ "#{script.outdir}/#{job.id}.conn"
61
+ end
62
+
63
+
64
+ private
65
+
66
+ # The hash of PBS header attributes for the job.
67
+ def _get_headers(headers)
68
+ h = {
69
+ PBS::ATTR[:N] => "VNC_Job",
70
+ PBS::ATTR[:o] => "#{script.outdir}/$PBS_JOBID.output",
71
+ PBS::ATTR[:j] => "oe",
72
+ PBS::ATTR[:S] => "/bin/bash",
73
+ }.merge headers
74
+ h[PBS::ATTR[:N]] = "#{ENV['APP_TOKEN']}/#{h[PBS::ATTR[:N]]}" if ENV['APP_TOKEN']
75
+
76
+ # add first charged account group as default account
77
+ account = Process.groups.map {|g| Etc.getgrgid(g).name}.grep(/^P./).first
78
+ h[PBS::ATTR[:A]] ||= account if account
79
+
80
+ h
81
+ end
82
+
83
+ # The hash of PBS resources requested for the job.
84
+ def _get_resources(resources)
85
+ {
86
+ :nodes => "1:ppn=1:#{script.cluster}",
87
+ :walltime => "24:00:00",
88
+ }.merge resources
89
+ end
90
+
91
+ # The hash of environment variables passed to the job.
92
+ def _get_envvars(envvars)
93
+ {
94
+ }.merge envvars
95
+ end
96
+
97
+ # Create a tcp listen server and set appropriate environment variables.
98
+ # for batch script to phone home
99
+ def _create_listen_server(envvars)
100
+ listen_server = create_listen
101
+ _, port, host, _ = listen_server.addr(:hostname)
102
+ envvars.merge! LISTEN_HOST: host, LISTEN_PORT: port
103
+ listen_server
104
+ end
105
+
106
+ # Write connection information from a TCP listening server.
107
+ def _write_listen_conn_info(server)
108
+ # Wait until VNC conn info is created by PBS batch script
109
+ # Timeout after 60 seconds if no info is sent
110
+ Timeout::timeout(60) do
111
+ File.open(conn_file, 'w', 0600) { |f| f.puts read_listen(server: server) }
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,6 @@
1
+ module OSC
2
+ module VNC
3
+ # The current version of osc-vnc.
4
+ VERSION = "1.0.6"
5
+ end
6
+ end
data/lib/osc/vnc.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'pbs'
2
+
3
+ # The namespace used for OSC gems.
4
+ module OSC
5
+ # The main namespace for osc-vnc. Provides the ability to submit and read back
6
+ # the connection information for a VNC job on the OSC clusters.
7
+ module VNC
8
+ # Path to configuration yml files.
9
+ CONFIG_PATH = File.dirname(__FILE__) + "/../../config"
10
+
11
+ # Patch to PBS script template.
12
+ SCRIPT_TEMPLATE_PATH = File.dirname(__FILE__) + "/../../templates/script"
13
+
14
+ # Path to different connection information view templates.
15
+ CONN_TEMPLATE_PATH = File.dirname(__FILE__) + "/../../templates/conn"
16
+ end
17
+ end
18
+
19
+ require_relative 'vnc/version'
20
+ require_relative 'vnc/error'
21
+ require_relative 'vnc/session'
22
+ require_relative 'vnc/scriptview'
23
+ require_relative 'vnc/connview'
data/osc-vnc.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'osc/vnc/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "osc-vnc"
8
+ spec.version = OSC::VNC::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.authors = ["Jeremy Nicklas"]
11
+ spec.email = ["jnicklas@osc.edu"]
12
+ spec.summary = %q{Library to create VNC jobs with HPC resources (OSC specific)}
13
+ spec.description = %q{This library submits VNC jobs to the Oxymoron cluster as well as obtains the connection information required for a connection to take place with a VNC client. (OSC specific)}
14
+ spec.homepage = "https://github.com/OSC/osc-vnc"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "pbs", "~> 1.0"
23
+ spec.add_runtime_dependency "mustache", "~> 0.99", ">= 0.99.5"
24
+ spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ end
@@ -0,0 +1 @@
1
+ awesim://{{#password}}:{{password}}@{{/password}}{{host}}:{{port}}
@@ -0,0 +1,49 @@
1
+ {{^ssh_tunnel?}}
2
+ <?xml version="1.0" encoding="UTF-8"?>
3
+ <jnlp spec="1.0+" codebase="http://mirror.osc.edu/mirror" >
4
+ <information>
5
+ <title>TightVnc Viewer</title>
6
+ <vendor>GlavSoft LLC.</vendor>
7
+ <offline-allowed/>
8
+ </information>
9
+ <security>
10
+ <all-permissions/>
11
+ </security>
12
+ <resources>
13
+ <j2se version="1.6+"/>
14
+ <jar href="TightVncViewerSigned.jar" main="true"/>
15
+ </resources>
16
+ <application-desc main-class="com.tightvnc.vncviewer.VncViewer">
17
+ <argument>HOST</argument>
18
+ <argument>{{host}}</argument>
19
+ <argument>PORT</argument>
20
+ <argument>{{port}}</argument>
21
+ <argument>PASSWORD</argument>
22
+ <argument>{{password}}</argument>
23
+ </application-desc>
24
+ </jnlp>
25
+ {{/ssh_tunnel?}}
26
+ {{#ssh_tunnel?}}
27
+ <?xml version="1.0" encoding="UTF-8"?>
28
+ <jnlp spec="1.0+" codebase="http://mirror.osc.edu/mirror" >
29
+ <information>
30
+ <title>TightVnc Viewer</title>
31
+ <vendor>GlavSoft LLC.</vendor>
32
+ <offline-allowed/>
33
+ </information>
34
+ <security>
35
+ <all-permissions/>
36
+ </security>
37
+ <resources>
38
+ <j2se version="1.6+"/>
39
+ <jar href="tightvnc-jviewer.jar" main="true"/>
40
+ </resources>
41
+ <application-desc main-class="com.glavsoft.viewer.Viewer">
42
+ <argument>-host={{host}}</argument>
43
+ <argument>-port={{port}}</argument>
44
+ <argument>-password={{password}}</argument>
45
+ <argument>-sshhost={{sshhost}}</argument>
46
+ <argument>-sshuser={{sshuser}}</argument>
47
+ </application-desc>
48
+ </jnlp>
49
+ {{/ssh_tunnel?}}
@@ -0,0 +1 @@
1
+ /rnode/{{host}}/{{web_port}}/vnc_auto.html?password={{#view_only}}{{spassword}}{{/view_only}}{{^view_only}}{{password}}{{/view_only}}&path=rnode/{{host}}/{{web_port}}/websockify
@@ -0,0 +1 @@
1
+ ssh -f -N -L {{localport}}:{{host}}:{{port}} {{sshuser}}@{{sshhost}} && open vnc://:{{password}}@localhost:{{localport}}
@@ -0,0 +1 @@
1
+ ssh -L {{localport}}:{{host}}:{{port}} {{sshuser}}@{{sshhost}}
@@ -0,0 +1,4 @@
1
+ Host: {{host}}
2
+ Port: {{port}}
3
+ Pass: {{password}}
4
+ Display: {{display_port}}
@@ -0,0 +1 @@
1
+ vnc://:{{password}}@localhost:{{localport}}
@@ -0,0 +1,6 @@
1
+ host: {{host}}
2
+ port: {{port}}
3
+ pass: {{password}}
4
+ display: {{display_port}}
5
+ sshuser: {{sshuser}}
6
+ sshhost: {{sshhost}}
@@ -0,0 +1,28 @@
1
+ # Generate random integer in range [$1..$2)
2
+ function random () {
3
+ local MIN=$1
4
+ local MAX=$2
5
+ local RANGE=$((MAX - MIN))
6
+ local RAND=$(od -An -N4 -t uL /dev/urandom | tr -d " ")
7
+ local RAND_MAX=$((2**(4*8)))
8
+
9
+ local FLOAT=$(echo "$RANGE * ($RAND / $RAND_MAX) + $MIN" | bc -l)
10
+
11
+ echo $(echo "$FLOAT / 1" | bc)
12
+ }
13
+
14
+ # Check if port is used
15
+ function used_ports () {
16
+ local PORT=$1
17
+
18
+ echo $(netstat -lnt | awk -v port=$PORT '$6 == "LISTEN" && $4 ~ ":"port"$"' | wc -l)
19
+ }
20
+
21
+ # Get available port
22
+ function get_port () {
23
+ local PORT=$(random 2000 65535)
24
+ while [[ $(used_ports ${PORT}) -ne 0 ]]; do
25
+ PORT=$(random 2000 65535)
26
+ done
27
+ echo ${PORT}
28
+ }
@@ -0,0 +1,7 @@
1
+ export VNC_LOGFILE={{outdir}}/${PBS_JOBID}.log
2
+ {{#tcp_server?}}
3
+ export VNC_OUTFILE=$(mktemp)
4
+ {{/tcp_server?}}
5
+ {{^tcp_server?}}
6
+ export VNC_OUTFILE={{outdir}}/${PBS_JOBID}.conn
7
+ {{/tcp_server?}}
@@ -0,0 +1,28 @@
1
+ {{#ssh_tunnel?}}
2
+ HOST=$(hostname)
3
+ {{/ssh_tunnel?}}
4
+ {{^ssh_tunnel?}}
5
+ # Get correct host
6
+ #
7
+ # opt2647.ten.osc.edu => vis033.osc.edu
8
+ # opt2648.ten.osc.edu => vis034.osc.edu
9
+ # opt2649.ten.osc.edu => vis035.osc.edu
10
+ # opt2650.ten.osc.edu => vis036.osc.edu
11
+ # n0691.ten.osc.edu => oak-vis001.osc.edu
12
+ # n0692.ten.osc.edu => oak-vis002.osc.edu
13
+ #
14
+ # 1. we grep the output of /sbin/ip a s to 192.148.0.0/16 to get 192.148.248.70/24, getting the first match only to ignore 192.148.248.255
15
+ #
16
+ # 7: eth0.70@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
17
+ # inet 192.148.248.75/24 brd 192.148.248.255 scope global eth0.70
18
+ #
19
+ # 2. we use this as argument to dig i.e. dig +short -x 192.148.248.70
20
+ #
21
+ # vis033.osc.edu.
22
+ #
23
+ # 3. we get rid of the ending .
24
+ function public_hostname {
25
+ /sbin/ip a s to 192.148.0.0/16 | egrep -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -n1 | xargs dig +short -x | sed 's/\.$//'
26
+ }
27
+ HOST=$(public_hostname)
28
+ {{/ssh_tunnel?}}
@@ -0,0 +1,38 @@
1
+ # Start up vnc server and create output
2
+ # If two servers start simultaneously one will fail, loop until it succeeds
3
+ i=0
4
+ while [[ -z ${VNC_PID} && ${i} -lt 30 ]]; do
5
+ # Clean up any failed vnc sessions that didn't clean themselves up
6
+ vncserver -list | awk '/^:/{display[$1] = $2} END{for(key in display) { if( system( "[ ! -e /proc/" display[key] " ]" ) == 0 ) { system( "vncserver -kill " key ) } }}'
7
+ # Run the vncserver
8
+ VNC_OUT=$(vncserver \
9
+ -name {{name}} \
10
+ -geometry {{geom}} \
11
+ -dpi {{dpi}} \
12
+ -fp {{fonts}} \
13
+ -{{^otp?}}no{{/otp?}}otp \
14
+ {{#vncauth?}}-rfbauth ${VNC_PASSFILE}{{/vncauth?}}{{^vncauth?}}-novncauth{{/vncauth?}} \
15
+ -{{^pam?}}no{{/pam?}}pam \
16
+ -nohttpd \
17
+ -idletimeout {{idletimeout}} \
18
+ -log ${VNC_LOGFILE} \
19
+ -noxstartup \
20
+ {{{extra_args}}} 2>&1)
21
+ VNC_PID=$(pgrep -s 0 Xvnc) # Get process id
22
+ # VNC couldn't find display so died
23
+ if [[ -z ${VNC_PID} ]]; then
24
+ sleep 0.$(($RANDOM % 100))s # Sleep between 0-1 seconds
25
+ fi
26
+ # Sometimes VNC will hang if it fails to find working display
27
+ if [[ ! -z ${VNC_PID} && ${VNC_OUT} =~ "Fatal server error" ]]; then
28
+ kill -9 ${VNC_PID}
29
+ unset VNC_PID
30
+ fi
31
+ i=$((i+1)) # increment counter
32
+ done
33
+ echo "${VNC_OUT}"
34
+
35
+ # Make sure it is running otherwise exit with error code 1
36
+ if [[ -z ${VNC_PID} ]]; then
37
+ exit 1
38
+ fi
@@ -0,0 +1,6 @@
1
+ {{#tcp_server?}}
2
+ # Send connection information over a TCP connection
3
+ # The server information should have been passed as environment variables
4
+ nc ${LISTEN_HOST} ${LISTEN_PORT} < ${VNC_OUTFILE}
5
+ rm -f ${VNC_OUTFILE}
6
+ {{/tcp_server?}}
@@ -0,0 +1,46 @@
1
+ # Set some environment variables used by this script
2
+ {{> _setup_env}}
3
+
4
+ {{#xinit}}
5
+ # Port helpers
6
+ {{> _port_helpers}}
7
+
8
+ # Run developer supplied xinit script
9
+ source {{xinit}}
10
+ {{/xinit}}
11
+
12
+ # Function that creates a connection information file
13
+ function create_connfile {
14
+ echo "Host: ${HOST}" > ${VNC_OUTFILE}
15
+ echo "Port: ${HOST_PORT}" >> ${VNC_OUTFILE}
16
+ echo "Password: ${PASSWORD}" >> ${VNC_OUTFILE}
17
+ chmod 600 ${VNC_OUTFILE}
18
+ }
19
+
20
+ # Clean up script run when "vncserver" finishes or dies prematurely
21
+ # Note: must be defined after `module load`
22
+ function clean_up {
23
+ echo "Exiting..."
24
+ {{{xlogout}}}
25
+ }
26
+ trap clean_up TERM EXIT
27
+
28
+ # Create logfile
29
+ > ${VNC_LOGFILE}
30
+
31
+ # Run the xstartup script on proper vncserver display
32
+ {{xstartup}} >> ${VNC_LOGFILE} 2>&1 &
33
+ SCRIPT_PID=$(pgrep -s 0 -f {{xstartup}})
34
+
35
+ {{> _ssh_tunnel}}
36
+
37
+ # Create the connection file
38
+ create_connfile
39
+
40
+ {{> _tcp_server}}
41
+
42
+ # Wait for main process to finish
43
+ while [ -e /proc/${SCRIPT_PID} ]; do sleep 0.1; done
44
+
45
+ # Exit cleanly
46
+ exit 0
@@ -0,0 +1,86 @@
1
+ # Set some environment variables used by this script
2
+ {{> _setup_env}}
3
+ export VNC_PASSFILE={{outdir}}/${PBS_JOBID}.pass
4
+
5
+ # Use turbovnc
6
+ {{{load_turbovnc}}}
7
+
8
+ {{#vncauth?}}
9
+ # Allow the ability to dynamically change VNC password
10
+ function change_passwd {
11
+ # Generate password for VNC
12
+ PASSWORD=$(mkpasswd -s 0 -l 8) # passwords truncated to 8 letters
13
+ SPASSWORD=${SPASSWORD:-$(mkpasswd -s 0 -l 8)}
14
+ printf "${PASSWORD}\n${SPASSWORD}" | vncpasswd -f > ${VNC_PASSFILE}
15
+ chmod 600 ${VNC_PASSFILE}
16
+ }
17
+ change_passwd
18
+ {{/vncauth?}}
19
+
20
+ # Function that creates a connection information file
21
+ function create_connfile {
22
+ echo "Host: ${HOST}" > ${VNC_OUTFILE}
23
+ echo "Port: ${HOST_PORT}" >> ${VNC_OUTFILE}
24
+ echo "Password: ${PASSWORD}" >> ${VNC_OUTFILE}
25
+ echo "SPassword: ${SPASSWORD}" >> ${VNC_OUTFILE}
26
+ echo "Display_Port: ${DISPLAY_PORT}" >> ${VNC_OUTFILE}
27
+ echo "Web_Port: ${WEB_PORT}" >> ${VNC_OUTFILE}
28
+ chmod 600 ${VNC_OUTFILE}
29
+ }
30
+
31
+ # Clean up script run when "vncserver" finishes or dies prematurely
32
+ # Note: must be defined after `module load`
33
+ function clean_up {
34
+ echo "Exiting..."
35
+ vncserver -kill :${DISPLAY_PORT}
36
+ {{{xlogout}}}
37
+ }
38
+ trap clean_up TERM EXIT
39
+
40
+ {{> _start_vncserver}}
41
+
42
+ # Parse output for ports
43
+ DISPLAY_PORT=$(echo "${VNC_OUT}" | awk -F':' '/^Desktop/{print $NF}')
44
+ HOST_PORT=$((5900+DISPLAY_PORT))
45
+
46
+ {{#otp?}}
47
+ # Parse output for password
48
+ PASSWORD=$(echo "${VNC_OUT}" | awk '/^Full/{print $NF}')
49
+ {{/otp?}}
50
+
51
+ # Run the xstartup script on proper vncserver display
52
+ DISPLAY=:${DISPLAY_PORT} {{xstartup}} >> ${VNC_LOGFILE} 2>&1 &
53
+ SCRIPT_PID=$(pgrep -s 0 -f {{xstartup}})
54
+
55
+ {{> _ssh_tunnel}}
56
+
57
+ {{#novnc?}}
58
+ # Port helpers
59
+ {{> _port_helpers}}
60
+
61
+ # Launch noVNC on available port
62
+ export WEB_PORT=$(get_port)
63
+ {{{novnc_launcher}}} --vnc localhost:${HOST_PORT} --listen ${WEB_PORT} >> ${VNC_LOGFILE} 2>&1 &
64
+ {{/novnc?}}
65
+
66
+ {{#vncauth?}}
67
+ # Check for authenticated user connections to VNC server then change password
68
+ while read -r line; do
69
+ if [[ ${line} =~ "Full-control authentication enabled for" ]]; then
70
+ change_passwd
71
+ create_connfile
72
+ echo "Changing VNC password..." >> ${VNC_LOGFILE}
73
+ fi
74
+ done < <(tail -f ${VNC_LOGFILE}) &
75
+ {{/vncauth?}}
76
+
77
+ # Create the connection file
78
+ create_connfile
79
+
80
+ {{> _tcp_server}}
81
+
82
+ # Wait for main process to finish
83
+ while [ -e /proc/${VNC_PID} ]; do sleep 0.1; done
84
+
85
+ # Exit cleanly
86
+ exit 0