class ABS
Public Class Methods
all_job_resources_accounted_for(allocated_resources, hosts)
click to toggle source
# File lib/vmfloaty/abs.rb, line 101 def self.all_job_resources_accounted_for(allocated_resources, hosts) allocated_host_list = allocated_resources.map { |ar| ar['hostname'] } (allocated_host_list - hosts).empty? end
check_queue(conn, _job_id, req_obj, verbose)
click to toggle source
# File lib/vmfloaty/abs.rb, line 333 def self.check_queue(conn, _job_id, req_obj, verbose) res = conn.post 'request', req_obj.to_json status = validate_queue_status_response(res.status, res.body, 'Check queue request', verbose) unless res.body.empty? || !valid_json?(res.body) res_body = JSON.parse(res.body) return res_body end res.body end
delete(verbose, url, hosts, token, user)
click to toggle source
# File lib/vmfloaty/abs.rb, line 106 def self.delete(verbose, url, hosts, token, user) # In ABS terms, this is a "returned" host. conn = Http.get_conn(verbose, supported_abs_url(url)) conn.headers['X-AUTH-TOKEN'] = token if token FloatyLogger.info "Trying to delete hosts #{hosts}" if verbose requests = get_active_requests(verbose, url, user) jobs_to_delete = [] ret_status = {} hosts.each do |host| ret_status[host] = { 'ok' => false } end requests.each do |req_hash| next unless req_hash['state'] == 'allocated' || req_hash['state'] == 'filled' if hosts.include? req_hash['request']['job']['id'] jobs_to_delete.push(req_hash) next end req_hash['allocated_resources'].each do |vm_name, _i| if hosts.include? vm_name['hostname'] if all_job_resources_accounted_for(req_hash['allocated_resources'], hosts) ret_status[vm_name['hostname']] = { 'ok' => true } jobs_to_delete.push(req_hash) else FloatyLogger.info "When using ABS you must delete all vms that you requested at the same time: Can't delete #{req_hash['request']['job']['id']}: #{hosts} does not include all of #{req_hash['allocated_resources']}" end end end end response_body = {} jobs_to_delete.each do |job| req_obj = { 'job_id' => job['request']['job']['id'], 'hosts' => job['allocated_resources'] } FloatyLogger.info "Deleting #{req_obj}" if verbose return_result = conn.post 'return', req_obj.to_json req_obj['hosts'].each do |host| response_body[host['hostname']] = { 'ok' => true } if return_result.body == 'OK' end end response_body end
disk(_verbose, _url, _hostname, _token, _disk)
click to toggle source
# File lib/vmfloaty/abs.rb, line 380 def self.disk(_verbose, _url, _hostname, _token, _disk) raise NoMethodError, 'disk is not defined for ABS' end
get_active_requests(verbose, url, user)
click to toggle source
# File lib/vmfloaty/abs.rb, line 66 def self.get_active_requests(verbose, url, user) conn = Http.get_conn(verbose, supported_abs_url(url)) res = conn.get 'status/queue' if valid_json?(res.body) requests = JSON.parse(res.body) else FloatyLogger.warn "Warning: couldn't parse body returned from abs/status/queue" end ret_val = [] requests.each do |req| next if req == 'null' if valid_json?(req) # legacy ABS had another JSON string always-be-scheduling/pull/306 req_hash = JSON.parse(req) elsif req.is_a?(Hash) req_hash = req else FloatyLogger.warn "Warning: couldn't parse request returned from abs/status/queue" next end begin next unless user == req_hash['request']['job']['user'] ret_val.push(req_hash) rescue NoMethodError FloatyLogger.warn "Warning: couldn't parse user returned from abs/status/queue: " end end ret_val end
list(verbose, url, os_filter = nil)
click to toggle source
List available VMs in ABS
# File lib/vmfloaty/abs.rb, line 165 def self.list(verbose, url, os_filter = nil) conn = Http.get_conn(verbose, supported_abs_url(url)) os_list = [] res = conn.get 'status/platforms/vmpooler' if valid_json?(res.body) res_body = JSON.parse(res.body) if res_body.key?('vmpooler_platforms') os_list << '*** VMPOOLER Pools ***' os_list += if res_body['vmpooler_platforms'].is_a?(String) JSON.parse(res_body['vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 else res_body['vmpooler_platforms'] end end end res = conn.get 'status/platforms/ondemand_vmpooler' if valid_json?(res.body) res_body = JSON.parse(res.body) if res_body.key?('ondemand_vmpooler_platforms') && res_body['ondemand_vmpooler_platforms'] != '[]' os_list << '' os_list << '*** VMPOOLER ONDEMAND Pools ***' if res_body['ondemand_vmpooler_platforms'].is_a?(String) os_list += JSON.parse(res_body['ondemand_vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 else os_list += res_body['ondemand_vmpooler_platforms'] end end end res = conn.get 'status/platforms/nspooler' if valid_json?(res.body) res_body = JSON.parse(res.body) if res_body.key?('nspooler_platforms') os_list << '' os_list << '*** NSPOOLER Pools ***' os_list += if res_body['nspooler_platforms'].is_a?(String) JSON.parse(res_body['nspooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 else res_body['nspooler_platforms'] end end end res = conn.get 'status/platforms/aws' if valid_json?(res.body) res_body = JSON.parse(res.body) if res_body.key?('aws_platforms') os_list << '' os_list << '*** AWS Pools ***' os_list += if res_body['aws_platforms'].is_a?(String) JSON.parse(res_body['aws_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306 else res_body['aws_platforms'] end end end os_list.delete 'ok' os_filter ? os_list.select { |i| i[/#{os_filter}/] } : os_list end
list_active(verbose, url, _token, user)
click to toggle source
# File lib/vmfloaty/abs.rb, line 53 def self.list_active(verbose, url, _token, user) hosts = [] get_active_requests(verbose, url, user).each do |req_hash| next unless req_hash.key?('allocated_resources') req_hash['allocated_resources'].each do |onehost| hosts.push(onehost['hostname']) end end hosts end
list_active_job_ids(verbose, url, user)
click to toggle source
# File lib/vmfloaty/abs.rb, line 42 def self.list_active_job_ids(verbose, url, user) all_job_ids = [] @active_hostnames = {} get_active_requests(verbose, url, user).each do |req_hash| @active_hostnames[req_hash['request']['job']['id']] = req_hash # full hash saved for later retrieval all_job_ids.push(req_hash['request']['job']['id']) end all_job_ids end
modify(_verbose, _url, _hostname, _token, _modify_hash)
click to toggle source
# File lib/vmfloaty/abs.rb, line 376 def self.modify(_verbose, _url, _hostname, _token, _modify_hash) raise NoMethodError, 'modify is not defined for ABS' end
query(verbose, url, job_id)
click to toggle source
# File lib/vmfloaty/abs.rb, line 359 def self.query(verbose, url, job_id) # return saved hostnames from the last time list_active was run # preventing having to query the API again. # This works as long as query is called after list_active return @active_hostnames if @active_hostnames && !@active_hostnames.empty? # If using the cli query job_id conn = Http.get_conn(verbose, supported_abs_url(url)) queue_info_res = conn.get "status/queue/info/#{job_id}" if valid_json?(queue_info_res.body) queue_info = JSON.parse(queue_info_res.body) else FloatyLogger.warn "Could not parse the status/queue/info/#{job_id}" end queue_info end
retrieve(verbose, os_types, token, url, user, config, _ondemand = nil, continue = nil)
click to toggle source
Retrieve an OS from ABS
.
# File lib/vmfloaty/abs.rb, line 231 def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil, continue = nil) # # Contents of post must be like: # # { # "resources": { # "centos-7-i386": 1, # "ubuntu-1404-x86_64": 2 # }, # "job": { # "id": "12345", # "tags": { # "user": "username", # } # } # } conn = Http.get_conn(verbose, supported_abs_url(url)) conn.headers['X-AUTH-TOKEN'] = token if token saved_job_id = if continue.nil? "#{user}-#{DateTime.now.strftime('%Q')}" else continue end req_obj = { resources: os_types, job: { id: saved_job_id, tags: { user: user } } } if config['vmpooler_fallback'] # optional and not available as cli flag vmpooler_config = Utils.get_vmpooler_service_config(config['vmpooler_fallback']) # request with this token, on behalf of this user req_obj[:vm_token] = vmpooler_config['token'] end if config['priority'] req_obj[:priority] = case config['priority'] when 'high' 1 when 'medium' 2 when 'low' 3 else config['priority'].to_i end end FloatyLogger.info "Posting to ABS #{req_obj.to_json}" if verbose # os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+') # raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty? FloatyLogger.info "Requesting VMs with job_id: #{saved_job_id} Will retry for up to an hour." res = conn.post 'request', req_obj.to_json retries = 360 status = validate_queue_status_response(res.status, res.body, 'Initial request', verbose) begin (1..retries).each do |i| res_body = check_queue(conn, saved_job_id, req_obj, verbose) return translated(res_body, saved_job_id) if res_body.is_a?(Array) # when we get a response with hostnames sleep_seconds = 10 if i >= 10 sleep_seconds = i if i < 10 FloatyLogger.info "Waiting #{sleep_seconds}s (x#{i}) #{res_body.strip}" sleep(sleep_seconds) end rescue SystemExit, Interrupt FloatyLogger.info "\n\nFloaty interrupted, you can resume polling with\n1) `floaty get [same arguments] and adding the flag --continue #{saved_job_id}` or query the state of the queue via\n2) `floaty query #{saved_job_id}` or delete it via\n3) `floaty delete #{saved_job_id}`" exit 1 end nil end
revert(_verbose, _url, _hostname, _token, _snapshot_sha)
click to toggle source
# File lib/vmfloaty/abs.rb, line 384 def self.revert(_verbose, _url, _hostname, _token, _snapshot_sha) raise NoMethodError, 'revert is not defined for ABS' end
snapshot(_verbose, _url, _hostname, _token)
click to toggle source
# File lib/vmfloaty/abs.rb, line 343 def self.snapshot(_verbose, _url, _hostname, _token) raise NoMethodError, "Can't snapshot with ABS, use '--service vmpooler' (even for vms checked out with ABS)" end
status(verbose, url)
click to toggle source
# File lib/vmfloaty/abs.rb, line 347 def self.status(verbose, url) conn = Http.get_conn(verbose, supported_abs_url(url)) res = conn.get 'status' res.body == 'OK' end
summary(_verbose, _url)
click to toggle source
# File lib/vmfloaty/abs.rb, line 355 def self.summary(_verbose, _url) raise NoMethodError, 'summary is not defined for ABS' end
supported_abs_url(url)
click to toggle source
when missing, adds the required api/v2 in the url
# File lib/vmfloaty/abs.rb, line 413 def self.supported_abs_url(url) expected_ending = 'api/v2' unless url.include?(expected_ending) # add a slash if missing expected_ending = "/#{expected_ending}" if url[-1] != '/' url = "#{url}#{expected_ending}" end url end
translated(res_body, job_id)
click to toggle source
We should fix the ABS
API to be more like the vmpooler or nspooler api, but for now
# File lib/vmfloaty/abs.rb, line 318 def self.translated(res_body, job_id) vmpooler_formatted_body = { 'job_id' => job_id } res_body.each do |host| if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].instance_of?(Array) vmpooler_formatted_body[host['type']]['hostname'] << host['hostname'] else vmpooler_formatted_body[host['type']] = { 'hostname' => [host['hostname']] } end end vmpooler_formatted_body['ok'] = true vmpooler_formatted_body end
valid_json?(json)
click to toggle source
# File lib/vmfloaty/abs.rb, line 405 def self.valid_json?(json) JSON.parse(json) true rescue TypeError, JSON::ParserError => e false end
validate_queue_status_response(status_code, body, request_name, verbose)
click to toggle source
Validate the http code returned during a queue status request.
Return a success message that can be displayed if the status code is success, otherwise raise an error.
# File lib/vmfloaty/abs.rb, line 392 def self.validate_queue_status_response(status_code, body, request_name, verbose) case status_code when 200 "#{request_name} returned success (Code 200)" if verbose when 202 "#{request_name} returned accepted, processing (Code 202)" if verbose when 401 raise AuthError, "HTTP #{status_code}: The token provided could not authenticate.\n#{body}" else raise "HTTP #{status_code}: #{request_name} request to ABS failed!\n#{body}" end end