Don't raise AnsibleConnectionFailure if the ssh process has already died. (#53534)

* Don't raise AnsibleConnectionFailure if the ssh_process has already died. Fixes #53487

* Better support for file not found messages

* Add changelog fragment
This commit is contained in:
Matt Martz 2019-03-12 10:41:30 -05:00 committed by GitHub
parent 15303b05ef
commit e9f9bcae6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 6 deletions

View file

@ -674,7 +674,7 @@ class Connection(ConnectionBase):
return b_command
def _send_initial_data(self, fh, in_data):
def _send_initial_data(self, fh, in_data, ssh_process):
'''
Writes initial data to the stdin filehandle of the subprocess and closes
it. (The handle must be closed; otherwise, for example, "sftp -b -" will
@ -687,7 +687,15 @@ class Connection(ConnectionBase):
fh.write(to_bytes(in_data))
fh.close()
except (OSError, IOError):
raise AnsibleConnectionFailure('SSH Error: data could not be sent to remote host "%s". Make sure this host can be reached over ssh' % self.host)
# The ssh connection may have already terminated at this point, with a more useful error
# Only raise AnsibleConnectionFailure if the ssh process is still alive
time.sleep(0.001)
ssh_process.poll()
if getattr(ssh_process, 'returncode', None) is None:
raise AnsibleConnectionFailure(
'SSH Error: data could not be sent to remote host "%s". Make sure this host can be reached '
'over ssh' % self.host
)
display.debug('Sent initial data (%d bytes)' % len(in_data))
@ -865,7 +873,7 @@ class Connection(ConnectionBase):
# If we can send initial data without waiting for anything, we do so
# before we start polling
if states[state] == 'ready_to_send' and in_data:
self._send_initial_data(stdin, in_data)
self._send_initial_data(stdin, in_data, p)
state += 1
try:
@ -979,7 +987,7 @@ class Connection(ConnectionBase):
if states[state] == 'ready_to_send':
if in_data:
self._send_initial_data(stdin, in_data)
self._send_initial_data(stdin, in_data, p)
state += 1
# Now we're awaiting_exit: has the child process exited? If it has,