diff --git a/lib/vmfloaty.rb b/lib/vmfloaty.rb index d1c2df2..19e194a 100644 --- a/lib/vmfloaty.rb +++ b/lib/vmfloaty.rb @@ -87,6 +87,7 @@ class Vmfloaty c.option '--verbose', 'Enables verbose output' c.option '--service STRING', String, 'Configured pooler service name' c.option '--active', 'Prints information about active vms for a given token' + c.option '--json', 'Prints information as JSON' c.option '--token STRING', String, 'Token for pooler service' c.option '--url STRING', String, 'URL of pooler service' c.action do |args, options| @@ -100,10 +101,18 @@ class Vmfloaty running_vms = service.list_active(verbose) host = URI.parse(service.url).host if running_vms.empty? - puts "You have no running VMs on #{host}" + if options.json + puts {}.to_json + else + FloatyLogger.info "You have no running VMs on #{host}" + end else - puts "Your VMs on #{host}:" - Utils.pretty_print_hosts(verbose, service, running_vms) + if options.json + puts Utils.get_host_data(verbose, service, running_vms).to_json + else + puts "Your VMs on #{host}:" + Utils.pretty_print_hosts(verbose, service, running_vms) + end end else # list available vms from pooler @@ -200,6 +209,7 @@ class Vmfloaty c.option '--service STRING', String, 'Configured pooler service name' c.option '--all', 'Deletes all vms acquired by a token' c.option '-f', 'Does not prompt user when deleting all vms' + c.option '--json', 'Outputs hosts scheduled for deletion as JSON' c.option '--token STRING', String, 'Token for pooler service' c.option '--url STRING', String, 'URL of pooler service' c.action do |args, options| @@ -215,12 +225,18 @@ class Vmfloaty if delete_all running_vms = service.list_active(verbose) if running_vms.empty? - puts 'You have no running VMs.' + if options.json + puts {}.to_json + else + FloatyLogger.info "You have no running VMs." + end else - Utils.pretty_print_hosts(verbose, service, running_vms, true) - # Confirm deletion confirmed = true - confirmed = agree('Delete all these VMs? [y/N]') unless force + unless force + Utils.pretty_print_hosts(verbose, service, running_vms, true) + # Confirm deletion + confirmed = agree('Delete all these VMs? [y/N]') + end if confirmed response = service.delete(verbose, running_vms) response.each do |hostname, result| @@ -257,9 +273,15 @@ class Vmfloaty unless successes.empty? FloatyLogger.info unless failures.empty? - puts 'Scheduled the following VMs for deletion:' - successes.each do |hostname| - puts "- #{hostname}" + if options.json + puts successes.to_json + else + puts 'Scheduled the following VMs for deletion:' + output = '' + successes.each do |hostname| + output += "- #{hostname}\n" + end + puts output end end diff --git a/lib/vmfloaty/utils.rb b/lib/vmfloaty/utils.rb index 0c2328b..0940fa4 100644 --- a/lib/vmfloaty/utils.rb +++ b/lib/vmfloaty/utils.rb @@ -79,40 +79,62 @@ class Utils end def self.pretty_print_hosts(verbose, service, hostnames = [], print_to_stderr = false) + fetched_data = self.get_host_data(verbose, service, hostnames) + fetched_data.each do |hostname, host_data| + case service.type + when 'ABS' + # For ABS, 'hostname' variable is the jobID + 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 + when 'Pooler' + tag_pairs = [] + tag_pairs = host_data['tags'].map { |key, value| "#{key}: #{value}" } unless host_data['tags'].nil? + duration = "#{host_data['running']}/#{host_data['lifetime']} hours" + metadata = [host_data['template'], duration, *tag_pairs] + puts "- #{hostname}.#{host_data['domain']} (#{metadata.join(', ')})" + when 'NonstandardPooler' + line = "- #{host_data['fqdn']} (#{host_data['os_triple']}" + line += ", #{host_data['hours_left_on_reservation']}h remaining" + line += ", reason: #{host_data['reserved_for_reason']}" unless host_data['reserved_for_reason'].empty? + line += ')' + puts line + else + raise "Invalid service type #{service.type}" + end + end + end + + def self.get_host_data(verbose, service, hostnames = []) + result = {} hostnames = [hostnames] unless hostnames.is_a? Array hostnames.each do |hostname| begin response = service.query(verbose, hostname) 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? - duration = "#{host_data['running']}/#{host_data['lifetime']} hours" - metadata = [host_data['template'], duration, *tag_pairs] - puts "- #{hostname}.#{host_data['domain']} (#{metadata.join(', ')})" - when 'NonstandardPooler' - line = "- #{host_data['fqdn']} (#{host_data['os_triple']}" - line += ", #{host_data['hours_left_on_reservation']}h remaining" - line += ", reason: #{host_data['reserved_for_reason']}" unless host_data['reserved_for_reason'].empty? - line += ')' - puts line + if block_given? + yield host_data result else - raise "Invalid service type #{service.type}" + case service.type + when 'ABS' + # For ABS, 'hostname' variable is the jobID + if host_data['state'] == 'allocated' || host_data['state'] == 'filled' + result[hostname] = host_data + end + when 'Pooler' + result[hostname] = host_data + when 'NonstandardPooler' + result[hostname] = host_data + else + raise "Invalid service type #{service.type}" + end end rescue StandardError => e FloatyLogger.error("Something went wrong while trying to gather information on #{hostname}:") FloatyLogger.error(e) end end + result end def self.pretty_print_status(verbose, service)