vmpooler 0.11.3 → 0.13.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/vmpooler +3 -1
- data/lib/vmpooler.rb +23 -1
- data/lib/vmpooler/api/helpers.rb +16 -16
- data/lib/vmpooler/api/v1.rb +285 -17
- data/lib/vmpooler/generic_connection_pool.rb +5 -23
- data/lib/vmpooler/graphite.rb +2 -0
- data/lib/vmpooler/pool_manager.rb +750 -389
- data/lib/vmpooler/providers/base.rb +2 -1
- data/lib/vmpooler/providers/dummy.rb +2 -2
- data/lib/vmpooler/providers/vsphere.rb +50 -30
- data/lib/vmpooler/util/parsing.rb +16 -0
- data/lib/vmpooler/version.rb +1 -1
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe0ef9bcf3e665cc952fce0975a4381883fca200ef93a883e54c7db7e1fc10e7
|
4
|
+
data.tar.gz: d44b61c41a57f940cf0df4bf07aabed10b1a72e91cae5b2105f092a7d98d6d05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0e7bbec11ceecc5fdee0fe15b3d37e290a6c884a708a6a5acb2e790d54fb1f1e24ec6966973f02bbecd204a29497e9c17ae3b8be26a0d3f15cec508a0d64532
|
7
|
+
data.tar.gz: 7302cf41676a65ff5d0bb4108a8f5ac03a96a92e3cd0ec56deee2f2a60d6e73f09eee569ef0f4140e3c27e81a16c3e2d24b951764a772bdeaa082a96d8bde1fe
|
data/bin/vmpooler
CHANGED
@@ -7,6 +7,8 @@ config = Vmpooler.config
|
|
7
7
|
redis_host = config[:redis]['server']
|
8
8
|
redis_port = config[:redis]['port']
|
9
9
|
redis_password = config[:redis]['password']
|
10
|
+
redis_connection_pool_size = config[:redis]['connection_pool_size']
|
11
|
+
redis_connection_pool_timeout = config[:redis]['connection_pool_timeout']
|
10
12
|
logger_file = config[:config]['logfile']
|
11
13
|
|
12
14
|
metrics = Vmpooler.new_metrics(config)
|
@@ -36,7 +38,7 @@ if torun.include? 'manager'
|
|
36
38
|
Vmpooler::PoolManager.new(
|
37
39
|
config,
|
38
40
|
Vmpooler.new_logger(logger_file),
|
39
|
-
Vmpooler.
|
41
|
+
Vmpooler.redis_connection_pool(redis_host, redis_port, redis_password, redis_connection_pool_size, redis_connection_pool_timeout, metrics),
|
40
42
|
metrics
|
41
43
|
).execute!
|
42
44
|
end
|
data/lib/vmpooler.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Vmpooler
|
4
|
+
require 'concurrent'
|
4
5
|
require 'date'
|
5
6
|
require 'json'
|
6
7
|
require 'net/ldap'
|
@@ -58,9 +59,14 @@ module Vmpooler
|
|
58
59
|
|
59
60
|
# Set some configuration defaults
|
60
61
|
parsed_config[:config]['task_limit'] = string_to_int(ENV['TASK_LIMIT']) || parsed_config[:config]['task_limit'] || 10
|
62
|
+
parsed_config[:config]['ondemand_clone_limit'] = string_to_int(ENV['ONDEMAND_CLONE_LIMIT']) || parsed_config[:config]['ondemand_clone_limit'] || 10
|
63
|
+
parsed_config[:config]['max_ondemand_instances_per_request'] = string_to_int(ENV['MAX_ONDEMAND_INSTANCES_PER_REQUEST']) || parsed_config[:config]['max_ondemand_instances_per_request'] || 10
|
61
64
|
parsed_config[:config]['migration_limit'] = string_to_int(ENV['MIGRATION_LIMIT']) if ENV['MIGRATION_LIMIT']
|
62
65
|
parsed_config[:config]['vm_checktime'] = string_to_int(ENV['VM_CHECKTIME']) || parsed_config[:config]['vm_checktime'] || 1
|
63
66
|
parsed_config[:config]['vm_lifetime'] = string_to_int(ENV['VM_LIFETIME']) || parsed_config[:config]['vm_lifetime'] || 24
|
67
|
+
parsed_config[:config]['max_lifetime_upper_limit'] = string_to_int(ENV['MAX_LIFETIME_UPPER_LIMIT']) || parsed_config[:config]['max_lifetime_upper_limit']
|
68
|
+
parsed_config[:config]['ready_ttl'] = string_to_int(ENV['READY_TTL']) || parsed_config[:config]['ready_ttl'] || 60
|
69
|
+
parsed_config[:config]['ondemand_request_ttl'] = string_to_int(ENV['ONDEMAND_REQUEST_TTL']) || parsed_config[:config]['ondemand_request_ttl'] || 5
|
64
70
|
parsed_config[:config]['prefix'] = ENV['PREFIX'] || parsed_config[:config]['prefix'] || ''
|
65
71
|
|
66
72
|
parsed_config[:config]['logfile'] = ENV['LOGFILE'] if ENV['LOGFILE']
|
@@ -72,7 +78,7 @@ module Vmpooler
|
|
72
78
|
parsed_config[:config]['vm_lifetime_auth'] = string_to_int(ENV['VM_LIFETIME_AUTH']) if ENV['VM_LIFETIME_AUTH']
|
73
79
|
parsed_config[:config]['max_tries'] = string_to_int(ENV['MAX_TRIES']) if ENV['MAX_TRIES']
|
74
80
|
parsed_config[:config]['retry_factor'] = string_to_int(ENV['RETRY_FACTOR']) if ENV['RETRY_FACTOR']
|
75
|
-
parsed_config[:config]['create_folders'] = ENV['CREATE_FOLDERS'] if ENV['CREATE_FOLDERS']
|
81
|
+
parsed_config[:config]['create_folders'] = true?(ENV['CREATE_FOLDERS']) if ENV['CREATE_FOLDERS']
|
76
82
|
parsed_config[:config]['create_template_delta_disks'] = ENV['CREATE_TEMPLATE_DELTA_DISKS'] if ENV['CREATE_TEMPLATE_DELTA_DISKS']
|
77
83
|
set_linked_clone(parsed_config)
|
78
84
|
parsed_config[:config]['experimental_features'] = ENV['EXPERIMENTAL_FEATURES'] if ENV['EXPERIMENTAL_FEATURES']
|
@@ -84,6 +90,8 @@ module Vmpooler
|
|
84
90
|
parsed_config[:redis]['port'] = string_to_int(ENV['REDIS_PORT']) if ENV['REDIS_PORT']
|
85
91
|
parsed_config[:redis]['password'] = ENV['REDIS_PASSWORD'] if ENV['REDIS_PASSWORD']
|
86
92
|
parsed_config[:redis]['data_ttl'] = string_to_int(ENV['REDIS_DATA_TTL']) || parsed_config[:redis]['data_ttl'] || 168
|
93
|
+
parsed_config[:redis]['connection_pool_size'] = string_to_int(ENV['REDIS_CONNECTION_POOL_SIZE']) || parsed_config[:redis]['connection_pool_size'] || 10
|
94
|
+
parsed_config[:redis]['connection_pool_timeout'] = string_to_int(ENV['REDIS_CONNECTION_POOL_TIMEOUT']) || parsed_config[:redis]['connection_pool_timeout'] || 5
|
87
95
|
|
88
96
|
parsed_config[:statsd] = parsed_config[:statsd] || {} if ENV['STATSD_SERVER']
|
89
97
|
parsed_config[:statsd]['server'] = ENV['STATSD_SERVER'] if ENV['STATSD_SERVER']
|
@@ -117,6 +125,7 @@ module Vmpooler
|
|
117
125
|
|
118
126
|
parsed_config[:pools].each do |pool|
|
119
127
|
parsed_config[:pool_names] << pool['name']
|
128
|
+
pool['ready_ttl'] ||= parsed_config[:config]['ready_ttl']
|
120
129
|
if pool['alias']
|
121
130
|
if pool['alias'].is_a?(Array)
|
122
131
|
pool['alias'].each do |pool_alias|
|
@@ -154,6 +163,19 @@ module Vmpooler
|
|
154
163
|
pools
|
155
164
|
end
|
156
165
|
|
166
|
+
def self.redis_connection_pool(host, port, password, size, timeout, metrics)
|
167
|
+
Vmpooler::PoolManager::GenericConnectionPool.new(
|
168
|
+
metrics: metrics,
|
169
|
+
metric_prefix: 'redis_connection_pool',
|
170
|
+
size: size,
|
171
|
+
timeout: timeout
|
172
|
+
) do
|
173
|
+
connection = Concurrent::Hash.new
|
174
|
+
redis = new_redis(host, port, password)
|
175
|
+
connection['connection'] = redis
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
157
179
|
def self.new_redis(host = 'localhost', port = nil, password = nil)
|
158
180
|
Redis.new(host: host, port: port, password: password)
|
159
181
|
end
|
data/lib/vmpooler/api/helpers.rb
CHANGED
@@ -84,29 +84,29 @@ module Vmpooler
|
|
84
84
|
when 'ldap'
|
85
85
|
ldap_base = auth[:ldap]['base']
|
86
86
|
ldap_port = auth[:ldap]['port'] || 389
|
87
|
+
ldap_user_obj = auth[:ldap]['user_object']
|
88
|
+
ldap_host = auth[:ldap]['host']
|
87
89
|
|
88
|
-
|
89
|
-
ldap_base
|
90
|
+
unless ldap_base.is_a? Array
|
91
|
+
ldap_base = ldap_base.split
|
92
|
+
end
|
93
|
+
|
94
|
+
unless ldap_user_obj.is_a? Array
|
95
|
+
ldap_user_obj = ldap_user_obj.split
|
96
|
+
end
|
97
|
+
|
98
|
+
ldap_base.each do |search_base|
|
99
|
+
ldap_user_obj.each do |search_user_obj|
|
90
100
|
result = authenticate_ldap(
|
91
101
|
ldap_port,
|
92
|
-
|
93
|
-
|
102
|
+
ldap_host,
|
103
|
+
search_user_obj,
|
94
104
|
search_base,
|
95
105
|
username_str,
|
96
106
|
password_str
|
97
107
|
)
|
98
|
-
return true if result
|
108
|
+
return true if result
|
99
109
|
end
|
100
|
-
else
|
101
|
-
result = authenticate_ldap(
|
102
|
-
ldap_port,
|
103
|
-
auth[:ldap]['host'],
|
104
|
-
auth[:ldap]['user_object'],
|
105
|
-
ldap_base,
|
106
|
-
username_str,
|
107
|
-
password_str
|
108
|
-
)
|
109
|
-
return result
|
110
110
|
end
|
111
111
|
|
112
112
|
return false
|
@@ -238,7 +238,7 @@ module Vmpooler
|
|
238
238
|
queue[:running] = get_total_across_pools_redis_scard(pools, 'vmpooler__running__', backend)
|
239
239
|
queue[:completed] = get_total_across_pools_redis_scard(pools, 'vmpooler__completed__', backend)
|
240
240
|
|
241
|
-
queue[:cloning] = backend.get('vmpooler__tasks__clone').to_i
|
241
|
+
queue[:cloning] = backend.get('vmpooler__tasks__clone').to_i + backend.get('vmpooler__tasks__ondemandclone').to_i
|
242
242
|
queue[:booting] = queue[:pending].to_i - queue[:cloning].to_i
|
243
243
|
queue[:booting] = 0 if queue[:booting] < 0
|
244
244
|
queue[:total] = queue[:pending].to_i + queue[:ready].to_i + queue[:running].to_i + queue[:completed].to_i
|
data/lib/vmpooler/api/v1.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'vmpooler/util/parsing'
|
4
|
+
|
3
5
|
module Vmpooler
|
4
6
|
class API
|
5
7
|
class V1 < Sinatra::Base
|
@@ -42,6 +44,68 @@ module Vmpooler
|
|
42
44
|
Vmpooler::API.settings.checkoutlock
|
43
45
|
end
|
44
46
|
|
47
|
+
def get_template_aliases(template)
|
48
|
+
result = []
|
49
|
+
aliases = Vmpooler::API.settings.config[:alias]
|
50
|
+
if aliases
|
51
|
+
result += aliases[template] if aliases[template].is_a?(Array)
|
52
|
+
template_backends << aliases[template] if aliases[template].is_a?(String)
|
53
|
+
end
|
54
|
+
result
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_pool_weights(template_backends)
|
58
|
+
pool_index = pool_index(pools)
|
59
|
+
weighted_pools = {}
|
60
|
+
template_backends.each do |t|
|
61
|
+
next unless pool_index.key? t
|
62
|
+
|
63
|
+
index = pool_index[t]
|
64
|
+
clone_target = pools[index]['clone_target'] || config['clone_target']
|
65
|
+
next unless config.key?('backend_weight')
|
66
|
+
|
67
|
+
weight = config['backend_weight'][clone_target]
|
68
|
+
if weight
|
69
|
+
weighted_pools[t] = weight
|
70
|
+
end
|
71
|
+
end
|
72
|
+
weighted_pools
|
73
|
+
end
|
74
|
+
|
75
|
+
def count_selection(selection)
|
76
|
+
result = {}
|
77
|
+
selection.uniq.each do |poolname|
|
78
|
+
result[poolname] = selection.count(poolname)
|
79
|
+
end
|
80
|
+
result
|
81
|
+
end
|
82
|
+
|
83
|
+
def evaluate_template_aliases(template, count)
|
84
|
+
template_backends = []
|
85
|
+
template_backends << template if backend.sismember('vmpooler__pools', template)
|
86
|
+
selection = []
|
87
|
+
aliases = get_template_aliases(template)
|
88
|
+
if aliases
|
89
|
+
template_backends += aliases
|
90
|
+
weighted_pools = get_pool_weights(template_backends)
|
91
|
+
|
92
|
+
pickup = Pickup.new(weighted_pools) if weighted_pools.count == template_backends.count
|
93
|
+
count.to_i.times do
|
94
|
+
if pickup
|
95
|
+
selection << pickup.pick
|
96
|
+
else
|
97
|
+
selection << template_backends.sample
|
98
|
+
end
|
99
|
+
end
|
100
|
+
else
|
101
|
+
count.to_i.times do
|
102
|
+
selection << template
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
count_selection(selection)
|
107
|
+
end
|
108
|
+
|
45
109
|
def fetch_single_vm(template)
|
46
110
|
template_backends = [template]
|
47
111
|
aliases = Vmpooler::API.settings.config[:alias]
|
@@ -245,11 +309,9 @@ module Vmpooler
|
|
245
309
|
pool_index = pool_index(pools)
|
246
310
|
template_configs = backend.hgetall('vmpooler__config__template')
|
247
311
|
template_configs&.each do |poolname, template|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
end
|
252
|
-
end
|
312
|
+
next unless pool_index.include? poolname
|
313
|
+
|
314
|
+
pools[pool_index[poolname]]['template'] = template
|
253
315
|
end
|
254
316
|
end
|
255
317
|
|
@@ -257,11 +319,9 @@ module Vmpooler
|
|
257
319
|
pool_index = pool_index(pools)
|
258
320
|
poolsize_configs = backend.hgetall('vmpooler__config__poolsize')
|
259
321
|
poolsize_configs&.each do |poolname, size|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
end
|
264
|
-
end
|
322
|
+
next unless pool_index.include? poolname
|
323
|
+
|
324
|
+
pools[pool_index[poolname]]['size'] = size.to_i
|
265
325
|
end
|
266
326
|
end
|
267
327
|
|
@@ -269,12 +329,70 @@ module Vmpooler
|
|
269
329
|
pool_index = pool_index(pools)
|
270
330
|
clone_target_configs = backend.hgetall('vmpooler__config__clone_target')
|
271
331
|
clone_target_configs&.each do |poolname, clone_target|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
332
|
+
next unless pool_index.include? poolname
|
333
|
+
|
334
|
+
pools[pool_index[poolname]]['clone_target'] = clone_target
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def too_many_requested?(payload)
|
339
|
+
payload&.each do |poolname, count|
|
340
|
+
next unless count.to_i > config['max_ondemand_instances_per_request']
|
341
|
+
|
342
|
+
metrics.increment('ondemandrequest.toomanyrequests.' + poolname)
|
343
|
+
return true
|
344
|
+
end
|
345
|
+
false
|
346
|
+
end
|
347
|
+
|
348
|
+
def generate_ondemand_request(payload)
|
349
|
+
result = { 'ok': false }
|
350
|
+
|
351
|
+
requested_instances = payload.reject { |k, _v| k == 'request_id' }
|
352
|
+
if too_many_requested?(requested_instances)
|
353
|
+
result['message'] = "requested amount of instances exceeds the maximum #{config['max_ondemand_instances_per_request']}"
|
354
|
+
status 403
|
355
|
+
return result
|
356
|
+
end
|
357
|
+
|
358
|
+
score = Time.now.to_i
|
359
|
+
request_id = payload['request_id']
|
360
|
+
request_id ||= generate_request_id
|
361
|
+
result['request_id'] = request_id
|
362
|
+
|
363
|
+
if backend.exists("vmpooler__odrequest__#{request_id}")
|
364
|
+
result['message'] = "request_id '#{request_id}' has already been created"
|
365
|
+
status 409
|
366
|
+
metrics.increment('ondemandrequest.generate.duplicaterequests')
|
367
|
+
return result
|
368
|
+
end
|
369
|
+
|
370
|
+
status 201
|
371
|
+
|
372
|
+
platforms_with_aliases = []
|
373
|
+
requested_instances.each do |poolname, count|
|
374
|
+
selection = evaluate_template_aliases(poolname, count)
|
375
|
+
selection.map { |selected_pool, selected_pool_count| platforms_with_aliases << "#{poolname}:#{selected_pool}:#{selected_pool_count}" }
|
376
|
+
end
|
377
|
+
platforms_string = platforms_with_aliases.join(',')
|
378
|
+
|
379
|
+
return result unless backend.zadd('vmpooler__provisioning__request', score, request_id)
|
380
|
+
|
381
|
+
backend.hset("vmpooler__odrequest__#{request_id}", 'requested', platforms_string)
|
382
|
+
if Vmpooler::API.settings.config[:auth] and has_token?
|
383
|
+
backend.hset("vmpooler__odrequest__#{request_id}", 'token:token', request.env['HTTP_X_AUTH_TOKEN'])
|
384
|
+
backend.hset("vmpooler__odrequest__#{request_id}", 'token:user',
|
385
|
+
backend.hget('vmpooler__token__' + request.env['HTTP_X_AUTH_TOKEN'], 'user'))
|
277
386
|
end
|
387
|
+
|
388
|
+
result['domain'] = config['domain'] if config['domain']
|
389
|
+
result[:ok] = true
|
390
|
+
metrics.increment('ondemandrequest.generate.success')
|
391
|
+
result
|
392
|
+
end
|
393
|
+
|
394
|
+
def generate_request_id
|
395
|
+
SecureRandom.uuid
|
278
396
|
end
|
279
397
|
|
280
398
|
get '/' do
|
@@ -395,7 +513,7 @@ module Vmpooler
|
|
395
513
|
end
|
396
514
|
|
397
515
|
# for backwards compatibility, include separate "empty" stats in "status" block
|
398
|
-
if ready == 0
|
516
|
+
if ready == 0 && max != 0
|
399
517
|
result[:status][:empty] ||= []
|
400
518
|
result[:status][:empty].push(pool['name'])
|
401
519
|
|
@@ -689,6 +807,88 @@ module Vmpooler
|
|
689
807
|
JSON.pretty_generate(result)
|
690
808
|
end
|
691
809
|
|
810
|
+
post "#{api_prefix}/ondemandvm/?" do
|
811
|
+
content_type :json
|
812
|
+
|
813
|
+
need_token! if Vmpooler::API.settings.config[:auth]
|
814
|
+
|
815
|
+
result = { 'ok' => false }
|
816
|
+
|
817
|
+
begin
|
818
|
+
payload = JSON.parse(request.body.read)
|
819
|
+
|
820
|
+
if payload
|
821
|
+
invalid = invalid_templates(payload.reject { |k, _v| k == 'request_id' })
|
822
|
+
if invalid.empty?
|
823
|
+
result = generate_ondemand_request(payload)
|
824
|
+
else
|
825
|
+
result[:bad_templates] = invalid
|
826
|
+
invalid.each do |bad_template|
|
827
|
+
metrics.increment('ondemandrequest.invalid.' + bad_template)
|
828
|
+
end
|
829
|
+
status 404
|
830
|
+
end
|
831
|
+
else
|
832
|
+
metrics.increment('ondemandrequest.invalid.unknown')
|
833
|
+
status 404
|
834
|
+
end
|
835
|
+
rescue JSON::ParserError
|
836
|
+
status 400
|
837
|
+
result = {
|
838
|
+
'ok' => false,
|
839
|
+
'message' => 'JSON payload could not be parsed'
|
840
|
+
}
|
841
|
+
end
|
842
|
+
|
843
|
+
JSON.pretty_generate(result)
|
844
|
+
end
|
845
|
+
|
846
|
+
post "#{api_prefix}/ondemandvm/:template/?" do
|
847
|
+
content_type :json
|
848
|
+
result = { 'ok' => false }
|
849
|
+
|
850
|
+
need_token! if Vmpooler::API.settings.config[:auth]
|
851
|
+
|
852
|
+
payload = extract_templates_from_query_params(params[:template])
|
853
|
+
|
854
|
+
if payload
|
855
|
+
invalid = invalid_templates(payload.reject { |k, _v| k == 'request_id' })
|
856
|
+
if invalid.empty?
|
857
|
+
result = generate_ondemand_request(payload)
|
858
|
+
else
|
859
|
+
result[:bad_templates] = invalid
|
860
|
+
invalid.each do |bad_template|
|
861
|
+
metrics.increment('ondemandrequest.invalid.' + bad_template)
|
862
|
+
end
|
863
|
+
status 404
|
864
|
+
end
|
865
|
+
else
|
866
|
+
metrics.increment('ondemandrequest.invalid.unknown')
|
867
|
+
status 404
|
868
|
+
end
|
869
|
+
|
870
|
+
JSON.pretty_generate(result)
|
871
|
+
end
|
872
|
+
|
873
|
+
get "#{api_prefix}/ondemandvm/:requestid/?" do
|
874
|
+
content_type :json
|
875
|
+
|
876
|
+
status 404
|
877
|
+
result = check_ondemand_request(params[:requestid])
|
878
|
+
|
879
|
+
JSON.pretty_generate(result)
|
880
|
+
end
|
881
|
+
|
882
|
+
delete "#{api_prefix}/ondemandvm/:requestid/?" do
|
883
|
+
content_type :json
|
884
|
+
need_token! if Vmpooler::API.settings.config[:auth]
|
885
|
+
|
886
|
+
status 404
|
887
|
+
result = delete_ondemand_request(params[:requestid])
|
888
|
+
|
889
|
+
JSON.pretty_generate(result)
|
890
|
+
end
|
891
|
+
|
692
892
|
post "#{api_prefix}/vm/?" do
|
693
893
|
content_type :json
|
694
894
|
result = { 'ok' => false }
|
@@ -764,6 +964,73 @@ module Vmpooler
|
|
764
964
|
invalid
|
765
965
|
end
|
766
966
|
|
967
|
+
def check_ondemand_request(request_id)
|
968
|
+
result = { 'ok' => false }
|
969
|
+
request_hash = backend.hgetall("vmpooler__odrequest__#{request_id}")
|
970
|
+
if request_hash.empty?
|
971
|
+
result['message'] = "no request found for request_id '#{request_id}'"
|
972
|
+
return result
|
973
|
+
end
|
974
|
+
|
975
|
+
result['request_id'] = request_id
|
976
|
+
result['ready'] = false
|
977
|
+
result['ok'] = true
|
978
|
+
status 202
|
979
|
+
|
980
|
+
if request_hash['status'] == 'ready'
|
981
|
+
result['ready'] = true
|
982
|
+
Parsing.get_platform_pool_count(request_hash['requested']) do |platform_alias, pool, _count|
|
983
|
+
instances = backend.smembers("vmpooler__#{request_id}__#{platform_alias}__#{pool}")
|
984
|
+
result[platform_alias] = { 'hostname': instances }
|
985
|
+
end
|
986
|
+
result['domain'] = config['domain'] if config['domain']
|
987
|
+
status 200
|
988
|
+
elsif request_hash['status'] == 'failed'
|
989
|
+
result['message'] = "The request failed to provision instances within the configured ondemand_request_ttl '#{config['ondemand_request_ttl']}'"
|
990
|
+
status 200
|
991
|
+
elsif request_hash['status'] == 'deleted'
|
992
|
+
result['message'] = 'The request has been deleted'
|
993
|
+
status 200
|
994
|
+
else
|
995
|
+
Parsing.get_platform_pool_count(request_hash['requested']) do |platform_alias, pool, count|
|
996
|
+
instance_count = backend.scard("vmpooler__#{request_id}__#{platform_alias}__#{pool}")
|
997
|
+
result[platform_alias] = {
|
998
|
+
'ready': instance_count.to_s,
|
999
|
+
'pending': (count.to_i - instance_count.to_i).to_s
|
1000
|
+
}
|
1001
|
+
end
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
result
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
def delete_ondemand_request(request_id)
|
1008
|
+
result = { 'ok' => false }
|
1009
|
+
|
1010
|
+
platforms = backend.hget("vmpooler__odrequest__#{request_id}", 'requested')
|
1011
|
+
unless platforms
|
1012
|
+
result['message'] = "no request found for request_id '#{request_id}'"
|
1013
|
+
return result
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
if backend.hget("vmpooler__odrequest__#{request_id}", 'status') == 'deleted'
|
1017
|
+
result['message'] = 'the request has already been deleted'
|
1018
|
+
else
|
1019
|
+
backend.hset("vmpooler__odrequest__#{request_id}", 'status', 'deleted')
|
1020
|
+
|
1021
|
+
Parsing.get_platform_pool_count(platforms) do |platform_alias, pool, _count|
|
1022
|
+
backend.smembers("vmpooler__#{request_id}__#{platform_alias}__#{pool}")&.each do |vm|
|
1023
|
+
backend.smove("vmpooler__running__#{pool}", "vmpooler__completed__#{pool}", vm)
|
1024
|
+
end
|
1025
|
+
backend.del("vmpooler__#{request_id}__#{platform_alias}__#{pool}")
|
1026
|
+
end
|
1027
|
+
backend.expire("vmpooler__odrequest__#{request_id}", 129_600_0)
|
1028
|
+
end
|
1029
|
+
status 200
|
1030
|
+
result['ok'] = true
|
1031
|
+
result
|
1032
|
+
end
|
1033
|
+
|
767
1034
|
post "#{api_prefix}/vm/:template/?" do
|
768
1035
|
content_type :json
|
769
1036
|
result = { 'ok' => false }
|
@@ -923,6 +1190,7 @@ module Vmpooler
|
|
923
1190
|
unless arg.to_i > 0
|
924
1191
|
failure.push("You provided a lifetime (#{arg}) but you must provide a positive number.")
|
925
1192
|
end
|
1193
|
+
|
926
1194
|
when 'tags'
|
927
1195
|
unless arg.is_a?(Hash)
|
928
1196
|
failure.push("You provided tags (#{arg}) as something other than a hash.")
|
@@ -1047,7 +1315,7 @@ module Vmpooler
|
|
1047
1315
|
invalid.each do |bad_template|
|
1048
1316
|
metrics.increment("config.invalid.#{bad_template}")
|
1049
1317
|
end
|
1050
|
-
result[:
|
1318
|
+
result[:not_configured] = invalid
|
1051
1319
|
status 400
|
1052
1320
|
end
|
1053
1321
|
else
|