mirror of
https://github.com/puppetlabs/vmpooler.git
synced 2026-01-26 10:08:40 -05:00
(POOLER-70) Update migrate_vm for VM Provider
Previously the Pool Manager would use vSphere objects directly. This commit - Modifies the pool_manager to use the VM provider methods instead
This commit is contained in:
parent
acf32a3f7b
commit
2974eac371
2 changed files with 67 additions and 56 deletions
|
|
@ -458,42 +458,43 @@ module Vmpooler
|
||||||
migration_limit if migration_limit >= 1
|
migration_limit if migration_limit >= 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def migrate_vm(vm, pool, provider)
|
def migrate_vm(vm_name, pool_name, provider)
|
||||||
Thread.new do
|
Thread.new do
|
||||||
_migrate_vm(vm, pool, provider)
|
begin
|
||||||
|
_migrate_vm(vm_name, pool_name, provider)
|
||||||
|
rescue => err
|
||||||
|
$logger.log('s', "[x] [#{pool_name}] '#{vm_name}' migration failed with an error: #{err}")
|
||||||
|
remove_vmpooler_migration_vm(pool_name, vm_name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def _migrate_vm(vm, pool, provider)
|
def _migrate_vm(vm_name, pool_name, provider)
|
||||||
begin
|
$redis.srem('vmpooler__migrating__' + pool_name, vm_name)
|
||||||
$redis.srem('vmpooler__migrating__' + pool, vm)
|
|
||||||
vm_object = provider.find_vm(vm)
|
|
||||||
parent_host, parent_host_name = get_vm_host_info(vm_object)
|
|
||||||
migration_limit = migration_limit $config[:config]['migration_limit']
|
|
||||||
migration_count = $redis.scard('vmpooler__migration')
|
|
||||||
|
|
||||||
if ! migration_limit
|
parent_host_name = provider.get_vm_host(pool_name, vm_name)
|
||||||
$logger.log('s', "[ ] [#{pool}] '#{vm}' is running on #{parent_host_name}")
|
raise('Unable to determine which host the VM is running on') if parent_host_name.nil?
|
||||||
|
migration_limit = migration_limit $config[:config]['migration_limit']
|
||||||
|
migration_count = $redis.scard('vmpooler__migration')
|
||||||
|
|
||||||
|
if ! migration_limit
|
||||||
|
$logger.log('s', "[ ] [#{pool_name}] '#{vm_name}' is running on #{parent_host_name}")
|
||||||
|
return
|
||||||
|
else
|
||||||
|
if migration_count >= migration_limit
|
||||||
|
$logger.log('s', "[ ] [#{pool_name}] '#{vm_name}' is running on #{parent_host_name}. No migration will be evaluated since the migration_limit has been reached")
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
if migration_count >= migration_limit
|
$redis.sadd('vmpooler__migration', vm_name)
|
||||||
$logger.log('s', "[ ] [#{pool}] '#{vm}' is running on #{parent_host_name}. No migration will be evaluated since the migration_limit has been reached")
|
host_name = provider.find_least_used_compatible_host(vm_name)
|
||||||
return
|
if host_name == parent_host_name
|
||||||
|
$logger.log('s', "[ ] [#{pool_name}] No migration required for '#{vm_name}' running on #{parent_host_name}")
|
||||||
else
|
else
|
||||||
$redis.sadd('vmpooler__migration', vm)
|
finish = migrate_vm_and_record_timing(vm_name, pool_name, parent_host_name, host_name, provider)
|
||||||
host, host_name = provider.find_least_used_compatible_host(vm_object)
|
$logger.log('s', "[>] [#{pool_name}] '#{vm_name}' migrated from #{parent_host_name} to #{host_name} in #{finish} seconds")
|
||||||
if host == parent_host
|
|
||||||
$logger.log('s', "[ ] [#{pool}] No migration required for '#{vm}' running on #{parent_host_name}")
|
|
||||||
else
|
|
||||||
finish = migrate_vm_and_record_timing(vm_object, vm, pool, host, parent_host_name, host_name, provider)
|
|
||||||
$logger.log('s', "[>] [#{pool}] '#{vm}' migrated from #{parent_host_name} to #{host_name} in #{finish} seconds")
|
|
||||||
end
|
|
||||||
remove_vmpooler_migration_vm(pool, vm)
|
|
||||||
end
|
end
|
||||||
|
remove_vmpooler_migration_vm(pool_name, vm_name)
|
||||||
end
|
end
|
||||||
rescue => err
|
|
||||||
$logger.log('s', "[x] [#{pool}] '#{vm}' migration failed with an error: #{err}")
|
|
||||||
remove_vmpooler_migration_vm(pool, vm)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1487,60 +1487,75 @@ EOT
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#migrate_vm' do
|
describe '#migrate_vm' do
|
||||||
let(:provider) { double('provider') }
|
before(:each) do
|
||||||
|
|
||||||
before do
|
|
||||||
expect(subject).not_to be_nil
|
expect(subject).not_to be_nil
|
||||||
|
expect(Thread).to receive(:new).and_yield
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calls _migrate_vm' do
|
it 'calls _migrate_vm' do
|
||||||
expect(Thread).to receive(:new).and_yield
|
|
||||||
expect(subject).to receive(:_migrate_vm).with(vm, pool, provider)
|
expect(subject).to receive(:_migrate_vm).with(vm, pool, provider)
|
||||||
|
|
||||||
subject.migrate_vm(vm, pool, provider)
|
subject.migrate_vm(vm, pool, provider)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'When an error is raised' do
|
||||||
|
before(:each) do
|
||||||
|
expect(subject).to receive(:_migrate_vm).with(vm, pool, provider).and_raise('MockError')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'logs a message' do
|
||||||
|
allow(logger).to receive(:log)
|
||||||
|
expect(logger).to receive(:log).with('s', "[x] [#{pool}] '#{vm}' migration failed with an error: MockError")
|
||||||
|
|
||||||
|
subject.migrate_vm(vm, pool, provider)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should attempt to remove from vmpooler_migration queue' do
|
||||||
|
expect(subject).to receive(:remove_vmpooler_migration_vm).with(pool, vm)
|
||||||
|
|
||||||
|
subject.migrate_vm(vm, pool, provider)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#_migrate_vm" do
|
describe "#_migrate_vm" do
|
||||||
let(:provider) { double('provider') }
|
|
||||||
let(:vm_parent_hostname) { 'parent1' }
|
let(:vm_parent_hostname) { 'parent1' }
|
||||||
let(:config) {
|
let(:config) {
|
||||||
YAML.load(<<-EOT
|
YAML.load(<<-EOT
|
||||||
---
|
---
|
||||||
:config:
|
:config:
|
||||||
migration_limit: 5
|
migration_limit: 5
|
||||||
:pools:
|
|
||||||
- name: #{pool}
|
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
before do
|
before(:each) do
|
||||||
expect(subject).not_to be_nil
|
expect(subject).not_to be_nil
|
||||||
|
allow(provider).to receive(:get_vm_host).with(pool, vm).and_return(vm_parent_hostname)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when an error occurs' do
|
context 'when an error occurs trying to retrieve the current host' do
|
||||||
it 'should log an error message and attempt to remove from vmpooler_migration queue' do
|
before(:each) do
|
||||||
expect(provider).to receive(:find_vm).with(vm).and_raise(RuntimeError,'MockError')
|
expect(provider).to receive(:get_vm_host).with(pool, vm).and_raise(RuntimeError,'MockError')
|
||||||
expect(logger).to receive(:log).with('s', "[x] [#{pool}] '#{vm}' migration failed with an error: MockError")
|
end
|
||||||
expect(subject).to receive(:remove_vmpooler_migration_vm)
|
|
||||||
subject._migrate_vm(vm, pool, provider)
|
it 'should raise an error' do
|
||||||
|
expect{ subject._migrate_vm(vm, pool, provider) }.to raise_error('MockError')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when VM does not exist' do
|
context 'when the current host can not be determined' do
|
||||||
it 'should log an error message when VM does not exist' do
|
before(:each) do
|
||||||
expect(provider).to receive(:find_vm).with(vm).and_return(nil)
|
expect(provider).to receive(:get_vm_host).with(pool, vm).and_return(nil)
|
||||||
# This test is quite fragile. Should refactor the code to make this scenario easier to detect
|
end
|
||||||
expect(logger).to receive(:log).with('s', "[x] [#{pool}] '#{vm}' migration failed with an error: undefined method `summary' for nil:NilClass")
|
|
||||||
subject._migrate_vm(vm, pool, provider)
|
it 'should raise an error' do
|
||||||
|
expect{ subject._migrate_vm(vm, pool, provider) }.to raise_error(/Unable to determine which host the VM is running on/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when VM exists but migration is disabled' do
|
context 'when VM exists but migration is disabled' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
expect(provider).to receive(:find_vm).with(vm).and_return(host)
|
|
||||||
allow(subject).to receive(:get_vm_host_info).with(host).and_return([{'name' => vm_parent_hostname}, vm_parent_hostname])
|
|
||||||
create_migrating_vm(vm, pool)
|
create_migrating_vm(vm, pool)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -1564,8 +1579,6 @@ EOT
|
||||||
|
|
||||||
context 'when VM exists but migration limit is reached' do
|
context 'when VM exists but migration limit is reached' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
expect(provider).to receive(:find_vm).with(vm).and_return(host)
|
|
||||||
allow(subject).to receive(:get_vm_host_info).with(host).and_return([{'name' => vm_parent_hostname}, vm_parent_hostname])
|
|
||||||
|
|
||||||
create_migrating_vm(vm, pool)
|
create_migrating_vm(vm, pool)
|
||||||
redis.sadd('vmpooler__migration', 'fakevm1')
|
redis.sadd('vmpooler__migration', 'fakevm1')
|
||||||
|
|
@ -1589,9 +1602,6 @@ EOT
|
||||||
|
|
||||||
context 'when VM exists but migration limit is not yet reached' do
|
context 'when VM exists but migration limit is not yet reached' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
expect(provider).to receive(:find_vm).with(vm).and_return(host)
|
|
||||||
allow(subject).to receive(:get_vm_host_info).with(host).and_return([{'name' => vm_parent_hostname}, vm_parent_hostname])
|
|
||||||
|
|
||||||
create_migrating_vm(vm, pool)
|
create_migrating_vm(vm, pool)
|
||||||
redis.sadd('vmpooler__migration', 'fakevm1')
|
redis.sadd('vmpooler__migration', 'fakevm1')
|
||||||
redis.sadd('vmpooler__migration', 'fakevm2')
|
redis.sadd('vmpooler__migration', 'fakevm2')
|
||||||
|
|
@ -1599,7 +1609,7 @@ EOT
|
||||||
|
|
||||||
context 'and host to migrate to is the same as the current host' do
|
context 'and host to migrate to is the same as the current host' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
expect(provider).to receive(:find_least_used_compatible_host).with(host).and_return([{'name' => vm_parent_hostname}, vm_parent_hostname])
|
expect(provider).to receive(:find_least_used_compatible_host).with(vm).and_return(vm_parent_hostname)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not migrate the VM" do
|
it "should not migrate the VM" do
|
||||||
|
|
@ -1628,8 +1638,8 @@ EOT
|
||||||
context 'and host to migrate to different to the current host' do
|
context 'and host to migrate to different to the current host' do
|
||||||
let(:vm_new_hostname) { 'new_hostname' }
|
let(:vm_new_hostname) { 'new_hostname' }
|
||||||
before(:each) do
|
before(:each) do
|
||||||
expect(provider).to receive(:find_least_used_compatible_host).with(host).and_return([{'name' => vm_new_hostname}, vm_new_hostname])
|
expect(provider).to receive(:find_least_used_compatible_host).with(vm).and_return(vm_new_hostname)
|
||||||
expect(subject).to receive(:migrate_vm_and_record_timing).with(host, vm, pool, Object, vm_parent_hostname, vm_new_hostname, provider).and_return('1.00')
|
expect(subject).to receive(:migrate_vm_and_record_timing).with(vm, pool, vm_parent_hostname, vm_new_hostname, provider).and_return('1.00')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should migrate the VM" do
|
it "should migrate the VM" do
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue