class OSC::Reservations::Adapters::OSCMoab
This adapter is designed for OSC
systems using the Moab scheduler. This adapter requires the parameters torque_name
and mrsvctl
in the Batch
object to work. Only tested on Torque >4.
Public Instance Methods
Queries the batch server for a given reservation. @param batch [Batch] The batch server to query for the reservation. @param id [String] The ID of the reservation. @return [Reservation, nil] @raise [CommandLineError] if a command run from the shell exits with error
# File lib/osc/reservations/adapters/osc_moab.rb, line 20 def query_reservation(batch, id) cmd = "#{batch.mrsvctl} --host=#{batch.server} -q #{id} --xml" begin xml = get_xml(cmd, batch) rescue CommandLineError return end r_xml = xml.xpath("//rsv") rsv = parse_rsv(r_xml) query_nodes(rsv, batch) query_node_users(rsv, batch) rsv end
Queries the batch server for a list of reservations. @param batch [Batch] The batch server to query for the reservation. @return [Array<Reservation>] @raise [CommandLineError] if a command run from the shell exits with error
# File lib/osc/reservations/adapters/osc_moab.rb, line 40 def query_reservations(batch) cmd = "#{batch.mrsvctl} --host=#{batch.server} -q ALL --xml" xml = get_xml(cmd, batch) xml = filter(xml) # filter out "fake" reservations rsv_list = [] xml.xpath("//rsv").each do |r_xml| rsv_list << parse_rsv(r_xml) end query_nodes(rsv_list, batch) query_node_users(rsv_list, batch) rsv_list end
Submits a given reservation to the batch server. @param batch [Batch] The batch server to submit the reservation at. @param reservation [Reservation] A reservation with necessary information. @return [Reservation] @raise [CommandLineError] if a command run from the shell exits with error
# File lib/osc/reservations/adapters/osc_moab.rb, line 60 def submit_reservation(batch, reservation) end
Private Instance Methods
Filter out unwanted reservations in a query @param xml [Nokogiri::XML::Document] The XML document to filter for this adapter. @return [Nokogiri::XML::Document] The filtered XML document.
# File lib/osc/reservations/adapters/osc_moab.rb, line 134 def filter(xml) # Remove running jobs xml.xpath("//rsv[@SubType='JobReservation']").remove # Remove debug queue from Glenn cluster # xml.xpath("//rsv[@SubType='StandingReservation']").remove xml end
Get reservation list as xml @param cmd [String] Command used in terminal to get XML reservation list. @param batch [Batch] The batch server object to use. @return [Nokogiri::XML::Document] The XML document corresponding to the queried reservation list.
# File lib/osc/reservations/adapters/osc_moab.rb, line 120 def get_xml(cmd, batch) Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr| exit_status = wait_thr.value unless exit_status.success? raise CommandLineError, "Bad exit status for: #{cmd}" end Nokogiri::XML(stdout.read) end end
Parse a reservation from a “rsv” element in XML @param xml [Nokogiri::XML::Element] The XML element corresponding to a reservation. @return [Reservation] The reservation object.
# File lib/osc/reservations/adapters/osc_moab.rb, line 147 def parse_rsv(xml) id = xml.xpath("@Name").to_s starttime = Time.at(xml.xpath("@starttime").to_s.to_i) endtime = Time.at(xml.xpath("@endtime").to_s.to_i) auser = xml.xpath("@AUser").to_s users = xml.xpath("ACL[@type='USER']/@name").map { |v| v.value } nodes = xml.xpath("@AllocNodeList").to_s.split(',') Reservation.new( id: id, starttime: starttime, endtime: endtime, auser: auser, users: users, nodes: nodes ) end
Query
what users are running jobs on the nodes for list of reservations @param rsvs [Array<Reservation>] An array of reservations to check. @param batch [Batch] The batch server object to use.
# File lib/osc/reservations/adapters/osc_moab.rb, line 99 def query_node_users(rsvs, batch) # make list of job ids jobs = [*rsvs].map{|r| r.nodes.map(&:jobs)}.flatten.uniq c = PBS::Conn.batch(batch.torque_name) q = PBS::Query.new(conn: c, type: :job) job_list = {} jobs.each do |j| job_list[j] = q.find(id: j)[0][:attribs][:Job_Owner].split('@')[0] end [*rsvs].each{|r| r.nodes.each{|n| n.users = n.jobs.map{|j| job_list[j]}.uniq}} end
Query
the nodes from the batch server @param rsvs [Array<Reservation>] An array of reservations to check. @param batch [Batch] The batch server object to use. @return [Array<Reservation>] The array of reservations on this batch server.
# File lib/osc/reservations/adapters/osc_moab.rb, line 69 def query_nodes(rsvs, batch) # make list of unique nodes for all reservations nodes = [*rsvs].map(&:nodes).flatten.uniq c = PBS::Conn.batch(batch.torque_name) q = PBS::Query.new(conn: c, type: :node) node_list = {} nodes.each do |n| node_hash = q.find(id: n)[0][:attribs] np = node_hash[:np].to_i props = node_hash[:properties].split(',') jobs = node_hash.fetch(:jobs, '').split(',').map{|j| j.split('/')[1]} users = [] node_list[n] = Node.new( id: n, np: np, props: props, jobs: jobs, users: users ) end # replace node lists with lists of Node objects [*rsvs].each{|r| r.nodes.map!{|n| node_list[n]}} end