mirror of
https://github.com/puppetlabs/vmpooler.git
synced 2026-01-26 01:58:41 -05:00
Adds a new mechanism to load providers from any gem or file path. (#263)
* Adds ability to load only providers used in config file
This commit is contained in:
parent
0a769b8901
commit
2daa5244b8
13 changed files with 316 additions and 15 deletions
|
|
@ -11,7 +11,7 @@ module Vmpooler
|
|||
require 'yaml'
|
||||
require 'set'
|
||||
|
||||
%w[api graphite logger pool_manager statsd dummy_statsd generic_connection_pool providers].each do |lib|
|
||||
%w[api graphite logger pool_manager statsd dummy_statsd generic_connection_pool].each do |lib|
|
||||
require "vmpooler/#{lib}"
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
require 'vmpooler/providers'
|
||||
|
||||
module Vmpooler
|
||||
class PoolManager
|
||||
CHECK_LOOP_DELAY_MIN_DEFAULT = 5
|
||||
|
|
@ -26,6 +28,9 @@ module Vmpooler
|
|||
@reconfigure_pool = {}
|
||||
|
||||
@vm_mutex = {}
|
||||
|
||||
# load specified providers from config file
|
||||
load_used_providers
|
||||
end
|
||||
|
||||
def config
|
||||
|
|
@ -457,19 +462,36 @@ module Vmpooler
|
|||
result
|
||||
end
|
||||
|
||||
# load only providers used in config file
|
||||
def load_used_providers
|
||||
Vmpooler::Providers.load_by_name(used_providers)
|
||||
end
|
||||
|
||||
# @return [Array] - a list of used providers from the config file, defaults to the default providers
|
||||
# ie. ["vsphere", "dummy"]
|
||||
def used_providers
|
||||
pools = config[:pools] || []
|
||||
@used_providers ||= (pools.map { |pool| pool[:provider] || pool['provider'] }.compact + default_providers ).uniq
|
||||
end
|
||||
|
||||
# @return [Array] - returns a list of providers that should always be loaded
|
||||
# note: vsphere is the default if user does not specify although this should not be
|
||||
# if vsphere is to no longer be loaded by default please remove
|
||||
def default_providers
|
||||
@default_providers ||= %w( vsphere dummy )
|
||||
end
|
||||
|
||||
def get_pool_name_for_vm(vm_name)
|
||||
# the 'template' is a bad name. Should really be 'poolname'
|
||||
$redis.hget('vmpooler__vm__' + vm_name, 'template')
|
||||
end
|
||||
|
||||
# @param pool_name [String] - the name of the pool
|
||||
# @return [Provider] - returns the provider class Object
|
||||
def get_provider_for_pool(pool_name)
|
||||
provider_name = nil
|
||||
$config[:pools].each do |pool|
|
||||
next unless pool['name'] == pool_name
|
||||
provider_name = pool['provider']
|
||||
end
|
||||
return nil if provider_name.nil?
|
||||
|
||||
pool = $config[:pools].find { |pool| pool['name'] == pool_name }
|
||||
return nil unless pool
|
||||
provider_name = pool.fetch('provider', nil)
|
||||
$providers[provider_name]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,119 @@
|
|||
%w[base dummy vsphere].each do |lib|
|
||||
begin
|
||||
require "vmpooler/providers/#{lib}"
|
||||
rescue LoadError
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), 'providers', lib))
|
||||
require 'pathname'
|
||||
|
||||
module Vmpooler
|
||||
class Providers
|
||||
|
||||
# @param names [Array] - an array of names or string name of a provider
|
||||
# @return [Array] - list of provider files loaded
|
||||
# ie. ["lib/vmpooler/providers/base.rb", "lib/vmpooler/providers/dummy.rb", "lib/vmpooler/providers/vsphere.rb"]
|
||||
def self.load_by_name(names)
|
||||
names = Array(names)
|
||||
instance = self.new
|
||||
names.map {|name| instance.load_from_gems(name)}.flatten
|
||||
end
|
||||
|
||||
# @return [Array] - array of provider files
|
||||
# ie. ["lib/vmpooler/providers/base.rb", "lib/vmpooler/providers/dummy.rb", "lib/vmpooler/providers/vsphere.rb"]
|
||||
# although these files can come from any gem
|
||||
def self.load_all_providers
|
||||
self.new.load_from_gems
|
||||
end
|
||||
|
||||
# @return [Array] - returns an array of gem names that contain a provider
|
||||
def self.installed_providers
|
||||
self.new.vmpooler_provider_gem_list.map(&:name)
|
||||
end
|
||||
|
||||
# @return [Array] returns a list of vmpooler providers gem plugin specs
|
||||
def vmpooler_provider_gem_list
|
||||
gemspecs.find_all { |spec| File.directory?(File.join(spec.full_gem_path, provider_path)) } + included_lib_dirs
|
||||
end
|
||||
|
||||
# Internal: Find any gems containing vmpooler provider plugins and load the main file in them.
|
||||
#
|
||||
# @return [Array[String]] - a array of provider files
|
||||
# @param name [String] - the name of the provider to load
|
||||
def load_from_gems(name = nil)
|
||||
paths = gem_directories.map do |gem_path|
|
||||
# we don't exactly know if the provider name matches the main file name that should be loaded
|
||||
# so we use globs to get everything like the name
|
||||
# this could mean that vsphere5 and vsphere6 are loaded when only vsphere5 is used
|
||||
Dir.glob(File.join(gem_path, "*#{name}*.rb")).each do |file|
|
||||
require file
|
||||
end
|
||||
end
|
||||
paths.flatten
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @return [String] - the relative path to the vmpooler provider dir
|
||||
# this is used when searching gems for this path
|
||||
def provider_path
|
||||
File.join('lib','vmpooler','providers')
|
||||
end
|
||||
|
||||
# Add constants to array to skip over classes, ie. Vmpooler::PoolManager::Provider::Dummy
|
||||
def excluded_classes
|
||||
[]
|
||||
end
|
||||
|
||||
# paths to include in the search path
|
||||
def included_lib_dirs
|
||||
[]
|
||||
end
|
||||
|
||||
# returns an array of plugin classes by looking in the object space for all loaded classes
|
||||
# that start with Vmpooler::PoolManager::Provider
|
||||
def plugin_classes
|
||||
unless @plugin_classes
|
||||
load_plugins
|
||||
# weed out any subclasses in the formatter
|
||||
klasses = ObjectSpace.each_object(Class).find_all do |c|
|
||||
c.name && c.name.split('::').count == 3 && c.name =~ /Vmpooler::PoolManager::Provider/
|
||||
end
|
||||
@plugin_classes = klasses - excluded_classes || []
|
||||
end
|
||||
@plugin_classes
|
||||
end
|
||||
|
||||
def plugin_map
|
||||
@plugin_map ||= Hash[plugin_classes.map { |gem| [gem.send(:name), gem] }]
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Internal: Retrieve a list of available gem paths from RubyGems.
|
||||
#
|
||||
# Returns an Array of Pathname objects.
|
||||
def gem_directories
|
||||
dirs = []
|
||||
if has_rubygems?
|
||||
dirs = gemspecs.map do |spec|
|
||||
lib_path = File.expand_path(File.join(spec.full_gem_path,provider_path))
|
||||
lib_path if File.exists? lib_path
|
||||
end + included_lib_dirs
|
||||
end
|
||||
dirs.reject { |dir| dir.nil? }.uniq
|
||||
end
|
||||
|
||||
# Internal: Check if RubyGems is loaded and available.
|
||||
#
|
||||
# Returns true if RubyGems is available, false if not.
|
||||
def has_rubygems?
|
||||
defined? ::Gem
|
||||
end
|
||||
|
||||
# Internal: Retrieve a list of available gemspecs.
|
||||
#
|
||||
# Returns an Array of Gem::Specification objects.
|
||||
def gemspecs
|
||||
@gemspecs ||= if Gem::Specification.respond_to?(:latest_specs)
|
||||
Gem::Specification.latest_specs
|
||||
else
|
||||
Gem.searcher.init_gemspecs
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
require 'yaml'
|
||||
require 'vmpooler/providers/base'
|
||||
|
||||
module Vmpooler
|
||||
class PoolManager
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
require 'vmpooler/providers/base'
|
||||
|
||||
module Vmpooler
|
||||
class PoolManager
|
||||
class Provider
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue