Merge pull request #221 from puppetlabs/sam-suppert-multiple-providers

Adding support for multiple vsphere providers
This commit is contained in:
Rob Braden 2017-06-20 15:08:32 -07:00 committed by GitHub
commit b54b248d75
5 changed files with 101 additions and 6 deletions

View file

@ -58,7 +58,7 @@ The following YAML configuration sets up two pools, `debian-7-i386` and `debian-
provider: vsphere provider: vsphere
``` ```
See the provided YAML configuration example, [vmpooler.yaml.example](vmpooler.yaml.example), for additional configuration options and parameters. See the provided YAML configuration example, [vmpooler.yaml.example](vmpooler.yaml.example), for additional configuration options and parameters or for supporting multiple providers.
### Running via Docker ### Running via Docker

View file

@ -694,14 +694,20 @@ module Vmpooler
raise raise
end end
def create_provider_object(config, logger, metrics, provider_name, options) # create a provider object based on the providers/*.rb class that implements providers/base.rb
case provider_name # provider_class: needs to match a provider class in providers/*.rb ie Vmpooler::PoolManager::Provider::X
# provider_name: should be a unique provider name
#
# returns an object Vmpooler::PoolManager::Provider::*
# or raises an error if the class does not exist
def create_provider_object(config, logger, metrics, provider_class, provider_name, options)
case provider_class
when 'vsphere' when 'vsphere'
Vmpooler::PoolManager::Provider::VSphere.new(config, logger, metrics, provider_name, options) Vmpooler::PoolManager::Provider::VSphere.new(config, logger, metrics, provider_name, options)
when 'dummy' when 'dummy'
Vmpooler::PoolManager::Provider::Dummy.new(config, logger, metrics, provider_name, options) Vmpooler::PoolManager::Provider::Dummy.new(config, logger, metrics, provider_name, options)
else else
raise("Provider '#{provider_name}' is unknown") raise("Provider '#{provider_class}' is unknown for pool with provider '#{provider_name}'")
end end
end end
@ -731,8 +737,28 @@ module Vmpooler
# Create the providers # Create the providers
$config[:pools].each do |pool| $config[:pools].each do |pool|
provider_name = pool['provider'] provider_name = pool['provider']
# The provider_class parameter can be defined in the provider's data eg
#:providers:
# :vsphere:
# provider_class: 'vsphere'
# :another-vsphere:
# provider_class: 'vsphere'
# the above would create two providers/vsphere.rb class objects named 'vsphere' and 'another-vsphere'
# each pools would then define which provider definition to use: vsphere or another-vsphere
#
# if provider_class is not defined it will try to use the provider_name as the class, this is to be
# backwards compatible for example when there is only one provider listed
# :providers:
# :dummy:
# filename: 'db.txs'
# the above example would create an object based on the class providers/dummy.rb
if $config[:providers].nil? || $config[:providers][provider_name.to_sym].nil? || $config[:providers][provider_name.to_sym]['provider_class'].nil?
provider_class = provider_name
else
provider_class = $config[:providers][provider_name.to_sym]['provider_class']
end
begin begin
$providers[provider_name] = create_provider_object($config, $logger, $metrics, provider_name, {}) if $providers[provider_name].nil? $providers[provider_name] = create_provider_object($config, $logger, $metrics, provider_class, provider_name, {}) if $providers[provider_name].nil?
rescue => err rescue => err
$logger.log('s', "Error while creating provider for pool #{pool['name']}: #{err}") $logger.log('s', "Error while creating provider for pool #{pool['name']}: #{err}")
raise raise

View file

@ -35,6 +35,7 @@ module Vmpooler
end end
end end
# name of the provider class
def name def name
'vsphere' 'vsphere'
end end

View file

@ -1754,7 +1754,7 @@ EOT
it 'should call create_provider_object idempotently' do it 'should call create_provider_object idempotently' do
# Even though there are two pools using the vsphere provider (the default), it should only # Even though there are two pools using the vsphere provider (the default), it should only
# create the provider object once. # create the provider object once.
expect(subject).to receive(:create_provider_object).with(Object, Object, Object, 'vsphere', Object).and_return(vsphere_provider) expect(subject).to receive(:create_provider_object).with(Object, Object, Object, 'vsphere', 'vsphere', Object).and_return(vsphere_provider)
subject.execute!(1,0) subject.execute!(1,0)
end end
@ -1774,6 +1774,50 @@ EOT
end end
end end
context 'creating multiple vsphere Providers' do
let(:vsphere_provider) { double('vsphere_provider') }
let(:vsphere_provider2) { double('vsphere_provider') }
let(:provider1) { Vmpooler::PoolManager::Provider::Base.new(config, logger, metrics, 'vsphere', provider_options) }
let(:provider2) { Vmpooler::PoolManager::Provider::Base.new(config, logger, metrics, 'secondvsphere', provider_options) }
let(:config) {
YAML.load(<<-EOT
---
:providers:
:vsphere:
server: 'blah1'
provider_class: 'vsphere'
:secondvsphere:
server: 'blah2'
provider_class: 'vsphere'
:pools:
- name: #{pool}
provider: 'vsphere'
- name: 'secondpool'
provider: 'secondvsphere'
EOT
)}
it 'should call create_provider_object twice' do
# The two pools use a different provider name, but each provider_class is vsphere
expect(subject).to receive(:create_provider_object).with(Object, Object, Object, "vsphere", "vsphere", Object).and_return(vsphere_provider)
expect(subject).to receive(:create_provider_object).with(Object, Object, Object, "vsphere", "secondvsphere", Object).and_return(vsphere_provider2)
subject.execute!(1,0)
end
it 'should have vsphere providers with different servers' do
allow(subject).to receive(:get_provider_for_pool).with(pool).and_return(provider1)
result = subject.get_provider_for_pool(pool)
allow(provider1).to receive(:provider_config).and_call_original
expect(result.provider_config['server']).to eq('blah1')
allow(subject).to receive(:get_provider_for_pool).with('secondpool').and_return(provider2)
result = subject.get_provider_for_pool('secondpool')
allow(provider1).to receive(:provider_config).and_call_original
expect(result.provider_config['server']).to eq('blah2')
subject.execute!(1,0)
end
end
context 'modify configuration on startup' do context 'modify configuration on startup' do
context 'move vSphere configuration to providers location' do context 'move vSphere configuration to providers location' do
let(:config) { let(:config) {

View file

@ -32,6 +32,11 @@
# - insecure # - insecure
# Whether to ignore any HTTPS negotiation errors (e.g. untrusted self-signed certificates) # Whether to ignore any HTTPS negotiation errors (e.g. untrusted self-signed certificates)
# (optional: default true) # (optional: default true)
#
# - provider_class
# For multiple providers, specify one of the supported backing services (vsphere or dummy)
# (optional: will default to it's parent :key: name eg. 'vsphere')
#
# Example: # Example:
:vsphere: :vsphere:
@ -39,6 +44,23 @@
username: 'vmpooler' username: 'vmpooler'
password: 'swimsw1msw!m' password: 'swimsw1msw!m'
# If you want to support more than one provider with different parameters (server, username or passwords) you have to specify the
# backing service in the provider_class configuration parameter for example 'vsphere' or 'dummy'. Each pool can specify
# the provider to use.
#
# Multiple providers example:
:vsphere-pdx:
server: 'vsphere.pdx.company.com'
username: 'vmpooler-pdx'
password: 'swimsw1msw!m'
provider_class: 'vsphere'
:vsphere-bfs:
server: 'vsphere.bfs.company.com'
username: 'vmpooler-bfs'
password: 'swimsw1msw!m'
provider_class: 'vsphere'
# :dummy: # :dummy:
# #
# The dummy backing service is a simple text file service that can be used # The dummy backing service is a simple text file service that can be used
@ -417,6 +439,8 @@
# The name of the VM provider which manage this pool. This should match # The name of the VM provider which manage this pool. This should match
# a name in the :providers: section above e.g. vsphere # a name in the :providers: section above e.g. vsphere
# (required; will default to vsphere for backwards compatibility) # (required; will default to vsphere for backwards compatibility)
# If you have more than one provider, this is where you would choose which
# one to use for this pool
# #
# - clone_target # - clone_target
# Per-pool option to override the global 'clone_target' cluster. # Per-pool option to override the global 'clone_target' cluster.