From 52bf6c4c8990db79ea0e9852d32c5f9d4ffdbe69 Mon Sep 17 00:00:00 2001 From: "kirby@puppetlabs.com" Date: Wed, 22 Apr 2020 21:25:01 -0700 Subject: [PATCH] First attempt at adding connection pool to pool manager --- bin/vmpooler | 3 +- lib/vmpooler.rb | 4 +- lib/vmpooler/pool_manager.rb | 850 ++++++++++++++++-------------- lib/vmpooler/providers/base.rb | 3 +- lib/vmpooler/providers/vsphere.rb | 51 +- 5 files changed, 498 insertions(+), 413 deletions(-) diff --git a/bin/vmpooler b/bin/vmpooler index 2f0f98f..b3ce6d7 100755 --- a/bin/vmpooler +++ b/bin/vmpooler @@ -24,7 +24,7 @@ end if torun.include? 'api' api = Thread.new do thr = Vmpooler::API.new - redis = Vmpooler.new_redis(redis_host, redis_port, redis_password) + redis = Vmpooler.redis_connection(redis_host, redis_port, redis_password) thr.helpers.configure(config, redis, metrics) thr.helpers.execute! end @@ -36,7 +36,6 @@ if torun.include? 'manager' Vmpooler::PoolManager.new( config, Vmpooler.new_logger(logger_file), - Vmpooler.new_redis(redis_host, redis_port, redis_password), metrics ).execute! end diff --git a/lib/vmpooler.rb b/lib/vmpooler.rb index 0926d4d..0bcbf91 100644 --- a/lib/vmpooler.rb +++ b/lib/vmpooler.rb @@ -110,7 +110,7 @@ module Vmpooler # Create an index of pool aliases parsed_config[:pool_names] = Set.new unless parsed_config[:pools] - redis = new_redis(parsed_config[:redis]['server'], parsed_config[:redis]['port'], parsed_config[:redis]['password']) + redis = redis_connection(parsed_config[:redis]['server'], parsed_config[:redis]['port'], parsed_config[:redis]['password']) parsed_config[:pools] = load_pools_from_redis(redis) end @@ -156,7 +156,7 @@ module Vmpooler pools end - def self.new_redis(host = 'localhost', port = nil, password = nil) + def self.redis_connection(host = 'localhost', port = nil, password = nil) Redis.new(host: host, port: port, password: password) end diff --git a/lib/vmpooler/pool_manager.rb b/lib/vmpooler/pool_manager.rb index e3447bb..4e30368 100644 --- a/lib/vmpooler/pool_manager.rb +++ b/lib/vmpooler/pool_manager.rb @@ -9,7 +9,7 @@ module Vmpooler CHECK_LOOP_DELAY_MAX_DEFAULT = 60 CHECK_LOOP_DELAY_DECAY_DEFAULT = 2.0 - def initialize(config, logger, redis, metrics) + def initialize(config, logger, metrics) $config = config # Load logger library @@ -18,8 +18,14 @@ module Vmpooler # metrics logging handle $metrics = metrics - # Connect to Redis - $redis = redis + # Redis connection pool + @redis = ConnectionPool.new(size: 10) { + Vmpooler.redis_connection( + $config[:config][:redis]['server'], + $config[:config][:redis]['port'], + $config[:config][:redis]['password'] + ) + } # VM Provider objects $providers = {} @@ -47,24 +53,26 @@ module Vmpooler # Place pool configuration in redis so an API instance can discover running pool configuration def load_pools_to_redis - previously_configured_pools = $redis.smembers('vmpooler__pools') - currently_configured_pools = [] - config[:pools].each do |pool| - currently_configured_pools << pool['name'] - $redis.sadd('vmpooler__pools', pool['name']) - pool_keys = pool.keys - pool_keys.delete('alias') - to_set = {} - pool_keys.each do |k| - to_set[k] = pool[k] + @redis.with do |redis| + previously_configured_pools = redis.smembers('vmpooler__pools') + currently_configured_pools = [] + config[:pools].each do |pool| + currently_configured_pools << pool['name'] + redis.sadd('vmpooler__pools', pool['name']) + pool_keys = pool.keys + pool_keys.delete('alias') + to_set = {} + pool_keys.each do |k| + to_set[k] = pool[k] + end + to_set['alias'] = pool['alias'].join(',') if to_set.key?('alias') + redis.hmset("vmpooler__pool__#{pool['name']}", to_set.to_a.flatten) unless to_set.empty? end - to_set['alias'] = pool['alias'].join(',') if to_set.key?('alias') - $redis.hmset("vmpooler__pool__#{pool['name']}", to_set.to_a.flatten) unless to_set.empty? - end - previously_configured_pools.each do |pool| - unless currently_configured_pools.include? pool - $redis.srem('vmpooler__pools', pool) - $redis.del("vmpooler__pool__#{pool}") + previously_configured_pools.each do |pool| + unless currently_configured_pools.include? pool + redis.srem('vmpooler__pools', pool) + redis.del("vmpooler__pool__#{pool}") + end end end nil @@ -88,36 +96,36 @@ module Vmpooler return if mutex.locked? mutex.synchronize do - request_id = $redis.hget("vmpooler__vm__#{vm}", 'request_id') + request_id = redis.hget("vmpooler__vm__#{vm}", 'request_id') if provider.vm_ready?(pool, vm) - move_pending_vm_to_ready(vm, pool, request_id) + move_pending_vm_to_ready(vm, pool, request_id, redis) else - fail_pending_vm(vm, pool, timeout, request_id = request_id) + fail_pending_vm(vm, pool, timeout, redis, request_id = request_id) end end end - def remove_nonexistent_vm(vm, pool) - $redis.srem("vmpooler__pending__#{pool}", vm) + def remove_nonexistent_vm(vm, pool, redis) + redis.srem("vmpooler__pending__#{pool}", vm) $logger.log('d', "[!] [#{pool}] '#{vm}' no longer exists. Removing from pending.") end - def fail_pending_vm(vm, pool, timeout, exists = true, request_id = nil) - clone_stamp = $redis.hget("vmpooler__vm__#{vm}", 'clone') + def fail_pending_vm(vm, pool, timeout, redis, exists = true, request_id = nil) + clone_stamp = redis.hget("vmpooler__vm__#{vm}", 'clone') return true unless clone_stamp time_since_clone = (Time.now - Time.parse(clone_stamp)) / 60 if time_since_clone > timeout if exists - pool_alias = get_alias_for_request(pool, request_id) if $request_id - $redis.multi - $redis.smove('vmpooler__pending__' + pool, 'vmpooler__completed__' + pool, vm) - $redis.zadd('vmpooler__odcreate__task', 1, "#{pool_alias}:#{pool_name}:1:#{request_id}") if request_id - $redis.exec + pool_alias = get_alias_for_request(pool, request_id, redis) if $request_id + redis.multi + redis.smove('vmpooler__pending__' + pool, 'vmpooler__completed__' + pool, vm) + redis.zadd('vmpooler__odcreate__task', 1, "#{pool_alias}:#{pool_name}:1:#{request_id}") if request_id + redis.exec $metrics.increment("errors.markedasfailed.#{pool}") $logger.log('d', "[!] [#{pool}] '#{vm}' marked as 'failed' after #{timeout} minutes") else - remove_nonexistent_vm(vm, pool) + remove_nonexistent_vm(vm, pool, redis) end end true @@ -126,49 +134,49 @@ module Vmpooler false end - def move_pending_vm_to_ready(vm, pool, request_id) - clone_time = $redis.hget('vmpooler__vm__' + vm, 'clone') + def move_pending_vm_to_ready(vm, pool, request_id, redis) + clone_time = redis.hget('vmpooler__vm__' + vm, 'clone') finish = format('%