vmpooler 1.1.1 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ae03cde5adef86e2f5b52928b1b241e6e300993f5ab9bca3c76fbba49b5f29a
4
- data.tar.gz: 3f04c605b3a255baf73ea7a5e985ab5d241411a43763b47e2b8739574b48178b
3
+ metadata.gz: 69a8b533d59906b740d63c48c2f237bac2d42c3bbc770ed178e41f9981c7f955
4
+ data.tar.gz: '0609a290e75b7deb1f167a059b6342c43ce7942e600c7f67ba29b3389f411b59'
5
5
  SHA512:
6
- metadata.gz: 4ec28d2335628c1fe8bf079940db915233c45100e885eb387ffa86bfdcb384078f9fb5aa7fb2985ead5e0b9c8e8f619037a66b0927a9325db8bc8a2cfc63e1ae
7
- data.tar.gz: dff5b02ccab6c7eab949dab4df8ea2c1d530d6c672278dd9fe7c485e9234b19045f6e65f28870dbe3fe1cbbb8d53aac4fea45cfe008b548e619307b04ba56f25
6
+ metadata.gz: bd7da108e63619bb0f7a80d1567ee38e6c05c3d87d77982fa81d117612577eb7480940f39c910c8d7fb0ec373972233a304f7bc63e80dae35c7d1f0ba9edddf4
7
+ data.tar.gz: d7023cc35609431f37f55a74fd07312afaefab627558ad55f9d03eaa320dce8929ffdb36fc4ca2ab6d0a299a1d93820a2767714680813e3f7f2fbb78fac01b27
@@ -56,14 +56,11 @@ module Vmpooler
56
56
  return false
57
57
  end
58
58
 
59
- def authenticate_ldap(port, host, user_object, base, username_str, password_str)
59
+ def authenticate_ldap(port, host, encryption_hash, user_object, base, username_str, password_str)
60
60
  ldap = Net::LDAP.new(
61
61
  :host => host,
62
62
  :port => port,
63
- :encryption => {
64
- :method => :start_tls,
65
- :tls_options => { :ssl_version => 'TLSv1' }
66
- },
63
+ :encryption => encryption_hash,
67
64
  :base => base,
68
65
  :auth => {
69
66
  :method => :simple,
@@ -86,6 +83,10 @@ module Vmpooler
86
83
  ldap_port = auth[:ldap]['port'] || 389
87
84
  ldap_user_obj = auth[:ldap]['user_object']
88
85
  ldap_host = auth[:ldap]['host']
86
+ ldap_encryption_hash = auth[:ldap]['encryption'] || {
87
+ :method => :start_tls,
88
+ :tls_options => { :ssl_version => 'TLSv1' }
89
+ }
89
90
 
90
91
  unless ldap_base.is_a? Array
91
92
  ldap_base = ldap_base.split
@@ -100,6 +101,7 @@ module Vmpooler
100
101
  result = authenticate_ldap(
101
102
  ldap_port,
102
103
  ldap_host,
104
+ ldap_encryption_hash,
103
105
  search_user_obj,
104
106
  search_base,
105
107
  username_str,
@@ -28,6 +28,10 @@ module Vmpooler
28
28
  Vmpooler::API.settings.config[:pools]
29
29
  end
30
30
 
31
+ def pools_at_startup
32
+ Vmpooler::API.settings.config[:pools_at_startup]
33
+ end
34
+
31
35
  def pool_exists?(template)
32
36
  Vmpooler::API.settings.config[:pool_names].include?(template)
33
37
  end
@@ -236,12 +240,25 @@ module Vmpooler
236
240
  result
237
241
  end
238
242
 
243
+ def component_to_test(match, labels_string)
244
+ return if labels_string.nil?
245
+
246
+ labels_string_parts = labels_string.split(',')
247
+ labels_string_parts.each do |part|
248
+ key, value = part.split('=')
249
+ next if value.nil?
250
+ return value if key == match
251
+ end
252
+ 'none'
253
+ end
254
+
239
255
  def update_user_metrics(operation, vmname)
240
256
  backend.multi
241
257
  backend.hget("vmpooler__vm__#{vmname}", 'tag:jenkins_build_url')
242
258
  backend.hget("vmpooler__vm__#{vmname}", 'token:user')
243
259
  backend.hget("vmpooler__vm__#{vmname}", 'template')
244
260
  jenkins_build_url, user, poolname = backend.exec
261
+ poolname = poolname.gsub('.', '_')
245
262
 
246
263
  if user
247
264
  user = user.gsub('.', '_')
@@ -276,6 +293,32 @@ module Vmpooler
276
293
  puts 'd', "[!] [#{poolname}] failed while evaluating usage labels on '#{vmname}' with an error: #{e}"
277
294
  end
278
295
 
296
+ def reset_pool_size(poolname)
297
+ result = { 'ok' => false }
298
+
299
+ pool_index = pool_index(pools)
300
+
301
+ pools_updated = 0
302
+ sync_pool_sizes
303
+
304
+ pool_size_now = pools[pool_index[poolname]]['size'].to_i
305
+ pool_size_original = pools_at_startup[pool_index[poolname]]['size'].to_i
306
+ result['pool_size_before_reset'] = pool_size_now
307
+ result['pool_size_before_overrides'] = pool_size_original
308
+
309
+ unless pool_size_now == pool_size_original
310
+ pools[pool_index[poolname]]['size'] = pool_size_original
311
+ backend.hdel('vmpooler__config__poolsize', poolname)
312
+ backend.sadd('vmpooler__pool__undo_size_override', poolname)
313
+ pools_updated += 1
314
+ status 201
315
+ end
316
+
317
+ status 200 unless pools_updated > 0
318
+ result['ok'] = true
319
+ result
320
+ end
321
+
279
322
  def update_pool_size(payload)
280
323
  result = { 'ok' => false }
281
324
 
@@ -296,6 +339,33 @@ module Vmpooler
296
339
  result
297
340
  end
298
341
 
342
+ def reset_pool_template(poolname)
343
+ result = { 'ok' => false }
344
+
345
+ pool_index_live = pool_index(pools)
346
+ pool_index_original = pool_index(pools_at_startup)
347
+
348
+ pools_updated = 0
349
+ sync_pool_templates
350
+
351
+ template_now = pools[pool_index_live[poolname]]['template']
352
+ template_original = pools_at_startup[pool_index_original[poolname]]['template']
353
+ result['template_before_reset'] = template_now
354
+ result['template_before_overrides'] = template_original
355
+
356
+ unless template_now == template_original
357
+ pools[pool_index_live[poolname]]['template'] = template_original
358
+ backend.hdel('vmpooler__config__template', poolname)
359
+ backend.sadd('vmpooler__pool__undo_template_override', poolname)
360
+ pools_updated += 1
361
+ status 201
362
+ end
363
+
364
+ status 200 unless pools_updated > 0
365
+ result['ok'] = true
366
+ result
367
+ end
368
+
299
369
  def update_pool_template(payload)
300
370
  result = { 'ok' => false }
301
371
 
@@ -1362,6 +1432,26 @@ module Vmpooler
1362
1432
  JSON.pretty_generate(result)
1363
1433
  end
1364
1434
 
1435
+ delete "#{api_prefix}/config/poolsize/:pool/?" do
1436
+ content_type :json
1437
+ result = { 'ok' => false }
1438
+
1439
+ if config['experimental_features']
1440
+ need_token! if Vmpooler::API.settings.config[:auth]
1441
+
1442
+ if pool_exists?(params[:pool])
1443
+ result = reset_pool_size(params[:pool])
1444
+ else
1445
+ metrics.increment('config.invalid.unknown')
1446
+ status 404
1447
+ end
1448
+ else
1449
+ status 405
1450
+ end
1451
+
1452
+ JSON.pretty_generate(result)
1453
+ end
1454
+
1365
1455
  post "#{api_prefix}/config/poolsize/?" do
1366
1456
  content_type :json
1367
1457
  result = { 'ok' => false }
@@ -1393,6 +1483,26 @@ module Vmpooler
1393
1483
  JSON.pretty_generate(result)
1394
1484
  end
1395
1485
 
1486
+ delete "#{api_prefix}/config/pooltemplate/:pool/?" do
1487
+ content_type :json
1488
+ result = { 'ok' => false }
1489
+
1490
+ if config['experimental_features']
1491
+ need_token! if Vmpooler::API.settings.config[:auth]
1492
+
1493
+ if pool_exists?(params[:pool])
1494
+ result = reset_pool_template(params[:pool])
1495
+ else
1496
+ metrics.increment('config.invalid.unknown')
1497
+ status 404
1498
+ end
1499
+ else
1500
+ status 405
1501
+ end
1502
+
1503
+ JSON.pretty_generate(result)
1504
+ end
1505
+
1396
1506
  post "#{api_prefix}/config/pooltemplate/?" do
1397
1507
  content_type :json
1398
1508
  result = { 'ok' => false }
@@ -478,18 +478,6 @@ module Vmpooler
478
478
  dereference_mutex(vm)
479
479
  end
480
480
 
481
- def component_to_test(match, labels_string)
482
- return if labels_string.nil?
483
-
484
- labels_string_parts = labels_string.split(',')
485
- labels_string_parts.each do |part|
486
- key, value = part.split('=')
487
- next if value.nil?
488
- return value if key == match
489
- end
490
- 'none'
491
- end
492
-
493
481
  def purge_unused_vms_and_folders
494
482
  global_purge = $config[:config]['purge_unconfigured_folders']
495
483
  providers = $config[:providers].keys
@@ -640,7 +628,7 @@ module Vmpooler
640
628
  end
641
629
 
642
630
  # @return [Array] - a list of used providers from the config file, defaults to the default providers
643
- # ie. ["vsphere", "dummy"]
631
+ # ie. ["dummy"]
644
632
  def used_providers
645
633
  pools = config[:pools] || []
646
634
  @used_providers ||= (pools.map { |pool| pool[:provider] || pool['provider'] }.compact + default_providers).uniq
@@ -650,7 +638,7 @@ module Vmpooler
650
638
  # note: vsphere is the default if user does not specify although this should not be
651
639
  # if vsphere is to no longer be loaded by default please remove
652
640
  def default_providers
653
- @default_providers ||= %w[vsphere dummy]
641
+ @default_providers ||= %w[dummy]
654
642
  end
655
643
 
656
644
  def get_pool_name_for_vm(vm_name, redis)
@@ -796,6 +784,10 @@ module Vmpooler
796
784
  # - Fires when a pool reset is requested
797
785
  # - Additional options
798
786
  # :poolname
787
+ # :undo_override
788
+ # - Fires when a pool override removal is requested
789
+ # - Additional options
790
+ # :poolname
799
791
  #
800
792
  def sleep_with_wakeup_events(loop_delay, wakeup_period = 5, options = {})
801
793
  exit_by = Time.now + loop_delay
@@ -838,6 +830,11 @@ module Vmpooler
838
830
  break if pending
839
831
  end
840
832
 
833
+ if options[:undo_override]
834
+ break if redis.sismember('vmpooler__pool__undo_template_override', options[:poolname])
835
+ break if redis.sismember('vmpooler__pool__undo_size_override', options[:poolname])
836
+ end
837
+
841
838
  if options[:pending_vm]
842
839
  pending_vm_count = redis.scard("vmpooler__pending__#{options[:poolname]}")
843
840
  break unless pending_vm_count == 0
@@ -892,7 +889,7 @@ module Vmpooler
892
889
  loop_delay = (loop_delay * loop_delay_decay).to_i
893
890
  loop_delay = loop_delay_max if loop_delay > loop_delay_max
894
891
  end
895
- sleep_with_wakeup_events(loop_delay, loop_delay_min, pool_size_change: true, poolname: pool['name'], pool_template_change: true, clone_target_change: true, pending_vm: true, pool_reset: true)
892
+ sleep_with_wakeup_events(loop_delay, loop_delay_min, pool_size_change: true, poolname: pool['name'], pool_template_change: true, clone_target_change: true, pending_vm: true, pool_reset: true, undo_override: true)
896
893
 
897
894
  unless maxloop == 0
898
895
  break if loop_count >= maxloop
@@ -1052,15 +1049,18 @@ module Vmpooler
1052
1049
  return if mutex.locked?
1053
1050
 
1054
1051
  @redis.with_metrics do |redis|
1055
- poolsize = redis.hget('vmpooler__config__poolsize', pool['name'])
1056
- break if poolsize.nil?
1052
+ pool_size_requested = redis.hget('vmpooler__config__poolsize', pool['name'])
1053
+ break if pool_size_requested.nil?
1057
1054
 
1058
- poolsize = Integer(poolsize)
1059
- break if poolsize == pool['size']
1055
+ pool_size_requested = Integer(pool_size_requested)
1056
+ pool_size_currently = pool['size']
1057
+ break if pool_size_requested == pool_size_currently
1060
1058
 
1061
1059
  mutex.synchronize do
1062
- pool['size'] = poolsize
1060
+ pool['size'] = pool_size_requested
1063
1061
  end
1062
+
1063
+ $logger.log('s', "[*] [#{pool['name']}] size updated from #{pool_size_currently} to #{pool_size_requested}")
1064
1064
  end
1065
1065
  end
1066
1066
 
@@ -1078,6 +1078,38 @@ module Vmpooler
1078
1078
  end
1079
1079
  end
1080
1080
 
1081
+ def undo_override(pool, provider)
1082
+ poolname = pool['name']
1083
+ mutex = pool_mutex(poolname)
1084
+ return if mutex.locked?
1085
+
1086
+ @redis.with_metrics do |redis|
1087
+ break unless redis.sismember('vmpooler__pool__undo_template_override', poolname)
1088
+
1089
+ redis.srem('vmpooler__pool__undo_template_override', poolname)
1090
+ template_now = pool['template']
1091
+ template_original = $config[:pools_at_startup][$config[:pool_index][poolname]]['template']
1092
+
1093
+ mutex.synchronize do
1094
+ update_pool_template(pool, provider, template_original, template_now, redis)
1095
+ end
1096
+ end
1097
+
1098
+ @redis.with_metrics do |redis|
1099
+ break unless redis.sismember('vmpooler__pool__undo_size_override', poolname)
1100
+
1101
+ redis.srem('vmpooler__pool__undo_size_override', poolname)
1102
+ pool_size_now = pool['size']
1103
+ pool_size_original = $config[:pools_at_startup][$config[:pool_index][poolname]]['size']
1104
+
1105
+ mutex.synchronize do
1106
+ pool['size'] = pool_size_original
1107
+ end
1108
+
1109
+ $logger.log('s', "[*] [#{poolname}] size updated from #{pool_size_now} to #{pool_size_original}")
1110
+ end
1111
+ end
1112
+
1081
1113
  def create_inventory(pool, provider, pool_check_response)
1082
1114
  inventory = {}
1083
1115
  begin
@@ -1312,6 +1344,9 @@ module Vmpooler
1312
1344
  # Reset a pool when poolreset is requested from the API
1313
1345
  reset_pool(pool)
1314
1346
 
1347
+ # Undo overrides submitted via the api
1348
+ undo_override(pool, provider)
1349
+
1315
1350
  pool_check_response
1316
1351
  end
1317
1352
 
@@ -1526,8 +1561,8 @@ module Vmpooler
1526
1561
  # Set default provider for all pools that do not have one defined
1527
1562
  $config[:pools].each do |pool|
1528
1563
  if pool['provider'].nil?
1529
- $logger.log('d', "[!] Setting provider for pool '#{pool['name']}' to 'vsphere' as default")
1530
- pool['provider'] = 'vsphere'
1564
+ $logger.log('d', "[!] Setting provider for pool '#{pool['name']}' to 'dummy' as default")
1565
+ pool['provider'] = 'dummy'
1531
1566
  end
1532
1567
  end
1533
1568
 
Binary file
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vmpooler
4
- VERSION = '1.1.1'
4
+ VERSION = '2.0.0'
5
5
  end
data/lib/vmpooler.rb CHANGED
@@ -7,7 +7,6 @@ module Vmpooler
7
7
  require 'net/ldap'
8
8
  require 'open-uri'
9
9
  require 'pickup'
10
- require 'rbvmomi'
11
10
  require 'redis'
12
11
  require 'set'
13
12
  require 'sinatra/base'
@@ -119,6 +118,11 @@ module Vmpooler
119
118
  parsed_config[:auth][:ldap]['port'] = string_to_int(ENV['LDAP_PORT']) if ENV['LDAP_PORT']
120
119
  parsed_config[:auth][:ldap]['base'] = ENV['LDAP_BASE'] if ENV['LDAP_BASE']
121
120
  parsed_config[:auth][:ldap]['user_object'] = ENV['LDAP_USER_OBJECT'] if ENV['LDAP_USER_OBJECT']
121
+ if parsed_config[:auth]['provider'] == 'ldap' && parsed_config[:auth][:ldap].key?('encryption')
122
+ parsed_config[:auth][:ldap]['encryption'] = parsed_config[:auth][:ldap]['encryption']
123
+ elsif parsed_config[:auth]['provider'] == 'ldap'
124
+ parsed_config[:auth][:ldap]['encryption'] = {}
125
+ end
122
126
  end
123
127
 
124
128
  # Create an index of pool aliases
@@ -128,8 +132,17 @@ module Vmpooler
128
132
  parsed_config[:pools] = load_pools_from_redis(redis)
129
133
  end
130
134
 
135
+ # Marshal.dump is paired with Marshal.load to create a copy that has its own memory space
136
+ # so that each can be edited independently
137
+ # rubocop:disable Security/MarshalLoad
138
+
139
+ # retain a copy of the pools that were observed at startup
140
+ serialized_pools = Marshal.dump(parsed_config[:pools])
141
+ parsed_config[:pools_at_startup] = Marshal.load(serialized_pools)
142
+
131
143
  # Create an index of pools by title
132
144
  parsed_config[:pool_index] = pool_index(parsed_config[:pools])
145
+ # rubocop:enable Security/MarshalLoad
133
146
 
134
147
  parsed_config[:pools].each do |pool|
135
148
  parsed_config[:pool_names] << pool['name']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vmpooler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-24 00:00:00.000000000 Z
11
+ date: 2021-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -226,26 +226,6 @@ dependencies:
226
226
  - - "~>"
227
227
  - !ruby/object:Gem::Version
228
228
  version: '13.0'
229
- - !ruby/object:Gem::Dependency
230
- name: rbvmomi
231
- requirement: !ruby/object:Gem::Requirement
232
- requirements:
233
- - - ">="
234
- - !ruby/object:Gem::Version
235
- version: '2.1'
236
- - - "<"
237
- - !ruby/object:Gem::Version
238
- version: '4.0'
239
- type: :runtime
240
- prerelease: false
241
- version_requirements: !ruby/object:Gem::Requirement
242
- requirements:
243
- - - ">="
244
- - !ruby/object:Gem::Version
245
- version: '2.1'
246
- - - "<"
247
- - !ruby/object:Gem::Version
248
- version: '4.0'
249
229
  - !ruby/object:Gem::Dependency
250
230
  name: redis
251
231
  requirement: !ruby/object:Gem::Requirement
@@ -400,6 +380,26 @@ dependencies:
400
380
  - - ">="
401
381
  - !ruby/object:Gem::Version
402
382
  version: 0.11.2
383
+ - !ruby/object:Gem::Dependency
384
+ name: thor
385
+ requirement: !ruby/object:Gem::Requirement
386
+ requirements:
387
+ - - "~>"
388
+ - !ruby/object:Gem::Version
389
+ version: '1.0'
390
+ - - ">="
391
+ - !ruby/object:Gem::Version
392
+ version: 1.0.1
393
+ type: :development
394
+ prerelease: false
395
+ version_requirements: !ruby/object:Gem::Requirement
396
+ requirements:
397
+ - - "~>"
398
+ - !ruby/object:Gem::Version
399
+ version: '1.0'
400
+ - - ">="
401
+ - !ruby/object:Gem::Version
402
+ version: 1.0.1
403
403
  - !ruby/object:Gem::Dependency
404
404
  name: yarjuf
405
405
  requirement: !ruby/object:Gem::Requirement
@@ -444,10 +444,10 @@ files:
444
444
  - lib/vmpooler/providers.rb
445
445
  - lib/vmpooler/providers/base.rb
446
446
  - lib/vmpooler/providers/dummy.rb
447
- - lib/vmpooler/providers/vsphere.rb
448
447
  - lib/vmpooler/public/bootstrap.min.css
449
448
  - lib/vmpooler/public/img/bg.png
450
449
  - lib/vmpooler/public/img/logo.gif
450
+ - lib/vmpooler/public/img/logo.png
451
451
  - lib/vmpooler/public/img/spinner.svg
452
452
  - lib/vmpooler/public/img/subtle_dots.png
453
453
  - lib/vmpooler/public/img/textured_paper.png
@@ -479,7 +479,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
479
479
  - !ruby/object:Gem::Version
480
480
  version: '0'
481
481
  requirements: []
482
- rubygems_version: 3.0.8
482
+ rubyforge_project:
483
+ rubygems_version: 2.7.6.2
483
484
  signing_key:
484
485
  specification_version: 4
485
486
  summary: vmpooler provides configurable pools of instantly-available (running) virtual