Merge pull request #561 from puppetlabs/update_redis

(RE-15162) Update Redis gem to version 5.0.
This commit is contained in:
Jake Spain 2023-08-14 13:59:24 -04:00 committed by GitHub
commit 77cc124510
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 56 deletions

View file

@ -3,7 +3,7 @@ PATH
specs: specs:
vmpooler (3.2.0) vmpooler (3.2.0)
concurrent-ruby (~> 1.1) concurrent-ruby (~> 1.1)
connection_pool (~> 2.2) connection_pool (~> 2.4)
deep_merge (~> 1.2) deep_merge (~> 1.2)
net-ldap (~> 0.16) net-ldap (~> 0.16)
opentelemetry-exporter-jaeger (= 0.23.0) opentelemetry-exporter-jaeger (= 0.23.0)
@ -18,7 +18,7 @@ PATH
puma (>= 5.0.4, < 7) puma (>= 5.0.4, < 7)
rack (>= 2.2, < 4.0) rack (>= 2.2, < 4.0)
rake (~> 13.0) rake (~> 13.0)
redis (~> 4.1) redis (~> 5.0)
sinatra (>= 2, < 4) sinatra (>= 2, < 4)
spicy-proton (~> 2.1) spicy-proton (~> 2.1)
statsd-ruby (~> 1.4) statsd-ruby (~> 1.4)
@ -124,7 +124,10 @@ GEM
rack (>= 1.3) rack (>= 1.3)
rainbow (3.1.1) rainbow (3.1.1)
rake (13.0.6) rake (13.0.6)
redis (4.8.1) redis (5.0.7)
redis-client (>= 0.9.0)
redis-client (0.15.0)
connection_pool
regexp_parser (2.8.1) regexp_parser (2.8.1)
rexml (3.2.6) rexml (3.2.6)
rspec (3.12.0) rspec (3.12.0)

View file

@ -103,7 +103,7 @@ module Vmpooler
parsed_config[:redis]['data_ttl'] = string_to_int(ENV['REDIS_DATA_TTL']) || parsed_config[:redis]['data_ttl'] || 168 parsed_config[:redis]['data_ttl'] = string_to_int(ENV['REDIS_DATA_TTL']) || parsed_config[:redis]['data_ttl'] || 168
parsed_config[:redis]['connection_pool_size'] = string_to_int(ENV['REDIS_CONNECTION_POOL_SIZE']) || parsed_config[:redis]['connection_pool_size'] || 10 parsed_config[:redis]['connection_pool_size'] = string_to_int(ENV['REDIS_CONNECTION_POOL_SIZE']) || parsed_config[:redis]['connection_pool_size'] || 10
parsed_config[:redis]['connection_pool_timeout'] = string_to_int(ENV['REDIS_CONNECTION_POOL_TIMEOUT']) || parsed_config[:redis]['connection_pool_timeout'] || 5 parsed_config[:redis]['connection_pool_timeout'] = string_to_int(ENV['REDIS_CONNECTION_POOL_TIMEOUT']) || parsed_config[:redis]['connection_pool_timeout'] || 5
parsed_config[:redis]['reconnect_attempts'] = string_to_int(ENV['REDIS_RECONNECT_ATTEMPTS']) || parsed_config[:redis]['reconnect_attempts'] || 10 parsed_config[:redis]['reconnect_attempts'] = string_array_to_array(ENV['REDIS_RECONNECT_ATTEMPTS']) || parsed_config[:redis]['reconnect_attempts'] || 10
parsed_config[:statsd] = parsed_config[:statsd] || {} if ENV['STATSD_SERVER'] parsed_config[:statsd] = parsed_config[:statsd] || {} if ENV['STATSD_SERVER']
parsed_config[:statsd]['server'] = ENV['STATSD_SERVER'] if ENV['STATSD_SERVER'] parsed_config[:statsd]['server'] = ENV['STATSD_SERVER'] if ENV['STATSD_SERVER']
@ -209,8 +209,13 @@ module Vmpooler
end end
def self.new_redis(host = 'localhost', port = nil, password = nil, redis_reconnect_attempts = 10) def self.new_redis(host = 'localhost', port = nil, password = nil, redis_reconnect_attempts = 10)
Redis.new(host: host, port: port, password: password, reconnect_attempts: redis_reconnect_attempts, reconnect_delay: 1.5, Redis.new(
reconnect_delay_max: 10.0) host: host,
port: port,
password: password,
reconnect_attempts: redis_reconnect_attempts,
connect_timeout: 300
)
end end
def self.pools(conf) def self.pools(conf)
@ -235,6 +240,13 @@ module Vmpooler
Integer(s) Integer(s)
end end
def self.string_array_to_array(s)
# Returns an array from an array like string
return if s.nil?
JSON.parse(s)
end
def self.true?(obj) def self.true?(obj)
obj.to_s.downcase == 'true' obj.to_s.downcase == 'true'
end end

View file

@ -25,7 +25,7 @@ module Vmpooler
def validate_token(backend) def validate_token(backend)
tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do tracer.in_span("Vmpooler::API::Helpers.#{__method__}") do
if valid_token?(backend) if valid_token?(backend)
backend.hset("vmpooler__token__#{request.env['HTTP_X_AUTH_TOKEN']}", 'last', Time.now) backend.hset("vmpooler__token__#{request.env['HTTP_X_AUTH_TOKEN']}", 'last', Time.now.to_s)
return true return true
end end

View file

@ -189,8 +189,8 @@ module Vmpooler
span.set_attribute('enduser.id', user) span.set_attribute('enduser.id', user)
has_token_result = has_token? has_token_result = has_token?
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.to_s)
backend.hset("vmpooler__vm__#{vm}", 'checkout', Time.now) backend.hset("vmpooler__vm__#{vm}", 'checkout', Time.now.to_s)
if Vmpooler::API.settings.config[:auth] and has_token_result if Vmpooler::API.settings.config[:auth] and has_token_result
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'])
@ -971,7 +971,7 @@ module Vmpooler
result['token'] = o[rand(25)] + (0...31).map { o[rand(o.length)] }.join result['token'] = o[rand(25)] + (0...31).map { o[rand(o.length)] }.join
backend.hset("vmpooler__token__#{result['token']}", 'user', @auth.username) backend.hset("vmpooler__token__#{result['token']}", 'user', @auth.username)
backend.hset("vmpooler__token__#{result['token']}", 'created', Time.now) backend.hset("vmpooler__token__#{result['token']}", 'created', Time.now.to_s)
span = OpenTelemetry::Trace.current_span span = OpenTelemetry::Trace.current_span
span.set_attribute('enduser.id', @auth.username) span.set_attribute('enduser.id', @auth.username)

View file

@ -59,7 +59,7 @@ module Vmpooler
currently_configured_pools = [] currently_configured_pools = []
config[:pools].each do |pool| config[:pools].each do |pool|
currently_configured_pools << pool['name'] currently_configured_pools << pool['name']
redis.sadd('vmpooler__pools', pool['name']) redis.sadd('vmpooler__pools', pool['name'].to_s)
pool_keys = pool.keys pool_keys = pool.keys
pool_keys.delete('alias') pool_keys.delete('alias')
to_set = {} to_set = {}
@ -68,11 +68,12 @@ module Vmpooler
end end
to_set['alias'] = pool['alias'].join(',') if to_set.key?('alias') to_set['alias'] = pool['alias'].join(',') if to_set.key?('alias')
to_set['domain'] = Vmpooler::Dns.get_domain_for_pool(config, pool['name']) to_set['domain'] = Vmpooler::Dns.get_domain_for_pool(config, pool['name'])
redis.hmset("vmpooler__pool__#{pool['name']}", to_set.to_a.flatten) unless to_set.empty?
redis.hmset("vmpooler__pool__#{pool['name']}", *to_set.to_a.flatten) unless to_set.empty?
end end
previously_configured_pools.each do |pool| previously_configured_pools.each do |pool|
unless currently_configured_pools.include? pool unless currently_configured_pools.include? pool
redis.srem('vmpooler__pools', pool) redis.srem('vmpooler__pools', pool.to_s)
redis.del("vmpooler__pool__#{pool}") redis.del("vmpooler__pool__#{pool}")
end end
end end
@ -129,7 +130,6 @@ module Vmpooler
if exists if exists
request_id = redis.hget("vmpooler__vm__#{vm}", 'request_id') request_id = redis.hget("vmpooler__vm__#{vm}", 'request_id')
pool_alias = redis.hget("vmpooler__vm__#{vm}", 'pool_alias') if request_id pool_alias = redis.hget("vmpooler__vm__#{vm}", 'pool_alias') if request_id
redis.multi
redis.smove("vmpooler__pending__#{pool}", "vmpooler__completed__#{pool}", vm) redis.smove("vmpooler__pending__#{pool}", "vmpooler__completed__#{pool}", vm)
if request_id if request_id
ondemandrequest_hash = redis.hgetall("vmpooler__odrequest__#{request_id}") ondemandrequest_hash = redis.hgetall("vmpooler__odrequest__#{request_id}")
@ -138,7 +138,6 @@ module Vmpooler
redis.zadd('vmpooler__odcreate__task', 1, "#{pool_alias}:#{pool}:1:#{request_id}") redis.zadd('vmpooler__odcreate__task', 1, "#{pool_alias}:#{pool}:1:#{request_id}")
end end
end end
redis.exec
$metrics.increment("errors.markedasfailed.#{pool}") $metrics.increment("errors.markedasfailed.#{pool}")
$logger.log('d', "[!] [#{pool}] '#{vm}' marked as 'failed' after #{timeout} minutes") $logger.log('d', "[!] [#{pool}] '#{vm}' marked as 'failed' after #{timeout} minutes")
else else
@ -168,8 +167,8 @@ module Vmpooler
pool_alias = redis.hget("vmpooler__vm__#{vm}", 'pool_alias') pool_alias = redis.hget("vmpooler__vm__#{vm}", 'pool_alias')
redis.pipelined do |pipeline| redis.pipelined do |pipeline|
pipeline.hset("vmpooler__active__#{pool}", vm, Time.now) pipeline.hset("vmpooler__active__#{pool}", vm, Time.now.to_s)
pipeline.hset("vmpooler__vm__#{vm}", 'checkout', Time.now) pipeline.hset("vmpooler__vm__#{vm}", 'checkout', Time.now.to_s)
if ondemandrequest_hash['token:token'] if ondemandrequest_hash['token:token']
pipeline.hset("vmpooler__vm__#{vm}", 'token:token', ondemandrequest_hash['token:token']) pipeline.hset("vmpooler__vm__#{vm}", 'token:token', ondemandrequest_hash['token:token'])
pipeline.hset("vmpooler__vm__#{vm}", 'token:user', ondemandrequest_hash['token:user']) pipeline.hset("vmpooler__vm__#{vm}", 'token:user', ondemandrequest_hash['token:user'])
@ -185,10 +184,10 @@ module Vmpooler
redis.pipelined do |pipeline| redis.pipelined do |pipeline|
pipeline.hset("vmpooler__boot__#{Date.today}", "#{pool}:#{vm}", finish) # maybe remove as this is never used by vmpooler itself? pipeline.hset("vmpooler__boot__#{Date.today}", "#{pool}:#{vm}", finish) # maybe remove as this is never used by vmpooler itself?
pipeline.hset("vmpooler__vm__#{vm}", 'ready', Time.now) pipeline.hset("vmpooler__vm__#{vm}", 'ready', Time.now.to_s)
# last boot time is displayed in API, and used by alarming script # last boot time is displayed in API, and used by alarming script
pipeline.hset('vmpooler__lastboot', pool, Time.now) pipeline.hset('vmpooler__lastboot', pool, Time.now.to_s)
end end
$metrics.timing("time_to_ready_state.#{pool}", finish) $metrics.timing("time_to_ready_state.#{pool}", finish)
@ -227,7 +226,7 @@ module Vmpooler
last_checked_too_soon = ((Time.now - Time.parse(check_stamp)).to_i < $config[:config]['vm_checktime'] * 60) if check_stamp last_checked_too_soon = ((Time.now - Time.parse(check_stamp)).to_i < $config[:config]['vm_checktime'] * 60) if check_stamp
break if check_stamp && last_checked_too_soon break if check_stamp && last_checked_too_soon
redis.hset("vmpooler__vm__#{vm}", 'check', Time.now) redis.hset("vmpooler__vm__#{vm}", 'check', Time.now.to_s)
# Check if the hosts TTL has expired # Check if the hosts TTL has expired
# if 'boottime' is nil, set bootime to beginning of unix epoch, forces TTL to be assumed expired # if 'boottime' is nil, set bootime to beginning of unix epoch, forces TTL to be assumed expired
boottime = redis.hget("vmpooler__vm__#{vm}", 'ready') boottime = redis.hget("vmpooler__vm__#{vm}", 'ready')
@ -428,16 +427,15 @@ module Vmpooler
mutex = vm_mutex(new_vmname) mutex = vm_mutex(new_vmname)
mutex.synchronize do mutex.synchronize do
@redis.with_metrics do |redis| @redis.with_metrics do |redis|
# Add VM to Redis inventory ('pending' pool) redis.multi do |transaction|
redis.multi transaction.sadd("vmpooler__pending__#{pool_name}", new_vmname)
redis.sadd("vmpooler__pending__#{pool_name}", new_vmname) transaction.hset("vmpooler__vm__#{new_vmname}", 'clone', Time.now.to_s)
redis.hset("vmpooler__vm__#{new_vmname}", 'clone', Time.now) transaction.hset("vmpooler__vm__#{new_vmname}", 'template', pool_name) # This value is used to represent the pool.
redis.hset("vmpooler__vm__#{new_vmname}", 'template', pool_name) # This value is used to represent the pool. transaction.hset("vmpooler__vm__#{new_vmname}", 'pool', pool_name)
redis.hset("vmpooler__vm__#{new_vmname}", 'pool', pool_name) transaction.hset("vmpooler__vm__#{new_vmname}", 'domain', pool_domain)
redis.hset("vmpooler__vm__#{new_vmname}", 'domain', pool_domain) transaction.hset("vmpooler__vm__#{new_vmname}", 'request_id', request_id) if request_id
redis.hset("vmpooler__vm__#{new_vmname}", 'request_id', request_id) if request_id transaction.hset("vmpooler__vm__#{new_vmname}", 'pool_alias', pool_alias) if pool_alias
redis.hset("vmpooler__vm__#{new_vmname}", 'pool_alias', pool_alias) if pool_alias end
redis.exec
end end
begin begin
@ -502,7 +500,7 @@ module Vmpooler
@redis.with_metrics do |redis| @redis.with_metrics do |redis|
redis.pipelined do |pipeline| redis.pipelined do |pipeline|
pipeline.hdel("vmpooler__active__#{pool}", vm) pipeline.hdel("vmpooler__active__#{pool}", vm)
pipeline.hset("vmpooler__vm__#{vm}", 'destroy', Time.now) pipeline.hset("vmpooler__vm__#{vm}", 'destroy', Time.now.to_s)
# Auto-expire metadata key # Auto-expire metadata key
pipeline.expire("vmpooler__vm__#{vm}", ($config[:redis]['data_ttl'].to_i * 60 * 60)) pipeline.expire("vmpooler__vm__#{vm}", ($config[:redis]['data_ttl'].to_i * 60 * 60))
@ -868,12 +866,13 @@ module Vmpooler
def sleep_with_wakeup_events(loop_delay, wakeup_period = 5, options = {}) def sleep_with_wakeup_events(loop_delay, wakeup_period = 5, options = {})
exit_by = Time.now + loop_delay exit_by = Time.now + loop_delay
wakeup_by = Time.now + wakeup_period wakeup_by = Time.now + wakeup_period
return if time_passed?(:exit_by, exit_by) return if time_passed?(:exit_by, exit_by)
@redis.with_metrics do |redis| @redis.with_metrics do |redis|
initial_ready_size = redis.scard("vmpooler__ready__#{options[:poolname]}") if options[:pool_size_change] initial_ready_size = redis.scard("vmpooler__ready__#{options[:poolname]}") if options[:pool_size_change]
initial_clone_target = redis.hget("vmpooler__pool__#{options[:poolname]}", options[:clone_target]) if options[:clone_target_change] initial_clone_target = redis.hget("vmpooler__pool__#{options[:poolname]}", options[:clone_target].to_s) if options[:clone_target_change]
initial_template = redis.hget('vmpooler__template__prepared', options[:poolname]) if options[:pool_template_change] initial_template = redis.hget('vmpooler__template__prepared', options[:poolname]) if options[:pool_template_change]
@ -917,11 +916,10 @@ module Vmpooler
end end
if options[:ondemand_request] if options[:ondemand_request]
redis.multi od_request = redis.zcard('vmpooler__provisioning__request')
redis.zcard('vmpooler__provisioning__request') od_processing = redis.zcard('vmpooler__provisioning__processing')
redis.zcard('vmpooler__provisioning__processing') od_createtask = redis.zcard('vmpooler__odcreate__task')
redis.zcard('vmpooler__odcreate__task')
od_request, od_processing, od_createtask = redis.exec
break unless od_request == 0 break unless od_request == 0
break unless od_processing == 0 break unless od_processing == 0
break unless od_createtask == 0 break unless od_createtask == 0
@ -1093,10 +1091,8 @@ module Vmpooler
def remove_excess_vms(pool) def remove_excess_vms(pool)
@redis.with_metrics do |redis| @redis.with_metrics do |redis|
redis.multi ready = redis.scard("vmpooler__ready__#{pool['name']}")
redis.scard("vmpooler__ready__#{pool['name']}") pending = redis.scard("vmpooler__pending__#{pool['name']}")
redis.scard("vmpooler__pending__#{pool['name']}")
ready, pending = redis.exec
total = pending.to_i + ready.to_i total = pending.to_i + ready.to_i
break if total.nil? break if total.nil?
break if total == 0 break if total == 0
@ -1334,11 +1330,10 @@ module Vmpooler
return if pool_mutex(pool_name).locked? return if pool_mutex(pool_name).locked?
@redis.with_metrics do |redis| @redis.with_metrics do |redis|
redis.multi ready = redis.scard("vmpooler__ready__#{pool_name}")
redis.scard("vmpooler__ready__#{pool_name}") pending = redis.scard("vmpooler__pending__#{pool_name}")
redis.scard("vmpooler__pending__#{pool_name}") running = redis.scard("vmpooler__running__#{pool_name}")
redis.scard("vmpooler__running__#{pool_name}")
ready, pending, running = redis.exec
total = pending.to_i + ready.to_i total = pending.to_i + ready.to_i
$metrics.gauge("ready.#{pool_name}", ready) $metrics.gauge("ready.#{pool_name}", ready)
@ -1596,11 +1591,9 @@ module Vmpooler
return unless vms_ready?(request_id, redis) return unless vms_ready?(request_id, redis)
redis.multi
redis.hset(ondemand_hash_key, 'status', 'ready') redis.hset(ondemand_hash_key, 'status', 'ready')
redis.expire(ondemand_hash_key, default_expiration) redis.expire(ondemand_hash_key, default_expiration)
redis.zrem(processing_key, request_id) redis.zrem(processing_key, request_id)
redis.exec
end end
def request_expired?(request_id, score, redis) def request_expired?(request_id, score, redis)

View file

@ -3594,8 +3594,9 @@ EOT
it 'should sleep until the provisioning request is detected' do it 'should sleep until the provisioning request is detected' do
redis_connection_pool.with do |redis| redis_connection_pool.with do |redis|
expect(subject).to receive(:sleep).exactly(3).times expect(subject).to receive(:sleep).exactly(3).times
expect(redis).to receive(:multi).and_return('OK').exactly(3).times expect(redis).to receive(:zcard).with('vmpooler__provisioning__request').and_return(0,0,1)
expect(redis).to receive(:exec).and_return([0,0,0],[0,0,0],[1,0,0]) expect(redis).to receive(:zcard).with('vmpooler__provisioning__processing').and_return(0,0,0)
expect(redis).to receive(:zcard).with('vmpooler__odcreate__task').and_return(0,0,0)
end end
subject.sleep_with_wakeup_events(loop_delay, wakeup_period, wakeup_option) subject.sleep_with_wakeup_events(loop_delay, wakeup_period, wakeup_option)
@ -3604,17 +3605,20 @@ EOT
it 'should sleep until provisioning processing is detected' do it 'should sleep until provisioning processing is detected' do
redis_connection_pool.with do |redis| redis_connection_pool.with do |redis|
expect(subject).to receive(:sleep).exactly(3).times expect(subject).to receive(:sleep).exactly(3).times
expect(redis).to receive(:multi).and_return('OK').exactly(3).times expect(redis).to receive(:zcard).with('vmpooler__provisioning__request').and_return(0,0,0)
expect(redis).to receive(:exec).and_return([0,0,0],[0,0,0],[0,1,0]) expect(redis).to receive(:zcard).with('vmpooler__provisioning__processing').and_return(0,0,1)
expect(redis).to receive(:zcard).with('vmpooler__odcreate__task').and_return(0,0,0)
end end
subject.sleep_with_wakeup_events(loop_delay, wakeup_period, wakeup_option) subject.sleep_with_wakeup_events(loop_delay, wakeup_period, wakeup_option)
end end
it 'should sleep until ondemand creation task is detected' do it 'should sleep until ondemand creation task is detected' do
redis_connection_pool.with do |redis| redis_connection_pool.with do |redis|
expect(subject).to receive(:sleep).exactly(3).times expect(subject).to receive(:sleep).exactly(3).times
expect(redis).to receive(:multi).and_return('OK').exactly(3).times expect(redis).to receive(:zcard).with('vmpooler__provisioning__request').and_return(0,0,0)
expect(redis).to receive(:exec).and_return([0,0,0],[0,0,0],[0,0,1]) expect(redis).to receive(:zcard).with('vmpooler__provisioning__processing').and_return(0,0,0)
expect(redis).to receive(:zcard).with('vmpooler__odcreate__task').and_return(0,0,1)
end end
subject.sleep_with_wakeup_events(loop_delay, wakeup_period, wakeup_option) subject.sleep_with_wakeup_events(loop_delay, wakeup_period, wakeup_option)

View file

@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.executables = 'vmpooler' s.executables = 'vmpooler'
s.require_paths = ["lib"] s.require_paths = ["lib"]
s.add_dependency 'concurrent-ruby', '~> 1.1' s.add_dependency 'concurrent-ruby', '~> 1.1'
s.add_dependency 'connection_pool', '~> 2.2' s.add_dependency 'connection_pool', '~> 2.4'
s.add_dependency 'deep_merge', '~> 1.2' s.add_dependency 'deep_merge', '~> 1.2'
s.add_dependency 'net-ldap', '~> 0.16' s.add_dependency 'net-ldap', '~> 0.16'
s.add_dependency 'opentelemetry-exporter-jaeger', '= 0.23.0' s.add_dependency 'opentelemetry-exporter-jaeger', '= 0.23.0'
@ -32,7 +32,7 @@ Gem::Specification.new do |s|
s.add_dependency 'puma', '>= 5.0.4', '< 7' s.add_dependency 'puma', '>= 5.0.4', '< 7'
s.add_dependency 'rack', '>= 2.2', '< 4.0' s.add_dependency 'rack', '>= 2.2', '< 4.0'
s.add_dependency 'rake', '~> 13.0' s.add_dependency 'rake', '~> 13.0'
s.add_dependency 'redis', '~> 4.1' s.add_dependency 'redis', '~> 5.0'
s.add_dependency 'sinatra', '>= 2', '< 4' s.add_dependency 'sinatra', '>= 2', '< 4'
s.add_dependency 'spicy-proton', '~> 2.1' s.add_dependency 'spicy-proton', '~> 2.1'
s.add_dependency 'statsd-ruby', '~> 1.4' s.add_dependency 'statsd-ruby', '~> 1.4'