vmfloaty 0.8.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +13 -8
- data/bin/floaty +2 -1
- data/lib/vmfloaty.rb +43 -49
- data/lib/vmfloaty/abs.rb +293 -0
- data/lib/vmfloaty/auth.rb +14 -22
- data/lib/vmfloaty/conf.rb +3 -2
- data/lib/vmfloaty/errors.rb +6 -4
- data/lib/vmfloaty/http.rb +14 -25
- data/lib/vmfloaty/nonstandard_pooler.rb +14 -30
- data/lib/vmfloaty/pooler.rb +31 -52
- data/lib/vmfloaty/service.rb +19 -15
- data/lib/vmfloaty/ssh.rb +17 -23
- data/lib/vmfloaty/utils.rb +89 -80
- data/lib/vmfloaty/version.rb +3 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/vmfloaty/abs/auth_spec.rb +84 -0
- data/spec/vmfloaty/abs_spec.rb +96 -0
- data/spec/vmfloaty/auth_spec.rb +39 -43
- data/spec/vmfloaty/nonstandard_pooler_spec.rb +130 -144
- data/spec/vmfloaty/pooler_spec.rb +100 -100
- data/spec/vmfloaty/service_spec.rb +17 -17
- data/spec/vmfloaty/utils_spec.rb +106 -105
- metadata +19 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7b08c0be5bb4c8a57ce706db190b37bdf89532e30964aca13bd53dc4b2649d46
|
4
|
+
data.tar.gz: aeaeb37cde837b342ddd438b6e3c389e9e84b12fd6caa36a40fcd87ff8b0427b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7bb8b68a6dcc391184c910883e4d05c1d7c8580dd7d969f141959fdd46b0e4a9ef4c7ec141a3d4526cab557923d80d0db62e8ae11e8fd76120d2d0e5367fde8
|
7
|
+
data.tar.gz: d0bb6b6ff8fd727a110814ebd3836dcd344b30c0e0fb5791ac4485ed0fafe2d715d00173e7d874ec9a41488eaecd0709d1ce53a8c5162419e3285912a1746b2d
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ $ floaty --help
|
|
53
53
|
Grabbing a token for authenticated pooler requests:
|
54
54
|
|
55
55
|
```
|
56
|
-
floaty token get --user username --url https://vmpooler.
|
56
|
+
floaty token get --user username --url https://vmpooler.example.net/api/v1
|
57
57
|
```
|
58
58
|
|
59
59
|
This command will then ask you to log in. If successful, it will return a token that you can save either in a dotfile or use with other cli commands.
|
@@ -61,18 +61,18 @@ This command will then ask you to log in. If successful, it will return a token
|
|
61
61
|
Grabbing vms:
|
62
62
|
|
63
63
|
```
|
64
|
-
floaty get centos-7-x86_64=2 debian-7-x86_64 windows-10=3 --token mytokenstring --url https://vmpooler.
|
64
|
+
floaty get centos-7-x86_64=2 debian-7-x86_64 windows-10=3 --token mytokenstring --url https://vmpooler.example.net/api/v1
|
65
65
|
```
|
66
66
|
|
67
67
|
### vmfloaty dotfile
|
68
68
|
|
69
|
-
If you do not wish to
|
69
|
+
If you do not wish to continually specify various config options with the cli, you can have a dotfile in your home directory for some defaults. For example:
|
70
70
|
|
71
71
|
#### Basic configuration
|
72
72
|
|
73
73
|
```yaml
|
74
74
|
# file at /Users/me/.vmfloaty.yml
|
75
|
-
url: 'https://vmpooler.
|
75
|
+
url: 'https://vmpooler.example.net/api/v1'
|
76
76
|
user: 'brian'
|
77
77
|
token: 'tokenstring'
|
78
78
|
```
|
@@ -90,10 +90,10 @@ To configure multiple services, you can set up your `~/.vmfloaty.yml` config fil
|
|
90
90
|
user: 'brian'
|
91
91
|
services:
|
92
92
|
main:
|
93
|
-
url: 'https://vmpooler.
|
93
|
+
url: 'https://vmpooler.example.net/api/v1'
|
94
94
|
token: 'tokenstring'
|
95
95
|
alternate:
|
96
|
-
url: 'https://vmpooler.
|
96
|
+
url: 'https://vmpooler.example.com/api/v1'
|
97
97
|
token: 'alternate-tokenstring'
|
98
98
|
```
|
99
99
|
|
@@ -125,12 +125,17 @@ vmfloaty is capable of working with Puppet's [nonstandard pooler](https://github
|
|
125
125
|
user: 'brian'
|
126
126
|
services:
|
127
127
|
vm:
|
128
|
-
url: 'https://vmpooler.
|
128
|
+
url: 'https://vmpooler.example.net/api/v1'
|
129
129
|
token: 'tokenstring'
|
130
130
|
ns:
|
131
|
-
url: 'https://nspooler.
|
131
|
+
url: 'https://nspooler.example.net/api/v1'
|
132
132
|
token: 'nspooler-tokenstring'
|
133
133
|
type: 'nonstandard' # <-- 'type' is necessary for any non-vmpooler service
|
134
|
+
abs:
|
135
|
+
url: 'https://abs.example.net/'
|
136
|
+
token: 'abs-tokenstring'
|
137
|
+
type: 'abs' # <-- 'type' is necessary for any non-vmpooler service
|
138
|
+
|
134
139
|
```
|
135
140
|
|
136
141
|
With this configuration, you could list available OS types from nspooler like this:
|
data/bin/floaty
CHANGED
data/lib/vmfloaty.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'commander'
|
@@ -17,7 +17,7 @@ require 'vmfloaty/ssh'
|
|
17
17
|
class Vmfloaty
|
18
18
|
include Commander::Methods
|
19
19
|
|
20
|
-
def run
|
20
|
+
def run # rubocop:disable Metrics/AbcSize
|
21
21
|
program :version, Vmfloaty::VERSION
|
22
22
|
program :description, 'A CLI helper tool for Puppet Labs VM poolers to help you stay afloat'
|
23
23
|
|
@@ -33,6 +33,7 @@ class Vmfloaty
|
|
33
33
|
c.option '--user STRING', String, 'User to authenticate with'
|
34
34
|
c.option '--url STRING', String, 'URL of pooler service'
|
35
35
|
c.option '--token STRING', String, 'Token for pooler service'
|
36
|
+
c.option '--priority STRING', 'Priority for supported backends(ABS) (High(1), Medium(2), Low(3))'
|
36
37
|
c.option '--notoken', 'Makes a request without a token'
|
37
38
|
c.option '--force', 'Forces vmfloaty to get requested vms'
|
38
39
|
c.option '--json', 'Prints retrieved vms in JSON format'
|
@@ -43,22 +44,22 @@ class Vmfloaty
|
|
43
44
|
force = options.force
|
44
45
|
|
45
46
|
if args.empty?
|
46
|
-
STDERR.puts
|
47
|
+
STDERR.puts 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
|
47
48
|
exit 1
|
48
49
|
end
|
49
50
|
|
50
51
|
os_types = Utils.generate_os_hash(args)
|
51
52
|
|
52
53
|
max_pool_request = 5
|
53
|
-
large_pool_requests = os_types.select{|_,v| v > max_pool_request}
|
54
|
-
if !
|
54
|
+
large_pool_requests = os_types.select { |_, v| v > max_pool_request }
|
55
|
+
if !large_pool_requests.empty? && !force
|
55
56
|
STDERR.puts "Requesting vms over #{max_pool_request} requires a --force flag."
|
56
|
-
STDERR.puts
|
57
|
+
STDERR.puts 'Try again with `floaty get --force`'
|
57
58
|
exit 1
|
58
59
|
end
|
59
60
|
|
60
61
|
if os_types.empty?
|
61
|
-
STDERR.puts
|
62
|
+
STDERR.puts 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
|
62
63
|
exit 1
|
63
64
|
end
|
64
65
|
|
@@ -84,6 +85,7 @@ class Vmfloaty
|
|
84
85
|
c.option '--url STRING', String, 'URL of pooler service'
|
85
86
|
c.action do |args, options|
|
86
87
|
verbose = options.verbose || config['verbose']
|
88
|
+
|
87
89
|
service = Service.new(options, config)
|
88
90
|
filter = args[0]
|
89
91
|
|
@@ -143,18 +145,18 @@ class Vmfloaty
|
|
143
145
|
hostname = args[0]
|
144
146
|
modify_all = options.all
|
145
147
|
|
146
|
-
if hostname.nil?
|
147
|
-
STDERR.puts
|
148
|
+
if hostname.nil? && !modify_all
|
149
|
+
STDERR.puts 'ERROR: Provide a hostname or specify --all.'
|
148
150
|
exit 1
|
149
151
|
end
|
150
|
-
running_vms = modify_all ? service.list_active(verbose) : hostname.split(
|
152
|
+
running_vms = modify_all ? service.list_active(verbose) : hostname.split(',')
|
151
153
|
|
152
154
|
tags = options.tags ? JSON.parse(options.tags) : nil
|
153
155
|
modify_hash = {
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
156
|
+
:lifetime => options.lifetime,
|
157
|
+
:disk => options.disk,
|
158
|
+
:tags => tags,
|
159
|
+
:reason => options.reason,
|
158
160
|
}
|
159
161
|
modify_hash.delete_if { |_, value| value.nil? }
|
160
162
|
|
@@ -171,11 +173,11 @@ class Vmfloaty
|
|
171
173
|
end
|
172
174
|
if ok
|
173
175
|
if modify_all
|
174
|
-
puts
|
176
|
+
puts 'Successfully modified all VMs.'
|
175
177
|
else
|
176
178
|
puts "Successfully modified VM #{hostname}."
|
177
179
|
end
|
178
|
-
puts
|
180
|
+
puts 'Use `floaty list --active` to see the results.'
|
179
181
|
end
|
180
182
|
end
|
181
183
|
end
|
@@ -205,15 +207,13 @@ class Vmfloaty
|
|
205
207
|
if delete_all
|
206
208
|
running_vms = service.list_active(verbose)
|
207
209
|
if running_vms.empty?
|
208
|
-
STDERR.puts
|
210
|
+
STDERR.puts 'You have no running VMs.'
|
209
211
|
else
|
210
212
|
Utils.pretty_print_hosts(verbose, service, running_vms)
|
211
213
|
# Confirm deletion
|
212
214
|
puts
|
213
215
|
confirmed = true
|
214
|
-
unless force
|
215
|
-
confirmed = agree('Delete all these VMs? [y/N]')
|
216
|
-
end
|
216
|
+
confirmed = agree('Delete all these VMs? [y/N]') unless force
|
217
217
|
if confirmed
|
218
218
|
response = service.delete(verbose, running_vms)
|
219
219
|
response.each do |hostname, result|
|
@@ -236,7 +236,7 @@ class Vmfloaty
|
|
236
236
|
end
|
237
237
|
end
|
238
238
|
else
|
239
|
-
STDERR.puts
|
239
|
+
STDERR.puts 'You did not provide any hosts to delete'
|
240
240
|
exit 1
|
241
241
|
end
|
242
242
|
|
@@ -302,9 +302,7 @@ class Vmfloaty
|
|
302
302
|
hostname = args[0]
|
303
303
|
snapshot_sha = args[1] || options.snapshot
|
304
304
|
|
305
|
-
if args[1] && options.snapshot
|
306
|
-
STDERR.puts "Two snapshot arguments were given....using snapshot #{snapshot_sha}"
|
307
|
-
end
|
305
|
+
STDERR.puts "Two snapshot arguments were given....using snapshot #{snapshot_sha}" if args[1] && options.snapshot
|
308
306
|
|
309
307
|
begin
|
310
308
|
revert_req = service.revert(verbose, hostname, snapshot_sha)
|
@@ -372,25 +370,23 @@ class Vmfloaty
|
|
372
370
|
|
373
371
|
begin
|
374
372
|
case action
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
STDERR.puts "Unknown action: #{action}"
|
393
|
-
exit 1
|
373
|
+
when 'get'
|
374
|
+
token = service.get_new_token(verbose)
|
375
|
+
puts token
|
376
|
+
when 'delete'
|
377
|
+
result = service.delete_token(verbose, options.token)
|
378
|
+
puts result
|
379
|
+
when 'status'
|
380
|
+
token_value = options.token
|
381
|
+
token_value = args[1] if token_value.nil?
|
382
|
+
status = service.token_status(verbose, token_value)
|
383
|
+
puts status
|
384
|
+
when nil
|
385
|
+
STDERR.puts 'No action provided'
|
386
|
+
exit 1
|
387
|
+
else
|
388
|
+
STDERR.puts "Unknown action: #{action}"
|
389
|
+
exit 1
|
394
390
|
end
|
395
391
|
rescue TokenError => e
|
396
392
|
STDERR.puts e
|
@@ -417,15 +413,13 @@ class Vmfloaty
|
|
417
413
|
use_token = !options.notoken
|
418
414
|
|
419
415
|
if args.empty?
|
420
|
-
STDERR.puts
|
416
|
+
STDERR.puts 'No operating systems provided to obtain. See `floaty ssh --help` for more information on how to get VMs.'
|
421
417
|
exit 1
|
422
418
|
end
|
423
419
|
|
424
420
|
host_os = args.first
|
425
421
|
|
426
|
-
if args.length > 1
|
427
|
-
STDERR.puts "Can't ssh to multiple hosts; Using #{host_os} only..."
|
428
|
-
end
|
422
|
+
STDERR.puts "Can't ssh to multiple hosts; Using #{host_os} only..." if args.length > 1
|
429
423
|
|
430
424
|
service.ssh(verbose, host_os, use_token)
|
431
425
|
exit 0
|
@@ -435,13 +429,13 @@ class Vmfloaty
|
|
435
429
|
command :completion do |c|
|
436
430
|
c.syntax = 'floaty completion [options]'
|
437
431
|
c.summary = 'Outputs path to completion script'
|
438
|
-
c.description = Utils.strip_heredoc(<<-
|
432
|
+
c.description = Utils.strip_heredoc(<<-DESCRIPTION)
|
439
433
|
Outputs path to a completion script for the specified shell (or 'bash' if not specified). This makes it easy to add the completion script to your profile:
|
440
434
|
|
441
435
|
source $(floaty completion --shell bash)
|
442
436
|
|
443
437
|
This subcommand will exit non-zero with an error message if no completion script is available for the requested shell.
|
444
|
-
|
438
|
+
DESCRIPTION
|
445
439
|
c.example 'Gets path to bash tab completion script', 'floaty completion --shell bash'
|
446
440
|
c.option '--shell STRING', String, 'Shell to request completion script for'
|
447
441
|
c.action do |_, options|
|
data/lib/vmfloaty/abs.rb
ADDED
@@ -0,0 +1,293 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'vmfloaty/errors'
|
4
|
+
require 'vmfloaty/http'
|
5
|
+
require 'faraday'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
class ABS
|
9
|
+
# List active VMs in ABS
|
10
|
+
# This is what a job request looks like:
|
11
|
+
# {
|
12
|
+
# "state":"filled",
|
13
|
+
# "last_processed":"2019-10-31 20:59:33 +0000",
|
14
|
+
# "allocated_resources": [
|
15
|
+
# {
|
16
|
+
# "hostname":"h3oyntawjm7xdch.delivery.puppetlabs.net",
|
17
|
+
# "type":"centos-7.2-tmpfs-x86_64",
|
18
|
+
# "engine":"vmpooler"}
|
19
|
+
# ],
|
20
|
+
# "audit_log":{
|
21
|
+
# "2019-10-30 20:33:12 +0000":"Allocated h3oyntawjm7xdch.delivery.puppetlabs.net for job 1572467589"
|
22
|
+
# },
|
23
|
+
# "request":{
|
24
|
+
# "resources":{
|
25
|
+
# "centos-7.2-tmpfs-x86_64":1
|
26
|
+
# },
|
27
|
+
# "job": {
|
28
|
+
# "id":1572467589,
|
29
|
+
# "tags": {
|
30
|
+
# "user":"mikker",
|
31
|
+
# "url_string":"floaty://mikker/1572467589"
|
32
|
+
# },
|
33
|
+
# "user":"mikker",
|
34
|
+
# "time-received":1572467589
|
35
|
+
# }
|
36
|
+
# }
|
37
|
+
# }
|
38
|
+
#
|
39
|
+
|
40
|
+
@active_hostnames = {}
|
41
|
+
|
42
|
+
def self.list_active(verbose, url, _token, user)
|
43
|
+
all_jobs = []
|
44
|
+
@active_hostnames = {}
|
45
|
+
|
46
|
+
get_active_requests(verbose, url, user).each do |req_hash|
|
47
|
+
all_jobs.push(req_hash['request']['job']['id'])
|
48
|
+
@active_hostnames[req_hash['request']['job']['id']] = req_hash
|
49
|
+
end
|
50
|
+
|
51
|
+
all_jobs
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.get_active_requests(verbose, url, user)
|
55
|
+
conn = Http.get_conn(verbose, url)
|
56
|
+
res = conn.get 'status/queue'
|
57
|
+
requests = JSON.parse(res.body)
|
58
|
+
|
59
|
+
ret_val = []
|
60
|
+
|
61
|
+
requests.each do |req|
|
62
|
+
next if req == 'null'
|
63
|
+
|
64
|
+
req_hash = JSON.parse(req)
|
65
|
+
|
66
|
+
begin
|
67
|
+
next unless user == req_hash['request']['job']['user']
|
68
|
+
|
69
|
+
ret_val.push(req_hash)
|
70
|
+
rescue NoMethodError
|
71
|
+
puts "Warning: couldn't parse line returned from abs/status/queue: ".yellow
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
ret_val
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.all_job_resources_accounted_for(allocated_resources, hosts)
|
79
|
+
allocated_host_list = allocated_resources.map { |ar| ar['hostname'] }
|
80
|
+
(allocated_host_list - hosts).empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.delete(verbose, url, hosts, token, user)
|
84
|
+
# In ABS terms, this is a "returned" host.
|
85
|
+
conn = Http.get_conn(verbose, url)
|
86
|
+
conn.headers['X-AUTH-TOKEN'] = token if token
|
87
|
+
|
88
|
+
puts "Trying to delete hosts #{hosts}" if verbose
|
89
|
+
requests = get_active_requests(verbose, url, user)
|
90
|
+
|
91
|
+
jobs_to_delete = []
|
92
|
+
|
93
|
+
ret_status = {}
|
94
|
+
hosts.each do |host|
|
95
|
+
ret_status[host] = {
|
96
|
+
'ok' => false,
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
requests.each do |req_hash|
|
101
|
+
next unless req_hash['state'] == 'allocated' || req_hash['state'] == 'filled'
|
102
|
+
|
103
|
+
req_hash['allocated_resources'].each do |vm_name, _i|
|
104
|
+
if hosts.include? vm_name['hostname']
|
105
|
+
if all_job_resources_accounted_for(req_hash['allocated_resources'], hosts)
|
106
|
+
ret_status[vm_name['hostname']] = {
|
107
|
+
'ok' => true,
|
108
|
+
}
|
109
|
+
jobs_to_delete.push(req_hash)
|
110
|
+
else
|
111
|
+
puts "When using ABS you must delete all vms that you requested at the same time: Can't delete #{req_hash['request']['job']['id']}: #{hosts} does not include all of #{req_hash['allocated_resources']}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
response_body = {}
|
118
|
+
|
119
|
+
jobs_to_delete.each do |job|
|
120
|
+
req_obj = {
|
121
|
+
'job_id' => job['request']['job']['id'],
|
122
|
+
'hosts' => job['allocated_resources'],
|
123
|
+
}
|
124
|
+
|
125
|
+
puts "Deleting #{req_obj}" if verbose
|
126
|
+
|
127
|
+
return_result = conn.post 'return', req_obj.to_json
|
128
|
+
req_obj['hosts'].each do |host|
|
129
|
+
response_body[host['hostname']] = { 'ok' => true } if return_result.body == 'OK'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
response_body
|
134
|
+
end
|
135
|
+
|
136
|
+
# List available VMs in ABS
|
137
|
+
def self.list(verbose, url, os_filter = nil)
|
138
|
+
conn = Http.get_conn(verbose, url)
|
139
|
+
|
140
|
+
os_list = []
|
141
|
+
|
142
|
+
res = conn.get 'status/platforms/vmpooler'
|
143
|
+
|
144
|
+
res_body = JSON.parse(res.body)
|
145
|
+
os_list << '*** VMPOOLER Pools ***'
|
146
|
+
os_list += JSON.parse(res_body['vmpooler_platforms'])
|
147
|
+
|
148
|
+
res = conn.get 'status/platforms/nspooler'
|
149
|
+
res_body = JSON.parse(res.body)
|
150
|
+
os_list << ''
|
151
|
+
os_list << '*** NSPOOLER Pools ***'
|
152
|
+
os_list += JSON.parse(res_body['nspooler_platforms'])
|
153
|
+
|
154
|
+
res = conn.get 'status/platforms/aws'
|
155
|
+
res_body = JSON.parse(res.body)
|
156
|
+
os_list << ''
|
157
|
+
os_list << '*** AWS Pools ***'
|
158
|
+
os_list += JSON.parse(res_body['aws_platforms'])
|
159
|
+
|
160
|
+
os_list.delete 'ok'
|
161
|
+
|
162
|
+
os_filter ? os_list.select { |i| i[/#{os_filter}/] } : os_list
|
163
|
+
end
|
164
|
+
|
165
|
+
# Retrieve an OS from ABS.
|
166
|
+
def self.retrieve(verbose, os_types, token, url, user, options)
|
167
|
+
#
|
168
|
+
# Contents of post must be like:
|
169
|
+
#
|
170
|
+
# {
|
171
|
+
# "resources": {
|
172
|
+
# "centos-7-i386": 1,
|
173
|
+
# "ubuntu-1404-x86_64": 2
|
174
|
+
# },
|
175
|
+
# "job": {
|
176
|
+
# "id": "12345",
|
177
|
+
# "tags": {
|
178
|
+
# "user": "username",
|
179
|
+
# }
|
180
|
+
# }
|
181
|
+
# }
|
182
|
+
|
183
|
+
conn = Http.get_conn(verbose, url)
|
184
|
+
conn.headers['X-AUTH-TOKEN'] = token if token
|
185
|
+
|
186
|
+
saved_job_id = DateTime.now.strftime('%Q')
|
187
|
+
|
188
|
+
req_obj = {
|
189
|
+
:resources => os_types,
|
190
|
+
:job => {
|
191
|
+
:id => saved_job_id,
|
192
|
+
:tags => {
|
193
|
+
:user => user,
|
194
|
+
},
|
195
|
+
},
|
196
|
+
}
|
197
|
+
|
198
|
+
if options['priority']
|
199
|
+
req_obj[:priority] = if options['priority'] == 'high'
|
200
|
+
1
|
201
|
+
elsif options['priority'] == 'medium'
|
202
|
+
2
|
203
|
+
elsif options['priority'] == 'low'
|
204
|
+
3
|
205
|
+
else
|
206
|
+
options['priority'].to_i
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
puts "Posting to ABS #{req_obj.to_json}" if verbose
|
211
|
+
|
212
|
+
# os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+')
|
213
|
+
# raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty?
|
214
|
+
puts "Requesting VMs with job_id: #{saved_job_id}. Will retry for up to an hour."
|
215
|
+
res = conn.post 'request', req_obj.to_json
|
216
|
+
|
217
|
+
retries = 360
|
218
|
+
|
219
|
+
raise AuthError, "HTTP #{res.status}: The token provided could not authenticate to the pooler.\n#{res_body}" if res.status == 401
|
220
|
+
|
221
|
+
(1..retries).each do |i|
|
222
|
+
queue_place, res_body = check_queue(conn, saved_job_id, req_obj)
|
223
|
+
return translated(res_body) if res_body
|
224
|
+
|
225
|
+
sleep_seconds = 10 if i >= 10
|
226
|
+
sleep_seconds = i if i < 10
|
227
|
+
puts "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})"
|
228
|
+
|
229
|
+
sleep(sleep_seconds)
|
230
|
+
end
|
231
|
+
nil
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
# We should fix the ABS API to be more like the vmpooler or nspooler api, but for now
|
236
|
+
#
|
237
|
+
def self.translated(res_body)
|
238
|
+
vmpooler_formatted_body = {}
|
239
|
+
|
240
|
+
res_body.each do |host|
|
241
|
+
if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].class == Array
|
242
|
+
vmpooler_formatted_body[host['type']]['hostname'] << host['hostname']
|
243
|
+
else
|
244
|
+
vmpooler_formatted_body[host['type']] = { 'hostname' => [host['hostname']] }
|
245
|
+
end
|
246
|
+
end
|
247
|
+
vmpooler_formatted_body['ok'] = true
|
248
|
+
|
249
|
+
vmpooler_formatted_body
|
250
|
+
end
|
251
|
+
|
252
|
+
def self.check_queue(conn, job_id, req_obj)
|
253
|
+
queue_info_res = conn.get "status/queue/info/#{job_id}"
|
254
|
+
queue_info = JSON.parse(queue_info_res.body)
|
255
|
+
|
256
|
+
res = conn.post 'request', req_obj.to_json
|
257
|
+
|
258
|
+
unless res.body.empty?
|
259
|
+
res_body = JSON.parse(res.body)
|
260
|
+
return queue_info['queue_place'], res_body
|
261
|
+
end
|
262
|
+
[queue_info['queue_place'], nil]
|
263
|
+
end
|
264
|
+
|
265
|
+
def self.snapshot(_verbose, _url, _hostname, _token)
|
266
|
+
puts "Can't snapshot with ABS, use '--service vmpooler' (even for vms checked out with ABS)"
|
267
|
+
end
|
268
|
+
|
269
|
+
def self.status(verbose, url)
|
270
|
+
conn = Http.get_conn(verbose, url)
|
271
|
+
|
272
|
+
res = conn.get 'status'
|
273
|
+
|
274
|
+
res.body == 'OK'
|
275
|
+
end
|
276
|
+
|
277
|
+
def self.summary(verbose, url)
|
278
|
+
conn = Http.get_conn(verbose, url)
|
279
|
+
|
280
|
+
res = conn.get 'summary'
|
281
|
+
JSON.parse(res.body)
|
282
|
+
end
|
283
|
+
|
284
|
+
def self.query(verbose, url, hostname)
|
285
|
+
return @active_hostnames if @active_hostnames
|
286
|
+
|
287
|
+
puts "For vmpooler/snapshot information, use '--service vmpooler' (even for vms checked out with ABS)"
|
288
|
+
conn = Http.get_conn(verbose, url)
|
289
|
+
|
290
|
+
res = conn.get "host/#{hostname}"
|
291
|
+
JSON.parse(res.body)
|
292
|
+
end
|
293
|
+
end
|