vmpooler 1.1.0 → 1.3.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: 9f802530711b24fac0c8b34198895a2b4b5d18f32942bc4fb7b35d5756ead742
4
- data.tar.gz: 31df1542e5d1c2441976780c10c523f95617a8d0ea57457e6c8afd3a488ef983
3
+ metadata.gz: 32b41fec26ba54f25cb6186a6dc1b97904a855f0e5ceeca19978c4c614b5ef55
4
+ data.tar.gz: 1937db66b56b998fe4030ed133eaad5bbabd15646d3786dfa1539a8ee6e35a95
5
5
  SHA512:
6
- metadata.gz: 40705e369c0b5dcc9b5f8a9d1f30258586f6df66528421b054fb772d2a51a5bcbcb3795f23efa1239e9948322b807406cffef2107f741d5c1d713a0f0c125592
7
- data.tar.gz: ef3eb7549072874d71c9ddb0e50913679f47006cdecff869a0db49e7cc8e7af00d4f4455a824e441fb93ef94999b81e411d06418ec5ce08481c9318b670a55aa
6
+ metadata.gz: 747e7156ec196e938a41ffcc7857d01c32d9412b28ce20bea8f52edc6d6579118c7f4d458bdca70d8765b1ce081e44926b0c5560081e6fa27d74110262ce1e2d
7
+ data.tar.gz: e77c0fe360af30347f20ada5cd34879087b4775aff81914ee41c83639d7a9c91951dc8a5cbf0f2028eabd65312d96e94a95bcc81457de3d1c897d121a79282c2
@@ -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
@@ -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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vmpooler
4
- VERSION = '1.1.0'
4
+ VERSION = '1.3.0'
5
5
  end
data/lib/vmpooler.rb CHANGED
@@ -119,6 +119,11 @@ module Vmpooler
119
119
  parsed_config[:auth][:ldap]['port'] = string_to_int(ENV['LDAP_PORT']) if ENV['LDAP_PORT']
120
120
  parsed_config[:auth][:ldap]['base'] = ENV['LDAP_BASE'] if ENV['LDAP_BASE']
121
121
  parsed_config[:auth][:ldap]['user_object'] = ENV['LDAP_USER_OBJECT'] if ENV['LDAP_USER_OBJECT']
122
+ if parsed_config[:auth]['provider'] == 'ldap' && parsed_config[:auth][:ldap].key?('encryption')
123
+ parsed_config[:auth][:ldap]['encryption'] = parsed_config[:auth][:ldap]['encryption']
124
+ elsif parsed_config[:auth]['provider'] == 'ldap'
125
+ parsed_config[:auth][:ldap]['encryption'] = {}
126
+ end
122
127
  end
123
128
 
124
129
  # Create an index of pool aliases
@@ -128,8 +133,17 @@ module Vmpooler
128
133
  parsed_config[:pools] = load_pools_from_redis(redis)
129
134
  end
130
135
 
136
+ # Marshal.dump is paired with Marshal.load to create a copy that has its own memory space
137
+ # so that each can be edited independently
138
+ # rubocop:disable Security/MarshalLoad
139
+
140
+ # retain a copy of the pools that were observed at startup
141
+ serialized_pools = Marshal.dump(parsed_config[:pools])
142
+ parsed_config[:pools_at_startup] = Marshal.load(serialized_pools)
143
+
131
144
  # Create an index of pools by title
132
145
  parsed_config[:pool_index] = pool_index(parsed_config[:pools])
146
+ # rubocop:enable Security/MarshalLoad
133
147
 
134
148
  parsed_config[:pools].each do |pool|
135
149
  parsed_config[:pool_names] << pool['name']
@@ -236,12 +250,12 @@ module Vmpooler
236
250
  if tracing_enabled.eql?('false')
237
251
  puts "Exporting of traces has been disabled so the span processor has been se to a 'NoopSpanExporter'"
238
252
  span_processor = OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
239
- exporter: OpenTelemetry::SDK::Trace::Export::NoopSpanExporter.new
253
+ OpenTelemetry::SDK::Trace::Export::NoopSpanExporter.new
240
254
  )
241
255
  else
242
256
  puts "Exporting of traces will be done over HTTP in binary Thrift format to #{tracing_jaeger_host}"
243
257
  span_processor = OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
244
- exporter: OpenTelemetry::Exporter::Jaeger::CollectorExporter.new(endpoint: tracing_jaeger_host)
258
+ OpenTelemetry::Exporter::Jaeger::CollectorExporter.new(endpoint: tracing_jaeger_host)
245
259
  )
246
260
  end
247
261
 
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.0
4
+ version: 1.3.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-18 00:00:00.000000000 Z
11
+ date: 2021-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -72,84 +72,84 @@ dependencies:
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 0.15.0
75
+ version: 0.17.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 0.15.0
82
+ version: 0.17.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: opentelemetry-instrumentation-concurrent_ruby
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 0.15.0
89
+ version: 0.17.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 0.15.0
96
+ version: 0.17.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: opentelemetry-instrumentation-redis
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 0.15.0
103
+ version: 0.17.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 0.15.0
110
+ version: 0.17.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: opentelemetry-instrumentation-sinatra
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 0.15.0
117
+ version: 0.17.0
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: 0.15.0
124
+ version: 0.17.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: opentelemetry-resource_detectors
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - '='
130
130
  - !ruby/object:Gem::Version
131
- version: 0.15.0
131
+ version: 0.17.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - '='
137
137
  - !ruby/object:Gem::Version
138
- version: 0.15.0
138
+ version: 0.17.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: opentelemetry-sdk
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - '='
144
144
  - !ruby/object:Gem::Version
145
- version: 0.15.0
145
+ version: 0.17.0
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - '='
151
151
  - !ruby/object:Gem::Version
152
- version: 0.15.0
152
+ version: 0.17.0
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: pickup
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -400,6 +400,26 @@ dependencies:
400
400
  - - ">="
401
401
  - !ruby/object:Gem::Version
402
402
  version: 0.11.2
403
+ - !ruby/object:Gem::Dependency
404
+ name: thor
405
+ requirement: !ruby/object:Gem::Requirement
406
+ requirements:
407
+ - - "~>"
408
+ - !ruby/object:Gem::Version
409
+ version: '1.0'
410
+ - - ">="
411
+ - !ruby/object:Gem::Version
412
+ version: 1.0.1
413
+ type: :development
414
+ prerelease: false
415
+ version_requirements: !ruby/object:Gem::Requirement
416
+ requirements:
417
+ - - "~>"
418
+ - !ruby/object:Gem::Version
419
+ version: '1.0'
420
+ - - ">="
421
+ - !ruby/object:Gem::Version
422
+ version: 1.0.1
403
423
  - !ruby/object:Gem::Dependency
404
424
  name: yarjuf
405
425
  requirement: !ruby/object:Gem::Requirement