diff --git a/lib/vmfloaty/abs.rb b/lib/vmfloaty/abs.rb index a826ed6..381d95b 100644 --- a/lib/vmfloaty/abs.rb +++ b/lib/vmfloaty/abs.rb @@ -7,8 +7,7 @@ require 'json' class ABS # List active VMs in ABS - # - # + # This is what a job request looks like: # { # "state":"filled", # "last_processed":"2019-10-31 20:59:33 +0000", @@ -37,33 +36,83 @@ class ABS # } # } # + + @@active_hostnames = Hash.new + def self.list_active(verbose, url, _token, user) + all_jobs = Array.new() + @@active_hostnames = Hash.new + + self.get_active_requests(verbose, url, user).each do |reqHash| + all_jobs.push(reqHash['request']['job']['id']) + @@active_hostnames[reqHash['request']['job']['id']] = reqHash + end + + all_jobs + end + + def self.get_active_requests verbose, url, user conn = Http.get_conn(verbose, url) res = conn.get 'status/queue' requests = JSON.parse(res.body) + retVal = [] requests.each do |req| reqHash = JSON.parse(req) next unless user == reqHash['request']['job']['user'] - - puts '------------------------------------' - puts "State: #{reqHash['state']}" - puts "Job ID: #{reqHash['request']['job']['id']}" - reqHash['request']['resources'].each do |vm_template, i| - puts "--VMRequest: #{vm_template}: #{i}" - end - if reqHash['state'] == 'allocated' || reqHash['state'] == 'filled' - reqHash['allocated_resources'].each do |vm_name, i| - puts "----VM: #{vm_name}: #{i}" - end - end - puts "User: #{reqHash['request']['job']['user']}" - puts '' + retVal.push(reqHash) end - sleep(100) + retVal end + def self.all_job_resources_accounted_for(allocated_resources, hosts) + allocated_host_list = allocated_resources.map {|ar| ar["hostname"] } + return (allocated_host_list-hosts).empty? + end + + def self.delete(verbose, url, hosts, token, user) + # In ABS terms, this is a "returned" host. + conn = Http.get_conn(verbose, url) + conn.headers['X-AUTH-TOKEN'] = token if token + + puts "Trying to delete hosts #{hosts}" if verbose + requests = self.get_active_requests(verbose, url, user) + + jobs_to_delete = [] + + requests.each do |reqHash| + if reqHash['state'] == 'allocated' || reqHash['state'] == 'filled' + reqHash['allocated_resources'].each do |vm_name, i| + if hosts.include? vm_name["hostname"] + if (all_job_resources_accounted_for(job['allocated_resources'], hosts)) + jobs_to_delete.push(reqHash) + else + puts "Can't delete #{job_id}: #{hosts} does not include all of #{job['allocated_resources']}" + end + end + end + end + end + + response_body = {} + + jobs_to_delete.each do |job| + reqObj = { + 'job_id': job['request']['job']['id'], + 'hosts': job['allocated_resources'], + } + + puts "Deleting #{reqObj}" if verbose + + res = conn.post 'api/v2/return', reqObj.to_json + response_body[job_id] = res_body + end + + return response_body + end + + # List available VMs in ABS def self.list(verbose, url, os_filter = nil) conn = Http.get_conn(verbose, url) @@ -96,7 +145,7 @@ class ABS # Retrieve an OS from ABS. def self.retrieve(verbose, os_types, token, url, user) # - # Contents of post must be:j + # Contents of post must be like: # # { # "resources": { @@ -179,6 +228,10 @@ class ABS [queue_info['queue_place'], nil] end + def self.snapshot(verbose, url, hostname, token) + puts "Can't snapshot with ABS, use '--service vmpooler' (even for vms checked out with ABS)" + end + def self.status(verbose, url) conn = Http.get_conn(verbose, url) @@ -194,6 +247,8 @@ class ABS end def self.query(verbose, url, hostname) + return @@active_hostnames if @@active_hostnames + puts "For vmpooler/snapshot information, use '--service vmpooler' (even for vms checked out with ABS)" conn = Http.get_conn(verbose, url) res = conn.get "host/#{hostname}" diff --git a/lib/vmfloaty/pooler.rb b/lib/vmfloaty/pooler.rb index 69de7da..354b8a9 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) + def self.retrieve(verbose, os_type, token, url, user) # 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 6d606f1..951db9c 100644 --- a/lib/vmfloaty/service.rb +++ b/lib/vmfloaty/service.rb @@ -112,7 +112,7 @@ class Service end def delete(verbose, hosts) - @service_object.delete verbose, url, hosts, token + @service_object.delete verbose, url, hosts, token, user end def status(verbose) diff --git a/lib/vmfloaty/utils.rb b/lib/vmfloaty/utils.rb index bd83f7e..eb3464a 100644 --- a/lib/vmfloaty/utils.rb +++ b/lib/vmfloaty/utils.rb @@ -85,6 +85,13 @@ class Utils host_data = response[hostname] case service.type + when 'ABS' + # For ABS, 'hostname' variable is the jobID + if host_data['state'] == 'allocated' || host_data['state'] == 'filled' + host_data['allocated_resources'].each do |vm_name, i| + puts "- [JobID:#{host_data['request']['job']['id']}] #{vm_name["hostname"]} (#{vm_name["type"]}) <#{host_data['state']}>" + end + end when 'Pooler' tag_pairs = [] tag_pairs = host_data['tags'].map { |key, value| "#{key}: #{value}" } unless host_data['tags'].nil? diff --git a/spec/vmfloaty/abs_spec.rb b/spec/vmfloaty/abs_spec.rb index 3939e61..c59e14c 100644 --- a/spec/vmfloaty/abs_spec.rb +++ b/spec/vmfloaty/abs_spec.rb @@ -34,5 +34,29 @@ describe ABS do vmpooler_formatted_compare.delete('ok') expect(vmpooler_formatted_response).to eq(vmpooler_formatted_compare) end + + it 'won\'t delete a job if not all vms are listed' do + hosts = ["host1"] + allocated_resources = [ + { + "hostname" => "host1" + }, + { + "hostname" => "host2" + } + ] + expect(ABS.all_job_resources_accounted_for(allocated_resources, hosts)).to eq(false) + + hosts = ["host1", "host2"] + allocated_resources = [ + { + "hostname" => "host1" + }, + { + "hostname" => "host2" + } + ] + expect(ABS.all_job_resources_accounted_for(allocated_resources, hosts)).to eq(true) + end end end