vmpooler 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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