f pool_manager_migration_spec

This commit is contained in:
Glenn Sarti 2017-02-01 20:42:47 -08:00
parent e1576782eb
commit e9d2c974c0

View file

@ -3,84 +3,96 @@ require 'mock_redis'
require 'time' require 'time'
describe 'Pool Manager' do describe 'Pool Manager' do
let(:logger) { double('logger') }
let(:redis) { MockRedis.new } let(:redis) { MockRedis.new }
let(:logger) { double('logger') }
let(:metrics) { Vmpooler::DummyStatsd.new } let(:metrics) { Vmpooler::DummyStatsd.new }
let(:config) { let(:config) {
{ {
config: { config: {
'site_name' => 'test pooler',
'migration_limit' => 2, 'migration_limit' => 2,
vsphere: {
'server' => 'vsphere.puppet.com',
'username' => 'vmpooler@vsphere.local',
'password' => '',
'insecure' => true
},
pools: [ {'name' => 'pool1', 'size' => 5, 'folder' => 'pool1_folder'} ],
statsd: { 'prefix' => 'stats_prefix'},
pool_names: [ 'pool1' ]
} }
} }
} }
let(:pool) { config[:config][:pools][0]['name'] } let(:backingservice) { double('backingservice') }
let(:vm) { let(:pool) { 'pool1' }
{ let(:vm) { 'vm1' }
'name' => 'vm1', let(:timeout) { 5 }
'host' => 'host1', let(:host) {
'template' => pool, fake_vm = {}
} fake_vm['name'] = 'vm1'
fake_vm['hostname'] = 'vm1'
fake_vm['template'] = 'pool1'
fake_vm['boottime'] = Time.now
fake_vm['powerstate'] = 'PoweredOn'
fake_vm
} }
let(:vm_host_hostname) { 'host1' }
subject { Vmpooler::PoolManager.new(config, logger, redis, metrics) }
describe "#migration_limit" do
it 'return false if config is nil' do
expect(subject.migration_limit(nil)).to equal(false)
end
it 'return false if config is 0' do
expect(subject.migration_limit(0)).to equal(false)
end
it 'return nil if config is -1' do
expect(subject.migration_limit(-1)).to equal(nil)
end
it 'return 1 if config is 1' do
expect(subject.migration_limit(1)).to equal(1)
end
it 'return 100 if config is 100' do
expect(subject.migration_limit(100)).to equal(100)
end
end
describe '#_migrate_vm' do describe '#_migrate_vm' do
let(:vsphere) { double(pool) }
let(:pooler) { Vmpooler::PoolManager.new(config, logger, redis, metrics) }
context 'evaluates VM for migration and logs host' do context 'evaluates VM for migration and logs host' do
before do before do
create_migrating_vm vm['name'], pool, redis create_migrating_vm vm, pool, redis
allow(vsphere).to receive(:find_vm).and_return(vm) allow(backingservice).to receive(:get_vm_host).with(vm).and_return(vm_host_hostname)
allow(pooler).to receive(:get_vm_host_info).and_return([{'name' => 'host1'}, 'host1'])
end end
it 'logs VM host when migration is disabled' do it 'logs VM host when migration is disabled' do
config[:config]['migration_limit'] = nil config[:config]['migration_limit'] = nil
expect(redis.sismember("vmpooler__migrating__#{pool}", vm['name'])).to be true expect(redis.sismember("vmpooler__migrating__#{pool}", vm)).to be true
expect(logger).to receive(:log).with('s', "[ ] [#{pool}] '#{vm['name']}' is running on #{vm['host']}") expect(logger).to receive(:log).with('s', "[ ] [#{pool}] '#{vm}' is running on #{vm_host_hostname}")
pooler._migrate_vm(vm['name'], pool, vsphere) subject._migrate_vm(vm, pool, backingservice)
expect(redis.sismember("vmpooler__migrating__#{pool}", vm['name'])).to be false expect(redis.sismember("vmpooler__migrating__#{pool}", vm)).to be false
end end
it 'verifies that migration_limit greater than or equal to migrations in progress and logs host' do it 'verifies that migration_limit greater than or equal to migrations in progress and logs host' do
add_vm_to_migration_set vm['name'], redis add_vm_to_migration_set vm, redis
add_vm_to_migration_set 'vm2', redis add_vm_to_migration_set 'vm2', redis
expect(logger).to receive(:log).with('s', "[ ] [#{pool}] '#{vm['name']}' is running on #{vm['host']}. No migration will be evaluated since the migration_limit has been reached") expect(logger).to receive(:log).with('s', "[ ] [#{pool}] '#{vm}' is running on #{vm_host_hostname}. No migration will be evaluated since the migration_limit has been reached")
pooler._migrate_vm(vm['name'], pool, vsphere) subject._migrate_vm(vm, pool, backingservice)
end end
it 'verifies that migration_limit is less than migrations in progress and logs old host, new host and migration time' do it 'verifies that migration_limit is less than migrations in progress and logs old host, new host and migration time' do
allow(vsphere).to receive(:find_least_used_compatible_host).and_return([{'name' => 'host2'}, 'host2']) allow(backingservice).to receive(:find_least_used_compatible_host).and_return('host2')
allow(vsphere).to receive(:migrate_vm_host) allow(backingservice).to receive(:migrate_vm_to_host).and_return(true)
expect(redis.hget("vmpooler__vm__#{vm['name']}", 'migration_time')) expect(redis.hget("vmpooler__vm__#{vm['name']}", 'migration_time'))
expect(redis.hget("vmpooler__vm__#{vm['name']}", 'checkout_to_migration')) expect(redis.hget("vmpooler__vm__#{vm['name']}", 'checkout_to_migration'))
expect(logger).to receive(:log).with('s', "[>] [#{pool}] '#{vm['name']}' migrated from #{vm['host']} to host2 in 0.00 seconds") expect(logger).to receive(:log).with('s', "[>] [#{pool}] '#{vm}' migrated from #{vm_host_hostname} to host2 in 0.00 seconds")
pooler._migrate_vm(vm['name'], pool, vsphere) subject._migrate_vm(vm, pool, backingservice)
end end
it 'fails when no suitable host can be found' do it 'fails when no suitable host can be found' do
error = 'ArgumentError: No target host found' error = 'ArgumentError: No target host found'
allow(vsphere).to receive(:find_least_used_compatible_host) allow(backingservice).to receive(:find_least_used_compatible_host).and_return('host2')
allow(vsphere).to receive(:migrate_vm_host).and_raise(error) allow(backingservice).to receive(:migrate_vm_to_host).and_raise(error)
expect(logger).to receive(:log).with('s', "[x] [#{pool}] '#{vm['name']}' migration failed with an error: #{error}") expect{subject._migrate_vm(vm, pool, backingservice)}.to raise_error(error)
pooler._migrate_vm(vm['name'], pool, vsphere)
end end
end end
end end