vmpooler 3.3.0 → 3.5.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: b586b8ee56526b89f47621d090f932159c46df74c6935002e8a71c18a02503fb
4
- data.tar.gz: 51e4f7cf4dd4a5daa3130ab1bb60b08b4347196e1ba1c39f94a820d7356f2937
3
+ metadata.gz: 421d86151ba2c7a9bcc2310e3596b43f27a0280df1b7cb0c042dd12a63c80086
4
+ data.tar.gz: 7f8e2dea7fc3f4089995fc65022e98e48771f5a40cbbd30b51ddf162fad7b3f7
5
5
  SHA512:
6
- metadata.gz: 39ba39f114252e74a08a6c3dbebd773cb2dda74adfc33216b7774dbf8fb83109f2a61076a3435cab54f8dc39adcdef60ee1cac44f24b3f3f441c7ceaf389e813
7
- data.tar.gz: e295be65e92e61fad459d32d1a6171396b0599795355b99821d7bc8272ecbe19cfee78dd735c88e49653d5156afb7e529f12935d484fc2b1c479e5eed4be69e1
6
+ metadata.gz: 4722f36453f515e66cf69d2c9c19cd472dd289e012514b2823e6ccf2febbdc525d78969e4a24777779b2fd9dbf5c0f8137421e6fe0bdf95f726effead80cd114
7
+ data.tar.gz: 979d40b555d547d6ebec64efeb57af5cdb68eb90fbc6f759cf6a1bbfef074e66404b9e238ad410bd938cef611ae006e430aad86c754a50e3901d9c659081c733
@@ -68,7 +68,7 @@ module Vmpooler
68
68
  end
69
69
  end
70
70
 
71
- def authenticate_ldap(port, host, encryption_hash, user_object, base, username_str, password_str)
71
+ def authenticate_ldap(port, host, encryption_hash, user_object, base, username_str, password_str, service_account_hash = nil)
72
72
  tracer.in_span(
73
73
  "Vmpooler::API::Helpers.#{__method__}",
74
74
  attributes: {
@@ -79,6 +79,14 @@ module Vmpooler
79
79
  },
80
80
  kind: :client
81
81
  ) do
82
+ if service_account_hash
83
+ username = service_account_hash[:user_dn]
84
+ password = service_account_hash[:password]
85
+ else
86
+ username = "#{user_object}=#{username_str},#{base}"
87
+ password = password_str
88
+ end
89
+
82
90
  ldap = Net::LDAP.new(
83
91
  :host => host,
84
92
  :port => port,
@@ -86,12 +94,22 @@ module Vmpooler
86
94
  :base => base,
87
95
  :auth => {
88
96
  :method => :simple,
89
- :username => "#{user_object}=#{username_str},#{base}",
90
- :password => password_str
97
+ :username => username,
98
+ :password => password
91
99
  }
92
100
  )
93
101
 
94
- return true if ldap.bind
102
+ if service_account_hash
103
+ return true if ldap.bind_as(
104
+ :base => base,
105
+ :filter => "(#{user_object}=#{username_str})",
106
+ :password => password_str
107
+ )
108
+ elsif ldap.bind
109
+ return true
110
+ else
111
+ return false
112
+ end
95
113
 
96
114
  return false
97
115
  end
@@ -116,6 +134,7 @@ module Vmpooler
116
134
  :method => :start_tls,
117
135
  :tls_options => { :ssl_version => 'TLSv1' }
118
136
  }
137
+ service_account_hash = auth[:ldap]['service_account_hash']
119
138
 
120
139
  unless ldap_base.is_a? Array
121
140
  ldap_base = ldap_base.split
@@ -134,7 +153,8 @@ module Vmpooler
134
153
  search_user_obj,
135
154
  search_base,
136
155
  username_str,
137
- password_str
156
+ password_str,
157
+ service_account_hash
138
158
  )
139
159
  return true if result
140
160
  end
@@ -551,18 +571,6 @@ module Vmpooler
551
571
  end
552
572
  end
553
573
  end
554
-
555
- def vm_ready?(vm_name, domain = nil)
556
- tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
557
- begin
558
- open_socket(vm_name, domain)
559
- rescue StandardError => _e
560
- return false
561
- end
562
-
563
- true
564
- end
565
- end
566
574
  end
567
575
  end
568
576
  end
@@ -82,31 +82,31 @@ module Vmpooler
82
82
  end
83
83
 
84
84
  # Check the state of a VM
85
- def check_pending_vm(vm, pool, timeout, provider)
85
+ def check_pending_vm(vm, pool, timeout, timeout_notification, provider)
86
86
  Thread.new do
87
87
  begin
88
- _check_pending_vm(vm, pool, timeout, provider)
88
+ _check_pending_vm(vm, pool, timeout, timeout_notification, provider)
89
89
  rescue StandardError => e
90
90
  $logger.log('s', "[!] [#{pool}] '#{vm}' #{timeout} #{provider} errored while checking a pending vm : #{e}")
91
91
  @redis.with_metrics do |redis|
92
- fail_pending_vm(vm, pool, timeout, redis)
92
+ fail_pending_vm(vm, pool, timeout, timeout_notification, redis)
93
93
  end
94
94
  raise
95
95
  end
96
96
  end
97
97
  end
98
98
 
99
- def _check_pending_vm(vm, pool, timeout, provider)
99
+ def _check_pending_vm(vm, pool, timeout, timeout_notification, provider)
100
100
  mutex = vm_mutex(vm)
101
101
  return if mutex.locked?
102
102
 
103
103
  mutex.synchronize do
104
104
  @redis.with_metrics do |redis|
105
105
  request_id = redis.hget("vmpooler__vm__#{vm}", 'request_id')
106
- if provider.vm_ready?(pool, vm)
106
+ if provider.vm_ready?(pool, vm, redis)
107
107
  move_pending_vm_to_ready(vm, pool, redis, request_id)
108
108
  else
109
- fail_pending_vm(vm, pool, timeout, redis)
109
+ fail_pending_vm(vm, pool, timeout, timeout_notification, redis)
110
110
  end
111
111
  end
112
112
  end
@@ -122,34 +122,53 @@ module Vmpooler
122
122
  $logger.log('d', "[!] [#{pool}] '#{vm}' no longer exists. Removing from pending.")
123
123
  end
124
124
 
125
- def fail_pending_vm(vm, pool, timeout, redis, exists: true)
125
+ def fail_pending_vm(vm, pool, timeout, timeout_notification, redis, exists: true)
126
126
  clone_stamp = redis.hget("vmpooler__vm__#{vm}", 'clone')
127
-
128
127
  time_since_clone = (Time.now - Time.parse(clone_stamp)) / 60
129
- if time_since_clone > timeout
130
- if exists
131
- request_id = redis.hget("vmpooler__vm__#{vm}", 'request_id')
132
- pool_alias = redis.hget("vmpooler__vm__#{vm}", 'pool_alias') if request_id
133
- redis.smove("vmpooler__pending__#{pool}", "vmpooler__completed__#{pool}", vm)
134
- if request_id
135
- ondemandrequest_hash = redis.hgetall("vmpooler__odrequest__#{request_id}")
136
- if ondemandrequest_hash && ondemandrequest_hash['status'] != 'failed' && ondemandrequest_hash['status'] != 'deleted'
137
- # will retry a VM that did not come up as vm_ready? only if it has not been market failed or deleted
138
- redis.zadd('vmpooler__odcreate__task', 1, "#{pool_alias}:#{pool}:1:#{request_id}")
139
- end
140
- end
141
- $metrics.increment("errors.markedasfailed.#{pool}")
142
- $logger.log('d', "[!] [#{pool}] '#{vm}' marked as 'failed' after #{timeout} minutes")
143
- else
128
+
129
+ already_timed_out = time_since_clone > timeout
130
+ timing_out_soon = time_since_clone > timeout_notification && !redis.hget("vmpooler__vm__#{vm}", 'timeout_notification')
131
+
132
+ if already_timed_out
133
+ unless exists
144
134
  remove_nonexistent_vm(vm, pool, redis)
135
+ return true
145
136
  end
137
+ open_socket_error = handle_timed_out_vm(vm, pool, redis)
146
138
  end
139
+
140
+ redis.hset("vmpooler__vm__#{vm}", 'timeout_notification', 1) if timing_out_soon
141
+
142
+ nonexist_warning = if already_timed_out
143
+ "[!] [#{pool}] '#{vm}' marked as 'failed' after #{timeout} minutes with error: #{open_socket_error}"
144
+ elsif timing_out_soon
145
+ "[!] [#{pool}] '#{vm}' no longer exists when attempting to send notification of impending failure"
146
+ else
147
+ "[!] [#{pool}] '#{vm}' This error is wholly unexpected"
148
+ end
149
+ $logger.log('d', nonexist_warning)
147
150
  true
148
151
  rescue StandardError => e
149
152
  $logger.log('d', "Fail pending VM failed with an error: #{e}")
150
153
  false
151
154
  end
152
155
 
156
+ def handle_timed_out_vm(vm, pool, redis)
157
+ request_id = redis.hget("vmpooler__vm__#{vm}", 'request_id')
158
+ pool_alias = redis.hget("vmpooler__vm__#{vm}", 'pool_alias') if request_id
159
+ open_socket_error = redis.hget("vmpooler__vm__#{vm}", 'open_socket_error')
160
+ redis.smove("vmpooler__pending__#{pool}", "vmpooler__completed__#{pool}", vm)
161
+ if request_id
162
+ ondemandrequest_hash = redis.hgetall("vmpooler__odrequest__#{request_id}")
163
+ if ondemandrequest_hash && ondemandrequest_hash['status'] != 'failed' && ondemandrequest_hash['status'] != 'deleted'
164
+ # will retry a VM that did not come up as vm_ready? only if it has not been market failed or deleted
165
+ redis.zadd('vmpooler__odcreate__task', 1, "#{pool_alias}:#{pool}:1:#{request_id}")
166
+ end
167
+ end
168
+ $metrics.increment("errors.markedasfailed.#{pool}")
169
+ open_socket_error
170
+ end
171
+
153
172
  def move_pending_vm_to_ready(vm, pool, redis, request_id = nil)
154
173
  clone_time = redis.hget("vmpooler__vm__#{vm}", 'clone')
155
174
  finish = format('%<time>.2f', time: Time.now - Time.parse(clone_time))
@@ -197,11 +216,12 @@ module Vmpooler
197
216
 
198
217
  def vm_still_ready?(pool_name, vm_name, provider, redis)
199
218
  # Check if the VM is still ready/available
200
- return true if provider.vm_ready?(pool_name, vm_name)
219
+ return true if provider.vm_ready?(pool_name, vm_name, redis)
201
220
 
202
221
  raise("VM #{vm_name} is not ready")
203
222
  rescue StandardError
204
- move_vm_queue(pool_name, vm_name, 'ready', 'completed', redis, "is unreachable, removed from 'ready' queue")
223
+ open_socket_error = redis.hget("vmpooler__vm__#{vm_name}", 'open_socket_error')
224
+ move_vm_queue(pool_name, vm_name, 'ready', 'completed', redis, "removed from 'ready' queue. vm unreachable with error: #{open_socket_error}")
205
225
  end
206
226
 
207
227
  def check_ready_vm(vm, pool_name, ttl, provider)
@@ -318,7 +338,7 @@ module Vmpooler
318
338
  redis.hset("vmpooler__vm__#{vm}", 'user_tagged', 'true') if success
319
339
  end
320
340
 
321
- throw :stop_checking if provider.vm_ready?(pool, vm)
341
+ throw :stop_checking if provider.vm_ready?(pool, vm, redis)
322
342
 
323
343
  throw :stop_checking if provider.get_vm(pool, vm)
324
344
 
@@ -450,6 +470,9 @@ module Vmpooler
450
470
  ip_start = Time.now
451
471
  ip = provider.get_vm_ip_address(new_vmname, pool_name)
452
472
  ip_finish = format('%<time>.2f', time: Time.now - ip_start)
473
+
474
+ raise StandardError, "failed to obtain IP after #{ip_finish} seconds" if ip.nil?
475
+
453
476
  $logger.log('s', "[+] [#{pool_name}] Obtained IP for '#{new_vmname}' in #{ip_finish} seconds")
454
477
 
455
478
  @redis.with_metrics do |redis|
@@ -1248,19 +1271,20 @@ module Vmpooler
1248
1271
  end
1249
1272
  end
1250
1273
 
1251
- def check_pending_pool_vms(pool_name, provider, pool_check_response, inventory, pool_timeout)
1274
+ def check_pending_pool_vms(pool_name, provider, pool_check_response, inventory, pool_timeout, pool_timeout_notification)
1252
1275
  pool_timeout ||= $config[:config]['timeout'] || 15
1276
+ pool_timeout_notification ||= $config[:config]['timeout_notification'] || 5
1253
1277
  @redis.with_metrics do |redis|
1254
1278
  redis.smembers("vmpooler__pending__#{pool_name}").reverse.each do |vm|
1255
1279
  if inventory[vm]
1256
1280
  begin
1257
1281
  pool_check_response[:checked_pending_vms] += 1
1258
- check_pending_vm(vm, pool_name, pool_timeout, provider)
1282
+ check_pending_vm(vm, pool_name, pool_timeout, pool_timeout_notification, provider)
1259
1283
  rescue StandardError => e
1260
1284
  $logger.log('d', "[!] [#{pool_name}] _check_pool failed with an error while evaluating pending VMs: #{e}")
1261
1285
  end
1262
1286
  else
1263
- fail_pending_vm(vm, pool_name, pool_timeout, redis, exists: false)
1287
+ fail_pending_vm(vm, pool_name, pool_timeout, pool_timeout_notification, redis, exists: false)
1264
1288
  end
1265
1289
  end
1266
1290
  end
@@ -1387,7 +1411,7 @@ module Vmpooler
1387
1411
 
1388
1412
  check_ready_pool_vms(pool['name'], provider, pool_check_response, inventory, pool['ready_ttl'] || $config[:config]['ready_ttl'])
1389
1413
 
1390
- check_pending_pool_vms(pool['name'], provider, pool_check_response, inventory, pool['timeout'])
1414
+ check_pending_pool_vms(pool['name'], provider, pool_check_response, inventory, pool['timeout'], pool['timeout_notification'])
1391
1415
 
1392
1416
  check_completed_pool_vms(pool['name'], provider, pool_check_response, inventory)
1393
1417
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vmpooler
4
- VERSION = '3.3.0'
4
+ VERSION = '3.5.0'
5
5
  end
data/lib/vmpooler.rb CHANGED
@@ -82,6 +82,7 @@ module Vmpooler
82
82
  end
83
83
  parsed_config[:config]['clone_target'] = ENV['CLONE_TARGET'] if ENV['CLONE_TARGET']
84
84
  parsed_config[:config]['timeout'] = string_to_int(ENV['TIMEOUT']) if ENV['TIMEOUT']
85
+ parsed_config[:config]['timeout_notification'] = string_to_int(ENV['TIMEOUT_NOTIFICATION']) if ENV['TIMEOUT_NOTIFICATION']
85
86
  parsed_config[:config]['vm_lifetime_auth'] = string_to_int(ENV['VM_LIFETIME_AUTH']) if ENV['VM_LIFETIME_AUTH']
86
87
  parsed_config[:config]['max_tries'] = string_to_int(ENV['MAX_TRIES']) if ENV['MAX_TRIES']
87
88
  parsed_config[:config]['retry_factor'] = string_to_int(ENV['RETRY_FACTOR']) if ENV['RETRY_FACTOR']
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: 3.3.0
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-16 00:00:00.000000000 Z
11
+ date: 2023-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement