vmfloaty 0.11.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -75
- data/extras/completions/floaty.bash +2 -2
- data/extras/completions/floaty.zsh +37 -0
- data/lib/vmfloaty.rb +92 -7
- data/lib/vmfloaty/abs.rb +118 -49
- data/lib/vmfloaty/conf.rb +1 -1
- data/lib/vmfloaty/service.rb +20 -0
- data/lib/vmfloaty/utils.rb +79 -11
- data/lib/vmfloaty/version.rb +2 -1
- data/spec/vmfloaty/abs_spec.rb +52 -5
- data/spec/vmfloaty/utils_spec.rb +436 -73
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4cf673c0a3e005fc4ef5102d232206f3105215de4f19cd76725de335b62937fd
|
4
|
+
data.tar.gz: e4791593e75d31d42a8f05cfb28b3655e42218ac1a7191ae1c8391ccdad5133b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b22ad1332f3a663407a6ce964525606938134925e0b91ccd151a8f9a4abc265cab53cddd9509ce92555abb357dc213f2beef50a02ea72eb501db31c9e3936983
|
7
|
+
data.tar.gz: 8436c38cc6a99b76c4e65da0dfa653edbbdbe9b7fcefb9607942983cd24014c40ab14f556b06e7d6a449dc57f84740e09df2668e15129cdb5dccbb3b6e746eff
|
data/README.md
CHANGED
@@ -14,9 +14,8 @@ A CLI helper tool for [Puppet's vmpooler](https://github.com/puppetlabs/vmpooler
|
|
14
14
|
- [Example workflow](#example-workflow)
|
15
15
|
- [vmfloaty dotfile](#vmfloaty-dotfile)
|
16
16
|
- [Basic configuration](#basic-configuration)
|
17
|
-
- [
|
18
|
-
- [
|
19
|
-
- [Using a Nonstandard Pooler service](#using-a-nonstandard-pooler-service)
|
17
|
+
- [Using multiple services](#using-multiple-services)
|
18
|
+
- [Using backends besides VMPooler](#using-backends-besides-vmpooler)
|
20
19
|
- [Valid config keys](#valid-config-keys)
|
21
20
|
- [Tab Completion](#tab-completion)
|
22
21
|
- [vmpooler API](#vmpooler-api)
|
@@ -54,6 +53,7 @@ $ floaty --help
|
|
54
53
|
modify Modify a VM's tags, time to live, disk space, or reservation reason
|
55
54
|
query Get information about a given vm
|
56
55
|
revert Reverts a vm to a specified snapshot
|
56
|
+
service Display information about floaty services and their configuration
|
57
57
|
snapshot Takes a snapshot of a given vm
|
58
58
|
ssh Grabs a single vm and sshs into it
|
59
59
|
status Prints the status of pools in the pooler service
|
@@ -90,95 +90,32 @@ floaty get centos-7-x86_64=2 debian-7-x86_64 windows-10=3 --token mytokenstring
|
|
90
90
|
|
91
91
|
### vmfloaty dotfile
|
92
92
|
|
93
|
-
If you do not wish to continually specify various config options with the cli, you can
|
93
|
+
If you do not wish to continually specify various config options with the cli, you can `~/.vmfloaty.yml` for some defaults. You can get a list of valid service types and example configuration files via `floaty service types` and `floaty service examples`, respectively.
|
94
94
|
|
95
95
|
#### Basic configuration
|
96
96
|
|
97
|
-
|
98
|
-
# file at ~/.vmfloaty.yml
|
99
|
-
url: 'https://vmpooler.example.net/api/v1'
|
100
|
-
user: 'brian'
|
101
|
-
token: 'tokenstring'
|
102
|
-
```
|
103
|
-
|
104
|
-
Now vmfloaty will use those config files if no flag was specified.
|
105
|
-
|
106
|
-
#### Default to Puppet's ABS instead of vmpooler
|
97
|
+
This is the simplest type of configuration where you only need a single service:
|
107
98
|
|
108
99
|
```yaml
|
109
100
|
# file at ~/.vmfloaty.yml
|
110
|
-
url: 'https://
|
101
|
+
url: 'https://vmpooler.example.net/api/v1'
|
111
102
|
user: 'brian'
|
112
103
|
token: 'tokenstring'
|
113
|
-
type: 'abs'
|
114
104
|
```
|
115
105
|
|
116
|
-
|
106
|
+
Run `floaty service examples` to see additional configuration options
|
117
107
|
|
118
|
-
|
108
|
+
#### Using multiple services
|
119
109
|
|
120
|
-
|
121
|
-
|
122
|
-
```yaml
|
123
|
-
# file at /Users/me/.vmfloaty.yml
|
124
|
-
user: 'brian'
|
125
|
-
services:
|
126
|
-
main:
|
127
|
-
url: 'https://vmpooler.example.net/api/v1'
|
128
|
-
token: 'tokenstring'
|
129
|
-
alternate:
|
130
|
-
url: 'https://vmpooler.example.com/api/v1'
|
131
|
-
token: 'alternate-tokenstring'
|
132
|
-
```
|
110
|
+
Most commands allow you to specify a `--service <servicename>` option to allow the use of multiple pooler instances. This can be useful when you'd rather not specify a `--url` or `--token` by hand for alternate services.
|
133
111
|
|
134
112
|
- If you run `floaty` without a `--service <name>` option, vmfloaty will use the first configured service by default.
|
135
|
-
With the config file above, the default would be to use the 'main' vmpooler instance.
|
136
113
|
- If keys are missing for a configured service, vmfloaty will attempt to fall back to the top-level values.
|
137
|
-
|
138
|
-
|
139
|
-
Examples using the above configuration:
|
140
|
-
|
141
|
-
List available vm types from our main vmpooler instance:
|
142
|
-
|
143
|
-
```bash
|
144
|
-
floaty list --service main
|
145
|
-
# or, since the first configured service is used by default:
|
146
|
-
floaty list
|
147
|
-
```
|
148
|
-
|
149
|
-
List available vm types from our alternate vmpooler instance:
|
150
|
-
|
151
|
-
```bash
|
152
|
-
floaty list --service alternate
|
153
|
-
```
|
114
|
+
This makes it so you can specify things like `user` once at the top of your `~/.vmfloaty.yml`.
|
154
115
|
|
155
|
-
#### Using
|
116
|
+
#### Using backends besides VMPooler
|
156
117
|
|
157
|
-
vmfloaty
|
158
|
-
|
159
|
-
```yaml
|
160
|
-
# file at /Users/me/.vmfloaty.yml
|
161
|
-
user: 'brian'
|
162
|
-
services:
|
163
|
-
vm:
|
164
|
-
url: 'https://vmpooler.example.net/api/v1'
|
165
|
-
token: 'tokenstring'
|
166
|
-
ns:
|
167
|
-
url: 'https://nspooler.example.net/api/v1'
|
168
|
-
token: 'nspooler-tokenstring'
|
169
|
-
type: 'nonstandard' # <-- 'type' is necessary for any non-vmpooler service
|
170
|
-
abs:
|
171
|
-
url: 'https://abs.example.net/'
|
172
|
-
token: 'abs-tokenstring'
|
173
|
-
type: 'abs' # <-- 'type' is necessary for any non-vmpooler service
|
174
|
-
|
175
|
-
```
|
176
|
-
|
177
|
-
With this configuration, you could list available OS types from nspooler like this:
|
178
|
-
|
179
|
-
```bash
|
180
|
-
floaty list --service ns
|
181
|
-
```
|
118
|
+
vmfloaty supports additional backends besides VMPooler. To see a complete list, run `floaty service types`. The output of `floaty service examples` will show you how to configure each of the supported backends.
|
182
119
|
|
183
120
|
#### Valid config keys
|
184
121
|
|
@@ -190,6 +127,7 @@ Here are the keys that vmfloaty currently supports:
|
|
190
127
|
- url (String)
|
191
128
|
- services (String)
|
192
129
|
- type (String)
|
130
|
+
- vmpooler_fallback (String)
|
193
131
|
|
194
132
|
### Tab Completion
|
195
133
|
|
@@ -207,6 +145,12 @@ If you are running on macOS and use Homebrew's `bash-completion` formula, you ca
|
|
207
145
|
ln -s $(floaty completion --shell bash) /usr/local/etc/bash_completion.d/floaty
|
208
146
|
```
|
209
147
|
|
148
|
+
There is also tab completion for zsh:
|
149
|
+
|
150
|
+
```zsh
|
151
|
+
source $(floaty completion --shell zsh)
|
152
|
+
```
|
153
|
+
|
210
154
|
## vmpooler API
|
211
155
|
|
212
156
|
This cli tool uses the [vmpooler API](https://github.com/puppetlabs/vmpooler/blob/master/API.md).
|
@@ -7,7 +7,7 @@ _vmfloaty()
|
|
7
7
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
8
8
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
9
9
|
|
10
|
-
subcommands="delete get help list modify query revert snapshot ssh status summary token"
|
10
|
+
subcommands="delete get help list modify query revert service snapshot ssh status summary token"
|
11
11
|
template_subcommands="get ssh"
|
12
12
|
hostname_subcommands="delete modify query revert snapshot"
|
13
13
|
|
@@ -21,7 +21,7 @@ _vmfloaty()
|
|
21
21
|
|
22
22
|
COMPREPLY=( $(compgen -W "${_vmfloaty_avail_templates}" -- "${cur}") )
|
23
23
|
elif [[ $hostname_subcommands =~ (^| )$prev($| ) ]] ; then
|
24
|
-
_vmfloaty_active_hostnames=$(floaty list --active 2>/dev/null
|
24
|
+
_vmfloaty_active_hostnames=$(floaty list --active --hostnameonly 2>/dev/null)
|
25
25
|
COMPREPLY=( $(compgen -W "${_vmfloaty_active_hostnames}" -- "${cur}") )
|
26
26
|
else
|
27
27
|
COMPREPLY=( $(compgen -W "${subcommands}" -- "${cur}") )
|
@@ -0,0 +1,37 @@
|
|
1
|
+
_floaty()
|
2
|
+
{
|
3
|
+
local line subcommands template_subcommands hostname_subcommands
|
4
|
+
|
5
|
+
subcommands="delete get help list modify query revert snapshot ssh status summary token"
|
6
|
+
|
7
|
+
template_subcommands=("get" "ssh")
|
8
|
+
hostname_subcommands=("delete" "modify" "query" "revert" "snapshot")
|
9
|
+
|
10
|
+
_arguments -C \
|
11
|
+
"1: :(${subcommands})" \
|
12
|
+
"*::arg:->args"
|
13
|
+
|
14
|
+
if ((template_subcommands[(Ie)$line[1]])); then
|
15
|
+
_floaty_template_sub
|
16
|
+
elif ((hostname_subcommands[(Ie)$line[1]])); then
|
17
|
+
_floaty_hostname_sub
|
18
|
+
fi
|
19
|
+
}
|
20
|
+
|
21
|
+
_floaty_template_sub()
|
22
|
+
{
|
23
|
+
if [[ -z "$_vmfloaty_avail_templates" ]] ; then
|
24
|
+
_vmfloaty_avail_templates=$(floaty list 2>/dev/null)
|
25
|
+
fi
|
26
|
+
|
27
|
+
_arguments "1: :(${_vmfloaty_avail_templates})"
|
28
|
+
}
|
29
|
+
|
30
|
+
_floaty_hostname_sub()
|
31
|
+
{
|
32
|
+
_vmfloaty_active_hostnames=$(floaty list --active --hostnameonly 2>/dev/null)
|
33
|
+
|
34
|
+
_arguments "1: :(${_vmfloaty_active_hostnames})"
|
35
|
+
}
|
36
|
+
|
37
|
+
compdef _floaty floaty
|
data/lib/vmfloaty.rb
CHANGED
@@ -20,7 +20,7 @@ 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"
|
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."
|
24
24
|
|
25
25
|
config = Conf.read_config
|
26
26
|
|
@@ -88,8 +88,10 @@ class Vmfloaty
|
|
88
88
|
c.option '--service STRING', String, 'Configured pooler service name'
|
89
89
|
c.option '--active', 'Prints information about active vms for a given token'
|
90
90
|
c.option '--json', 'Prints information as JSON'
|
91
|
+
c.option '--hostnameonly', 'When listing active vms, prints only hostnames, one per line'
|
91
92
|
c.option '--token STRING', String, 'Token for pooler service'
|
92
93
|
c.option '--url STRING', String, 'URL of pooler service'
|
94
|
+
c.option '--user STRING', String, 'User to authenticate with'
|
93
95
|
c.action do |args, options|
|
94
96
|
verbose = options.verbose || config['verbose']
|
95
97
|
|
@@ -98,7 +100,12 @@ class Vmfloaty
|
|
98
100
|
|
99
101
|
if options.active
|
100
102
|
# list active vms
|
101
|
-
|
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
|
102
109
|
host = URI.parse(service.url).host
|
103
110
|
if running_vms.empty?
|
104
111
|
if options.json
|
@@ -109,6 +116,10 @@ class Vmfloaty
|
|
109
116
|
else
|
110
117
|
if options.json
|
111
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
|
112
123
|
else
|
113
124
|
puts "Your VMs on #{host}:"
|
114
125
|
Utils.pretty_print_hosts(verbose, service, running_vms)
|
@@ -125,7 +136,7 @@ class Vmfloaty
|
|
125
136
|
command :query do |c|
|
126
137
|
c.syntax = 'floaty query hostname [options]'
|
127
138
|
c.summary = 'Get information about a given vm'
|
128
|
-
c.description = 'Given a hostname from the pooler service, vmfloaty with query the service to get various details about the vm.'
|
139
|
+
c.description = 'Given a hostname from the pooler service, vmfloaty with query the service to get various details about the vm. If using ABS, you can query a job_id'
|
129
140
|
c.example 'Get information about a sample host', 'floaty query hostname --url http://vmpooler.example.com'
|
130
141
|
c.option '--verbose', 'Enables verbose output'
|
131
142
|
c.option '--service STRING', String, 'Configured pooler service name'
|
@@ -164,7 +175,12 @@ class Vmfloaty
|
|
164
175
|
FloatyLogger.error 'ERROR: Provide a hostname or specify --all.'
|
165
176
|
exit 1
|
166
177
|
end
|
167
|
-
running_vms =
|
178
|
+
running_vms =
|
179
|
+
if modify_all
|
180
|
+
service.list_active(verbose)
|
181
|
+
else
|
182
|
+
hostname.split(',')
|
183
|
+
end
|
168
184
|
|
169
185
|
tags = options.tags ? JSON.parse(options.tags) : nil
|
170
186
|
modify_hash = {
|
@@ -188,7 +204,7 @@ class Vmfloaty
|
|
188
204
|
end
|
189
205
|
if ok
|
190
206
|
if modify_all
|
191
|
-
puts
|
207
|
+
puts "Successfully modified all #{running_vms.count} VMs."
|
192
208
|
else
|
193
209
|
puts "Successfully modified VM #{hostname}."
|
194
210
|
end
|
@@ -212,6 +228,7 @@ class Vmfloaty
|
|
212
228
|
c.option '--json', 'Outputs hosts scheduled for deletion as JSON'
|
213
229
|
c.option '--token STRING', String, 'Token for pooler service'
|
214
230
|
c.option '--url STRING', String, 'URL of pooler service'
|
231
|
+
c.option '--user STRING', String, 'User to authenticate with'
|
215
232
|
c.action do |args, options|
|
216
233
|
verbose = options.verbose || config['verbose']
|
217
234
|
service = Service.new(options, config)
|
@@ -223,7 +240,12 @@ class Vmfloaty
|
|
223
240
|
successes = []
|
224
241
|
|
225
242
|
if delete_all
|
226
|
-
|
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
|
227
249
|
if running_vms.empty?
|
228
250
|
if options.json
|
229
251
|
puts {}.to_json
|
@@ -272,7 +294,6 @@ class Vmfloaty
|
|
272
294
|
end
|
273
295
|
|
274
296
|
unless successes.empty?
|
275
|
-
FloatyLogger.info unless failures.empty?
|
276
297
|
if options.json
|
277
298
|
puts successes.to_json
|
278
299
|
else
|
@@ -481,6 +502,70 @@ class Vmfloaty
|
|
481
502
|
end
|
482
503
|
end
|
483
504
|
|
505
|
+
command :service do |c|
|
506
|
+
c.syntax = 'floaty service <types examples>'
|
507
|
+
c.summary = 'Display information about floaty services and their configuration'
|
508
|
+
c.description = 'Display information about floaty services to aid in setting up a configuration file.'
|
509
|
+
c.example 'Print a list of the valid service types', 'floaty service types'
|
510
|
+
c.example 'Print a sample config file with multiple services', 'floaty service examples'
|
511
|
+
c.example 'list vms from the service named "nspooler-prod"', 'floaty list --service nspooler-prod'
|
512
|
+
c.action do |args, options|
|
513
|
+
action = args.first
|
514
|
+
|
515
|
+
example_config = Utils.strip_heredoc(<<-CONFIG)
|
516
|
+
# Sample ~/.vmfloaty.yml with just vmpooler
|
517
|
+
user: 'jdoe'
|
518
|
+
url: 'https://vmpooler.example.net'
|
519
|
+
token: '456def789'
|
520
|
+
|
521
|
+
# Sample ~/.vmfloaty.yml with multiple services
|
522
|
+
# Note: when the --service is not specified on the command line,
|
523
|
+
# the first service listed here is selected automatically
|
524
|
+
user: 'jdoe'
|
525
|
+
services:
|
526
|
+
abs-prod:
|
527
|
+
type: 'abs'
|
528
|
+
url: 'https://abs.example.net/api/v2'
|
529
|
+
token: '123abc456'
|
530
|
+
vmpooler_fallback: 'vmpooler-prod'
|
531
|
+
nspooler-prod:
|
532
|
+
type: 'nspooler'
|
533
|
+
url: 'https://nspooler.example.net'
|
534
|
+
token: '789ghi012'
|
535
|
+
vmpooler-dev:
|
536
|
+
type: 'vmpooler'
|
537
|
+
url: 'https://vmpooler-dev.example.net'
|
538
|
+
token: '987dsa654'
|
539
|
+
vmpooler-prod:
|
540
|
+
type: 'vmpooler'
|
541
|
+
url: 'https://vmpooler.example.net'
|
542
|
+
token: '456def789'
|
543
|
+
|
544
|
+
CONFIG
|
545
|
+
|
546
|
+
types_output = Utils.strip_heredoc(<<-TYPES)
|
547
|
+
The values on the left below can be used in ~/.vmfloaty.yml as the value of type:
|
548
|
+
|
549
|
+
abs: Puppet's Always Be Scheduling
|
550
|
+
nspooler: Puppet's Non-standard Pooler, aka NSPooler
|
551
|
+
vmpooler: Puppet's VMPooler
|
552
|
+
TYPES
|
553
|
+
|
554
|
+
case action
|
555
|
+
when 'examples'
|
556
|
+
FloatyLogger.info example_config
|
557
|
+
when 'types'
|
558
|
+
FloatyLogger.info types_output
|
559
|
+
when nil
|
560
|
+
FloatyLogger.error 'No action provided'
|
561
|
+
exit 1
|
562
|
+
else
|
563
|
+
FloatyLogger.error "Unknown action: #{action}"
|
564
|
+
exit 1
|
565
|
+
end
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
484
569
|
run!
|
485
570
|
end
|
486
571
|
end
|
data/lib/vmfloaty/abs.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'vmfloaty/errors'
|
4
4
|
require 'vmfloaty/http'
|
5
|
+
require 'vmfloaty/utils'
|
5
6
|
require 'faraday'
|
6
7
|
require 'json'
|
7
8
|
|
@@ -36,39 +37,61 @@ class ABS
|
|
36
37
|
# }
|
37
38
|
# }
|
38
39
|
#
|
39
|
-
|
40
40
|
@active_hostnames = {}
|
41
41
|
|
42
|
-
def self.
|
43
|
-
|
42
|
+
def self.list_active_job_ids(verbose, url, user)
|
43
|
+
all_job_ids = []
|
44
44
|
@active_hostnames = {}
|
45
|
+
get_active_requests(verbose, url, user).each do |req_hash|
|
46
|
+
@active_hostnames[req_hash['request']['job']['id']] = req_hash # full hash saved for later retrieval
|
47
|
+
all_job_ids.push(req_hash['request']['job']['id'])
|
48
|
+
end
|
49
|
+
|
50
|
+
all_job_ids
|
51
|
+
end
|
45
52
|
|
53
|
+
def self.list_active(verbose, url, _token, user)
|
54
|
+
hosts = []
|
46
55
|
get_active_requests(verbose, url, user).each do |req_hash|
|
47
|
-
|
48
|
-
|
56
|
+
if req_hash.key?('allocated_resources')
|
57
|
+
req_hash['allocated_resources'].each do |onehost|
|
58
|
+
hosts.push(onehost['hostname'])
|
59
|
+
end
|
60
|
+
end
|
49
61
|
end
|
50
62
|
|
51
|
-
|
63
|
+
hosts
|
52
64
|
end
|
53
65
|
|
54
66
|
def self.get_active_requests(verbose, url, user)
|
55
67
|
conn = Http.get_conn(verbose, url)
|
56
68
|
res = conn.get 'status/queue'
|
57
|
-
|
69
|
+
if valid_json?(res.body)
|
70
|
+
requests = JSON.parse(res.body)
|
71
|
+
else
|
72
|
+
FloatyLogger.warn "Warning: couldn't parse body returned from abs/status/queue"
|
73
|
+
end
|
58
74
|
|
59
75
|
ret_val = []
|
60
76
|
|
61
77
|
requests.each do |req|
|
62
78
|
next if req == 'null'
|
63
79
|
|
64
|
-
|
80
|
+
if valid_json?(req) # legacy ABS had another JSON string always-be-scheduling/pull/306
|
81
|
+
req_hash = JSON.parse(req)
|
82
|
+
elsif req.is_a?(Hash)
|
83
|
+
req_hash = req
|
84
|
+
else
|
85
|
+
FloatyLogger.warn "Warning: couldn't parse request returned from abs/status/queue"
|
86
|
+
next
|
87
|
+
end
|
65
88
|
|
66
89
|
begin
|
67
90
|
next unless user == req_hash['request']['job']['user']
|
68
91
|
|
69
92
|
ret_val.push(req_hash)
|
70
93
|
rescue NoMethodError
|
71
|
-
FloatyLogger.warn "Warning: couldn't parse
|
94
|
+
FloatyLogger.warn "Warning: couldn't parse user returned from abs/status/queue: "
|
72
95
|
end
|
73
96
|
end
|
74
97
|
|
@@ -145,30 +168,59 @@ class ABS
|
|
145
168
|
os_list = []
|
146
169
|
|
147
170
|
res = conn.get 'status/platforms/vmpooler'
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
171
|
+
if valid_json?(res.body)
|
172
|
+
res_body = JSON.parse(res.body)
|
173
|
+
if res_body.key?('vmpooler_platforms')
|
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
|
180
|
+
end
|
181
|
+
end
|
152
182
|
|
153
183
|
res = conn.get 'status/platforms/ondemand_vmpooler'
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
184
|
+
if valid_json?(res.body)
|
185
|
+
res_body = JSON.parse(res.body)
|
186
|
+
if res_body.key?('ondemand_vmpooler_platforms') && res_body['ondemand_vmpooler_platforms'] != '[]'
|
187
|
+
os_list << ''
|
188
|
+
os_list << '*** VMPOOLER ONDEMAND Pools ***'
|
189
|
+
if res_body['ondemand_vmpooler_platforms'].is_a?(String)
|
190
|
+
os_list += JSON.parse(res_body['ondemand_vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
|
191
|
+
else
|
192
|
+
os_list += res_body['ondemand_vmpooler_platforms']
|
193
|
+
end
|
194
|
+
end
|
159
195
|
end
|
160
196
|
|
161
197
|
res = conn.get 'status/platforms/nspooler'
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
198
|
+
if valid_json?(res.body)
|
199
|
+
res_body = JSON.parse(res.body)
|
200
|
+
if res_body.key?('nspooler_platforms')
|
201
|
+
os_list << ''
|
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
|
208
|
+
end
|
209
|
+
end
|
166
210
|
|
167
211
|
res = conn.get 'status/platforms/aws'
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
212
|
+
if valid_json?(res.body)
|
213
|
+
res_body = JSON.parse(res.body)
|
214
|
+
if res_body.key?('aws_platforms')
|
215
|
+
os_list << ''
|
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
|
222
|
+
end
|
223
|
+
end
|
172
224
|
|
173
225
|
os_list.delete 'ok'
|
174
226
|
|
@@ -176,7 +228,7 @@ class ABS
|
|
176
228
|
end
|
177
229
|
|
178
230
|
# Retrieve an OS from ABS.
|
179
|
-
def self.retrieve(verbose, os_types, token, url, user,
|
231
|
+
def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil)
|
180
232
|
#
|
181
233
|
# Contents of post must be like:
|
182
234
|
#
|
@@ -197,7 +249,7 @@ class ABS
|
|
197
249
|
conn.headers['X-AUTH-TOKEN'] = token if token
|
198
250
|
|
199
251
|
saved_job_id = DateTime.now.strftime('%Q')
|
200
|
-
|
252
|
+
vmpooler_config = Utils.get_vmpooler_service_config(config['vmpooler_fallback'])
|
201
253
|
req_obj = {
|
202
254
|
:resources => os_types,
|
203
255
|
:job => {
|
@@ -206,17 +258,18 @@ class ABS
|
|
206
258
|
:user => user,
|
207
259
|
},
|
208
260
|
},
|
261
|
+
:vm_token => vmpooler_config['token'] # request with this token, on behalf of this user
|
209
262
|
}
|
210
263
|
|
211
|
-
if
|
212
|
-
req_obj[:priority] = if
|
264
|
+
if config['priority']
|
265
|
+
req_obj[:priority] = if config['priority'] == 'high'
|
213
266
|
1
|
214
|
-
elsif
|
267
|
+
elsif config['priority'] == 'medium'
|
215
268
|
2
|
216
|
-
elsif
|
269
|
+
elsif config['priority'] == 'low'
|
217
270
|
3
|
218
271
|
else
|
219
|
-
|
272
|
+
config['priority'].to_i
|
220
273
|
end
|
221
274
|
end
|
222
275
|
|
@@ -233,7 +286,7 @@ class ABS
|
|
233
286
|
|
234
287
|
(1..retries).each do |i|
|
235
288
|
queue_place, res_body = check_queue(conn, saved_job_id, req_obj, verbose)
|
236
|
-
return translated(res_body) if res_body
|
289
|
+
return translated(res_body, saved_job_id) if res_body
|
237
290
|
|
238
291
|
sleep_seconds = 10 if i >= 10
|
239
292
|
sleep_seconds = i if i < 10
|
@@ -247,8 +300,8 @@ class ABS
|
|
247
300
|
#
|
248
301
|
# We should fix the ABS API to be more like the vmpooler or nspooler api, but for now
|
249
302
|
#
|
250
|
-
def self.translated(res_body)
|
251
|
-
vmpooler_formatted_body = {}
|
303
|
+
def self.translated(res_body, job_id)
|
304
|
+
vmpooler_formatted_body = {'job_id' => job_id}
|
252
305
|
|
253
306
|
res_body.each do |host|
|
254
307
|
if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].class == Array
|
@@ -264,12 +317,17 @@ class ABS
|
|
264
317
|
|
265
318
|
def self.check_queue(conn, job_id, req_obj, verbose)
|
266
319
|
queue_info_res = conn.get "status/queue/info/#{job_id}"
|
267
|
-
|
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
|
268
326
|
|
269
327
|
res = conn.post 'request', req_obj.to_json
|
270
328
|
validate_queue_status_response(res.status, res.body, "Check queue request", verbose)
|
271
329
|
|
272
|
-
unless res.body.empty?
|
330
|
+
unless res.body.empty? || !valid_json?(res.body)
|
273
331
|
res_body = JSON.parse(res.body)
|
274
332
|
return queue_info['queue_place'], res_body
|
275
333
|
end
|
@@ -277,7 +335,7 @@ class ABS
|
|
277
335
|
end
|
278
336
|
|
279
337
|
def self.snapshot(_verbose, _url, _hostname, _token)
|
280
|
-
|
338
|
+
raise NoMethodError, "Can't snapshot with ABS, use '--service vmpooler' (even for vms checked out with ABS)"
|
281
339
|
end
|
282
340
|
|
283
341
|
def self.status(verbose, url)
|
@@ -289,20 +347,24 @@ class ABS
|
|
289
347
|
end
|
290
348
|
|
291
349
|
def self.summary(verbose, url)
|
292
|
-
|
293
|
-
|
294
|
-
res = conn.get 'summary'
|
295
|
-
JSON.parse(res.body)
|
350
|
+
raise NoMethodError, 'summary is not defined for ABS'
|
296
351
|
end
|
297
352
|
|
298
|
-
def self.query(verbose, url,
|
299
|
-
return
|
353
|
+
def self.query(verbose, url, job_id)
|
354
|
+
# return saved hostnames from the last time list_active was run
|
355
|
+
# preventing having to query the API again.
|
356
|
+
# This works as long as query is called after list_active
|
357
|
+
return @active_hostnames if @active_hostnames && !@active_hostnames.empty?
|
300
358
|
|
301
|
-
|
359
|
+
# If using the cli query job_id
|
302
360
|
conn = Http.get_conn(verbose, url)
|
303
|
-
|
304
|
-
|
305
|
-
|
361
|
+
queue_info_res = conn.get "status/queue/info/#{job_id}"
|
362
|
+
if valid_json?(queue_info_res.body)
|
363
|
+
queue_info = JSON.parse(queue_info_res.body)
|
364
|
+
else
|
365
|
+
FloatyLogger.warn "Could not parse the status/queue/info/#{job_id}"
|
366
|
+
end
|
367
|
+
queue_info
|
306
368
|
end
|
307
369
|
|
308
370
|
def self.modify(_verbose, _url, _hostname, _token, _modify_hash)
|
@@ -333,4 +395,11 @@ class ABS
|
|
333
395
|
raise "HTTP #{status_code}: #{request_name} request to ABS failed!\n#{body}"
|
334
396
|
end
|
335
397
|
end
|
398
|
+
|
399
|
+
def self.valid_json?(json)
|
400
|
+
JSON.parse(json)
|
401
|
+
return true
|
402
|
+
rescue TypeError, JSON::ParserError => e
|
403
|
+
return false
|
404
|
+
end
|
336
405
|
end
|