mirror of
https://github.com/puppetlabs/vmfloaty.git
synced 2026-01-26 13:28:42 -05:00
Merge pull request #131 from puppetlabs/DIO-908
(DIO-908) Floaty can now report the status of ABS requests
This commit is contained in:
commit
796cd8e858
7 changed files with 60 additions and 31 deletions
|
|
@ -39,8 +39,13 @@ 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.option '--loglevel STRING', String, 'the log level to use (debug, info, error)'
|
||||||
c.action do |args, options|
|
c.action do |args, options|
|
||||||
verbose = options.verbose || config['verbose']
|
verbose = options.verbose || config['verbose']
|
||||||
|
if options.loglevel
|
||||||
|
FloatyLogger.setlevel = options.loglevel
|
||||||
|
end
|
||||||
service = Service.new(options, config)
|
service = Service.new(options, config)
|
||||||
use_token = !options.notoken
|
use_token = !options.notoken
|
||||||
force = options.force
|
force = options.force
|
||||||
|
|
@ -52,6 +57,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 +70,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
|
||||||
|
|
||||||
|
|
@ -92,8 +97,12 @@ class Vmfloaty
|
||||||
c.option '--token STRING', String, 'Token for pooler service'
|
c.option '--token STRING', String, 'Token for pooler service'
|
||||||
c.option '--url STRING', String, 'URL of pooler service'
|
c.option '--url STRING', String, 'URL of pooler service'
|
||||||
c.option '--user STRING', String, 'User to authenticate with'
|
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|
|
c.action do |args, options|
|
||||||
verbose = options.verbose || config['verbose']
|
verbose = options.verbose || config['verbose']
|
||||||
|
if options.loglevel
|
||||||
|
FloatyLogger.setlevel = options.loglevel
|
||||||
|
end
|
||||||
|
|
||||||
service = Service.new(options, config)
|
service = Service.new(options, config)
|
||||||
filter = args[0]
|
filter = args[0]
|
||||||
|
|
@ -229,8 +238,13 @@ class Vmfloaty
|
||||||
c.option '--token STRING', String, 'Token for pooler service'
|
c.option '--token STRING', String, 'Token for pooler service'
|
||||||
c.option '--url STRING', String, 'URL of pooler service'
|
c.option '--url STRING', String, 'URL of pooler service'
|
||||||
c.option '--user STRING', String, 'User to authenticate with'
|
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|
|
c.action do |args, options|
|
||||||
verbose = options.verbose || config['verbose']
|
verbose = options.verbose || config['verbose']
|
||||||
|
if options.loglevel
|
||||||
|
FloatyLogger.setlevel = options.loglevel
|
||||||
|
end
|
||||||
|
|
||||||
service = Service.new(options, config)
|
service = Service.new(options, config)
|
||||||
hostnames = args[0]
|
hostnames = args[0]
|
||||||
delete_all = options.all
|
delete_all = options.all
|
||||||
|
|
@ -374,8 +388,12 @@ class Vmfloaty
|
||||||
c.option '--service STRING', String, 'Configured pooler service name'
|
c.option '--service STRING', String, 'Configured pooler service name'
|
||||||
c.option '--url STRING', String, 'URL of pooler service'
|
c.option '--url STRING', String, 'URL of pooler service'
|
||||||
c.option '--json', 'Prints status in JSON format'
|
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|
|
c.action do |_, options|
|
||||||
verbose = options.verbose || config['verbose']
|
verbose = options.verbose || config['verbose']
|
||||||
|
if options.loglevel
|
||||||
|
FloatyLogger.setlevel = options.loglevel
|
||||||
|
end
|
||||||
service = Service.new(options, config)
|
service = Service.new(options, config)
|
||||||
if options.json
|
if options.json
|
||||||
pp service.status(verbose)
|
pp service.status(verbose)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
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 = {
|
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)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,19 @@ class FloatyLogger < ::Logger
|
||||||
FloatyLogger.logger.error msg
|
FloatyLogger.logger.error msg
|
||||||
end
|
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
|
def initialize
|
||||||
super(STDERR)
|
super(STDERR)
|
||||||
self.level = ::Logger::INFO
|
self.level = ::Logger::INFO
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue