From 673c55f2efce52c155872c80b0bff160e4a7b7b7 Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Tue, 3 Jul 2018 10:20:37 -0700 Subject: [PATCH] Separate some 255 exit codes that are not ssh errors The ssh connection plugin is overzealous in thinking that error code 255 can only come from ssh. Python can return 255 in some circumstances and error from php does as well. --- changelogs/fragments/fix-255-exit-code.yaml | 6 ++++++ lib/ansible/plugins/connection/ssh.py | 24 ++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/fix-255-exit-code.yaml diff --git a/changelogs/fragments/fix-255-exit-code.yaml b/changelogs/fragments/fix-255-exit-code.yaml new file mode 100644 index 0000000000..4a14262bb6 --- /dev/null +++ b/changelogs/fragments/fix-255-exit-code.yaml @@ -0,0 +1,6 @@ +--- +bugfixes: +- 'The ssh connection plugin was categorizing all 255 exit statuses as an ssh + error but modules can return exit code 255 as well. The connection plugin + has now been changed to know that certain instances of exit code 255 are not + ssh-related. (https://github.com/ansible/ansible/pull/41716)' diff --git a/lib/ansible/plugins/connection/ssh.py b/lib/ansible/plugins/connection/ssh.py index be4c8aca73..5acc0f236a 100644 --- a/lib/ansible/plugins/connection/ssh.py +++ b/lib/ansible/plugins/connection/ssh.py @@ -297,6 +297,11 @@ except ImportError: display = Display() +NOT_SSH_ERRORS = ('Traceback (most recent call last):', # Python-2.6 when there's an exception + # while invoking a script via -m + 'PHP Parse error:', # Php always returns error 255 + ) + SSHPASS_AVAILABLE = None @@ -333,7 +338,7 @@ def _ssh_retry(func): display.vvv(return_tuple, host=self.host) # 0 = success # 1-254 = remote command return code - # 255 = failure from the ssh command itself + # 255 could be a failure from the ssh command itself except (AnsibleControlPersistBrokenPipeError) as e: # Retry one more time because of the ControlPersist broken pipe (see #16731) cmd = args[0] @@ -344,10 +349,19 @@ def _ssh_retry(func): display.vvv(u"RETRYING BECAUSE OF CONTROLPERSIST BROKEN PIPE") return_tuple = func(self, *args, **kwargs) - if return_tuple[0] != 255: - break - else: - raise AnsibleConnectionFailure("Failed to connect to the host via ssh: %s" % to_native(return_tuple[2])) + if return_tuple[0] == 255: + SSH_ERROR = True + for signature in NOT_SSH_ERRORS: + if signature in return_tuple[1]: + SSH_ERROR = False + break + + if SSH_ERROR: + raise AnsibleConnectionFailure("Failed to connect to the host via ssh: %s" + % to_native(return_tuple[2])) + + break + except (AnsibleConnectionFailure, Exception) as e: if attempt == remaining_tries - 1: raise