mirror of
https://github.com/puppetlabs/vmpooler.git
synced 2026-01-26 10:08:40 -05:00
(QENG-7530) Add check for unique hostnames
Prior to this commit the pooler had no awareness of the complete set of hostnames that are currently in use. This meant that it was possible to allocate the same hostname twice, which would result in the original host with that hostname becoming unreachable. This commit adds a check for the existence of the `vmpooler__vm__<hostname>` key before attempting to clone the vm. This should prevent duplicate hostnames. If the hostname is already taken, `_clone_vm` will retry with a new random hostname multiple times before raising an exception.
This commit is contained in:
parent
1df13e4974
commit
019ed021b0
2 changed files with 28 additions and 2 deletions
|
|
@ -267,10 +267,34 @@ module Vmpooler
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def _clone_vm(pool_name, provider)
|
def generate_and_check_hostname(pool_name)
|
||||||
# Generate a randomized hostname
|
# Generate a randomized hostname
|
||||||
random_name = [@name_generator.adjective(max: 7), @name_generator.noun(max: 7)].join('-')
|
random_name = [@name_generator.adjective(max: 7), @name_generator.noun(max: 7)].join('-')
|
||||||
new_vmname = $config[:config]['prefix'] + random_name
|
hostname = $config[:config]['prefix'] + random_name
|
||||||
|
available = $redis.hlen('vmpooler__vm__' + hostname) == 0
|
||||||
|
|
||||||
|
return hostname, available
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_unique_hostname(pool_name)
|
||||||
|
hostname_retries = 0
|
||||||
|
max_hostname_retries = 3
|
||||||
|
while hostname_retries < max_hostname_retries
|
||||||
|
hostname, available = generate_and_check_hostname(pool_name)
|
||||||
|
break if available
|
||||||
|
|
||||||
|
hostname_retries += 1
|
||||||
|
$metrics.increment("errors.duplicatehostname.#{pool_name}")
|
||||||
|
$logger.log('s', "[!] [#{pool_name}] Generated hostname #{hostname} was not unique (attempt \##{hostname_retries} of #{max_hostname_retries})")
|
||||||
|
end
|
||||||
|
|
||||||
|
raise "Unable to generate a unique hostname after #{hostname_retries} attempts. The last hostname checked was #{hostname}" unless available
|
||||||
|
|
||||||
|
hostname
|
||||||
|
end
|
||||||
|
|
||||||
|
def _clone_vm(pool_name, provider)
|
||||||
|
new_vmname = find_unique_hostname(pool_name)
|
||||||
|
|
||||||
# Add VM to Redis inventory ('pending' pool)
|
# Add VM to Redis inventory ('pending' pool)
|
||||||
$redis.sadd('vmpooler__pending__' + pool_name, new_vmname)
|
$redis.sadd('vmpooler__pending__' + pool_name, new_vmname)
|
||||||
|
|
|
||||||
|
|
@ -608,6 +608,7 @@ EOT
|
||||||
expect(metrics).to receive(:timing).with(/clone\./,/0/)
|
expect(metrics).to receive(:timing).with(/clone\./,/0/)
|
||||||
expect(provider).to receive(:create_vm).with(pool, String)
|
expect(provider).to receive(:create_vm).with(pool, String)
|
||||||
allow(logger).to receive(:log)
|
allow(logger).to receive(:log)
|
||||||
|
expect(subject).to receive(:find_unique_hostname).with(pool).and_return(vm)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should create a cloning VM' do
|
it 'should create a cloning VM' do
|
||||||
|
|
@ -649,6 +650,7 @@ EOT
|
||||||
before(:each) do
|
before(:each) do
|
||||||
expect(provider).to receive(:create_vm).with(pool, String).and_raise('MockError')
|
expect(provider).to receive(:create_vm).with(pool, String).and_raise('MockError')
|
||||||
allow(logger).to receive(:log)
|
allow(logger).to receive(:log)
|
||||||
|
expect(subject).to receive(:find_unique_hostname).with(pool).and_return(vm)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not create a cloning VM' do
|
it 'should not create a cloning VM' do
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue