vmfloaty 0.8.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|