diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index 713349b33..bca8c26f3 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -35,6 +35,55 @@ module VagrantPlugins @inserted_key = false end + def wait_for_ready(timeout) + Timeout.timeout(timeout) do + # Wait for ssh_info to be ready + ssh_info = nil + while true + ssh_info = @machine.ssh_info + break if ssh_info + sleep 0.5 + end + + # Got it! Let the user know what we're connecting to. + @machine.ui.detail("SSH address: #{ssh_info[:host]}:#{ssh_info[:port]}") + @machine.ui.detail("SSH username: #{ssh_info[:username]}") + ssh_auth_type = "private key" + ssh_auth_type = "password" if ssh_info[:password] + @machine.ui.detail("SSH auth method: #{ssh_auth_type}") + + while true + begin + begin + connect(retries: 1) + return true + rescue Vagrant::Errors::VagrantError => e + @logger.info("SSH not ready: #{e.inspect}") + raise + end + rescue Errno::ETIMEDOUT, Timeout::Error + message = "Connection timout." + rescue Net::SSH::AuthenticationFailed + message = "Authentication failure." + rescue Net::SSH::Disconnect + message = "Remote connection disconnect." + rescue Errno::ECONNREFUSED + message = "Connection refused." + rescue Errno::ECONNRESET + message = "Connection reset." + rescue Errno::EHOSTDOWN + message = "Host appears down." + rescue Errno::EHOSTUNREACH + message = "Host unreachable." + end + + @machine.ui.detail("Error: #{message} Retrying...") + end + end + rescue Timeout::Error + return false + end + def ready? @logger.debug("Checking whether SSH is ready...") @@ -171,7 +220,7 @@ module VagrantPlugins protected # Opens an SSH connection and yields it to a block. - def connect + def connect(**opts) if @connection && !@connection.closed? # There is a chance that the socket is closed despite us checking # 'closed?' above. To test this we need to send data through the @@ -198,8 +247,11 @@ module VagrantPlugins ssh_info = @machine.ssh_info raise Vagrant::Errors::SSHNotReady if ssh_info.nil? + # Default some options + opts[:retries] = 5 if !opts.has_key?(:retries) + # Build the options we'll use to initiate the connection via Net::SSH - opts = { + common_connect_opts = { :auth_methods => ["none", "publickey", "hostbased", "password"], :config => false, :forward_agent => ssh_info[:forward_agent], @@ -208,7 +260,9 @@ module VagrantPlugins :paranoid => false, :password => ssh_info[:password], :port => ssh_info[:port], - :user_known_hosts_file => [] + :timeout => 15, + :user_known_hosts_file => [], + :verbose => :debug, } # Check that the private key permissions are valid @@ -233,11 +287,10 @@ module VagrantPlugins Timeout::Error ] - retries = 5 timeout = 60 @logger.info("Attempting SSH connnection...") - connection = retryable(:tries => retries, :on => exceptions) do + connection = retryable(:tries => opts[:retries], :on => exceptions) do Timeout.timeout(timeout) do begin # This logger will get the Net-SSH log data for us. @@ -245,11 +298,8 @@ module VagrantPlugins ssh_logger = Logger.new(ssh_logger_io) # Setup logging for connections - connect_opts = opts.merge({ - :logger => ssh_logger, - :timeout => 15, - :verbose => :debug - }) + connect_opts = common_connect_opts.dup + connect_opts[:logger] = ssh_logger if ssh_info[:proxy_command] connect_opts[:proxy] = Net::SSH::Proxy::Command.new(ssh_info[:proxy_command]) diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 5438dab66..275a6d2a5 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -304,8 +304,11 @@ en: boot_timeout: |- Timed out while waiting for the machine to boot. This means that Vagrant was unable to communicate with the guest machine within - the configured ("config.vm.boot_timeout" value) time period. This can - mean a number of things. + the configured ("config.vm.boot_timeout" value) time period. + + If you look above, you should be able to see the error(s) that + Vagrant had when attempting to connect to the machine. These errors + are usually good hints as to what may be wrong. If you're using a custom box, make sure that networking is properly working and you're able to connect to the machine. It is a common