(DIO-908) Floaty can now report the status of ABS requests

- If ABS queries returns a body for 200 or 202, floaty will print it
this is useful in the new version of ABS, since it shows the progress
for ondemand requests (AWS or vmpooler)
- removed the queue_place and querying the queue for a 'get' request
this queue_place number was misleading since it was just a redis index
and did not represent well where the request was in the queue
- Also added a flag option --continue to be used when the cli was
interrupted for example with ctrl-c
This commit is contained in:
Samuel Beaulieu 2021-02-09 11:29:08 -06:00
parent 85a63e85fe
commit a3d8484124
6 changed files with 30 additions and 31 deletions

View file

@ -39,6 +39,7 @@ class Vmfloaty
c.option '--force', 'Forces vmfloaty to get requested vms' c.option '--force', 'Forces vmfloaty to get requested vms'
c.option '--json', 'Prints retrieved vms in JSON format' c.option '--json', 'Prints retrieved vms in JSON format'
c.option '--ondemand', 'Requested vms are provisioned upon receival of the request, tracked by a request ID' c.option '--ondemand', 'Requested vms are provisioned upon receival of the request, tracked by a request ID'
c.option '--continue STRING', String, 'resume polling ABS for job_id, for use when the cli was interrupted'
c.action do |args, options| c.action do |args, options|
verbose = options.verbose || config['verbose'] verbose = options.verbose || config['verbose']
service = Service.new(options, config) service = Service.new(options, config)
@ -52,6 +53,11 @@ class Vmfloaty
os_types = Utils.generate_os_hash(args) os_types = Utils.generate_os_hash(args)
if os_types.empty?
FloatyLogger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
exit 1
end
max_pool_request = 5 max_pool_request = 5
large_pool_requests = os_types.select { |_, v| v > max_pool_request } large_pool_requests = os_types.select { |_, v| v > max_pool_request }
if !large_pool_requests.empty? && !force if !large_pool_requests.empty? && !force
@ -60,12 +66,7 @@ class Vmfloaty
exit 1 exit 1
end end
if os_types.empty? response = service.retrieve(verbose, os_types, use_token, options.ondemand, options.continue)
FloatyLogger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
exit 1
end
response = service.retrieve(verbose, os_types, use_token, options.ondemand)
request_id = response['request_id'] if options.ondemand request_id = response['request_id'] if options.ondemand
response = service.wait_for_request(verbose, request_id) if options.ondemand response = service.wait_for_request(verbose, request_id) if options.ondemand

View file

@ -228,7 +228,7 @@ class ABS
end end
# Retrieve an OS from ABS. # Retrieve an OS from ABS.
def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil) def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil, continue = nil)
# #
# Contents of post must be like: # Contents of post must be like:
# #
@ -248,7 +248,12 @@ class ABS
conn = Http.get_conn(verbose, supported_abs_url(url)) conn = Http.get_conn(verbose, supported_abs_url(url))
conn.headers['X-AUTH-TOKEN'] = token if token conn.headers['X-AUTH-TOKEN'] = token if token
if continue.nil?
saved_job_id = user + "-" + DateTime.now.strftime('%Q') saved_job_id = user + "-" + DateTime.now.strftime('%Q')
else
saved_job_id = continue
end
req_obj = { req_obj = {
:resources => os_types, :resources => os_types,
:job => { :job => {
@ -281,26 +286,28 @@ class ABS
# os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+') # os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+')
# raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty? # 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." 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 res = conn.post 'request', req_obj.to_json
retries = 360 retries = 360
validate_queue_status_response(res.status, res.body, "Initial request", verbose) status = validate_queue_status_response(res.status, res.body, "Initial request", verbose)
begin begin
(1..retries).each do |i| (1..retries).each do |i|
queue_place, res_body = check_queue(conn, saved_job_id, req_obj, verbose) res_body = check_queue(conn, saved_job_id, req_obj, verbose)
return translated(res_body, saved_job_id) if res_body if res_body && res_body.is_a?(Array) # when we get a response with hostnames
return translated(res_body, saved_job_id)
end
sleep_seconds = 10 if i >= 10 sleep_seconds = 10 if i >= 10
sleep_seconds = i if i < 10 sleep_seconds = i if i < 10
FloatyLogger.info "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})" FloatyLogger.info "Waiting #{sleep_seconds}s (x#{i}) #{res_body.strip}"
sleep(sleep_seconds) sleep(sleep_seconds)
end end
rescue SystemExit, Interrupt rescue SystemExit, Interrupt
FloatyLogger.info "\n\nFloaty interrupted, you can query the state of your request via\n1) `floaty query #{saved_job_id}` or delete it via\n2) `floaty delete #{saved_job_id}`" 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 exit 1
end end
nil nil
@ -325,22 +332,13 @@ class ABS
end end
def self.check_queue(conn, job_id, req_obj, verbose) def self.check_queue(conn, job_id, req_obj, verbose)
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}"
return [nil, nil]
end
res = conn.post 'request', req_obj.to_json res = conn.post 'request', req_obj.to_json
validate_queue_status_response(res.status, res.body, "Check queue request", verbose) status = validate_queue_status_response(res.status, res.body, "Check queue request", verbose)
unless res.body.empty? || !valid_json?(res.body) unless res.body.empty? || !valid_json?(res.body)
res_body = JSON.parse(res.body) res_body = JSON.parse(res.body)
return queue_info['queue_place'], res_body return res_body
end end
[queue_info['queue_place'], nil] res.body
end end
def self.snapshot(_verbose, _url, _hostname, _token) def self.snapshot(_verbose, _url, _hostname, _token)

View file

@ -22,7 +22,7 @@ class NonstandardPooler
status['reserved_hosts'] || [] status['reserved_hosts'] || []
end end
def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil) def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil, _continue = nil)
conn = Http.get_conn(verbose, url) conn = Http.get_conn(verbose, url)
conn.headers['X-AUTH-TOKEN'] = token if token conn.headers['X-AUTH-TOKEN'] = token if token

View file

@ -28,7 +28,7 @@ class Pooler
vms vms
end end
def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil) def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil, _continue = nil)
# NOTE: # NOTE:
# Developers can use `Utils.generate_os_hash` to # Developers can use `Utils.generate_os_hash` to
# generate the os_type param. # generate the os_type param.

View file

@ -77,10 +77,10 @@ class Service
@service_object.list_active verbose, url, token, user @service_object.list_active verbose, url, token, user
end end
def retrieve(verbose, os_types, use_token = true, ondemand = nil) def retrieve(verbose, os_types, use_token = true, ondemand = nil, continue = nil)
FloatyLogger.info 'Requesting a vm without a token...' unless use_token FloatyLogger.info 'Requesting a vm without a token...' unless use_token
token_value = use_token ? token : nil token_value = use_token ? token : nil
@service_object.retrieve verbose, os_types, token_value, url, user, @config, ondemand @service_object.retrieve verbose, os_types, token_value, url, user, @config, ondemand, continue
end end
def wait_for_request(verbose, requestid) def wait_for_request(verbose, requestid)

View file

@ -116,7 +116,7 @@ class Utils
output_target.puts "- [JobID:#{host_data['request']['job']['id']}] <#{host_data['state']}>" output_target.puts "- [JobID:#{host_data['request']['job']['id']}] <#{host_data['state']}>"
host_data['allocated_resources'].each do |allocated_resources, _i| host_data['allocated_resources'].each do |allocated_resources, _i|
if allocated_resources['engine'] == "vmpooler" && service.config["vmpooler_fallback"] if (allocated_resources['engine'] == "vmpooler" || allocated_resources['engine'] == 'ondemand') && service.config["vmpooler_fallback"]
vmpooler_service = service.clone vmpooler_service = service.clone
vmpooler_service.silent = true vmpooler_service.silent = true
vmpooler_service.maybe_use_vmpooler vmpooler_service.maybe_use_vmpooler