(POOLER-193) Mark checked out VM as active

This change sets a VM as running in redis as soon as it is checked out. Without this change when allocated several instances it is possible for a machine that has been allocated for a checkout, but not yet marked as active, to be identified as running when it should not be, which was added in POOLER-191. Without this change a machine may be destroyed during checkout by pool_manager if there are several instances being allocated.

Additionally, redis multi is added for vm checkout operations to minimize the round trips to redis during a checkout operation. Without this addition each VM checkout causes several redis interactions.
This commit is contained in:
kirby@puppetlabs.com 2020-11-06 13:16:38 -08:00
parent a3cfe7749e
commit cfd6a5f991

View file

@ -163,26 +163,31 @@ module Vmpooler
end end
def return_vm_to_ready_state(template, vm) def return_vm_to_ready_state(template, vm)
backend.multi
backend.srem("vmpooler__migrating__#{template}", vm)
backend.hdel("vmpooler__active__#{template}", vm)
backend.hdel("vmpooler__vm__#{vm}", 'checkout', 'token:token', 'token:user')
backend.smove("vmpooler__running__#{template}", "vmpooler__ready__#{template}", vm) backend.smove("vmpooler__running__#{template}", "vmpooler__ready__#{template}", vm)
backend.exec
end end
def account_for_starting_vm(template, vm) def account_for_starting_vm(template, vm)
user = backend.hget("vmpooler__token__#{request.env['HTTP_X_AUTH_TOKEN']}", 'user')
has_token_result = has_token?
backend.multi
backend.sadd("vmpooler__migrating__#{template}", vm) backend.sadd("vmpooler__migrating__#{template}", vm)
backend.hset("vmpooler__active__#{template}", vm, Time.now) backend.hset("vmpooler__active__#{template}", vm, Time.now)
backend.hset("vmpooler__vm__#{vm}", 'checkout', Time.now) backend.hset("vmpooler__vm__#{vm}", 'checkout', Time.now)
if Vmpooler::API.settings.config[:auth] and has_token? if Vmpooler::API.settings.config[:auth] and has_token_result
validate_token(backend)
backend.hset("vmpooler__vm__#{vm}", 'token:token', request.env['HTTP_X_AUTH_TOKEN']) backend.hset("vmpooler__vm__#{vm}", 'token:token', request.env['HTTP_X_AUTH_TOKEN'])
backend.hset("vmpooler__vm__#{vm}", 'token:user', backend.hset("vmpooler__vm__#{vm}", 'token:user', user)
backend.hget("vmpooler__token__#{request.env['HTTP_X_AUTH_TOKEN']}", 'user')
)
if config['vm_lifetime_auth'].to_i > 0 if config['vm_lifetime_auth'].to_i > 0
backend.hset("vmpooler__vm__#{vm}", 'lifetime', config['vm_lifetime_auth'].to_i) backend.hset("vmpooler__vm__#{vm}", 'lifetime', config['vm_lifetime_auth'].to_i)
end end
end end
backend.exec
end end
def update_result_hosts(result, template, vm) def update_result_hosts(result, template, vm)
@ -200,16 +205,19 @@ module Vmpooler
failed = false failed = false
vms = [] vms = []
validate_token(backend) if Vmpooler::API.settings.config[:auth] and has_token?
payload.each do |requested, count| payload.each do |requested, count|
count.to_i.times do |_i| count.to_i.times do |_i|
vmname, vmpool, vmtemplate = fetch_single_vm(requested) vmname, vmpool, vmtemplate = fetch_single_vm(requested)
if !vmname if vmname
account_for_starting_vm(vmpool, vmname)
vms << [vmpool, vmname, vmtemplate]
metrics.increment("checkout.success.#{vmtemplate}")
else
failed = true failed = true
metrics.increment("checkout.empty.#{requested}") metrics.increment("checkout.empty.#{requested}")
break break
else
vms << [vmpool, vmname, vmtemplate]
metrics.increment("checkout.success.#{vmpool}")
end end
end end
end end
@ -220,8 +228,7 @@ module Vmpooler
end end
status 503 status 503
else else
vms.each do |(vmpool, vmname, vmtemplate)| vms.each do |(_vmpool, vmname, vmtemplate)|
account_for_starting_vm(vmpool, vmname)
update_result_hosts(result, vmtemplate, vmname) update_result_hosts(result, vmtemplate, vmname)
end end
@ -1094,7 +1101,7 @@ module Vmpooler
result[params[:hostname]]['lifetime'] = (rdata['lifetime'] || config['vm_lifetime']).to_i result[params[:hostname]]['lifetime'] = (rdata['lifetime'] || config['vm_lifetime']).to_i
if rdata['destroy'] if rdata['destroy']
result[params[:hostname]]['running'] = ((Time.parse(rdata['destroy']) - Time.parse(rdata['checkout'])) / 60 / 60).round(2) result[params[:hostname]]['running'] = ((Time.parse(rdata['destroy']) - Time.parse(rdata['checkout'])) / 60 / 60).round(2) if rdata['checkout']
result[params[:hostname]]['state'] = 'destroyed' result[params[:hostname]]['state'] = 'destroyed'
elsif rdata['checkout'] elsif rdata['checkout']
result[params[:hostname]]['running'] = ((Time.now - Time.parse(rdata['checkout'])) / 60 / 60).round(2) result[params[:hostname]]['running'] = ((Time.now - Time.parse(rdata['checkout'])) / 60 / 60).round(2)