diff --git a/lib/vmpooler/pool_manager.rb b/lib/vmpooler/pool_manager.rb index 07dd7cd..2fb71f9 100644 --- a/lib/vmpooler/pool_manager.rb +++ b/lib/vmpooler/pool_manager.rb @@ -25,40 +25,50 @@ module Vmpooler # Check the state of a VM def check_pending_vm(vm, pool, timeout) Thread.new do - host = $vsphere[pool].find_vm(vm) + _check_pending_vm(vm, pool, timeout) + end + end - if host - if - (host.summary) && - (host.summary.guest) && - (host.summary.guest.hostName) && - (host.summary.guest.hostName == vm) + def _check_pending_vm(vm, pool, timeout) + host = $vsphere[pool].find_vm(vm) - begin - Socket.getaddrinfo(vm, nil) - rescue - end + if host + move_pending_vm_to_ready(vm, pool, host) + else + fail_pending_vm(vm, pool, timeout) + end + end - clone_time = $redis.hget('vmpooler__vm__' + vm, 'clone') - finish = '%.2f' % (Time.now - Time.parse(clone_time)) if clone_time + def fail_pending_vm(vm, pool, timeout) + clone_stamp = $redis.hget('vmpooler__vm__' + vm, 'clone') - $redis.smove('vmpooler__pending__' + pool, 'vmpooler__ready__' + pool, vm) - $redis.hset('vmpooler__boot__' + Date.today.to_s, pool + ':' + vm, finish) + if (clone_stamp) && + (((Time.now - Time.parse(clone_stamp)) / 60) > timeout) - $logger.log('s', "[>] [#{pool}] '#{vm}' moved to 'ready' queue") - end - else - clone_stamp = $redis.hget('vmpooler__vm__' + vm, 'clone') + $redis.smove('vmpooler__pending__' + pool, 'vmpooler__completed__' + pool, vm) - if - (clone_stamp) && - (((Time.now - Time.parse(clone_stamp)) / 60) > timeout) + $logger.log('d', "[!] [#{pool}] '#{vm}' marked as 'failed' after #{timeout} minutes") + end + end - $redis.smove('vmpooler__pending__' + pool, 'vmpooler__completed__' + pool, vm) + def move_pending_vm_to_ready(vm, pool, host) + if (host.summary) && + (host.summary.guest) && + (host.summary.guest.hostName) && + (host.summary.guest.hostName == vm) - $logger.log('d', "[!] [#{pool}] '#{vm}' marked as 'failed' after #{timeout} minutes") - end + begin + Socket.getaddrinfo(vm, nil) + rescue end + + clone_time = $redis.hget('vmpooler__vm__' + vm, 'clone') + finish = '%.2f' % (Time.now - Time.parse(clone_time)) if clone_time + + $redis.smove('vmpooler__pending__' + pool, 'vmpooler__ready__' + pool, vm) + $redis.hset('vmpooler__boot__' + Date.today.to_s, pool + ':' + vm, finish) + + $logger.log('s', "[>] [#{pool}] '#{vm}' moved to 'ready' queue") end end diff --git a/spec/vmpooler/pool_manager_spec.rb b/spec/vmpooler/pool_manager_spec.rb new file mode 100644 index 0000000..1bc09e1 --- /dev/null +++ b/spec/vmpooler/pool_manager_spec.rb @@ -0,0 +1,150 @@ +require 'spec_helper' + +describe 'Pool Manager' do + let(:logger) { double('logger') } + let(:redis) { double('redis') } + let(:config) { {} } + let(:pools) { {} } + let(:graphite) { nil } + let(:pool) { 'pool1' } + let(:vm) { 'vm1' } + let(:timeout) { 5 } + let(:host) { double('host') } + + subject { Vmpooler::PoolManager.new(config, pools, logger, redis, graphite) } + + describe '#_check_pending_vm' do + let(:pool_helper) { double('pool') } + let(:vsphere) { {pool => pool_helper} } + + before do + expect(subject).not_to be_nil + $vsphere = vsphere + end + + context 'host not in pool' do + + it 'calls fail_pending_vm' do + allow(pool_helper).to receive(:find_vm).and_return(nil) + allow(redis).to receive(:hget) + expect(redis).to receive(:hget).with(String, 'clone').once + subject._check_pending_vm(vm, pool, timeout) + end + + end + + context 'host is in pool' do + let(:vm_finder) { double('vm_finder') } + + it 'calls move_pending_vm_to_ready' do + allow(pool_helper).to receive(:find_vm).and_return(vm_finder) + allow(vm_finder).to receive(:summary).and_return(nil) + + expect(vm_finder).to receive(:summary).once + expect(redis).not_to receive(:hget).with(String, 'clone') + + subject._check_pending_vm(vm, pool, timeout) + end + end + end + + describe '#move_vm_to_ready' do + before do + expect(subject).not_to be_nil + end + + context 'a host without correct summary' do + + it 'does nothing when summary is nil' do + allow(host).to receive(:summary).and_return nil + subject.move_pending_vm_to_ready(vm, pool, host) + end + + it 'does nothing when guest is nil' do + allow(host).to receive(:summary).and_return true + allow(host).to receive_message_chain(:summary, :guest).and_return nil + subject.move_pending_vm_to_ready(vm, pool, host) + end + + it 'does nothing when hostName is nil' do + allow(host).to receive(:summary).and_return true + allow(host).to receive_message_chain(:summary, :guest).and_return true + allow(host).to receive_message_chain(:summary, :guest, :hostName).and_return nil + subject.move_pending_vm_to_ready(vm, pool, host) + end + + it 'does nothing when hostName does not match vm' do + allow(host).to receive(:summary).and_return true + allow(host).to receive_message_chain(:summary, :guest).and_return true + allow(host).to receive_message_chain(:summary, :guest, :hostName).and_return 'adifferentvm' + subject.move_pending_vm_to_ready(vm, pool, host) + end + end + + context 'a host with proper summary' do + before do + allow(host).to receive(:summary).and_return true + allow(host).to receive_message_chain(:summary, :guest).and_return true + allow(host).to receive_message_chain(:summary, :guest, :hostName).and_return vm + + allow(redis).to receive(:hget) + allow(redis).to receive(:smove) + allow(redis).to receive(:hset) + allow(logger).to receive(:log) + end + + it 'moves vm to ready' do + allow(redis).to receive(:hget).with(String, 'clone').and_return Time.now.to_s + + expect(redis).to receive(:smove).with(String, String, vm) + expect(redis).to receive(:hset).with(String, String, String) + expect(logger).to receive(:log).with('s', String) + + subject.move_pending_vm_to_ready(vm, pool, host) + end + + it 'sets finish to nil when clone_time is nil' do + expect(redis).to receive(:smove).with(String, String, vm) + expect(redis).to receive(:hset).with(String, String, nil) + expect(logger).to receive(:log).with('s', String) + + subject.move_pending_vm_to_ready(vm, pool, host) + end + + end + end + + describe '#fail_pending_vm' do + before do + expect(subject).not_to be_nil + end + + context 'does not have a clone stamp' do + it 'has no side effects' do + allow(redis).to receive(:hget) + subject.fail_pending_vm(vm, pool, timeout) + end + end + + context 'has valid clone stamp' do + it 'does nothing when less than timeout' do + allow(redis).to receive(:hget).with(String, 'clone').and_return Time.now.to_s + subject.fail_pending_vm(vm, pool, timeout) + end + + it 'moves vm to completed when over timeout' do + allow(redis).to receive(:hget).with(String, 'clone').and_return '2005-01-1' + allow(redis).to receive(:smove).with(String, String, String) + allow(logger).to receive(:log).with(String, String) + + expect(redis).to receive(:smove).with(String, String, vm) + expect(logger).to receive(:log).with('d', String) + + subject.fail_pending_vm(vm, pool, timeout) + end + + end + end + + +end \ No newline at end of file