From 2acded113c8f8915038b6230df1acfac43332c0c Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Tue, 25 Apr 2017 13:38:24 -0700 Subject: [PATCH] Retry SSH connection on Errno::ECONNABORTED In some cases the SSH connection may be aborted while waiting for setup. This includes aborted connections in the list of applicable exceptions to retry on while waiting for the connection to become available. Fixes #8520 --- lib/vagrant/errors.rb | 4 +++ plugins/communicators/ssh/communicator.rb | 36 +++++++++++++---------- templates/locales/en.yml | 7 +++++ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index fbcad904f..982fdf91e 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -664,6 +664,10 @@ module Vagrant error_key(:ssh_connection_refused) end + class SSHConnectionAborted < VagrantError + error_key(:ssh_connection_aborted) + end + class SSHConnectionReset < VagrantError error_key(:ssh_connection_reset) end diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index a8abadead..be48252a8 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -25,6 +25,20 @@ module VagrantPlugins PTY_DELIM_END = "bccbb768c119429488cfd109aacea6b5-pty" # Marker for start of regular command output CMD_GARBAGE_MARKER = "41e57d38-b4f7-4e46-9c38-13873d338b86-vagrant-ssh" + # These are the exceptions that we retry because they represent + # errors that are generally fixed from a retry and don't + # necessarily represent immediate failure cases. + SSH_RETRY_EXCEPTIONS = [ + Errno::EACCES, + Errno::EADDRINUSE, + Errno::ECONNABORTED, + Errno::ECONNREFUSED, + Errno::ECONNRESET, + Errno::ENETUNREACH, + Errno::EHOSTUNREACH, + Net::SSH::Disconnect, + Timeout::Error + ] include Vagrant::Util::ANSIEscapeCodeRemover include Vagrant::Util::Retryable @@ -81,6 +95,8 @@ module VagrantPlugins message = "Connection refused." rescue Vagrant::Errors::SSHConnectionReset message = "Connection reset." + rescue Vagrant::Errors::SSHConnectionAborted + message = "Connection aborted." rescue Vagrant::Errors::SSHHostDown message = "Host appears down." rescue Vagrant::Errors::SSHNoRoute @@ -350,24 +366,10 @@ module VagrantPlugins # Connect to SSH, giving it a few tries connection = nil begin - # These are the exceptions that we retry because they represent - # errors that are generally fixed from a retry and don't - # necessarily represent immediate failure cases. - exceptions = [ - Errno::EACCES, - Errno::EADDRINUSE, - Errno::ECONNREFUSED, - Errno::ECONNRESET, - Errno::ENETUNREACH, - Errno::EHOSTUNREACH, - Net::SSH::Disconnect, - Timeout::Error - ] - timeout = 60 @logger.info("Attempting SSH connection...") - connection = retryable(tries: opts[:retries], on: exceptions) do + connection = retryable(tries: opts[:retries], on: SSH_RETRY_EXCEPTIONS) do Timeout.timeout(timeout) do begin # This logger will get the Net-SSH log data for us. @@ -426,6 +428,10 @@ module VagrantPlugins # This is raised if we failed to connect the max number of times # due to an ECONNRESET. raise Vagrant::Errors::SSHConnectionReset + rescue Errno::ECONNABORTED + # This is raised if we failed to connect the max number of times + # due to an ECONNABORTED + raise Vagrant::Errors::SSHConnectionAborted rescue Errno::EHOSTDOWN # This is raised if we get an ICMP DestinationUnknown error. raise Vagrant::Errors::SSHHostDown diff --git a/templates/locales/en.yml b/templates/locales/en.yml index aac75731f..c026bd325 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -1189,6 +1189,13 @@ en: If that doesn't work, destroy your VM and recreate it with a `vagrant destroy` followed by a `vagrant up`. If that doesn't work, contact a Vagrant maintainer (support channels listed on the website) for more assistance. + ssh_connection_aborted: |- + SSH connection was aborted! This usually happens when the machine is taking + too long to reboot or the SSH daemon is not properly configured on the VM. + First, try reloading your machine with `vagrant reload`, since a simple + restart sometimes fixes things. If that doesn't work, destroy your machine + and recreate it with a `vagrant destroy` followed by a `vagrant up`. If that + doesn't work, contact support. ssh_connection_reset: |- SSH connection was reset! This usually happens when the machine is taking too long to reboot. First, try reloading your machine with