pbs 1.1.3

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.
@@ -0,0 +1,103 @@
1
+ module PBS
2
+ class Query
3
+ attr_reader :type
4
+ attr_reader :conn
5
+ attr_accessor :where_procs
6
+
7
+ STATTYPE = {job: :pbs_statjob, queue: :pbs_statque,
8
+ node: :pbs_statnode, server: :pbs_statserver}
9
+
10
+ # Needs a connection object and a query type
11
+ # Query types: :job, :queue, :server, :node
12
+ def initialize(args = {})
13
+ @conn = args[:conn] || Conn.new
14
+ @type = args[:type] || :job
15
+ @where_procs = []
16
+ end
17
+
18
+ # Boolean procs used to filter out query results
19
+ # Examples:
20
+ # where {|h| h[PBS::ATTR[:N]] == "SimpleJob"}
21
+ # where(PBS::ATTR[:N]) {|v| v == "SimpleJob"}
22
+ # where
23
+ # the last one is used with other methods
24
+ # i.e., where.not(PBS::ATTR[:N]) => "SimpleJob")
25
+ def where(arg = nil, &block)
26
+ relation = self.clone
27
+ relation.where_procs = @where_procs.clone
28
+ relation.where_procs << (arg ? Proc.new {|h| block.call(h[arg])} : block)
29
+ relation
30
+ end
31
+
32
+ # Used to filter where key attrib is equal to value
33
+ # where.is(PBS::ATTR[:N] => "SimpleJob")
34
+ def is(hash)
35
+ key, value = hash.first
36
+ raise PBS::Error, "`where' method not called before" if where_procs.empty? || where_procs[-1]
37
+ self.where_procs[-1] = Proc.new {|h| h[key] == value}
38
+ self
39
+ end
40
+
41
+ # Used to filter where key attrib is NOT equal to value
42
+ # where.not(PBS::ATTR[:N] => "SimpleJob")
43
+ def not(hash)
44
+ key, value = hash.first
45
+ raise PBS::Error, "`where' method not called before" if where_procs.empty? || where_procs[-1]
46
+ self.where_procs[-1] = Proc.new {|h| h[key] != value}
47
+ self
48
+ end
49
+
50
+ # Used to filter specific user
51
+ # where.user("username")
52
+ def user(name)
53
+ raise PBS::Error, "`where' method not called before" if where_procs.empty? || where_procs[-1]
54
+ self.where_procs[-1] = Proc.new {|h| /^#{name}@/ =~ h[ATTR[:owner]]}
55
+ self
56
+ end
57
+
58
+ def find(args = {})
59
+ id = args[:id] || nil
60
+ filters = args[:filters]
61
+ filters = [args[:filter]] if args[:filter]
62
+
63
+ # Get array of batch status hashes
64
+ batch_list = _pbs_batchstat(id, filters)
65
+
66
+ # Further filter results and then output them
67
+ _filter_where_values(batch_list)
68
+ end
69
+
70
+ # Filter an array of hashes based on the defined where procs
71
+ # Comparisons are done inside the :attribs hash only
72
+ def _filter_where_values(array)
73
+ array.select do |hash|
74
+ pass = true
75
+ where_procs.each do |p|
76
+ pass = false unless p.call(hash[:attribs])
77
+ end
78
+ pass
79
+ end
80
+ end
81
+
82
+ # Connect, get status on batch server,
83
+ # disconnect, parse output, and finally check for errors
84
+ # Don't forget to free up memory the C-library creates
85
+ def _pbs_batchstat(id, filters)
86
+ # Generate attribute list from filter list
87
+ attrib_list = PBS::Torque::Attrl.from_list(filters) if filters
88
+
89
+ batch_status = nil
90
+ conn.connect unless conn.connected?
91
+ if type == :server
92
+ batch_status = Torque.send(STATTYPE[type], conn.conn_id, attrib_list, nil)
93
+ else
94
+ batch_status = Torque.send(STATTYPE[type], conn.conn_id, id, attrib_list, nil)
95
+ end
96
+ conn.disconnect
97
+ batch_list = batch_status.to_a
98
+ Torque.pbs_statfree(batch_status)
99
+ Torque.check_for_error
100
+ batch_list
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,305 @@
1
+ require "ffi"
2
+
3
+ module PBS
4
+ module Torque
5
+ extend FFI::Library
6
+
7
+ # Define torque methods using a supplied library
8
+ def self.init(args = {})
9
+ @@lib = args[:lib] || "torque"
10
+
11
+ # Set up FFI to use this library
12
+ ffi_lib @@lib
13
+
14
+ # int pbs_errno
15
+ attach_variable :pbs_errno, :int
16
+
17
+ # char *pbs_server
18
+ attach_variable :pbs_server, :string
19
+
20
+ # int pbs_connect(char *server)
21
+ attach_function :pbs_connect, [ :pointer ], :int
22
+
23
+ # char *pbs_default(void)
24
+ attach_function :pbs_default, [], :string
25
+
26
+ # char *pbs_strerror(int errno)
27
+ attach_function :pbs_strerror, [ :int ], :string
28
+
29
+ # int pbs_deljob(int connect, char *job_id, char *extend)
30
+ attach_function :pbs_deljob, [ :int, :pointer, :pointer ], :int
31
+
32
+ # int pbs_disconnect(int connect)
33
+ attach_function :pbs_disconnect, [ :int ], :int
34
+
35
+ # int pbs_holdjob(int connect, char *job_id, char *hold_type, char *extend)
36
+ attach_function :pbs_holdjob, [ :int, :pointer, :pointer, :pointer ], :int
37
+
38
+ # int pbs_rlsjob(int connect, char *job_id, char *hold_type, char *extend)
39
+ attach_function :pbs_rlsjob, [ :int, :pointer, :pointer, :pointer ], :int
40
+
41
+ # void pbs_statfree(struct batch_status *stat)
42
+ attach_function :pbs_statfree, [ :pointer ], :void
43
+
44
+ # batch_status * pbs_statjob(int connect, char *id, struct attrl *attrib, char *extend)
45
+ attach_function :pbs_statjob, [ :int, :pointer, :pointer, :pointer ], BatchStatus.ptr
46
+
47
+ # batch_status * pbs_statnode(int connect, char *id, struct attrl *attrib, char *extend)
48
+ attach_function :pbs_statnode, [ :int, :pointer, :pointer, :pointer ], BatchStatus.ptr
49
+
50
+ # batch_status * pbs_statque(int connect, char *id, struct attrl *attrib, char *extend)
51
+ attach_function :pbs_statque, [ :int, :pointer, :pointer, :pointer ], BatchStatus.ptr
52
+
53
+ # batch_status * pbs_statserver(int connect, struct attrl *attrib, char *extend)
54
+ attach_function :pbs_statserver, [ :int, :pointer, :pointer ], BatchStatus.ptr
55
+
56
+ # char *pbs_submit(int connect, struct attropl *attrib, char *script, char *destination, char *extend)
57
+ attach_function :pbs_submit, [ :int, :pointer, :pointer, :pointer, :pointer ], :string
58
+ end
59
+
60
+ def self.check_for_error
61
+ errno = pbs_errno
62
+ self.pbs_errno = 0 # reset error number
63
+ raise_error(errno) if errno > 0
64
+ end
65
+
66
+ def self.raise_error(errno)
67
+ raise (ERROR_CODES[errno] || PBS::Error), "#{pbs_strerror(errno)}"
68
+ end
69
+
70
+ # Data structures defined in pbs_ifl.h
71
+
72
+ # Enum for Batch Operation
73
+ BatchOp = enum(:set, :unset, :incr, :decr, :eq, :ne, :ge, :gt, :le, :lt, :dflt, :merge, :incr_old)
74
+
75
+ # Struct for Attribute C-linked list
76
+ class Attrl < FFI::Struct
77
+ layout :next, Attrl.ptr, # pointer to next Attrl object
78
+ :name, :pointer, # string for name of attribute
79
+ :resource, :pointer, # string for resource if this attribute is a resource
80
+ :value, :pointer, # string for value of attribute
81
+ :op, BatchOp # not used in an Attrl object
82
+
83
+ def self.from_list(list)
84
+ attrl = nil
85
+ prev = Attrl.new(FFI::Pointer::NULL)
86
+ list.each do |key|
87
+ attrl = Attrl.new
88
+ attrl[:name] = FFI::MemoryPointer.from_string(key.to_s)
89
+ attrl[:resource] = FFI::Pointer::NULL
90
+ attrl[:value] = FFI::Pointer::NULL
91
+ attrl[:op] = 0
92
+ attrl[:next] = prev
93
+ prev = attrl
94
+ end
95
+ attrl
96
+ end
97
+
98
+ def to_hash
99
+ hash = Hash.new{ |h,k| h[k] = Hash.new() }
100
+ attrl = self
101
+ until attrl.to_ptr.null?
102
+ name = attrl[:name].read_string.to_sym
103
+ value = attrl[:value].read_string
104
+ resource = nil
105
+ resource = attrl[:resource].read_string.to_sym unless attrl[:resource].null?
106
+ if resource.nil?
107
+ hash[name] = value
108
+ else
109
+ hash[name][resource] = value
110
+ end
111
+ attrl = attrl[:next]
112
+ end
113
+ hash
114
+ end
115
+ end
116
+
117
+ # Struct for Attribute Operation C-linked list
118
+ class Attropl < FFI::Struct
119
+ layout :next, Attropl.ptr, # pointer to next Attropl object
120
+ :name, :pointer, # string for name of attribute
121
+ :resource, :pointer, # string for resource if this attribute is a resource
122
+ :value, :pointer, # string for value of attribute
123
+ :op, BatchOp # operation to perform for this attribute
124
+
125
+ def self.from_hash(hash)
126
+ # Convert hash into array
127
+ # Format: {name: value, name: {resource: value, resource: value}}
128
+ # {a: 1, b: {c: 2, d: 3}} => [[:a,1],[:b,2,:c],[:b,3,:d]]
129
+ ary = hash.map{|k,v| [*v].map{|v2| [k,*[*v2].reverse]}}.flatten(1)
130
+ attropl = nil
131
+ prev = Attropl.new(FFI::Pointer::NULL)
132
+ ary.each do |attrib|
133
+ attropl = Attropl.new
134
+ attropl[:name] = FFI::MemoryPointer.from_string(attrib[0].to_s)
135
+ attropl[:value] = FFI::MemoryPointer.from_string(attrib[1])
136
+ attropl[:resource] = FFI::MemoryPointer.from_string(attrib[2].to_s) unless attrib[2].nil?
137
+ attropl[:op] = 0
138
+ attropl[:next] = prev
139
+ prev = attropl
140
+ end
141
+ attropl
142
+ end
143
+ end
144
+
145
+ # Struct for status of batch
146
+ class BatchStatus < FFI::ManagedStruct
147
+ layout :next, BatchStatus.ptr, # pointer to next BatchStatus object
148
+ :name, :string, # string for name of this status
149
+ :attribs, Attrl.ptr, # pointer to beginning of C-linked list of an Attrl object
150
+ :text, :string # string containing unknown text
151
+
152
+ def self.release(ptr)
153
+ pbs_statfree(ptr)
154
+ end
155
+
156
+ def to_a
157
+ ary = []
158
+ batch = self
159
+ until batch.to_ptr.null?
160
+ ary << {name: batch[:name], attribs: batch[:attribs].to_hash}
161
+ batch = batch[:next]
162
+ end
163
+ ary
164
+ end
165
+ end
166
+
167
+ # Defined error codes
168
+ # valid as of Torque >=4.2.10
169
+ ERROR_CODES = {
170
+ 15001 => PBS::UnkjobidError,
171
+ 15002 => PBS::NoattrError,
172
+ 15003 => PBS::AttrroError,
173
+ 15004 => PBS::IvalreqError,
174
+ 15005 => PBS::UnkreqError,
175
+ 15006 => PBS::ToomanyError,
176
+ 15007 => PBS::PermError,
177
+ 15008 => PBS::IffNotFoundError,
178
+ 15009 => PBS::MungeNotFoundError,
179
+ 15010 => PBS::BadhostError,
180
+ 15011 => PBS::JobexistError,
181
+ 15012 => PBS::SystemError,
182
+ 15013 => PBS::InternalError,
183
+ 15014 => PBS::RegrouteError,
184
+ 15015 => PBS::UnksigError,
185
+ 15016 => PBS::BadatvalError,
186
+ 15017 => PBS::ModatrrunError,
187
+ 15018 => PBS::BadstateError,
188
+ 15020 => PBS::UnkqueError,
189
+ 15021 => PBS::BadcredError,
190
+ 15022 => PBS::ExpiredError,
191
+ 15023 => PBS::QunoenbError,
192
+ 15024 => PBS::QacessError,
193
+ 15025 => PBS::BaduserError,
194
+ 15026 => PBS::HopcountError,
195
+ 15027 => PBS::QueexistError,
196
+ 15028 => PBS::AttrtypeError,
197
+ 15029 => PBS::QuebusyError,
198
+ 15030 => PBS::QuenbigError,
199
+ 15031 => PBS::NosupError,
200
+ 15032 => PBS::QuenoenError,
201
+ 15033 => PBS::ProtocolError,
202
+ 15034 => PBS::BadatlstError,
203
+ 15035 => PBS::NoconnectsError,
204
+ 15036 => PBS::NoserverError,
205
+ 15037 => PBS::UnkrescError,
206
+ 15038 => PBS::ExcqrescError,
207
+ 15039 => PBS::QuenodfltError,
208
+ 15040 => PBS::NorerunError,
209
+ 15041 => PBS::RouterejError,
210
+ 15042 => PBS::RouteexpdError,
211
+ 15043 => PBS::MomrejectError,
212
+ 15044 => PBS::BadscriptError,
213
+ 15045 => PBS::StageinError,
214
+ 15046 => PBS::RescunavError,
215
+ 15047 => PBS::BadgrpError,
216
+ 15048 => PBS::MaxquedError,
217
+ 15049 => PBS::CkpbsyError,
218
+ 15050 => PBS::ExlimitError,
219
+ 15051 => PBS::BadacctError,
220
+ 15052 => PBS::AlrdyexitError,
221
+ 15053 => PBS::NocopyfileError,
222
+ 15054 => PBS::CleanedoutError,
223
+ 15055 => PBS::NosyncmstrError,
224
+ 15056 => PBS::BaddependError,
225
+ 15057 => PBS::DuplistError,
226
+ 15058 => PBS::DisprotoError,
227
+ 15059 => PBS::ExecthereError,
228
+ 15060 => PBS::SisrejectError,
229
+ 15061 => PBS::SiscommError,
230
+ 15062 => PBS::SvrdownError,
231
+ 15063 => PBS::CkpshortError,
232
+ 15064 => PBS::UnknodeError,
233
+ 15065 => PBS::UnknodeatrError,
234
+ 15066 => PBS::NonodesError,
235
+ 15067 => PBS::NodenbigError,
236
+ 15068 => PBS::NodeexistError,
237
+ 15069 => PBS::BadndatvalError,
238
+ 15070 => PBS::MutualexError,
239
+ 15071 => PBS::GmoderrError,
240
+ 15072 => PBS::NorelymomError,
241
+ 15073 => PBS::NotsnodeError,
242
+ 15074 => PBS::JobtypeError,
243
+ 15075 => PBS::BadaclhostError,
244
+ 15076 => PBS::MaxuserquedError,
245
+ 15077 => PBS::BaddisallowtypeError,
246
+ 15078 => PBS::NointeractiveError,
247
+ 15079 => PBS::NobatchError,
248
+ 15080 => PBS::NorerunableError,
249
+ 15081 => PBS::NononrerunableError,
250
+ 15082 => PBS::UnkarrayidError,
251
+ 15083 => PBS::BadArrayReqError,
252
+ 15084 => PBS::BadArrayDataError,
253
+ 15085 => PBS::TimeoutError,
254
+ 15086 => PBS::JobnotfoundError,
255
+ 15087 => PBS::NofaulttolerantError,
256
+ 15088 => PBS::NofaultintolerantError,
257
+ 15089 => PBS::NojobarraysError,
258
+ 15090 => PBS::RelayedToMomError,
259
+ 15091 => PBS::MemMallocError,
260
+ 15092 => PBS::MutexError,
261
+ 15093 => PBS::ThreadattrError,
262
+ 15094 => PBS::ThreadError,
263
+ 15095 => PBS::SelectError,
264
+ 15096 => PBS::SocketFaultError,
265
+ 15097 => PBS::SocketWriteError,
266
+ 15098 => PBS::SocketReadError,
267
+ 15099 => PBS::SocketCloseError,
268
+ 15100 => PBS::SocketListenError,
269
+ 15101 => PBS::AuthInvalidError,
270
+ 15102 => PBS::NotImplementedError,
271
+ 15103 => PBS::QuenotavailableError,
272
+ 15104 => PBS::TmpdiffownerError,
273
+ 15105 => PBS::TmpnotdirError,
274
+ 15106 => PBS::TmpnonameError,
275
+ 15107 => PBS::CantopensocketError,
276
+ 15108 => PBS::CantcontactsistersError,
277
+ 15109 => PBS::CantcreatetmpdirError,
278
+ 15110 => PBS::BadmomstateError,
279
+ 15111 => PBS::SocketInformationError,
280
+ 15112 => PBS::SocketDataError,
281
+ 15113 => PBS::ClientInvalidError,
282
+ 15114 => PBS::PrematureEofError,
283
+ 15115 => PBS::CanNotSaveFileError,
284
+ 15116 => PBS::CanNotOpenFileError,
285
+ 15117 => PBS::CanNotWriteFileError,
286
+ 15118 => PBS::JobFileCorruptError,
287
+ 15119 => PBS::JobRerunError,
288
+ 15120 => PBS::ConnectError,
289
+ 15121 => PBS::JobworkdelayError,
290
+ 15122 => PBS::BadParameterError,
291
+ 15123 => PBS::ContinueError,
292
+ 15124 => PBS::JobsubstateError,
293
+ 15125 => PBS::CanNotMoveFileError,
294
+ 15126 => PBS::JobRecycledError,
295
+ 15127 => PBS::JobAlreadyInQueueError,
296
+ 15128 => PBS::InvalidMutexError,
297
+ 15129 => PBS::MutexAlreadyLockedError,
298
+ 15130 => PBS::MutexAlreadyUnlockedError,
299
+ 15131 => PBS::InvalidSyntaxError,
300
+ 15132 => PBS::NodeDownError,
301
+ 15133 => PBS::ServerNotFoundError,
302
+ 15134 => PBS::ServerBusyError,
303
+ }
304
+ end
305
+ end
@@ -0,0 +1,3 @@
1
+ module PBS
2
+ VERSION = "1.1.3"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pbs/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pbs"
8
+ spec.version = PBS::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.authors = ["Jeremy Nicklas"]
11
+ spec.email = ["jnicklas@osc.edu"]
12
+ spec.summary = %q{PBS FFI Ruby gem to use FFI to interface with Adaptive Computing's resource manager Torque}
13
+ spec.description = %q{PBS FFI Ruby gem to use FFI to interface with Adaptive Computing's resource manager Torque}
14
+ spec.homepage = "https://github.com/OSC/pbs-ruby"
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 "ffi", "~> 1.9", ">= 1.9.6"
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pbs
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Nicklas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.9.6
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.9'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.9.6
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.3'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.3'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ description: PBS FFI Ruby gem to use FFI to interface with Adaptive Computing's resource
62
+ manager Torque
63
+ email:
64
+ - jnicklas@osc.edu
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - ".gitignore"
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - config/batch.yml
75
+ - config/websvcs02.osc.edu.yml
76
+ - config/websvcs08.osc.edu.yml
77
+ - examples/simplejob.rb
78
+ - lib/pbs.rb
79
+ - lib/pbs/attributes.rb
80
+ - lib/pbs/conn.rb
81
+ - lib/pbs/error.rb
82
+ - lib/pbs/job.rb
83
+ - lib/pbs/query.rb
84
+ - lib/pbs/torque.rb
85
+ - lib/pbs/version.rb
86
+ - pbs.gemspec
87
+ homepage: https://github.com/OSC/pbs-ruby
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.4.8
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: PBS FFI Ruby gem to use FFI to interface with Adaptive Computing's resource
111
+ manager Torque
112
+ test_files: []