diff --git a/lib/vmfloaty.rb b/lib/vmfloaty.rb index 7d015f3..0e1bad5 100644 --- a/lib/vmfloaty.rb +++ b/lib/vmfloaty.rb @@ -39,8 +39,13 @@ class Vmfloaty c.option '--force', 'Forces vmfloaty to get requested vms' 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 '--continue STRING', String, 'resume polling ABS for job_id, for use when the cli was interrupted' + c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)' c.action do |args, options| verbose = options.verbose || config['verbose'] + if options.loglevel + FloatyLogger.setlevel = options.loglevel + end service = Service.new(options, config) use_token = !options.notoken force = options.force @@ -52,6 +57,11 @@ class Vmfloaty 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 large_pool_requests = os_types.select { |_, v| v > max_pool_request } if !large_pool_requests.empty? && !force @@ -60,12 +70,7 @@ class Vmfloaty exit 1 end - 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 - - response = service.retrieve(verbose, os_types, use_token, options.ondemand) + response = service.retrieve(verbose, os_types, use_token, options.ondemand, options.continue) request_id = response['request_id'] if options.ondemand response = service.wait_for_request(verbose, request_id) if options.ondemand @@ -92,8 +97,12 @@ class Vmfloaty c.option '--token STRING', String, 'Token for pooler service' c.option '--url STRING', String, 'URL of pooler service' c.option '--user STRING', String, 'User to authenticate with' + c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)' c.action do |args, options| verbose = options.verbose || config['verbose'] + if options.loglevel + FloatyLogger.setlevel = options.loglevel + end service = Service.new(options, config) filter = args[0] @@ -229,8 +238,13 @@ class Vmfloaty c.option '--token STRING', String, 'Token for pooler service' c.option '--url STRING', String, 'URL of pooler service' c.option '--user STRING', String, 'User to authenticate with' + c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)' c.action do |args, options| verbose = options.verbose || config['verbose'] + if options.loglevel + FloatyLogger.setlevel = options.loglevel + end + service = Service.new(options, config) hostnames = args[0] delete_all = options.all @@ -374,8 +388,12 @@ class Vmfloaty c.option '--service STRING', String, 'Configured pooler service name' c.option '--url STRING', String, 'URL of pooler service' c.option '--json', 'Prints status in JSON format' + c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)' c.action do |_, options| verbose = options.verbose || config['verbose'] + if options.loglevel + FloatyLogger.setlevel = options.loglevel + end service = Service.new(options, config) if options.json pp service.status(verbose) diff --git a/lib/vmfloaty/abs.rb b/lib/vmfloaty/abs.rb index 873a0e0..08027b7 100644 --- a/lib/vmfloaty/abs.rb +++ b/lib/vmfloaty/abs.rb @@ -228,7 +228,7 @@ class ABS end # 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: # @@ -248,7 +248,12 @@ class ABS conn = Http.get_conn(verbose, supported_abs_url(url)) conn.headers['X-AUTH-TOKEN'] = token if token - saved_job_id = user + "-" + DateTime.now.strftime('%Q') + if continue.nil? + saved_job_id = user + "-" + DateTime.now.strftime('%Q') + else + saved_job_id = continue + end + req_obj = { :resources => os_types, :job => { @@ -281,26 +286,28 @@ class ABS # 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." + 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 - validate_queue_status_response(res.status, res.body, "Initial request", verbose) + status = validate_queue_status_response(res.status, res.body, "Initial request", verbose) begin (1..retries).each do |i| - queue_place, res_body = check_queue(conn, saved_job_id, req_obj, verbose) - return translated(res_body, saved_job_id) if res_body + res_body = check_queue(conn, saved_job_id, req_obj, verbose) + 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 = 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) end 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 end nil @@ -325,22 +332,13 @@ class ABS end 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 - 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) res_body = JSON.parse(res.body) - return queue_info['queue_place'], res_body + return res_body end - [queue_info['queue_place'], nil] + res.body end def self.snapshot(_verbose, _url, _hostname, _token) diff --git a/lib/vmfloaty/logger.rb b/lib/vmfloaty/logger.rb index d669d78..88bf5f1 100644 --- a/lib/vmfloaty/logger.rb +++ b/lib/vmfloaty/logger.rb @@ -17,6 +17,19 @@ class FloatyLogger < ::Logger FloatyLogger.logger.error msg end + def self.setlevel=(level) + level = level.downcase + if level == "debug" + self.logger.level = ::Logger::DEBUG + elsif level == "info" + self.logger.level = ::Logger::INFO + elsif level == "error" + self.logger.level = ::Logger::ERROR + else + error("set loglevel to debug, info or error") + end + end + def initialize super(STDERR) self.level = ::Logger::INFO diff --git a/lib/vmfloaty/nonstandard_pooler.rb b/lib/vmfloaty/nonstandard_pooler.rb index 5d755a9..0746034 100644 --- a/lib/vmfloaty/nonstandard_pooler.rb +++ b/lib/vmfloaty/nonstandard_pooler.rb @@ -22,7 +22,7 @@ class NonstandardPooler status['reserved_hosts'] || [] 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.headers['X-AUTH-TOKEN'] = token if token diff --git a/lib/vmfloaty/pooler.rb b/lib/vmfloaty/pooler.rb index fb811cf..5b5f65c 100644 --- a/lib/vmfloaty/pooler.rb +++ b/lib/vmfloaty/pooler.rb @@ -28,7 +28,7 @@ class Pooler vms 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: # Developers can use `Utils.generate_os_hash` to # generate the os_type param. diff --git a/lib/vmfloaty/service.rb b/lib/vmfloaty/service.rb index ee41648..196ac4c 100644 --- a/lib/vmfloaty/service.rb +++ b/lib/vmfloaty/service.rb @@ -77,10 +77,10 @@ class Service @service_object.list_active verbose, url, token, user 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 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 def wait_for_request(verbose, requestid) diff --git a/lib/vmfloaty/utils.rb b/lib/vmfloaty/utils.rb index e3408f3..a356ec3 100644 --- a/lib/vmfloaty/utils.rb +++ b/lib/vmfloaty/utils.rb @@ -116,7 +116,7 @@ class Utils output_target.puts "- [JobID:#{host_data['request']['job']['id']}] <#{host_data['state']}>" 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.silent = true vmpooler_service.maybe_use_vmpooler