osc-vnc 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|