osc-vnc 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +169 -0
- data/Rakefile +1 -0
- data/config/script.yml +35 -0
- data/examples/desktop/xstartup +5 -0
- data/examples/paraview/fvwm/fvwmrc +80 -0
- data/examples/paraview/fvwm/winxp/images/close-activedown.xpm +237 -0
- data/examples/paraview/fvwm/winxp/images/close-activeup.xpm +286 -0
- data/examples/paraview/fvwm/winxp/images/close-inactive.xpm +88 -0
- data/examples/paraview/fvwm/winxp/images/maximize-activedown.xpm +190 -0
- data/examples/paraview/fvwm/winxp/images/maximize-activeup.xpm +257 -0
- data/examples/paraview/fvwm/winxp/images/maximize-inactive.xpm +66 -0
- data/examples/paraview/fvwm/winxp/images/title-active.xpm +58 -0
- data/examples/paraview/fvwm/winxp/images/title-inactive.xpm +58 -0
- data/examples/paraview/xstartup +17 -0
- data/examples/totalsim-desktop/config/menus/applications.menu +84 -0
- data/examples/totalsim-desktop/config/menus/settings.menu +20 -0
- data/examples/totalsim-desktop/images/TS_LOGO.jpg +0 -0
- data/examples/totalsim-desktop/xlogout +8 -0
- data/examples/totalsim-desktop/xstartup +20 -0
- data/lib/osc/vnc/connview.rb +95 -0
- data/lib/osc/vnc/error.rb +6 -0
- data/lib/osc/vnc/listenable.rb +45 -0
- data/lib/osc/vnc/scriptview.rb +63 -0
- data/lib/osc/vnc/session.rb +116 -0
- data/lib/osc/vnc/version.rb +6 -0
- data/lib/osc/vnc.rb +23 -0
- data/osc-vnc.gemspec +26 -0
- data/templates/conn/awesim.mustache +1 -0
- data/templates/conn/jnlp.mustache +49 -0
- data/templates/conn/novnc.mustache +1 -0
- data/templates/conn/osxvnc.mustache +1 -0
- data/templates/conn/terminal.mustache +1 -0
- data/templates/conn/txt.mustache +4 -0
- data/templates/conn/vnc.mustache +1 -0
- data/templates/conn/yaml.mustache +6 -0
- data/templates/script/_port_helpers.mustache +28 -0
- data/templates/script/_setup_env.mustache +7 -0
- data/templates/script/_ssh_tunnel.mustache +28 -0
- data/templates/script/_start_vncserver.mustache +38 -0
- data/templates/script/_tcp_server.mustache +6 -0
- data/templates/script/server.mustache +46 -0
- data/templates/script/vnc.mustache +86 -0
- 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
|
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 @@
|
|
1
|
+
vnc://:{{password}}@localhost:{{localport}}
|
@@ -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,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,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
|