vmpooler 2.0.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vmpooler/api/helpers.rb +365 -294
- data/lib/vmpooler/api/reroute.rb +16 -0
- data/lib/vmpooler/api/v1.rb +500 -377
- data/lib/vmpooler/api/v2.rb +429 -0
- data/lib/vmpooler/api.rb +2 -1
- data/lib/vmpooler/pool_manager.rb +105 -88
- data/lib/vmpooler/providers/base.rb +26 -3
- data/lib/vmpooler/util/parsing.rb +21 -1
- data/lib/vmpooler/version.rb +1 -1
- data/lib/vmpooler.rb +11 -3
- metadata +82 -48
@@ -60,6 +60,7 @@ module Vmpooler
|
|
60
60
|
to_set[k] = pool[k]
|
61
61
|
end
|
62
62
|
to_set['alias'] = pool['alias'].join(',') if to_set.key?('alias')
|
63
|
+
to_set['domain'] = Parsing.get_domain_for_pool(config, pool['name'])
|
63
64
|
redis.hmset("vmpooler__pool__#{pool['name']}", to_set.to_a.flatten) unless to_set.empty?
|
64
65
|
end
|
65
66
|
previously_configured_pools.each do |pool|
|
@@ -148,15 +149,15 @@ module Vmpooler
|
|
148
149
|
end
|
149
150
|
pool_alias = redis.hget("vmpooler__vm__#{vm}", 'pool_alias')
|
150
151
|
|
151
|
-
redis.pipelined do
|
152
|
-
|
153
|
-
|
152
|
+
redis.pipelined do |pipeline|
|
153
|
+
pipeline.hset("vmpooler__active__#{pool}", vm, Time.now)
|
154
|
+
pipeline.hset("vmpooler__vm__#{vm}", 'checkout', Time.now)
|
154
155
|
if ondemandrequest_hash['token:token']
|
155
|
-
|
156
|
-
|
157
|
-
|
156
|
+
pipeline.hset("vmpooler__vm__#{vm}", 'token:token', ondemandrequest_hash['token:token'])
|
157
|
+
pipeline.hset("vmpooler__vm__#{vm}", 'token:user', ondemandrequest_hash['token:user'])
|
158
|
+
pipeline.hset("vmpooler__vm__#{vm}", 'lifetime', $config[:config]['vm_lifetime_auth'].to_i)
|
158
159
|
end
|
159
|
-
|
160
|
+
pipeline.sadd("vmpooler__#{request_id}__#{pool_alias}__#{pool}", vm)
|
160
161
|
end
|
161
162
|
move_vm_queue(pool, vm, 'pending', 'running', redis)
|
162
163
|
check_ondemand_request_ready(request_id, redis)
|
@@ -164,12 +165,12 @@ module Vmpooler
|
|
164
165
|
redis.smove("vmpooler__pending__#{pool}", "vmpooler__ready__#{pool}", vm)
|
165
166
|
end
|
166
167
|
|
167
|
-
redis.pipelined do
|
168
|
-
|
169
|
-
|
168
|
+
redis.pipelined do |pipeline|
|
169
|
+
pipeline.hset("vmpooler__boot__#{Date.today}", "#{pool}:#{vm}", finish) # maybe remove as this is never used by vmpooler itself?
|
170
|
+
pipeline.hset("vmpooler__vm__#{vm}", 'ready', Time.now)
|
170
171
|
|
171
172
|
# last boot time is displayed in API, and used by alarming script
|
172
|
-
|
173
|
+
pipeline.hset('vmpooler__lastboot', pool, Time.now)
|
173
174
|
end
|
174
175
|
|
175
176
|
$metrics.timing("time_to_ready_state.#{pool}", finish)
|
@@ -294,6 +295,12 @@ module Vmpooler
|
|
294
295
|
move_vm_queue(pool, vm, 'running', 'completed', redis, 'is listed as running, but has no checkouttime data. Removing from running')
|
295
296
|
end
|
296
297
|
|
298
|
+
# tag VM if not tagged yet, this ensures the method is only called once
|
299
|
+
unless redis.hget("vmpooler__vm__#{vm}", 'user_tagged')
|
300
|
+
success = provider.tag_vm_user(pool, vm)
|
301
|
+
redis.hset("vmpooler__vm__#{vm}", 'user_tagged', 'true') if success
|
302
|
+
end
|
303
|
+
|
297
304
|
throw :stop_checking if provider.vm_ready?(pool, vm)
|
298
305
|
|
299
306
|
throw :stop_checking if provider.get_vm(pool, vm)
|
@@ -355,35 +362,47 @@ module Vmpooler
|
|
355
362
|
max_hostname_retries = 3
|
356
363
|
while hostname_retries < max_hostname_retries
|
357
364
|
hostname, hostname_available = generate_and_check_hostname
|
358
|
-
domain =
|
359
|
-
|
365
|
+
domain = Parsing.get_domain_for_pool(config, pool_name)
|
366
|
+
if domain
|
367
|
+
fqdn = "#{hostname}.#{domain}"
|
368
|
+
else
|
369
|
+
fqdn = hostname
|
370
|
+
end
|
371
|
+
|
372
|
+
# skip dns check if the provider is set to skip_dns_check_before_creating_vm
|
373
|
+
provider = get_provider_for_pool(pool_name)
|
374
|
+
if provider && provider.provider_config['skip_dns_check_before_creating_vm']
|
375
|
+
dns_available = true
|
376
|
+
else
|
377
|
+
dns_ip, dns_available = check_dns_available(fqdn)
|
378
|
+
end
|
379
|
+
|
360
380
|
break if hostname_available && dns_available
|
361
381
|
|
362
382
|
hostname_retries += 1
|
363
383
|
|
364
384
|
if !hostname_available
|
365
385
|
$metrics.increment("errors.duplicatehostname.#{pool_name}")
|
366
|
-
$logger.log('s', "[!] [#{pool_name}] Generated hostname #{
|
386
|
+
$logger.log('s', "[!] [#{pool_name}] Generated hostname #{fqdn} was not unique (attempt \##{hostname_retries} of #{max_hostname_retries})")
|
367
387
|
elsif !dns_available
|
368
388
|
$metrics.increment("errors.staledns.#{pool_name}")
|
369
|
-
$logger.log('s', "[!] [#{pool_name}] Generated hostname #{
|
389
|
+
$logger.log('s', "[!] [#{pool_name}] Generated hostname #{fqdn} already exists in DNS records (#{dns_ip}), stale DNS")
|
370
390
|
end
|
371
391
|
end
|
372
392
|
|
373
|
-
raise "Unable to generate a unique hostname after #{hostname_retries} attempts. The last hostname checked was #{
|
393
|
+
raise "Unable to generate a unique hostname after #{hostname_retries} attempts. The last hostname checked was #{fqdn}" unless hostname_available && dns_available
|
374
394
|
|
375
395
|
hostname
|
376
396
|
end
|
377
397
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
vm_name = "#{vm_name}.#{domain}" if domain
|
398
|
+
# Query the DNS for the name we want to create and if it already exists, mark it unavailable
|
399
|
+
# This protects against stale DNS records
|
400
|
+
def check_dns_available(vm_name)
|
382
401
|
begin
|
383
402
|
dns_ip = Resolv.getaddress(vm_name)
|
384
403
|
rescue Resolv::ResolvError
|
385
404
|
# this is the expected case, swallow the error
|
386
|
-
# eg "no address for blah-daisy"
|
405
|
+
# eg "no address for blah-daisy.example.com"
|
387
406
|
return ['', true]
|
388
407
|
end
|
389
408
|
[dns_ip, false]
|
@@ -391,6 +410,7 @@ module Vmpooler
|
|
391
410
|
|
392
411
|
def _clone_vm(pool_name, provider, request_id = nil, pool_alias = nil)
|
393
412
|
new_vmname = find_unique_hostname(pool_name)
|
413
|
+
pool_domain = Parsing.get_domain_for_pool(config, pool_name)
|
394
414
|
mutex = vm_mutex(new_vmname)
|
395
415
|
mutex.synchronize do
|
396
416
|
@redis.with_metrics do |redis|
|
@@ -400,6 +420,7 @@ module Vmpooler
|
|
400
420
|
redis.hset("vmpooler__vm__#{new_vmname}", 'clone', Time.now)
|
401
421
|
redis.hset("vmpooler__vm__#{new_vmname}", 'template', pool_name) # This value is used to represent the pool.
|
402
422
|
redis.hset("vmpooler__vm__#{new_vmname}", 'pool', pool_name)
|
423
|
+
redis.hset("vmpooler__vm__#{new_vmname}", 'domain', pool_domain) if pool_domain
|
403
424
|
redis.hset("vmpooler__vm__#{new_vmname}", 'request_id', request_id) if request_id
|
404
425
|
redis.hset("vmpooler__vm__#{new_vmname}", 'pool_alias', pool_alias) if pool_alias
|
405
426
|
redis.exec
|
@@ -412,9 +433,9 @@ module Vmpooler
|
|
412
433
|
finish = format('%<time>.2f', time: Time.now - start)
|
413
434
|
|
414
435
|
@redis.with_metrics do |redis|
|
415
|
-
redis.pipelined do
|
416
|
-
|
417
|
-
|
436
|
+
redis.pipelined do |pipeline|
|
437
|
+
pipeline.hset("vmpooler__clone__#{Date.today}", "#{pool_name}:#{new_vmname}", finish)
|
438
|
+
pipeline.hset("vmpooler__vm__#{new_vmname}", 'clone_time', finish)
|
418
439
|
end
|
419
440
|
end
|
420
441
|
$logger.log('s', "[+] [#{pool_name}] '#{new_vmname}' cloned in #{finish} seconds")
|
@@ -422,10 +443,10 @@ module Vmpooler
|
|
422
443
|
$metrics.timing("clone.#{pool_name}", finish)
|
423
444
|
rescue StandardError
|
424
445
|
@redis.with_metrics do |redis|
|
425
|
-
redis.pipelined do
|
426
|
-
|
446
|
+
redis.pipelined do |pipeline|
|
447
|
+
pipeline.srem("vmpooler__pending__#{pool_name}", new_vmname)
|
427
448
|
expiration_ttl = $config[:redis]['data_ttl'].to_i * 60 * 60
|
428
|
-
|
449
|
+
pipeline.expire("vmpooler__vm__#{new_vmname}", expiration_ttl)
|
429
450
|
end
|
430
451
|
end
|
431
452
|
raise
|
@@ -456,12 +477,12 @@ module Vmpooler
|
|
456
477
|
|
457
478
|
mutex.synchronize do
|
458
479
|
@redis.with_metrics do |redis|
|
459
|
-
redis.pipelined do
|
460
|
-
|
461
|
-
|
480
|
+
redis.pipelined do |pipeline|
|
481
|
+
pipeline.hdel("vmpooler__active__#{pool}", vm)
|
482
|
+
pipeline.hset("vmpooler__vm__#{vm}", 'destroy', Time.now)
|
462
483
|
|
463
484
|
# Auto-expire metadata key
|
464
|
-
|
485
|
+
pipeline.expire("vmpooler__vm__#{vm}", ($config[:redis]['data_ttl'].to_i * 60 * 60))
|
465
486
|
end
|
466
487
|
|
467
488
|
start = Time.now
|
@@ -478,15 +499,15 @@ module Vmpooler
|
|
478
499
|
dereference_mutex(vm)
|
479
500
|
end
|
480
501
|
|
481
|
-
def
|
482
|
-
global_purge = $config[:config]['
|
502
|
+
def purge_unused_vms_and_resources
|
503
|
+
global_purge = $config[:config]['purge_unconfigured_resources']
|
483
504
|
providers = $config[:providers].keys
|
484
505
|
providers.each do |provider_key|
|
485
|
-
provider_purge = $config[:providers][provider_key]['
|
506
|
+
provider_purge = $config[:providers][provider_key]['purge_unconfigured_resources'] || global_purge
|
486
507
|
if provider_purge
|
487
508
|
Thread.new do
|
488
509
|
begin
|
489
|
-
|
510
|
+
purge_vms_and_resources(provider_key)
|
490
511
|
rescue StandardError => e
|
491
512
|
$logger.log('s', "[!] failed while purging provider #{provider_key} VMs and folders with an error: #{e}")
|
492
513
|
end
|
@@ -496,33 +517,16 @@ module Vmpooler
|
|
496
517
|
nil
|
497
518
|
end
|
498
519
|
|
499
|
-
|
500
|
-
def pool_folders(provider_name)
|
501
|
-
folders = {}
|
502
|
-
$config[:pools].each do |pool|
|
503
|
-
next unless pool['provider'] == provider_name.to_s
|
504
|
-
|
505
|
-
folder_parts = pool['folder'].split('/')
|
506
|
-
datacenter = $providers[provider_name.to_s].get_target_datacenter_from_config(pool['name'])
|
507
|
-
folders[folder_parts.pop] = "#{datacenter}/vm/#{folder_parts.join('/')}"
|
508
|
-
end
|
509
|
-
folders
|
510
|
-
end
|
511
|
-
|
512
|
-
def get_base_folders(folders)
|
513
|
-
base = []
|
514
|
-
folders.each do |_key, value|
|
515
|
-
base << value
|
516
|
-
end
|
517
|
-
base.uniq
|
518
|
-
end
|
519
|
-
|
520
|
-
def purge_vms_and_folders(provider_name)
|
520
|
+
def purge_vms_and_resources(provider_name)
|
521
521
|
provider = $providers[provider_name.to_s]
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
522
|
+
# Deprecated, will be removed in version 3
|
523
|
+
if provider.provider_config['folder_whitelist']
|
524
|
+
$logger.log('d', "[!] [deprecation] rename configuration 'folder_whitelist' to 'resources_allowlist' for provider #{provider_name}")
|
525
|
+
allowlist = provider.provider_config['folder_whitelist']
|
526
|
+
else
|
527
|
+
allowlist = provider.provider_config['resources_allowlist']
|
528
|
+
end
|
529
|
+
provider.purge_unconfigured_resources(allowlist)
|
526
530
|
end
|
527
531
|
|
528
532
|
def create_vm_disk(pool_name, vm, disk_size, provider)
|
@@ -630,8 +634,21 @@ module Vmpooler
|
|
630
634
|
# @return [Array] - a list of used providers from the config file, defaults to the default providers
|
631
635
|
# ie. ["dummy"]
|
632
636
|
def used_providers
|
633
|
-
|
634
|
-
|
637
|
+
# create an array of provider classes based on the config
|
638
|
+
if config[:providers]
|
639
|
+
config_provider_names = config[:providers].keys
|
640
|
+
config_providers = config_provider_names.map do |config_provider_name|
|
641
|
+
if config[:providers][config_provider_name] && config[:providers][config_provider_name]['provider_class']
|
642
|
+
config[:providers][config_provider_name]['provider_class'].to_s
|
643
|
+
else
|
644
|
+
config_provider_name.to_s
|
645
|
+
end
|
646
|
+
end.compact.uniq
|
647
|
+
else
|
648
|
+
config_providers = []
|
649
|
+
end
|
650
|
+
# return the unique array of providers from the config and VMPooler defaults
|
651
|
+
@used_providers ||= (config_providers + default_providers).uniq
|
635
652
|
end
|
636
653
|
|
637
654
|
# @return [Array] - returns a list of providers that should always be loaded
|
@@ -877,7 +894,7 @@ module Vmpooler
|
|
877
894
|
loop_count = 1
|
878
895
|
loop_delay = loop_delay_min
|
879
896
|
provider = get_provider_for_pool(pool['name'])
|
880
|
-
raise("Could not find provider '#{pool['provider']}") if provider.nil?
|
897
|
+
raise("Could not find provider '#{pool['provider']}'") if provider.nil?
|
881
898
|
|
882
899
|
sync_pool_template(pool)
|
883
900
|
loop do
|
@@ -1202,19 +1219,19 @@ module Vmpooler
|
|
1202
1219
|
pool_check_response[:destroyed_vms] += 1
|
1203
1220
|
destroy_vm(vm, pool_name, provider)
|
1204
1221
|
rescue StandardError => e
|
1205
|
-
redis.pipelined do
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1222
|
+
redis.pipelined do |pipeline|
|
1223
|
+
pipeline.srem("vmpooler__completed__#{pool_name}", vm)
|
1224
|
+
pipeline.hdel("vmpooler__active__#{pool_name}", vm)
|
1225
|
+
pipeline.del("vmpooler__vm__#{vm}")
|
1209
1226
|
end
|
1210
1227
|
$logger.log('d', "[!] [#{pool_name}] _check_pool failed with an error while evaluating completed VMs: #{e}")
|
1211
1228
|
end
|
1212
1229
|
else
|
1213
1230
|
$logger.log('s', "[!] [#{pool_name}] '#{vm}' not found in inventory, removed from 'completed' queue")
|
1214
|
-
redis.pipelined do
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1231
|
+
redis.pipelined do |pipeline|
|
1232
|
+
pipeline.srem("vmpooler__completed__#{pool_name}", vm)
|
1233
|
+
pipeline.hdel("vmpooler__active__#{pool_name}", vm)
|
1234
|
+
pipeline.del("vmpooler__vm__#{vm}")
|
1218
1235
|
end
|
1219
1236
|
end
|
1220
1237
|
end
|
@@ -1364,7 +1381,7 @@ module Vmpooler
|
|
1364
1381
|
|
1365
1382
|
return provider_klass.const_get(classname).new(config, logger, metrics, redis_connection_pool, provider_name, options)
|
1366
1383
|
end
|
1367
|
-
raise("Provider '#{provider_class}' is unknown for pool with provider name '#{provider_name}'") if
|
1384
|
+
raise("Provider '#{provider_class}' is unknown for pool with provider name '#{provider_name}'") if provider_klass.nil?
|
1368
1385
|
end
|
1369
1386
|
|
1370
1387
|
def check_ondemand_requests(maxloop = 0,
|
@@ -1430,12 +1447,12 @@ module Vmpooler
|
|
1430
1447
|
score = redis.zscore('vmpooler__provisioning__request', request_id)
|
1431
1448
|
requested = requested.split(',')
|
1432
1449
|
|
1433
|
-
redis.pipelined do
|
1450
|
+
redis.pipelined do |pipeline|
|
1434
1451
|
requested.each do |request|
|
1435
|
-
|
1452
|
+
pipeline.zadd('vmpooler__odcreate__task', Time.now.to_i, "#{request}:#{request_id}")
|
1436
1453
|
end
|
1437
|
-
|
1438
|
-
|
1454
|
+
pipeline.zrem('vmpooler__provisioning__request', request_id)
|
1455
|
+
pipeline.zadd('vmpooler__provisioning__processing', score, request_id)
|
1439
1456
|
end
|
1440
1457
|
end
|
1441
1458
|
|
@@ -1465,9 +1482,9 @@ module Vmpooler
|
|
1465
1482
|
redis.incr('vmpooler__tasks__ondemandclone')
|
1466
1483
|
clone_vm(pool, provider, request_id, pool_alias)
|
1467
1484
|
end
|
1468
|
-
redis.pipelined do
|
1469
|
-
|
1470
|
-
|
1485
|
+
redis.pipelined do |pipeline|
|
1486
|
+
pipeline.zrem(queue_key, request)
|
1487
|
+
pipeline.zadd(queue_key, score, "#{pool_alias}:#{pool}:#{remaining_count}:#{request_id}")
|
1471
1488
|
end
|
1472
1489
|
end
|
1473
1490
|
end
|
@@ -1518,10 +1535,10 @@ module Vmpooler
|
|
1518
1535
|
|
1519
1536
|
$logger.log('s', "Ondemand request for '#{request_id}' failed to provision all instances within the configured ttl '#{ondemand_request_ttl}'")
|
1520
1537
|
expiration_ttl = $config[:redis]['data_ttl'].to_i * 60 * 60
|
1521
|
-
redis.pipelined do
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1538
|
+
redis.pipelined do |pipeline|
|
1539
|
+
pipeline.zrem('vmpooler__provisioning__processing', request_id)
|
1540
|
+
pipeline.hset("vmpooler__odrequest__#{request_id}", 'status', 'failed')
|
1541
|
+
pipeline.expire("vmpooler__odrequest__#{request_id}", expiration_ttl)
|
1525
1542
|
end
|
1526
1543
|
remove_vms_for_failed_request(request_id, expiration_ttl, redis)
|
1527
1544
|
true
|
@@ -1531,11 +1548,11 @@ module Vmpooler
|
|
1531
1548
|
request_hash = redis.hgetall("vmpooler__odrequest__#{request_id}")
|
1532
1549
|
Parsing.get_platform_pool_count(request_hash['requested']) do |platform_alias, pool, _count|
|
1533
1550
|
pools_filled = redis.smembers("vmpooler__#{request_id}__#{platform_alias}__#{pool}")
|
1534
|
-
redis.pipelined do
|
1551
|
+
redis.pipelined do |pipeline|
|
1535
1552
|
pools_filled&.each do |vm|
|
1536
|
-
move_vm_queue(pool, vm, 'running', 'completed',
|
1553
|
+
move_vm_queue(pool, vm, 'running', 'completed', pipeline, "moved to completed queue. '#{request_id}' could not be filled in time")
|
1537
1554
|
end
|
1538
|
-
|
1555
|
+
pipeline.expire("vmpooler__#{request_id}__#{platform_alias}__#{pool}", expiration_ttl)
|
1539
1556
|
end
|
1540
1557
|
end
|
1541
1558
|
end
|
@@ -1606,7 +1623,7 @@ module Vmpooler
|
|
1606
1623
|
end
|
1607
1624
|
end
|
1608
1625
|
|
1609
|
-
|
1626
|
+
purge_unused_vms_and_resources
|
1610
1627
|
|
1611
1628
|
loop_count = 1
|
1612
1629
|
loop do
|
@@ -212,6 +212,22 @@ module Vmpooler
|
|
212
212
|
raise("#{self.class.name} does not implement vm_ready?")
|
213
213
|
end
|
214
214
|
|
215
|
+
# tag_vm_user This method is called once we know who is using the VM (it is running). This method enables seeing
|
216
|
+
# who is using what in the provider pools.
|
217
|
+
# This method should be implemented in the providers, if it is not implemented, this base method will be called
|
218
|
+
# and should be a noop. The implementation should check if the vm has a user (as per redis) and add a new tag
|
219
|
+
# with the information.
|
220
|
+
# inputs
|
221
|
+
# [String] pool_name : Name of the pool
|
222
|
+
# [String] vm_name : Name of the VM to check if ready
|
223
|
+
# returns
|
224
|
+
# [Boolean] : true if successful, false if an error occurred and it should retry
|
225
|
+
def tag_vm_user(_pool_name, _vm_name)
|
226
|
+
# noop by design. If the provider does not implement this method, this base method is called (because inherited)
|
227
|
+
# and should basically do nothing.
|
228
|
+
true
|
229
|
+
end
|
230
|
+
|
215
231
|
# inputs
|
216
232
|
# [String] pool_name : Name of the pool
|
217
233
|
# [String] vm_name : Name of the VM to check if it exists
|
@@ -226,7 +242,7 @@ module Vmpooler
|
|
226
242
|
# returns
|
227
243
|
# nil when successful. Raises error when encountered
|
228
244
|
def create_template_delta_disks(_pool)
|
229
|
-
|
245
|
+
puts("#{self.class.name} does not implement create_template_delta_disks")
|
230
246
|
end
|
231
247
|
|
232
248
|
# inputs
|
@@ -237,8 +253,15 @@ module Vmpooler
|
|
237
253
|
raise("#{self.class.name} does not implement get_target_datacenter_from_config")
|
238
254
|
end
|
239
255
|
|
240
|
-
def
|
241
|
-
raise("#{self.class.name} does not implement
|
256
|
+
def purge_unconfigured_resources(_allowlist)
|
257
|
+
raise("#{self.class.name} does not implement purge_unconfigured_resources")
|
258
|
+
end
|
259
|
+
|
260
|
+
# DEPRECATED if a provider does not implement the new method, it will hit this base class method
|
261
|
+
# and return a deprecation message
|
262
|
+
def purge_unconfigured_folders(_deprecated, _deprecated2, allowlist)
|
263
|
+
logger.log('s', '[!] purge_unconfigured_folders was renamed to purge_unconfigured_resources, please update your provider implementation')
|
264
|
+
purge_unconfigured_resources(allowlist)
|
242
265
|
end
|
243
266
|
end
|
244
267
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# utility class shared between apps
|
3
|
+
# utility class shared between apps api and pool_manager
|
4
4
|
module Vmpooler
|
5
5
|
class Parsing
|
6
6
|
def self.get_platform_pool_count(requested, &_block)
|
@@ -12,5 +12,25 @@ module Vmpooler
|
|
12
12
|
yield platform_alias, pool, count
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
# @param config [String] - the full config structure
|
17
|
+
# @param pool_name [String] - the name of the pool
|
18
|
+
# @return [String] - domain name for pool, if set in the provider for the pool or in the config block
|
19
|
+
def self.get_domain_for_pool(config, pool_name)
|
20
|
+
pool = config[:pools].find { |p| p['name'] == pool_name }
|
21
|
+
return nil unless pool
|
22
|
+
|
23
|
+
provider_name = pool.fetch('provider', 'vsphere') # see vmpooler.yaml.example where it states defaulting to vsphere
|
24
|
+
|
25
|
+
if config[:providers] && config[:providers][provider_name.to_sym] && config[:providers][provider_name.to_sym]['domain']
|
26
|
+
domain = config[:providers][provider_name.to_sym]['domain']
|
27
|
+
elsif config[:config] && config[:config]['domain']
|
28
|
+
domain = config[:config]['domain']
|
29
|
+
else
|
30
|
+
domain = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
domain
|
34
|
+
end
|
15
35
|
end
|
16
36
|
end
|
data/lib/vmpooler/version.rb
CHANGED
data/lib/vmpooler.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
module Vmpooler
|
4
4
|
require 'concurrent'
|
5
5
|
require 'date'
|
6
|
+
require 'deep_merge'
|
6
7
|
require 'json'
|
7
8
|
require 'net/ldap'
|
8
9
|
require 'open-uri'
|
@@ -16,6 +17,7 @@ module Vmpooler
|
|
16
17
|
|
17
18
|
# Dependencies for tracing
|
18
19
|
require 'opentelemetry-instrumentation-concurrent_ruby'
|
20
|
+
require 'opentelemetry-instrumentation-http_client'
|
19
21
|
require 'opentelemetry-instrumentation-redis'
|
20
22
|
require 'opentelemetry-instrumentation-sinatra'
|
21
23
|
require 'opentelemetry-sdk'
|
@@ -31,7 +33,7 @@ module Vmpooler
|
|
31
33
|
if ENV['VMPOOLER_CONFIG']
|
32
34
|
config_string = ENV['VMPOOLER_CONFIG']
|
33
35
|
# Parse the YAML config into a Hash
|
34
|
-
#
|
36
|
+
# Allow the Symbol class
|
35
37
|
parsed_config = YAML.safe_load(config_string, [Symbol])
|
36
38
|
else
|
37
39
|
# Take the name of the config file either from an ENV variable or from the filepath argument
|
@@ -41,8 +43,9 @@ module Vmpooler
|
|
41
43
|
if parsed_config[:config]['extra_config']
|
42
44
|
extra_configs = parsed_config[:config]['extra_config'].split(',')
|
43
45
|
extra_configs.each do |config|
|
46
|
+
puts "loading extra_config file #{config}"
|
44
47
|
extra_config = YAML.load_file(config)
|
45
|
-
parsed_config.
|
48
|
+
parsed_config.deep_merge(extra_config)
|
46
49
|
end
|
47
50
|
end
|
48
51
|
end
|
@@ -81,10 +84,13 @@ module Vmpooler
|
|
81
84
|
parsed_config[:config]['retry_factor'] = string_to_int(ENV['RETRY_FACTOR']) if ENV['RETRY_FACTOR']
|
82
85
|
parsed_config[:config]['create_folders'] = true?(ENV['CREATE_FOLDERS']) if ENV['CREATE_FOLDERS']
|
83
86
|
parsed_config[:config]['experimental_features'] = ENV['EXPERIMENTAL_FEATURES'] if ENV['EXPERIMENTAL_FEATURES']
|
84
|
-
parsed_config[:config]['purge_unconfigured_folders'] = ENV['PURGE_UNCONFIGURED_FOLDERS'] if ENV['PURGE_UNCONFIGURED_FOLDERS']
|
85
87
|
parsed_config[:config]['usage_stats'] = ENV['USAGE_STATS'] if ENV['USAGE_STATS']
|
86
88
|
parsed_config[:config]['request_logger'] = ENV['REQUEST_LOGGER'] if ENV['REQUEST_LOGGER']
|
87
89
|
parsed_config[:config]['create_template_delta_disks'] = ENV['CREATE_TEMPLATE_DELTA_DISKS'] if ENV['CREATE_TEMPLATE_DELTA_DISKS']
|
90
|
+
parsed_config[:config]['purge_unconfigured_resources'] = ENV['PURGE_UNCONFIGURED_RESOURCES'] if ENV['PURGE_UNCONFIGURED_RESOURCES']
|
91
|
+
parsed_config[:config]['purge_unconfigured_resources'] = ENV['PURGE_UNCONFIGURED_FOLDERS'] if ENV['PURGE_UNCONFIGURED_FOLDERS']
|
92
|
+
# ENV PURGE_UNCONFIGURED_FOLDERS deprecated, will be removed in version 3
|
93
|
+
puts '[!] [deprecation] rename ENV var \'PURGE_UNCONFIGURED_FOLDERS\' to \'PURGE_UNCONFIGURED_RESOURCES\'' if ENV['PURGE_UNCONFIGURED_FOLDERS']
|
88
94
|
set_linked_clone(parsed_config)
|
89
95
|
|
90
96
|
parsed_config[:redis] = parsed_config[:redis] || {}
|
@@ -128,6 +134,7 @@ module Vmpooler
|
|
128
134
|
# Create an index of pool aliases
|
129
135
|
parsed_config[:pool_names] = Set.new
|
130
136
|
unless parsed_config[:pools]
|
137
|
+
puts 'loading pools configuration from redis, since the config[:pools] is empty'
|
131
138
|
redis = new_redis(parsed_config[:redis]['server'], parsed_config[:redis]['port'], parsed_config[:redis]['password'])
|
132
139
|
parsed_config[:pools] = load_pools_from_redis(redis)
|
133
140
|
end
|
@@ -261,6 +268,7 @@ module Vmpooler
|
|
261
268
|
OpenTelemetry::SDK.configure do |c|
|
262
269
|
c.use 'OpenTelemetry::Instrumentation::Sinatra'
|
263
270
|
c.use 'OpenTelemetry::Instrumentation::ConcurrentRuby'
|
271
|
+
c.use 'OpenTelemetry::Instrumentation::HttpClient'
|
264
272
|
c.use 'OpenTelemetry::Instrumentation::Redis'
|
265
273
|
|
266
274
|
c.add_span_processor(span_processor)
|