ood_core 0.10.0 → 0.12.0

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.
@@ -1,5 +1,19 @@
1
1
  #!/bin/bash
2
- hostname
2
+ SSH_HOSTS=(<%= ssh_hosts.join(' ').to_s %>)
3
+ hostnames=`hostname -A`
4
+ for host in ${SSH_HOSTS[@]}
5
+ do
6
+ if [[ " ${hostnames[@]} " =~ " ${host} " ]]; then
7
+ hostname=$host
8
+ fi
9
+ done
10
+
11
+ if [ -z "$hostname" ]; then
12
+ printf >&2 "ERROR: Can't start job on [${hostnames[@]}] because it does not match any hostname configured \nin ssh_hosts [${SSH_HOSTS[@]}]. The output of 'hostname -A' must match an entry in ssh_hosts \nfrom the cluster configuration."
13
+ exit 1
14
+ fi
15
+
16
+ echo $hostname
3
17
 
4
18
  # Put the script into a temp file on localhost
5
19
  <% if debug %>
@@ -14,6 +14,7 @@ module OodCore
14
14
  # @option config [#to_s] :serverdir ('') Path to lsf client etc dir
15
15
  # @option config [#to_s] :cluster ('') name of cluster, if in multi-cluster mode
16
16
  # @option config [#to_h] :bin_overrides ({}) Optional overrides to LSF client executables
17
+ # @option config [#to_s] :submit_host ('') Host to submit commands to
17
18
  def self.build_lsf(config)
18
19
  batch = Adapters::Lsf::Batch.new(config.to_h.symbolize_keys)
19
20
  Adapters::Lsf.new(batch: batch)
@@ -167,6 +168,10 @@ module OodCore
167
168
  raise JobAdapterError, e.message
168
169
  end
169
170
 
171
+ def directive_prefix
172
+ '#BSUB'
173
+ end
174
+
170
175
  private
171
176
  # Determine state from LSF state code
172
177
  def get_state(st)
@@ -2,21 +2,22 @@
2
2
  #
3
3
  # @api private
4
4
  class OodCore::Job::Adapters::Lsf::Batch
5
- attr_reader :bindir, :libdir, :envdir, :serverdir, :cluster, :bin_overrides
5
+ attr_reader :bindir, :libdir, :envdir, :serverdir, :cluster, :bin_overrides, :submit_host, :strict_host_checking
6
6
 
7
7
  # The root exception class that all LSF-specific exceptions inherit
8
8
  # from
9
9
  class Error < StandardError; end
10
10
 
11
11
  # @param bin [#to_s] path to LSF installation binaries
12
- def initialize(bindir: "", envdir: "", libdir: "", serverdir: "", cluster: "", bin_overrides: {}, **_)
12
+ def initialize(bindir: "", envdir: "", libdir: "", serverdir: "", cluster: "", bin_overrides: {}, submit_host: "", strict_host_checking: true, **_)
13
13
  @bindir = Pathname.new(bindir.to_s)
14
-
15
14
  @envdir = Pathname.new(envdir.to_s)
16
15
  @libdir = Pathname.new(libdir.to_s)
17
16
  @serverdir = Pathname.new(serverdir.to_s)
18
17
  @cluster = cluster.to_s
19
18
  @bin_overrides = bin_overrides
19
+ @submit_host = submit_host.to_s
20
+ @strict_host_checking = strict_host_checking
20
21
  end
21
22
 
22
23
  def default_env
@@ -143,6 +144,7 @@ class OodCore::Job::Adapters::Lsf::Batch
143
144
  cmd = OodCore::Job::Adapters::Helper.bin_path(cmd, bindir, bin_overrides)
144
145
  args = cluster_args + args
145
146
  env = default_env.merge(env.to_h)
147
+ cmd, args = OodCore::Job::Adapters::Helper.ssh_wrap(submit_host, cmd, args, strict_host_checking, env)
146
148
  o, e, s = Open3.capture3(env, cmd, *(args.map(&:to_s)), stdin_data: stdin.to_s)
147
149
  s.success? ? o : raise(Error, e)
148
150
  end
@@ -78,34 +78,40 @@ class OodCore::Job::Adapters::Lsf::Helper
78
78
  def batch_submit_args(script, after: [], afterok: [], afternotok: [], afterany: [])
79
79
  args = []
80
80
 
81
- args += ["-P", script.accounting_id] unless script.accounting_id.nil?
82
- args += ["-cwd", script.workdir.to_s] unless script.workdir.nil?
83
- args += ["-J", script.job_name] unless script.job_name.nil?
84
- args[-1] += "[#{script.job_array_request}]" unless script.job_array_request.nil?
85
-
86
- args += ["-q", script.queue_name] unless script.queue_name.nil?
87
- args += ["-U", script.reservation_id] unless script.reservation_id.nil?
88
- args += ["-sp", script.priority] unless script.priority.nil?
89
- args += ["-H"] if script.submit_as_hold
90
- args += (script.rerunnable ? ["-r"] : ["-rn"]) unless script.rerunnable.nil?
91
- args += ["-b", script.start_time.localtime.strftime("%Y:%m:%d:%H:%M")] unless script.start_time.nil?
92
- args += ["-W", (script.wall_time / 60).to_i] unless script.wall_time.nil?
93
- args += ["-L", script.shell_path.to_s] unless script.shell_path.nil?
81
+ args.concat ["-P", script.accounting_id] unless script.accounting_id.nil?
82
+ args.concat ["-cwd", script.workdir.to_s] unless script.workdir.nil?
83
+ args.concat ["-J", script.job_name] unless script.job_name.nil?
84
+ args[-1].concat "[#{script.job_array_request}]" unless script.job_array_request.nil?
85
+
86
+ args.concat ["-q", script.queue_name] unless script.queue_name.nil?
87
+ args.concat ["-U", script.reservation_id] unless script.reservation_id.nil?
88
+ args.concat ["-sp", script.priority] unless script.priority.nil?
89
+ args.concat ["-H"] if script.submit_as_hold
90
+ args.concat (script.rerunnable ? ["-r"] : ["-rn"]) unless script.rerunnable.nil?
91
+ args.concat ["-b", script.start_time.localtime.strftime("%Y:%m:%d:%H:%M")] unless script.start_time.nil?
92
+ args.concat ["-W", (script.wall_time / 60).to_i] unless script.wall_time.nil?
93
+ args.concat ["-L", script.shell_path.to_s] unless script.shell_path.nil?
94
+
95
+ # environment
96
+ env = script.job_environment || {}
97
+ # To preserve pre-existing behavior we only act when true or false, when nil we do nothing
98
+ if script.copy_environment?
99
+ args.concat ["-env", (["all"] + env.keys).join(",")]
100
+ elsif script.copy_environment? == false
101
+ args.concat ["-env", (["none"] + env.keys).join(",")]
102
+ end
94
103
 
95
104
  # input and output files
96
- args += ["-i", script.input_path] unless script.input_path.nil?
97
- args += ["-o", script.output_path] unless script.output_path.nil?
98
- args += ["-e", script.error_path] unless script.error_path.nil?
105
+ args.concat ["-i", script.input_path] unless script.input_path.nil?
106
+ args.concat ["-o", script.output_path] unless script.output_path.nil?
107
+ args.concat ["-e", script.error_path] unless script.error_path.nil?
99
108
 
100
109
  # email
101
- args += ["-B"] if script.email_on_started
102
- args += ["-N"] if script.email_on_terminated
103
- args += ["-u", script.email.join(",")] unless script.email.nil? || script.email.empty?
110
+ args.concat ["-B"] if script.email_on_started
111
+ args.concat ["-N"] if script.email_on_terminated
112
+ args.concat ["-u", script.email.join(",")] unless script.email.nil? || script.email.empty?
104
113
 
105
- args += script.native unless script.native.nil?
106
-
107
- # environment
108
- env = script.job_environment || {}
114
+ args.concat script.native unless script.native.nil?
109
115
 
110
116
  {args: args, env: env}
111
117
  end
@@ -10,17 +10,21 @@ module OodCore
10
10
  # Build the PBS Pro adapter from a configuration
11
11
  # @param config [#to_h] the configuration for job adapter
12
12
  # @option config [Object] :host (nil) The batch server host
13
+ # @option config [Object] :submit_host ("") The login node where the job is submitted
14
+ # @option config [Object] :strict_host_checking (true) Whether to use strict host checking when ssh to submit_host
13
15
  # @option config [Object] :exec (nil) Path to PBS Pro executables
14
16
  # @option config [Object] :qstat_factor (nil) Deciding factor on how to
15
17
  # call qstat for a user
16
18
  # @option config [#to_h] :bin_overrides ({}) Optional overrides to PBS Pro client executables
17
19
  def self.build_pbspro(config)
18
20
  c = config.to_h.compact.symbolize_keys
19
- host = c.fetch(:host, nil)
20
- pbs_exec = c.fetch(:exec, nil)
21
- qstat_factor = c.fetch(:qstat_factor, nil)
22
- bin_overrides = c.fetch(:bin_overrides, {})
23
- pbspro = Adapters::PBSPro::Batch.new(host: host, pbs_exec: pbs_exec, bin_overrides: bin_overrides)
21
+ host = c.fetch(:host, nil)
22
+ submit_host = c.fetch(:submit_host, "")
23
+ strict_host_checking = c.fetch(:strict_host_checking, true)
24
+ pbs_exec = c.fetch(:exec, nil)
25
+ qstat_factor = c.fetch(:qstat_factor, nil)
26
+ bin_overrides = c.fetch(:bin_overrides, {})
27
+ pbspro = Adapters::PBSPro::Batch.new(host: host, submit_host: submit_host, strict_host_checking: strict_host_checking, pbs_exec: pbs_exec, bin_overrides: bin_overrides)
24
28
  Adapters::PBSPro.new(pbspro: pbspro, qstat_factor: qstat_factor)
25
29
  end
26
30
  end
@@ -41,6 +45,18 @@ module OodCore
41
45
  # @return [String, nil] the batch server host
42
46
  attr_reader :host
43
47
 
48
+ # The login node to submit the job via ssh
49
+ # @example
50
+ # my_batch.submit_host #=> "my_batch.server.edu"
51
+ # @return [String, nil] the login node
52
+ attr_reader :submit_host
53
+
54
+ # Whether to use strict host checking when ssh to submit_host
55
+ # @example
56
+ # my_batch.strict_host_checking #=> "false"
57
+ # @return [Bool, true] the login node; true if not present
58
+ attr_reader :strict_host_checking
59
+
44
60
  # The path containing the PBS executables
45
61
  # @example
46
62
  # my_batch.pbs_exec.to_s #=> "/usr/local/pbspro/10.0.0
@@ -58,11 +74,15 @@ module OodCore
58
74
  class Error < StandardError; end
59
75
 
60
76
  # @param host [#to_s, nil] the batch server host
77
+ # @param submit_host [#to_s, nil] the login node to ssh to
78
+ # @param strict_host_checking [bool, true] wheter to use strict host checking when ssh to submit_host
61
79
  # @param exec [#to_s, nil] path to pbs executables
62
- def initialize(host: nil, pbs_exec: nil, bin_overrides: {})
63
- @host = host && host.to_s
64
- @pbs_exec = pbs_exec && Pathname.new(pbs_exec.to_s)
65
- @bin_overrides = bin_overrides
80
+ def initialize(host: nil, submit_host: "", strict_host_checking: true, pbs_exec: nil, bin_overrides: {})
81
+ @host = host && host.to_s
82
+ @submit_host = submit_host && submit_host.to_s
83
+ @strict_host_checking = strict_host_checking
84
+ @pbs_exec = pbs_exec && Pathname.new(pbs_exec.to_s)
85
+ @bin_overrides = bin_overrides
66
86
  end
67
87
 
68
88
  # Get a list of hashes detailing each of the jobs on the batch server
@@ -87,7 +107,7 @@ module OodCore
87
107
  # @return [Array<Hash>] list of details for jobs
88
108
  def get_jobs(id: "")
89
109
  args = ["-f", "-t"] # display all information
90
- args += [id.to_s] unless id.to_s.empty?
110
+ args.concat [id.to_s] unless id.to_s.empty?
91
111
  lines = call("qstat", *args).gsub("\n\t", "").split("\n").map(&:strip)
92
112
 
93
113
  jobs = []
@@ -159,12 +179,12 @@ module OodCore
159
179
  cmd = cmd.to_s
160
180
  bindir = (!!pbs_exec) ? pbs_exec.join("bin").to_s : ''
161
181
  cmd = OodCore::Job::Adapters::Helper.bin_path(cmd, bindir, bin_overrides)
162
- args = args.map(&:to_s)
163
182
  env = env.to_h.each_with_object({}) { |(k, v), h| h[k.to_s] = v.to_s }
164
183
  env["PBS_DEFAULT"] = host.to_s if host
165
184
  env["PBS_EXEC"] = pbs_exec.to_s if pbs_exec
185
+ cmd, args = OodCore::Job::Adapters::Helper.ssh_wrap(submit_host, cmd, args, strict_host_checking)
166
186
  chdir ||= "."
167
- o, e, s = Open3.capture3(env, cmd, *args, stdin_data: stdin.to_s, chdir: chdir.to_s)
187
+ o, e, s = Open3.capture3(env, cmd, *(args.map(&:to_s)), stdin_data: stdin.to_s, chdir: chdir.to_s)
168
188
  s.success? ? o : raise(Error, e)
169
189
  end
170
190
  end
@@ -227,28 +247,28 @@ module OodCore
227
247
  # Set qsub options
228
248
  args = []
229
249
  # ignore args, can't use these if submitting from STDIN
230
- args += ["-h"] if script.submit_as_hold
231
- args += ["-r", script.rerunnable ? "y" : "n"] unless script.rerunnable.nil?
232
- args += ["-M", script.email.join(",")] unless script.email.nil?
250
+ args.concat ["-h"] if script.submit_as_hold
251
+ args.concat ["-r", script.rerunnable ? "y" : "n"] unless script.rerunnable.nil?
252
+ args.concat ["-M", script.email.join(",")] unless script.email.nil?
233
253
  if script.email_on_started && script.email_on_terminated
234
- args += ["-m", "be"]
254
+ args.concat ["-m", "be"]
235
255
  elsif script.email_on_started
236
- args += ["-m", "b"]
256
+ args.concat ["-m", "b"]
237
257
  elsif script.email_on_terminated
238
- args += ["-m", "e"]
258
+ args.concat ["-m", "e"]
239
259
  end
240
- args += ["-N", script.job_name] unless script.job_name.nil?
241
- args += ["-S", script.shell_path] unless script.shell_path.nil?
260
+ args.concat ["-N", script.job_name] unless script.job_name.nil?
261
+ args.concat ["-S", script.shell_path] unless script.shell_path.nil?
242
262
  # ignore input_path (not defined in PBS Pro)
243
- args += ["-o", script.output_path] unless script.output_path.nil?
244
- args += ["-e", script.error_path] unless script.error_path.nil?
263
+ args.concat ["-o", script.output_path] unless script.output_path.nil?
264
+ args.concat ["-e", script.error_path] unless script.error_path.nil?
245
265
  # Reservations are actually just queues in PBS Pro
246
- args += ["-q", script.reservation_id] if !script.reservation_id.nil? && script.queue_name.nil?
247
- args += ["-q", script.queue_name] unless script.queue_name.nil?
248
- args += ["-p", script.priority] unless script.priority.nil?
249
- args += ["-a", script.start_time.localtime.strftime("%C%y%m%d%H%M.%S")] unless script.start_time.nil?
250
- args += ["-A", script.accounting_id] unless script.accounting_id.nil?
251
- args += ["-l", "walltime=#{seconds_to_duration(script.wall_time)}"] unless script.wall_time.nil?
266
+ args.concat ["-q", script.reservation_id] if !script.reservation_id.nil? && script.queue_name.nil?
267
+ args.concat ["-q", script.queue_name] unless script.queue_name.nil?
268
+ args.concat ["-p", script.priority] unless script.priority.nil?
269
+ args.concat ["-a", script.start_time.localtime.strftime("%C%y%m%d%H%M.%S")] unless script.start_time.nil?
270
+ args.concat ["-A", script.accounting_id] unless script.accounting_id.nil?
271
+ args.concat ["-l", "walltime=#{seconds_to_duration(script.wall_time)}"] unless script.wall_time.nil?
252
272
 
253
273
  # Set dependencies
254
274
  depend = []
@@ -256,20 +276,21 @@ module OodCore
256
276
  depend << "afterok:#{afterok.join(":")}" unless afterok.empty?
257
277
  depend << "afternotok:#{afternotok.join(":")}" unless afternotok.empty?
258
278
  depend << "afterany:#{afterany.join(":")}" unless afterany.empty?
259
- args += ["-W", "depend=#{depend.join(",")}"] unless depend.empty?
279
+ args.concat ["-W", "depend=#{depend.join(",")}"] unless depend.empty?
260
280
 
261
281
  # Set environment variables
262
282
  envvars = script.job_environment.to_h
263
- args += ["-v", envvars.map{|k,v| "#{k}=#{v}"}.join(",")] unless envvars.empty?
283
+ args.concat ["-v", envvars.map{|k,v| "#{k}=#{v}"}.join(",")] unless envvars.empty?
284
+ args.concat ["-V"] if script.copy_environment?
264
285
 
265
286
  # If error_path is not specified we join stdout & stderr (as this
266
287
  # mimics what the other resource managers do)
267
- args += ["-j", "oe"] if script.error_path.nil?
288
+ args.concat ["-j", "oe"] if script.error_path.nil?
268
289
 
269
- args += ["-J", script.job_array_request] unless script.job_array_request.nil?
290
+ args.concat ["-J", script.job_array_request] unless script.job_array_request.nil?
270
291
 
271
292
  # Set native options
272
- args += script.native if script.native
293
+ args.concat script.native if script.native
273
294
 
274
295
  # Submit job
275
296
  @pbspro.submit_string(script.content, args: args, chdir: script.workdir)
@@ -397,6 +418,10 @@ module OodCore
397
418
  raise JobAdapterError, e.message unless /Unknown Job Id/ =~ e.message || /Job has finished/ =~ e.message
398
419
  end
399
420
 
421
+ def directive_prefix
422
+ '#PBS'
423
+ end
424
+
400
425
  private
401
426
  # Convert duration to seconds
402
427
  def duration_in_seconds(time)
@@ -157,6 +157,10 @@ module OodCore
157
157
  rescue Batch::Error => e
158
158
  raise JobAdapterError, e.message
159
159
  end
160
+
161
+ def directive_prefix
162
+ '#$'
163
+ end
160
164
  end
161
165
  end
162
166
  end
@@ -15,7 +15,7 @@ end
15
15
  class OodCore::Job::Adapters::Sge::Batch
16
16
  using OodCore::Refinements::HashExtensions
17
17
 
18
- attr_reader :bin, :bin_overrides, :conf, :cluster, :helper
18
+ attr_reader :bin, :bin_overrides, :conf, :cluster, :helper, :submit_host, :strict_host_checking
19
19
 
20
20
  require "ood_core/job/adapters/sge/qstat_xml_j_r_listener"
21
21
  require "ood_core/job/adapters/sge/qstat_xml_r_listener"
@@ -33,10 +33,11 @@ class OodCore::Job::Adapters::Sge::Batch
33
33
  # @see Factory.build_sge
34
34
  def initialize(config)
35
35
  @cluster = config.fetch(:cluster, nil)
36
- @conf = Pathname.new(config.fetch(:conf, nil))
37
- @bin = Pathname.new(config.fetch(:bin, nil))
36
+ @bin = Pathname.new(config.fetch(:bin, nil).to_s)
38
37
  @sge_root = Pathname.new(config[:sge_root] || ENV['SGE_ROOT'] || "/var/lib/gridengine")
39
38
  @bin_overrides = config.fetch(:bin_overrides, {})
39
+ @submit_host = config.fetch(:submit_host, "")
40
+ @strict_host_checking = config.fetch(:strict_host_checking, true)
40
41
 
41
42
  # FIXME: hack as this affects env of the process!
42
43
  ENV['SGE_ROOT'] = @sge_root.to_s
@@ -63,7 +64,7 @@ class OodCore::Job::Adapters::Sge::Batch
63
64
  def get_all(owner: nil)
64
65
  listener = QstatXmlRListener.new
65
66
  argv = ['qstat', '-r', '-xml']
66
- argv += ['-u', owner] unless owner.nil?
67
+ argv.concat ['-u', owner] unless owner.nil?
67
68
  REXML::Parsers::StreamParser.new(call(*argv), listener).parse
68
69
 
69
70
  listener.parsed_jobs.map{
@@ -167,11 +168,10 @@ class OodCore::Job::Adapters::Sge::Batch
167
168
  # Call a forked SGE command for a given batch server
168
169
  def call(cmd, *args, env: {}, stdin: "", chdir: nil)
169
170
  cmd = OodCore::Job::Adapters::Helper.bin_path(cmd, bin, bin_overrides)
170
- args = args.map(&:to_s)
171
-
172
171
  env = env.to_h.each_with_object({}) { |(k, v), h| h[k.to_s] = v.to_s }
172
+ cmd, args = OodCore::Job::Adapters::Helper.ssh_wrap(submit_host, cmd, args, strict_host_checking, env)
173
173
  chdir ||= "."
174
- o, e, s = Open3.capture3(env, cmd, *args, stdin_data: stdin.to_s, chdir: chdir.to_s)
174
+ o, e, s = Open3.capture3(env, cmd, *(args.map(&:to_s)), stdin_data: stdin.to_s, chdir: chdir.to_s)
175
175
  s.success? ? o : raise(Error, e)
176
176
  end
177
177
 
@@ -17,37 +17,38 @@ class OodCore::Job::Adapters::Sge::Helper
17
17
  raise_error_on_unsupported_args(script, after: after, afterok: afterok, afternotok: afternotok, afterany: afterany)
18
18
 
19
19
  args = []
20
- args += ['-h'] if script.submit_as_hold
21
- args += ['-r', 'yes'] if script.rerunnable
22
- script.job_environment.each_pair {|k, v| args += ['-v', "#{k.to_s}=#{v.to_s}"]} unless script.job_environment.nil?
20
+ args.concat ['-h'] if script.submit_as_hold
21
+ args.concat ['-r', 'yes'] if script.rerunnable
22
+ script.job_environment.each_pair {|k, v| args.concat ['-v', "#{k.to_s}=#{v.to_s}"]} unless script.job_environment.nil?
23
+ args.concat ["-V"] if script.copy_environment?
23
24
 
24
25
  if script.workdir
25
- args += ['-wd', script.workdir]
26
+ args.concat ['-wd', script.workdir]
26
27
  elsif ! script_contains_wd_directive?(script.content)
27
- args += ['-cwd']
28
+ args.concat ['-cwd']
28
29
  end
29
30
 
30
31
  on_event_email = []
31
32
  on_event_email << 'b' if script.email_on_started # beginning
32
33
  on_event_email << 'ea' if script.email_on_terminated # end, aborted
33
34
 
34
- args += ['-M', script.email.first, '-m', on_event_email.join] if script.email && ! on_event_email.empty?
35
+ args.concat ['-M', script.email.first, '-m', on_event_email.join] if script.email && ! on_event_email.empty?
35
36
 
36
37
  afterok = Array(afterok).map(&:to_s)
37
- args += ['-hold_jid_ad', afterok.join(',')] unless afterok.empty?
38
+ args.concat ['-hold_jid_ad', afterok.join(',')] unless afterok.empty?
38
39
 
39
40
  # ignoring email_on_started
40
- args += ['-N', script.job_name] unless script.job_name.nil?
41
- args += ['-e', script.error_path] unless script.error_path.nil?
42
- args += ['-o', script.output_path] unless script.output_path.nil?
43
- args += ['-ar', script.reservation_id] unless script.reservation_id.nil?
44
- args += ['-q', script.queue_name] unless script.queue_name.nil?
45
- args += ['-p', script.priority] unless script.priority.nil?
46
- args += ['-a', script.start_time.strftime('%C%y%m%d%H%M.%S')] unless script.start_time.nil?
47
- args += ['-l', "h_rt=" + seconds_to_duration(script.wall_time)] unless script.wall_time.nil?
48
- args += ['-P', script.accounting_id] unless script.accounting_id.nil?
49
- args += ['-t', script.job_array_request] unless script.job_array_request.nil?
50
- args += Array.wrap(script.native) if script.native
41
+ args.concat ['-N', script.job_name] unless script.job_name.nil?
42
+ args.concat ['-e', script.error_path] unless script.error_path.nil?
43
+ args.concat ['-o', script.output_path] unless script.output_path.nil?
44
+ args.concat ['-ar', script.reservation_id] unless script.reservation_id.nil?
45
+ args.concat ['-q', script.queue_name] unless script.queue_name.nil?
46
+ args.concat ['-p', script.priority] unless script.priority.nil?
47
+ args.concat ['-a', script.start_time.strftime('%C%y%m%d%H%M.%S')] unless script.start_time.nil?
48
+ args.concat ['-l', "h_rt=" + seconds_to_duration(script.wall_time)] unless script.wall_time.nil?
49
+ args.concat ['-P', script.accounting_id] unless script.accounting_id.nil?
50
+ args.concat ['-t', script.job_array_request] unless script.job_array_request.nil?
51
+ args.concat Array.wrap(script.native) if script.native
51
52
 
52
53
  args
53
54
  end
@@ -27,29 +27,44 @@ class QstatXmlJRListener
27
27
  @parsed_job = {
28
28
  :tasks => [],
29
29
  :status => :queued,
30
- :procs => 1, # un-knowable from SGE qstat output
31
- :native => {} # TODO: improve native attribute reporting
30
+ :procs => 1,
31
+ :native => {
32
+ :ST_name => ''
33
+ }
32
34
  }
33
35
  @current_text = nil
34
36
  @current_request = nil
37
+ @processing_JB_stdout_path_list = false
35
38
 
36
39
  @processing_job_array_spec = false
40
+ @adding_slots = false
41
+
37
42
  @job_array_spec = {
38
43
  start: nil,
39
44
  stop: nil,
40
45
  step: 1, # Step can have a default of 1
41
46
  }
42
47
  @running_tasks = []
48
+ @native_tags = ['JB_job_number', 'JB_job_name', 'JB_version', 'JB_project', 'JB_exec_file', 'JB_script_file', 'JB_script_size', 'JB_submission_time', 'JB_execution_time', 'JB_deadline', 'JB_owner', 'JB_uid', 'JB_group', 'JB_gid', 'JB_account', 'JB_cwd', 'JB_notify', 'JB_type', 'JB_reserve', 'JB_priority', 'JB_jobshare', 'JB_verify', 'JB_checkpoint_attr', 'JB_checkpoint_interval', 'JB_restart']
43
49
  end
44
50
 
45
51
  def tag_start(name, attrs)
46
52
  case name
47
53
  when 'task_id_range'
48
54
  toggle_processing_array_spec
55
+ when 'JB_pe_range'
56
+ toggle_adding_slots
57
+ when 'JB_stdout_path_list'
58
+ @processing_JB_stdout_path_list = true
49
59
  end
50
60
  end
51
61
 
52
62
  def tag_end(name)
63
+ #Add to native hash if in native_tags
64
+ if (@native_tags.include?(name))
65
+ @parsed_job[:native][:"#{name}"] = @current_text
66
+ end
67
+
53
68
  case name
54
69
  when 'JB_ja_tasks'
55
70
  end_JB_ja_tasks
@@ -78,13 +93,20 @@ class QstatXmlJRListener
78
93
  when 'djob_info'
79
94
  finalize_parsed_job
80
95
  when 'RN_min'
81
- set_job_array_piece(:start)
96
+ set_job_array_piece(:start) if @processing_job_array_spec
97
+ set_slots if @adding_slots
82
98
  when 'RN_max'
83
- set_job_array_piece(:stop)
99
+ set_job_array_piece(:stop) if @processing_job_array_spec
84
100
  when 'RN_step'
85
- set_job_array_piece(:step)
101
+ set_job_array_piece(:step) if @processing_job_array_spec
86
102
  when 'task_id_range'
87
103
  toggle_processing_array_spec
104
+ when 'JB_pe_range'
105
+ toggle_adding_slots
106
+ when 'PN_path'
107
+ end_PN_path
108
+ when 'ST_name'
109
+ end_ST_name
88
110
  end
89
111
  end
90
112
 
@@ -111,7 +133,7 @@ class QstatXmlJRListener
111
133
  end
112
134
 
113
135
  def end_JB_submission_time
114
- @parsed_job[:submission_time] = @current_text.to_i
136
+ @parsed_job[:submission_time] = ms_to_seconds(@current_text.to_i)
115
137
  end
116
138
 
117
139
  def end_JB_ja_tasks
@@ -120,7 +142,7 @@ class QstatXmlJRListener
120
142
 
121
143
  def end_JAT_start_time
122
144
  @parsed_job[:status] = :running
123
- @parsed_job[:dispatch_time] = @current_text.to_i
145
+ @parsed_job[:dispatch_time] = ms_to_seconds(@current_text.to_i)
124
146
  @parsed_job[:wallclock_time] = Time.now.to_i - @parsed_job[:dispatch_time]
125
147
  end
126
148
 
@@ -146,6 +168,15 @@ class QstatXmlJRListener
146
168
  @running_tasks << @current_text
147
169
  end
148
170
 
171
+ def end_PN_path
172
+ @parsed_job[:native][:PN_path] = @current_text if @processing_JB_stdout_path_list
173
+ @processing_JB_stdout_path_list = false
174
+ end
175
+
176
+ def end_ST_name
177
+ @parsed_job[:native][:ST_name] = @parsed_job[:native][:ST_name] + @current_text + ' '
178
+ end
179
+
149
180
  def set_job_array_piece(key)
150
181
  @job_array_spec[key] = @current_text if @processing_job_array_spec
151
182
  end
@@ -186,5 +217,20 @@ class QstatXmlJRListener
186
217
  def toggle_processing_array_spec
187
218
  @processing_job_array_spec = ! @processing_job_array_spec
188
219
  end
189
- end
190
220
 
221
+ def toggle_adding_slots
222
+ @adding_slots = ! @adding_slots
223
+ end
224
+
225
+ def set_slots
226
+ @parsed_job[:procs] = @current_text.to_i
227
+ end
228
+
229
+ private
230
+
231
+ # Some Grid Engines (like UGE) use milliseconds were others use
232
+ # seconds past the epoch.
233
+ def ms_to_seconds(raw)
234
+ raw.digits.length >= 13 ? raw / 1000 : raw
235
+ end
236
+ end