vmfloaty 1.0.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4cf673c0a3e005fc4ef5102d232206f3105215de4f19cd76725de335b62937fd
4
- data.tar.gz: e4791593e75d31d42a8f05cfb28b3655e42218ac1a7191ae1c8391ccdad5133b
3
+ metadata.gz: 7dde0d683f0fd9ba231b9441473e3b501fc45979de87256403809c68e03c1b43
4
+ data.tar.gz: 79e88b4ff40d432fcea114b82b2cd8ef952d74e8b4bb6a3bcf047be345d54be6
5
5
  SHA512:
6
- metadata.gz: b22ad1332f3a663407a6ce964525606938134925e0b91ccd151a8f9a4abc265cab53cddd9509ce92555abb357dc213f2beef50a02ea72eb501db31c9e3936983
7
- data.tar.gz: 8436c38cc6a99b76c4e65da0dfa653edbbdbe9b7fcefb9607942983cd24014c40ab14f556b06e7d6a449dc57f84740e09df2668e15129cdb5dccbb3b6e746eff
6
+ metadata.gz: b6c470d8d4c369f5e39b8a42d031ae4378165278e44bd00cacfbdfc7dc7aabafdf8a8bb1291fe33ab081be7c1c45195e10567708e45a0c34d2ff40340338b8e3
7
+ data.tar.gz: 2f7305e4f363dbb71ae45d1d14a38ddbde7289e6c5d0d58c72faef01c6840ae39ad76eacde81b638387dc12fcdcf446ad5225f0dad8d4f87c346ba57a8e587a9
@@ -2,29 +2,37 @@
2
2
 
3
3
  _vmfloaty()
4
4
  {
5
- local cur prev subcommands template_subcommands hostname_subcommands
5
+ local cur prev commands template_arg_commands hostname_arg_commands service_subcommands
6
+
6
7
  COMPREPLY=()
7
8
  cur="${COMP_WORDS[COMP_CWORD]}"
8
9
  prev="${COMP_WORDS[COMP_CWORD-1]}"
9
10
 
10
- subcommands="delete get help list modify query revert service snapshot ssh status summary token"
11
- template_subcommands="get ssh"
12
- hostname_subcommands="delete modify query revert snapshot"
11
+ commands="delete get help list modify query revert service snapshot ssh status summary token"
12
+ template_arg_commands="get ssh"
13
+ hostname_arg_commands="delete modify query revert snapshot"
14
+ service_subcommands="types examples"
13
15
 
14
16
  if [[ $cur == -* ]] ; then
15
17
  # TODO: option completion
16
18
  COMPREPLY=()
17
- elif [[ $template_subcommands =~ (^| )$prev($| ) ]] ; then
19
+ elif [[ $template_arg_commands =~ (^| )$prev($| ) ]] ; then
18
20
  if [[ -z "$_vmfloaty_avail_templates" ]] ; then
21
+ # TODO: need a --hostnameonly equivalent here because the section headers of
22
+ # `floaty list` are adding some spurious entries (including files in current
23
+ # directory because part of the headers is `**` which is getting expanded)
19
24
  _vmfloaty_avail_templates=$(floaty list 2>/dev/null)
20
25
  fi
21
26
 
22
27
  COMPREPLY=( $(compgen -W "${_vmfloaty_avail_templates}" -- "${cur}") )
23
- elif [[ $hostname_subcommands =~ (^| )$prev($| ) ]] ; then
28
+ elif [[ $hostname_arg_commands =~ (^| )$prev($| ) ]] ; then
24
29
  _vmfloaty_active_hostnames=$(floaty list --active --hostnameonly 2>/dev/null)
25
30
  COMPREPLY=( $(compgen -W "${_vmfloaty_active_hostnames}" -- "${cur}") )
26
- else
27
- COMPREPLY=( $(compgen -W "${subcommands}" -- "${cur}") )
31
+ elif [[ "service" == $prev ]] ; then
32
+ COMPREPLY=( $(compgen -W "${service_subcommands}" -- "${cur}") )
33
+ elif [[ $1 == $prev ]] ; then
34
+ # only show top level commands we are at root
35
+ COMPREPLY=( $(compgen -W "${commands}" -- "${cur}") )
28
36
  fi
29
37
  }
30
38
  complete -F _vmfloaty floaty
@@ -1,26 +1,32 @@
1
1
  _floaty()
2
2
  {
3
- local line subcommands template_subcommands hostname_subcommands
3
+ local line commands template_arg_commands hostname_arg_commands service_subcommands
4
4
 
5
- subcommands="delete get help list modify query revert snapshot ssh status summary token"
5
+ commands="delete get help list modify query revert service snapshot ssh status summary token"
6
6
 
7
- template_subcommands=("get" "ssh")
8
- hostname_subcommands=("delete" "modify" "query" "revert" "snapshot")
7
+ template_arg_commands=("get" "ssh")
8
+ hostname_arg_commands=("delete" "modify" "query" "revert" "snapshot")
9
+ service_subcommands=("types" "examples")
9
10
 
10
11
  _arguments -C \
11
- "1: :(${subcommands})" \
12
+ "1: :(${commands})" \
12
13
  "*::arg:->args"
13
14
 
14
- if ((template_subcommands[(Ie)$line[1]])); then
15
+ if ((template_arg_commands[(Ie)$line[1]])); then
15
16
  _floaty_template_sub
16
- elif ((hostname_subcommands[(Ie)$line[1]])); then
17
+ elif ((hostname_arg_commands[(Ie)$line[1]])); then
17
18
  _floaty_hostname_sub
19
+ elif [[ "service" == $line[1] ]]; then
20
+ _arguments "1: :(${service_subcommands})"
18
21
  fi
19
22
  }
20
23
 
21
24
  _floaty_template_sub()
22
25
  {
23
26
  if [[ -z "$_vmfloaty_avail_templates" ]] ; then
27
+ # TODO: need a --hostnameonly equivalent here because the section headers of
28
+ # `floaty list` are adding some spurious entries (including files in current
29
+ # directory because part of the headers is `**` which is getting expanded)
24
30
  _vmfloaty_avail_templates=$(floaty list 2>/dev/null)
25
31
  fi
26
32
 
data/lib/vmfloaty.rb CHANGED
@@ -20,7 +20,8 @@ class Vmfloaty
20
20
 
21
21
  def run # rubocop:disable Metrics/AbcSize
22
22
  program :version, Vmfloaty::VERSION
23
- program :description, "A CLI helper tool for Puppet's vmpooler to help you stay afloat.\n\nConfiguration may be placed in a ~/.vmfloaty.yml file."
23
+ program :description,
24
+ "A CLI helper tool for Puppet's vmpooler to help you stay afloat.\n\nConfiguration may be placed in a ~/.vmfloaty.yml file."
24
25
 
25
26
  config = Conf.read_config
26
27
 
@@ -39,8 +40,11 @@ class Vmfloaty
39
40
  c.option '--force', 'Forces vmfloaty to get requested vms'
40
41
  c.option '--json', 'Prints retrieved vms in JSON format'
41
42
  c.option '--ondemand', 'Requested vms are provisioned upon receival of the request, tracked by a request ID'
43
+ c.option '--continue STRING', String, 'resume polling ABS for job_id, for use when the cli was interrupted'
44
+ c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)'
42
45
  c.action do |args, options|
43
46
  verbose = options.verbose || config['verbose']
47
+ FloatyLogger.setlevel = options.loglevel if options.loglevel
44
48
  service = Service.new(options, config)
45
49
  use_token = !options.notoken
46
50
  force = options.force
@@ -52,6 +56,11 @@ class Vmfloaty
52
56
 
53
57
  os_types = Utils.generate_os_hash(args)
54
58
 
59
+ if os_types.empty?
60
+ FloatyLogger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
61
+ exit 1
62
+ end
63
+
55
64
  max_pool_request = 5
56
65
  large_pool_requests = os_types.select { |_, v| v > max_pool_request }
57
66
  if !large_pool_requests.empty? && !force
@@ -60,12 +69,7 @@ class Vmfloaty
60
69
  exit 1
61
70
  end
62
71
 
63
- if os_types.empty?
64
- FloatyLogger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
65
- exit 1
66
- end
67
-
68
- response = service.retrieve(verbose, os_types, use_token, options.ondemand)
72
+ response = service.retrieve(verbose, os_types, use_token, options.ondemand, options.continue)
69
73
  request_id = response['request_id'] if options.ondemand
70
74
  response = service.wait_for_request(verbose, request_id) if options.ondemand
71
75
 
@@ -92,20 +96,22 @@ class Vmfloaty
92
96
  c.option '--token STRING', String, 'Token for pooler service'
93
97
  c.option '--url STRING', String, 'URL of pooler service'
94
98
  c.option '--user STRING', String, 'User to authenticate with'
99
+ c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)'
95
100
  c.action do |args, options|
96
101
  verbose = options.verbose || config['verbose']
102
+ FloatyLogger.setlevel = options.loglevel if options.loglevel
97
103
 
98
104
  service = Service.new(options, config)
99
105
  filter = args[0]
100
106
 
101
107
  if options.active
102
108
  # list active vms
103
- if service.type == "ABS"
104
- # this is actually job_ids
105
- running_vms = service.list_active_job_ids(verbose, service.url, service.user)
106
- else
107
- running_vms = service.list_active(verbose)
108
- end
109
+ running_vms = if service.type == 'ABS'
110
+ # this is actually job_ids
111
+ service.list_active_job_ids(verbose, service.url, service.user)
112
+ else
113
+ service.list_active(verbose)
114
+ end
109
115
  host = URI.parse(service.url).host
110
116
  if running_vms.empty?
111
117
  if options.json
@@ -113,17 +119,15 @@ class Vmfloaty
113
119
  else
114
120
  FloatyLogger.info "You have no running VMs on #{host}"
115
121
  end
116
- else
117
- if options.json
118
- puts Utils.get_host_data(verbose, service, running_vms).to_json
119
- elsif options.hostnameonly
120
- Utils.get_host_data(verbose, service, running_vms).each do |hostname, host_data|
121
- Utils.print_fqdn_for_host(service, hostname, host_data)
122
- end
123
- else
124
- puts "Your VMs on #{host}:"
125
- Utils.pretty_print_hosts(verbose, service, running_vms)
122
+ elsif options.json
123
+ puts Utils.get_host_data(verbose, service, running_vms).to_json
124
+ elsif options.hostnameonly
125
+ Utils.get_host_data(verbose, service, running_vms).each do |hostname, host_data|
126
+ Utils.print_fqdn_for_host(service, hostname, host_data)
126
127
  end
128
+ else
129
+ puts "Your VMs on #{host}:"
130
+ Utils.pretty_print_hosts(verbose, service, running_vms)
127
131
  end
128
132
  else
129
133
  # list available vms from pooler
@@ -155,7 +159,8 @@ class Vmfloaty
155
159
  c.syntax = 'floaty modify hostname [options]'
156
160
  c.summary = 'Modify a VM\'s tags, time to live, disk space, or reservation reason'
157
161
  c.description = 'This command makes modifications to the virtual machines state in the pooler service. You can either append tags to the vm, increase how long it stays active for, or increase the amount of disk space.'
158
- c.example 'Modifies myhost1 to have a TTL of 12 hours and adds a custom tag', 'floaty modify myhost1 --lifetime 12 --url https://myurl --token mytokenstring --tags \'{"tag":"myvalue"}\''
162
+ c.example 'Modifies myhost1 to have a TTL of 12 hours and adds a custom tag',
163
+ 'floaty modify myhost1 --lifetime 12 --url https://myurl --token mytokenstring --tags \'{"tag":"myvalue"}\''
159
164
  c.option '--verbose', 'Enables verbose output'
160
165
  c.option '--service STRING', String, 'Configured pooler service name'
161
166
  c.option '--url STRING', String, 'URL of pooler service'
@@ -176,18 +181,18 @@ class Vmfloaty
176
181
  exit 1
177
182
  end
178
183
  running_vms =
179
- if modify_all
180
- service.list_active(verbose)
181
- else
182
- hostname.split(',')
183
- end
184
+ if modify_all
185
+ service.list_active(verbose)
186
+ else
187
+ hostname.split(',')
188
+ end
184
189
 
185
190
  tags = options.tags ? JSON.parse(options.tags) : nil
186
191
  modify_hash = {
187
- :lifetime => options.lifetime,
188
- :disk => options.disk,
189
- :tags => tags,
190
- :reason => options.reason,
192
+ lifetime: options.lifetime,
193
+ disk: options.disk,
194
+ tags: tags,
195
+ reason: options.reason
191
196
  }
192
197
  modify_hash.delete_if { |_, value| value.nil? }
193
198
 
@@ -195,12 +200,10 @@ class Vmfloaty
195
200
  ok = true
196
201
  modified_hash = {}
197
202
  running_vms.each do |vm|
198
- begin
199
- modified_hash[vm] = service.modify(verbose, vm, modify_hash)
200
- rescue ModifyError => e
201
- FloatyLogger.error e
202
- ok = false
203
- end
203
+ modified_hash[vm] = service.modify(verbose, vm, modify_hash)
204
+ rescue ModifyError => e
205
+ FloatyLogger.error e
206
+ ok = false
204
207
  end
205
208
  if ok
206
209
  if modify_all
@@ -229,8 +232,11 @@ class Vmfloaty
229
232
  c.option '--token STRING', String, 'Token for pooler service'
230
233
  c.option '--url STRING', String, 'URL of pooler service'
231
234
  c.option '--user STRING', String, 'User to authenticate with'
235
+ c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)'
232
236
  c.action do |args, options|
233
237
  verbose = options.verbose || config['verbose']
238
+ FloatyLogger.setlevel = options.loglevel if options.loglevel
239
+
234
240
  service = Service.new(options, config)
235
241
  hostnames = args[0]
236
242
  delete_all = options.all
@@ -240,17 +246,17 @@ class Vmfloaty
240
246
  successes = []
241
247
 
242
248
  if delete_all
243
- if service.type == "ABS"
244
- # this is actually job_ids
245
- running_vms = service.list_active_job_ids(verbose, service.url, service.user)
246
- else
247
- running_vms = service.list_active(verbose)
248
- end
249
+ running_vms = if service.type == 'ABS'
250
+ # this is actually job_ids
251
+ service.list_active_job_ids(verbose, service.url, service.user)
252
+ else
253
+ service.list_active(verbose)
254
+ end
249
255
  if running_vms.empty?
250
256
  if options.json
251
257
  puts {}.to_json
252
258
  else
253
- FloatyLogger.info "You have no running VMs."
259
+ FloatyLogger.info 'You have no running VMs.'
254
260
  end
255
261
  else
256
262
  confirmed = true
@@ -314,7 +320,8 @@ class Vmfloaty
314
320
  c.syntax = 'floaty snapshot hostname [options]'
315
321
  c.summary = 'Takes a snapshot of a given vm'
316
322
  c.description = 'Will request a snapshot be taken of the given hostname in the pooler service. This command is known to take a while depending on how much load is on the pooler service.'
317
- c.example 'Takes a snapshot for a given host', 'floaty snapshot myvm.example.com --url http://vmpooler.example.com --token a9znth9dn01t416hrguu56ze37t790bl'
323
+ c.example 'Takes a snapshot for a given host',
324
+ 'floaty snapshot myvm.example.com --url http://vmpooler.example.com --token a9znth9dn01t416hrguu56ze37t790bl'
318
325
  c.option '--verbose', 'Enables verbose output'
319
326
  c.option '--service STRING', String, 'Configured pooler service name'
320
327
  c.option '--url STRING', String, 'URL of pooler service'
@@ -340,7 +347,8 @@ class Vmfloaty
340
347
  c.syntax = 'floaty revert hostname snapshot [options]'
341
348
  c.summary = 'Reverts a vm to a specified snapshot'
342
349
  c.description = 'Given a snapshot SHA, vmfloaty will request a revert to the pooler service to go back to a previous snapshot.'
343
- c.example 'Reverts to a snapshot for a given host', 'floaty revert myvm.example.com n4eb4kdtp7rwv4x158366vd9jhac8btq --url http://vmpooler.example.com --token a9znth9dn01t416hrguu56ze37t790bl'
350
+ c.example 'Reverts to a snapshot for a given host',
351
+ 'floaty revert myvm.example.com n4eb4kdtp7rwv4x158366vd9jhac8btq --url http://vmpooler.example.com --token a9znth9dn01t416hrguu56ze37t790bl'
344
352
  c.option '--verbose', 'Enables verbose output'
345
353
  c.option '--service STRING', String, 'Configured pooler service name'
346
354
  c.option '--url STRING', String, 'URL of pooler service'
@@ -352,7 +360,9 @@ class Vmfloaty
352
360
  hostname = args[0]
353
361
  snapshot_sha = args[1] || options.snapshot
354
362
 
355
- FloatyLogger.info "Two snapshot arguments were given....using snapshot #{snapshot_sha}" if args[1] && options.snapshot
363
+ if args[1] && options.snapshot
364
+ FloatyLogger.info "Two snapshot arguments were given....using snapshot #{snapshot_sha}"
365
+ end
356
366
 
357
367
  begin
358
368
  revert_req = service.revert(verbose, hostname, snapshot_sha)
@@ -374,8 +384,10 @@ class Vmfloaty
374
384
  c.option '--service STRING', String, 'Configured pooler service name'
375
385
  c.option '--url STRING', String, 'URL of pooler service'
376
386
  c.option '--json', 'Prints status in JSON format'
387
+ c.option '--loglevel STRING', String, 'the log level to use (debug, info, error)'
377
388
  c.action do |_, options|
378
389
  verbose = options.verbose || config['verbose']
390
+ FloatyLogger.setlevel = options.loglevel if options.loglevel
379
391
  service = Service.new(options, config)
380
392
  if options.json
381
393
  pp service.status(verbose)
@@ -509,7 +521,7 @@ class Vmfloaty
509
521
  c.example 'Print a list of the valid service types', 'floaty service types'
510
522
  c.example 'Print a sample config file with multiple services', 'floaty service examples'
511
523
  c.example 'list vms from the service named "nspooler-prod"', 'floaty list --service nspooler-prod'
512
- c.action do |args, options|
524
+ c.action do |args, _options|
513
525
  action = args.first
514
526
 
515
527
  example_config = Utils.strip_heredoc(<<-CONFIG)
data/lib/vmfloaty/abs.rb CHANGED
@@ -53,10 +53,10 @@ class ABS
53
53
  def self.list_active(verbose, url, _token, user)
54
54
  hosts = []
55
55
  get_active_requests(verbose, url, user).each do |req_hash|
56
- if req_hash.key?('allocated_resources')
57
- req_hash['allocated_resources'].each do |onehost|
58
- hosts.push(onehost['hostname'])
59
- end
56
+ next unless req_hash.key?('allocated_resources')
57
+
58
+ req_hash['allocated_resources'].each do |onehost|
59
+ hosts.push(onehost['hostname'])
60
60
  end
61
61
  end
62
62
 
@@ -64,7 +64,7 @@ class ABS
64
64
  end
65
65
 
66
66
  def self.get_active_requests(verbose, url, user)
67
- conn = Http.get_conn(verbose, url)
67
+ conn = Http.get_conn(verbose, supported_abs_url(url))
68
68
  res = conn.get 'status/queue'
69
69
  if valid_json?(res.body)
70
70
  requests = JSON.parse(res.body)
@@ -105,7 +105,7 @@ class ABS
105
105
 
106
106
  def self.delete(verbose, url, hosts, token, user)
107
107
  # In ABS terms, this is a "returned" host.
108
- conn = Http.get_conn(verbose, url)
108
+ conn = Http.get_conn(verbose, supported_abs_url(url))
109
109
  conn.headers['X-AUTH-TOKEN'] = token if token
110
110
 
111
111
  FloatyLogger.info "Trying to delete hosts #{hosts}" if verbose
@@ -116,7 +116,7 @@ class ABS
116
116
  ret_status = {}
117
117
  hosts.each do |host|
118
118
  ret_status[host] = {
119
- 'ok' => false,
119
+ 'ok' => false
120
120
  }
121
121
  end
122
122
 
@@ -132,7 +132,7 @@ class ABS
132
132
  if hosts.include? vm_name['hostname']
133
133
  if all_job_resources_accounted_for(req_hash['allocated_resources'], hosts)
134
134
  ret_status[vm_name['hostname']] = {
135
- 'ok' => true,
135
+ 'ok' => true
136
136
  }
137
137
  jobs_to_delete.push(req_hash)
138
138
  else
@@ -147,7 +147,7 @@ class ABS
147
147
  jobs_to_delete.each do |job|
148
148
  req_obj = {
149
149
  'job_id' => job['request']['job']['id'],
150
- 'hosts' => job['allocated_resources'],
150
+ 'hosts' => job['allocated_resources']
151
151
  }
152
152
 
153
153
  FloatyLogger.info "Deleting #{req_obj}" if verbose
@@ -163,7 +163,7 @@ class ABS
163
163
 
164
164
  # List available VMs in ABS
165
165
  def self.list(verbose, url, os_filter = nil)
166
- conn = Http.get_conn(verbose, url)
166
+ conn = Http.get_conn(verbose, supported_abs_url(url))
167
167
 
168
168
  os_list = []
169
169
 
@@ -172,11 +172,11 @@ class ABS
172
172
  res_body = JSON.parse(res.body)
173
173
  if res_body.key?('vmpooler_platforms')
174
174
  os_list << '*** VMPOOLER Pools ***'
175
- if res_body['vmpooler_platforms'].is_a?(String)
176
- os_list += JSON.parse(res_body['vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
177
- else
178
- os_list += res_body['vmpooler_platforms']
179
- end
175
+ os_list += if res_body['vmpooler_platforms'].is_a?(String)
176
+ JSON.parse(res_body['vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
177
+ else
178
+ res_body['vmpooler_platforms']
179
+ end
180
180
  end
181
181
  end
182
182
 
@@ -200,11 +200,11 @@ class ABS
200
200
  if res_body.key?('nspooler_platforms')
201
201
  os_list << ''
202
202
  os_list << '*** NSPOOLER Pools ***'
203
- if res_body['nspooler_platforms'].is_a?(String)
204
- os_list += JSON.parse(res_body['nspooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
205
- else
206
- os_list += res_body['nspooler_platforms']
207
- end
203
+ os_list += if res_body['nspooler_platforms'].is_a?(String)
204
+ JSON.parse(res_body['nspooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
205
+ else
206
+ res_body['nspooler_platforms']
207
+ end
208
208
  end
209
209
  end
210
210
 
@@ -214,11 +214,11 @@ class ABS
214
214
  if res_body.key?('aws_platforms')
215
215
  os_list << ''
216
216
  os_list << '*** AWS Pools ***'
217
- if res_body['aws_platforms'].is_a?(String)
218
- os_list += JSON.parse(res_body['aws_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
219
- else
220
- os_list += res_body['aws_platforms']
221
- end
217
+ os_list += if res_body['aws_platforms'].is_a?(String)
218
+ JSON.parse(res_body['aws_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
219
+ else
220
+ res_body['aws_platforms']
221
+ end
222
222
  end
223
223
  end
224
224
 
@@ -228,7 +228,7 @@ class ABS
228
228
  end
229
229
 
230
230
  # Retrieve an OS from ABS.
231
- def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil)
231
+ def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil, continue = nil)
232
232
  #
233
233
  # Contents of post must be like:
234
234
  #
@@ -245,28 +245,38 @@ class ABS
245
245
  # }
246
246
  # }
247
247
 
248
- conn = Http.get_conn(verbose, url)
248
+ conn = Http.get_conn(verbose, supported_abs_url(url))
249
249
  conn.headers['X-AUTH-TOKEN'] = token if token
250
250
 
251
- saved_job_id = DateTime.now.strftime('%Q')
252
- vmpooler_config = Utils.get_vmpooler_service_config(config['vmpooler_fallback'])
251
+ saved_job_id = if continue.nil?
252
+ "#{user}-#{DateTime.now.strftime('%Q')}"
253
+ else
254
+ continue
255
+ end
256
+
253
257
  req_obj = {
254
- :resources => os_types,
255
- :job => {
256
- :id => saved_job_id,
257
- :tags => {
258
- :user => user,
259
- },
260
- },
261
- :vm_token => vmpooler_config['token'] # request with this token, on behalf of this user
258
+ resources: os_types,
259
+ job: {
260
+ id: saved_job_id,
261
+ tags: {
262
+ user: user
263
+ }
264
+ }
262
265
  }
263
266
 
267
+ if config['vmpooler_fallback'] # optional and not available as cli flag
268
+ vmpooler_config = Utils.get_vmpooler_service_config(config['vmpooler_fallback'])
269
+ # request with this token, on behalf of this user
270
+ req_obj[:vm_token] = vmpooler_config['token']
271
+ end
272
+
264
273
  if config['priority']
265
- req_obj[:priority] = if config['priority'] == 'high'
274
+ req_obj[:priority] = case config['priority']
275
+ when 'high'
266
276
  1
267
- elsif config['priority'] == 'medium'
277
+ when 'medium'
268
278
  2
269
- elsif config['priority'] == 'low'
279
+ when 'low'
270
280
  3
271
281
  else
272
282
  config['priority'].to_i
@@ -277,22 +287,27 @@ class ABS
277
287
 
278
288
  # os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+')
279
289
  # raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty?
280
- FloatyLogger.info "Requesting VMs with job_id: #{saved_job_id}. Will retry for up to an hour."
290
+ FloatyLogger.info "Requesting VMs with job_id: #{saved_job_id} Will retry for up to an hour."
281
291
  res = conn.post 'request', req_obj.to_json
282
292
 
283
293
  retries = 360
284
294
 
285
- validate_queue_status_response(res.status, res.body, "Initial request", verbose)
295
+ status = validate_queue_status_response(res.status, res.body, 'Initial request', verbose)
286
296
 
287
- (1..retries).each do |i|
288
- queue_place, res_body = check_queue(conn, saved_job_id, req_obj, verbose)
289
- return translated(res_body, saved_job_id) if res_body
297
+ begin
298
+ (1..retries).each do |i|
299
+ res_body = check_queue(conn, saved_job_id, req_obj, verbose)
300
+ return translated(res_body, saved_job_id) if res_body.is_a?(Array) # when we get a response with hostnames
290
301
 
291
- sleep_seconds = 10 if i >= 10
292
- sleep_seconds = i if i < 10
293
- FloatyLogger.info "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})"
302
+ sleep_seconds = 10 if i >= 10
303
+ sleep_seconds = i if i < 10
304
+ FloatyLogger.info "Waiting #{sleep_seconds}s (x#{i}) #{res_body.strip}"
294
305
 
295
- sleep(sleep_seconds)
306
+ sleep(sleep_seconds)
307
+ end
308
+ rescue SystemExit, Interrupt
309
+ 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}`"
310
+ exit 1
296
311
  end
297
312
  nil
298
313
  end
@@ -301,10 +316,10 @@ class ABS
301
316
  # We should fix the ABS API to be more like the vmpooler or nspooler api, but for now
302
317
  #
303
318
  def self.translated(res_body, job_id)
304
- vmpooler_formatted_body = {'job_id' => job_id}
319
+ vmpooler_formatted_body = { 'job_id' => job_id }
305
320
 
306
321
  res_body.each do |host|
307
- if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].class == Array
322
+ if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].instance_of?(Array)
308
323
  vmpooler_formatted_body[host['type']]['hostname'] << host['hostname']
309
324
  else
310
325
  vmpooler_formatted_body[host['type']] = { 'hostname' => [host['hostname']] }
@@ -315,23 +330,14 @@ class ABS
315
330
  vmpooler_formatted_body
316
331
  end
317
332
 
318
- def self.check_queue(conn, job_id, req_obj, verbose)
319
- queue_info_res = conn.get "status/queue/info/#{job_id}"
320
- if valid_json?(queue_info_res.body)
321
- queue_info = JSON.parse(queue_info_res.body)
322
- else
323
- FloatyLogger.warn "Could not parse the status/queue/info/#{job_id}"
324
- return [nil, nil]
325
- end
326
-
333
+ def self.check_queue(conn, _job_id, req_obj, verbose)
327
334
  res = conn.post 'request', req_obj.to_json
328
- validate_queue_status_response(res.status, res.body, "Check queue request", verbose)
329
-
335
+ status = validate_queue_status_response(res.status, res.body, 'Check queue request', verbose)
330
336
  unless res.body.empty? || !valid_json?(res.body)
331
337
  res_body = JSON.parse(res.body)
332
- return queue_info['queue_place'], res_body
338
+ return res_body
333
339
  end
334
- [queue_info['queue_place'], nil]
340
+ res.body
335
341
  end
336
342
 
337
343
  def self.snapshot(_verbose, _url, _hostname, _token)
@@ -339,14 +345,14 @@ class ABS
339
345
  end
340
346
 
341
347
  def self.status(verbose, url)
342
- conn = Http.get_conn(verbose, url)
348
+ conn = Http.get_conn(verbose, supported_abs_url(url))
343
349
 
344
350
  res = conn.get 'status'
345
351
 
346
352
  res.body == 'OK'
347
353
  end
348
354
 
349
- def self.summary(verbose, url)
355
+ def self.summary(_verbose, _url)
350
356
  raise NoMethodError, 'summary is not defined for ABS'
351
357
  end
352
358
 
@@ -357,7 +363,7 @@ class ABS
357
363
  return @active_hostnames if @active_hostnames && !@active_hostnames.empty?
358
364
 
359
365
  # If using the cli query job_id
360
- conn = Http.get_conn(verbose, url)
366
+ conn = Http.get_conn(verbose, supported_abs_url(url))
361
367
  queue_info_res = conn.get "status/queue/info/#{job_id}"
362
368
  if valid_json?(queue_info_res.body)
363
369
  queue_info = JSON.parse(queue_info_res.body)
@@ -398,8 +404,19 @@ class ABS
398
404
 
399
405
  def self.valid_json?(json)
400
406
  JSON.parse(json)
401
- return true
407
+ true
402
408
  rescue TypeError, JSON::ParserError => e
403
- return false
409
+ false
410
+ end
411
+
412
+ # when missing, adds the required api/v2 in the url
413
+ def self.supported_abs_url(url)
414
+ expected_ending = 'api/v2'
415
+ unless url.include?(expected_ending)
416
+ # add a slash if missing
417
+ expected_ending = "/#{expected_ending}" if url[-1] != '/'
418
+ url = "#{url}#{expected_ending}"
419
+ end
420
+ url
404
421
  end
405
422
  end