SSH.up? timeout slowly ramps up based on configuration values, giving later attempts more time.

This commit is contained in:
Mitchell Hashimoto 2010-03-11 17:59:25 -08:00
parent b03af8ccc2
commit 2c1483ae80
7 changed files with 84 additions and 16 deletions

View File

@ -9,7 +9,9 @@ Vagrant::Config.run do |config|
config.ssh.host = "localhost"
config.ssh.forwarded_port_key = "ssh"
config.ssh.max_tries = 10
config.ssh.timeout = 30
config.ssh.timeout = 5
config.ssh.retry_timeout_delta = 5
config.ssh.max_timeout_delta = 30
config.vm.box_ovf = "box.ovf"
config.vm.base_mac = "0800279C2E42"

View File

@ -29,13 +29,18 @@ error
def wait_for_boot
logger.info "Waiting for VM to boot..."
current_timeout = Vagrant.config.ssh.timeout
max_timeout = current_timeout + Vagrant.config.ssh.max_timeout_delta
Vagrant.config[:ssh][:max_tries].to_i.times do |i|
logger.info "Trying to connect (attempt ##{i+1} of #{Vagrant.config[:ssh][:max_tries]})..."
if Vagrant::SSH.up?
if Vagrant::SSH.up?(current_timeout)
logger.info "VM booted and ready for use!"
return true
end
current_timeout += Vagrant.config.ssh.retry_timeout_delta unless current_timeout >= max_timeout
end
logger.info "Failed to connect to VM! Failed to boot?"

View File

@ -64,6 +64,8 @@ module Vagrant
attr_accessor :forwarded_port_key
attr_accessor :max_tries
attr_accessor :timeout
attr_accessor :retry_timeout_delta
attr_accessor :max_timeout_delta
end
class VMConfig < Base

View File

@ -25,11 +25,13 @@ module Vagrant
end
end
def up?
def up?(timeout=nil)
timeout ||= Vagrant.config.ssh.timeout
check_thread = Thread.new do
begin
Thread.current[:result] = false
Net::SSH.start(Vagrant.config.ssh.host, Vagrant.config.ssh.username, :port => port, :password => Vagrant.config.ssh.password, :timeout => Vagrant.config.ssh.timeout) do |ssh|
Net::SSH.start(Vagrant.config.ssh.host, Vagrant.config.ssh.username, :port => port, :password => Vagrant.config.ssh.password, :timeout => timeout) do |ssh|
Thread.current[:result] = true
end
rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
@ -37,7 +39,7 @@ module Vagrant
end
end
check_thread.join(Vagrant.config.ssh.timeout)
check_thread.join(timeout)
return check_thread[:result]
end

View File

@ -31,6 +31,8 @@ class Test::Unit::TestCase
config.ssh.forwarded_port_key = "ssh"
config.ssh.max_tries = 10
config.ssh.timeout = 10
config.ssh.retry_timeout_delta = 5
config.ssh.max_timeout_delta = 30
config.vm.box = "foo"
config.vm.box_ovf = "box.ovf"

View File

@ -51,5 +51,27 @@ class BootActionTest < Test::Unit::TestCase
Vagrant::SSH.expects(:up?).times(Vagrant.config[:ssh][:max_tries].to_i).returns(false)
assert !@action.wait_for_boot
end
should "slowly increase timeout given to up? up to maximum specified" do
@timeout = 30
@retry_delta = 5
@max_delta = 30
mock_config do |config|
config.ssh.timeout = @timeout
config.ssh.retry_timeout_delta = @retry_delta
config.ssh.max_timeout_delta = @max_delta
end
up_sequence = sequence("up_seq")
current_timeout = @timeout
max_timeout = @timeout + @max_delta
Vagrant.config.ssh.max_tries.times do |i|
Vagrant::SSH.expects(:up?).with(current_timeout).returns(false).in_sequence(up_sequence)
current_timeout += @retry_delta unless current_timeout >= max_timeout
end
assert !@action.wait_for_boot
end
end
end

View File

@ -56,26 +56,59 @@ class SshTest < Test::Unit::TestCase
context "checking if host is up" do
setup do
mock_config
end
should "return true if SSH connection works" do
Net::SSH.expects(:start).yields("success")
assert Vagrant::SSH.up?
end
@timeout = 7
should "return false if SSH connection times out" do
Net::SSH.expects(:start)
assert !Vagrant::SSH.up?
end
should "allow the thread the configured timeout time" do
@thread = mock("thread")
@thread.stubs(:[])
@thread.stubs(:[]=)
@thread.stubs(:join)
Thread.stubs(:current).returns(@thread)
Thread.stubs(:new).returns(@thread).yields
Net::SSH.stubs(:start)
end
should "return the value of result in thread" do
result = mock("result")
@thread.expects(:[]).with(:result).returns(result)
assert_equal result, Vagrant::SSH.up?
end
should "start SSH with proper configuration" do
Net::SSH.expects(:start).with(Vagrant.config.ssh.host, Vagrant.config.ssh.username, :port => Vagrant::SSH.port, :password => Vagrant.config.ssh.password, :timeout => Vagrant.config.ssh.timeout).once
Vagrant::SSH.up?
end
should "start SSH with proper timeout value if given" do
Net::SSH.expects(:start).with(Vagrant.config.ssh.host, Vagrant.config.ssh.username, :port => Vagrant::SSH.port, :password => Vagrant.config.ssh.password, :timeout => @timeout).once
Vagrant::SSH.up?(@timeout)
end
should "set result to true if SSH connection works" do
@thread.expects(:[]=).with(:result, true)
Net::SSH.expects(:start).yields("success")
Vagrant::SSH.up?
end
should "set result to false if SSH connection times out" do
@thread.expects(:[]=).with(:result, false)
Net::SSH.expects(:start)
Vagrant::SSH.up?
end
should "allow the thread the configured timeout time by default" do
Thread.expects(:new).returns(@thread)
@thread.expects(:join).with(Vagrant.config.ssh.timeout).once
Vagrant::SSH.up?
end
should "allow the thread the given timeout time if given" do
Thread.expects(:new).returns(@thread)
@thread.expects(:join).with(@timeout).once
Vagrant::SSH.up?(@timeout)
end
should "return false if the connection is refused" do
Net::SSH.expects(:start).raises(Errno::ECONNREFUSED)
assert_nothing_raised {