Class: OSC::Machete::TorqueHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/osc/machete/torque_helper.rb

Overview

Helper object: ruby interface to torque shell commands

in the same vein as stdlib’s Shell which “implements an idiomatic Ruby interface for common UNIX shell commands” also helps to have these separate so we can use a mock shell for unit tests

FIXME: This contains no state whatsoever. It should probably be changed into a module.

Constant Summary collapse

LIB =

FIXME: Use ood_cluster gem

ENV['TORQUE_LIB'] || '/opt/torque/lib64'
BIN =
ENV['TORQUE_BIN'] || '/opt/torque/bin'
HOSTS =
{
  'oakley' => 'oak-batch.osc.edu',
  'ruby'   => 'ruby-batch.ten.osc.edu',
  'quick'  => 'quick-batch.ten.osc.edu',
  'owens'  => 'owens-batch.ten.osc.edu',
  :default => 'oak-batch.osc.edu'
}

Class Attribute Summary collapse

Instance Method Summary collapse

Class Attribute Details

.defaultTorqueHelper



24
# File 'lib/osc/machete/torque_helper.rb', line 24

attr_writer :default

Instance Method Details

#account_string_valid_project?(account_string) ⇒ Boolean



102
103
104
# File 'lib/osc/machete/torque_helper.rb', line 102

def ()
  /^P./ =~ 
end

#default_account_stringString

return the account string required for accounting purposes having this in a separate method is useful for monkeypatching in short term or overridding with a subclass you pass into OSC::Machete::Job

FIXME: this may belong on OSC::Machete::User; but it is OSC specific…



98
99
100
# File 'lib/osc/machete/torque_helper.rb', line 98

def 
  OSC::Machete::Process.new.groupname
end

#pbs(host: nil, id: nil, script: nil) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/osc/machete/torque_helper.rb', line 133

def pbs(host: nil, id: nil, script: nil)
  if host
    # actually check if host is "oakley" i.e. a cluster key
    host = HOSTS.fetch(host.to_s, host.to_s)
  else
    # try to determine host
    key = host_from_pbsid(id) if id
    key = host_from_script_pbs_header(script) if script && key.nil?

    host = HOSTS.fetch(key, HOSTS.fetch(:default))
  end

  PBS::Batch.new(
    host: host,
    lib: LIB,
    bin: BIN
  )
end

#qdel(pbsid, host: nil) ⇒ nil

Perform a qdel command on a single job.



126
127
128
129
130
131
# File 'lib/osc/machete/torque_helper.rb', line 126

def qdel(pbsid, host: nil)
  id = pbsid.to_s
  pbs(host: host, id: id).delete_job(id)
rescue PBS::UnkjobidError
  # Common use case where trying to delete a job that is no longer in the system.
end

#qstat(pbsid, host: nil) ⇒ Status

Performs a qstat request on a single job.

**FIXME: this might not belong here!**



113
114
115
116
117
118
119
# File 'lib/osc/machete/torque_helper.rb', line 113

def qstat(pbsid, host: nil)
  id = pbsid.to_s
  status = pbs(host: host, id: id).get_job(id, filters: [:job_state])
  status_for_char status[id][:job_state][0] # get status from status char value
rescue PBS::UnkjobidError
  OSC::Machete::Status.passed
end

#qsub(script, host: nil, depends_on: {}, account_string: nil) ⇒ Object

usage: qsub("/path/to/script") or

<tt>qsub("/path/to/script", depends_on: { afterany: ["1234.oak-batch.osc.edu"] })</tt>

Where depends_on is a hash with key being dependency type and array containing the arguments. See documentation on dependency_list in qsub man pages for details.

Bills against the project specified by the primary group of the user.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/osc/machete/torque_helper.rb', line 67

def qsub(script, host: nil, depends_on: {}, account_string: nil)
  headers = { depend: qsub_dependencies_header(depends_on) }
  headers.clear if headers[:depend].empty?

  # currently we set the billable project to the name of the primary group
  # this will probably be both SUPERCOMPUTER CENTER SPECIFIC and must change
  # when we want to enable our users at OSC to specify which billable project
  # to bill against
  if 
    headers[PBS::ATTR[:A]] = 
  elsif ()
    headers[PBS::ATTR[:A]] = 
  end

  pbs(host: host, script: script).submit_script(script, headers: headers, qsub: true)
end

#qsub_dependencies_header(depends_on = {}) ⇒ Object

convert dependencies hash to a PBS header string



85
86
87
88
89
# File 'lib/osc/machete/torque_helper.rb', line 85

def qsub_dependencies_header(depends_on = {})
  depends_on.map { |x|
    x.first.to_s + ":" + Array(x.last).join(":") unless Array(x.last).empty?
  }.compact.join(",")
end

#status_for_char(char) ⇒ OSC::Machete::Status

Returns an OSC::Machete::Status ValueObject for a char

Examples:

Passed

status_for_char("C") #=> OSC::Machete::Status.passed

Queued

status_for_char("W") #=> OSC::Machete::Status.queued


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/osc/machete/torque_helper.rb', line 40

def status_for_char(char)
  case char
  when "C", nil
    OSC::Machete::Status.passed
  when "Q", "T", "W" # T W happen before job starts
    OSC::Machete::Status.queued
  when "H"
    OSC::Machete::Status.held
  else
    # all other statuses considerd "running" state
    # including S, E, etc.
    # see http://docs.adaptivecomputing.com/torque/4-1-3/Content/topics/commands/qstat.htm
    OSC::Machete::Status.running
  end
end