Stub out dns provider usage

This commit is contained in:
Jake Spain 2023-02-03 17:02:47 -05:00
parent 16d23a0226
commit ac96550f57
No known key found for this signature in database
GPG key ID: BC1C4DA0A085E113
5 changed files with 300 additions and 6 deletions

67
lib/vmpooler/dns.rb Normal file
View file

@ -0,0 +1,67 @@
require 'pathname'
module Vmpooler
class Dns
# Load one or more VMPooler DNS plugin gems by name
#
# @param names [Array<String>] The list of gem names to load
def self.load_by_name(names)
names = Array(names)
instance = new
names.map { |name| instance.load_from_gems(name) }.flatten
end
# Returns the plugin class for the specified dns config by name
#
# @param config [Object] The entire VMPooler config object
# @param name [Symbol] The name of the dns config key to get the dns class
# @return [String] The plugin class for the specifid dns config
def self.get_dns_plugin_class_by_name(config, name)
dns_configs = config[:dns_configs].keys
plugin_class = ''
dns_configs.map do |dns_config_name|
if dns_config_name.to_s == name
plugin_class = config[:dns_configs][dns_config_name]['dns_class']
end
end
plugin_class
end
# Returns a list of DNS plugin classes specified in the vmpooler configuration
#
# @param config [Object] The entire VMPooler config object
# @return [Array<String] A list of DNS plugin classes
def self.get_dns_plugin_config_classes(config)
if config[:dns_configs]
dns_configs = config[:dns_configs].keys
dns_plugins = dns_configs.map do |dns_config_name|
if config[:dns_configs][dns_config_name] && config[:dns_configs][dns_config_name]['dns_class']
config[:dns_configs][dns_config_name]['dns_class'].to_s
else
dns_config_name.to_s
end
end.compact.uniq
# dynamic-dns is not actually a class, it's just used as a value to denote
# that dynamic dns is used so no loading or record management is needed
dns_plugins.delete('dynamic-dns')
end
dns_plugins
end
# Load a single DNS plugin gem by name
#
# @param name [String] The name of the DNS plugin gem to load
# @return [String] The full require path to the specified gem
def load_from_gems(name = nil)
require_path = 'vmpooler/dns/' + name.gsub('-', '/')
require require_path
$logger.log('d', "[*] [dns_manager] Loading DNS plugins from dns_configs: #{name}")
require_path
end
end
end

69
lib/vmpooler/dns/base.rb Normal file
View file

@ -0,0 +1,69 @@
module Vmpooler
class PoolManager
class Dns
class Base
# These defs must be overidden in child classes
# Helper Methods
# Global Logger object
attr_reader :logger
# Global Metrics object
attr_reader :metrics
# Provider options passed in during initialization
attr_reader :dns_options
def initialize(config, logger, metrics, redis_connection_pool, name, options)
@config = config
@logger = logger
@metrics = metrics
@redis = redis_connection_pool
@dns_plugin_name = name
@dns_options = options
logger.log('s', "[!] Creating dns plugin '#{name}'")
# Your code goes here...
end
def pool_config(pool_name)
# Get the configuration of a specific pool
@config[:pools].each do |pool|
return pool if pool['name'] == pool_name
end
nil
end
def global_config
# This entire VM Pooler config
@config
end
def name
@dns_plugin_name
end
def get_ip(vm_name)
@redis.with_metrics do |redis|
ip = redis.hget("vmpooler__vm__#{vm_name}", 'ip')
return ip
end
end
# returns
# Array[String] : Array of pool names this provider services
def provided_pools
list = []
@config[:pools].each do |pool|
list << pool['name'] if pool['dns_config'] == name
end
list
end
def create_or_replace_record(hostname)
raise("#{self.class.name} does not implement create_or_replace_record")
end
end
end
end
end

View file

@ -1,5 +1,6 @@
# frozen_string_literal: true
require 'vmpooler/dns'
require 'vmpooler/providers'
require 'vmpooler/util/parsing'
require 'spicy-proton'
@ -26,6 +27,9 @@ module Vmpooler
# VM Provider objects
$providers = Concurrent::Hash.new
# VM DNS objects
$dns_plugins = Concurrent::Hash.new
# Our thread-tracker object
$threads = Concurrent::Hash.new
@ -39,6 +43,9 @@ module Vmpooler
# load specified providers from config file
load_used_providers
# load specified dns plugins from config file
load_used_dns_plugins
end
def config
@ -323,10 +330,10 @@ module Vmpooler
end
# Clone a VM
def clone_vm(pool_name, provider, request_id = nil, pool_alias = nil)
def clone_vm(pool_name, provider, dns_plugin, request_id = nil, pool_alias = nil)
Thread.new do
begin
_clone_vm(pool_name, provider, request_id, pool_alias)
_clone_vm(pool_name, provider, dns_plugin, request_id, pool_alias)
rescue StandardError => e
if request_id
$logger.log('s', "[!] [#{pool_name}] failed while cloning VM for request #{request_id} with an error: #{e}")
@ -414,7 +421,7 @@ module Vmpooler
[dns_ip, false]
end
def _clone_vm(pool_name, provider, request_id = nil, pool_alias = nil)
def _clone_vm(pool_name, provider, dns_plugin, request_id = nil, pool_alias = nil)
new_vmname = find_unique_hostname(pool_name)
pool_domain = Parsing.get_domain_for_pool(config, pool_name)
mutex = vm_mutex(new_vmname)
@ -447,6 +454,8 @@ module Vmpooler
$logger.log('s', "[+] [#{pool_name}] '#{new_vmname}' cloned in #{finish} seconds")
$metrics.timing("clone.#{pool_name}", finish)
dns_plugin.create_or_replace_record(new_vmname)
rescue StandardError
@redis.with_metrics do |redis|
redis.pipelined do |pipeline|
@ -632,6 +641,12 @@ module Vmpooler
result
end
# load only dns plugins used in config file
def load_used_dns_plugins
dns_plugins = Vmpooler::Dns.get_dns_plugin_config_classes(config)
Vmpooler::Dns.load_by_name(dns_plugins)
end
# load only providers used in config file
def load_used_providers
Vmpooler::Providers.load_by_name(used_providers)
@ -679,6 +694,15 @@ module Vmpooler
$providers[provider_name]
end
def get_dns_plugin_class_for_pool(pool_name)
pool = $config[:pools].find { |p| p['name'] == pool_name }
return nil unless pool
plugin_name = pool.fetch('dns_plugin')
plugin_class = Vmpooler::Dns.get_dns_plugin_class_by_name(config, plugin_name)
$dns_plugins[plugin_class]
end
def check_disk_queue(maxloop = 0, loop_delay = 5)
$logger.log('d', '[*] [disk_manager] starting worker thread')
@ -1290,6 +1314,8 @@ module Vmpooler
$metrics.gauge("ready.#{pool_name}", ready)
$metrics.gauge("running.#{pool_name}", running)
dns_plugin = get_dns_plugin_class_for_pool(pool_name)
unless pool_size == 0
if redis.get("vmpooler__empty__#{pool_name}")
redis.del("vmpooler__empty__#{pool_name}") unless ready == 0
@ -1304,7 +1330,7 @@ module Vmpooler
begin
redis.incr('vmpooler__tasks__clone')
pool_check_response[:cloned_vms] += 1
clone_vm(pool_name, provider)
clone_vm(pool_name, provider, dns_plugin)
rescue StandardError => e
$logger.log('s', "[!] [#{pool_name}] clone failed during check_pool with an error: #{e}")
redis.decr('vmpooler__tasks__clone')
@ -1390,6 +1416,16 @@ module Vmpooler
raise("Provider '#{provider_class}' is unknown for pool with provider name '#{provider_name}'") if provider_klass.nil?
end
def create_dns_object(config, logger, metrics, redis_connection_pool, dns_class, dns_name, options)
dns_klass = Vmpooler::PoolManager::Dns
dns_klass.constants.each do |classname|
next unless classname.to_s.casecmp(dns_class) == 0
return dns_klass.const_get(classname).new(config, logger, metrics, redis_connection_pool, dns_name, options)
end
raise("DNS '#{dns_class}' is unknown for pool with dns name '#{dns_name}'") if dns_klass.nil?
end
def check_ondemand_requests(maxloop = 0,
loop_delay_min = CHECK_LOOP_DELAY_MIN_DEFAULT,
loop_delay_max = CHECK_LOOP_DELAY_MAX_DEFAULT,
@ -1473,20 +1509,21 @@ module Vmpooler
pool_alias, pool, count, request_id = request.split(':')
count = count.to_i
provider = get_provider_for_pool(pool)
dns_plugin = get_dns_plugin_class_for_pool(pool)
slots = ondemand_clone_limit - clone_count
break if slots == 0
if slots >= count
count.times do
redis.incr('vmpooler__tasks__ondemandclone')
clone_vm(pool, provider, request_id, pool_alias)
clone_vm(pool, provider, dns_plugin, request_id, pool_alias)
end
redis.zrem(queue_key, request)
else
remaining_count = count - slots
slots.times do
redis.incr('vmpooler__tasks__ondemandclone')
clone_vm(pool, provider, request_id, pool_alias)
clone_vm(pool, provider, dns_plugin, request_id, pool_alias)
end
redis.pipelined do |pipeline|
pipeline.zrem(queue_key, request)
@ -1601,6 +1638,7 @@ module Vmpooler
# Create the providers
$config[:pools].each do |pool|
provider_name = pool['provider']
dns_plugin_name = pool['dns_plugin']
# The provider_class parameter can be defined in the provider's data eg
# :providers:
# :vsphere:
@ -1621,12 +1659,22 @@ module Vmpooler
else
provider_class = $config[:providers][provider_name.to_sym]['provider_class']
end
begin
$providers[provider_name] = create_provider_object($config, $logger, $metrics, @redis, provider_class, provider_name, {}) if $providers[provider_name].nil?
rescue StandardError => e
$logger.log('s', "Error while creating provider for pool #{pool['name']}: #{e}")
raise
end
dns_plugin_class = $config[:dns_configs][dns_plugin_name.to_sym]['dns_class']
begin
$dns_plugins[dns_plugin_class] = create_dns_object($config, $logger, $metrics, @redis, dns_plugin_class, dns_plugin_name, {}) if $dns_plugins[dns_plugin_class].nil?
rescue StandardError => e
$logger.log('s', "Error while creating dns plugin for pool #{pool['name']}: #{e}")
raise
end
end
purge_unused_vms_and_resources

View file

@ -34,6 +34,10 @@ module Vmpooler
# Helper Methods
def get_dns_plugin_for_pool(pool_name)
end
# inputs
# [String] pool_name : Name of the pool to get the configuration
# returns