(POOLER-153) Add endpoint for resetting a pool

This commit adds a capability to vmpooler to reset a pool, deleting its ready and pending instances and replacing them with fresh ones. Without this change vmpooler does not offer a mechanism to reset a pool without also changing its template.
This commit is contained in:
kirby@puppetlabs.com 2020-02-11 16:34:19 -08:00
parent 3732ed750e
commit 52b60b074c
5 changed files with 237 additions and 1 deletions

View file

@ -200,6 +200,17 @@ module Vmpooler
result
end
def reset_pool(payload)
result = { 'ok' => false }
payload.each do |poolname, count|
backend.sadd('vmpooler__poolreset', poolname)
end
status 201
result['ok'] = true
result
end
def update_clone_target(payload)
result = { 'ok' => false }
@ -1063,6 +1074,44 @@ module Vmpooler
JSON.pretty_generate(result)
end
post "#{api_prefix}/poolreset/?" do
content_type :json
result = { 'ok' => false }
if config['experimental_features']
need_token! if Vmpooler::API.settings.config[:auth]
begin
payload = JSON.parse(request.body.read)
if payload
invalid = invalid_templates(payload)
if invalid.empty?
result = reset_pool(payload)
else
invalid.each do |bad_pool|
metrics.increment("poolreset.invalid.#{bad_pool}")
end
result[:bad_pools] = invalid
status 400
end
else
metrics.increment('poolreset.invalid.unknown')
status 404
end
rescue JSON::ParserError
status 400
result = {
'ok' => false,
'message' => 'JSON payload could not be parsed'
}
end
else
status 405
end
JSON.pretty_generate(result)
end
post "#{api_prefix}/config/clonetarget/?" do
content_type :json
result = { 'ok' => false }

View file

@ -680,6 +680,10 @@ module Vmpooler
# - Fires when a template configuration update is requested
# - Additional options
# :poolname
# :pool_reset
# - Fires when a pool reset is requested
# - Additional options
# :poolname
#
def sleep_with_wakeup_events(loop_delay, wakeup_period = 5, options = {})
exit_by = Time.now + loop_delay
@ -726,6 +730,10 @@ module Vmpooler
end
end
if options[:pool_reset]
break if $redis.sismember('vmpooler__poolreset', options[:poolname])
end
end
break if time_passed?(:exit_by, exit_by)
@ -763,7 +771,7 @@ module Vmpooler
loop_delay = (loop_delay * loop_delay_decay).to_i
loop_delay = loop_delay_max if loop_delay > loop_delay_max
end
sleep_with_wakeup_events(loop_delay, loop_delay_min, pool_size_change: true, poolname: pool['name'], pool_template_change: true, clone_target_change: true)
sleep_with_wakeup_events(loop_delay, loop_delay_min, pool_size_change: true, poolname: pool['name'], pool_template_change: true, clone_target_change: true, pool_reset: true)
unless maxloop.zero?
break if loop_count >= maxloop
@ -917,6 +925,17 @@ module Vmpooler
end
end
def reset_pool(pool)
poolname = pool['name']
return unless $redis.sismember('vmpooler__poolreset', poolname)
$redis.srem('vmpooler__poolreset', poolname)
mutex = pool_mutex(poolname)
mutex.synchronize do
drain_pool(poolname)
$logger.log('s', "[*] [#{poolname}] reset has cleared ready and pending instances")
end
end
def create_inventory(pool, provider, pool_check_response)
inventory = {}
begin
@ -1125,6 +1144,9 @@ module Vmpooler
# Remove VMs in excess of the configured pool size
remove_excess_vms(pool)
# Reset a pool when poolreset is requested from the API
reset_pool(pool)
pool_check_response
end