summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Borean <jborean93@gmail.com>2019-03-05 11:31:00 +1000
committerToshio Kuratomi <a.badger@gmail.com>2019-03-06 14:28:06 -0800
commitbfe072c9dcb6dc1739ea86f46f6f47c0536377c6 (patch)
tree67bd94d8cd2fe89fd35afa260a0aa9e428876df8
parented12e93f73886b155c556caa35cf6d7d79183289 (diff)
downloadansible-bfe072c9dcb6dc1739ea86f46f6f47c0536377c6.tar.gz
winrm - try and recover from a send input failure (#53187)
(cherry picked from commit ae24bbff4abf7dce43026f18bf113c2f76ba8301)
-rw-r--r--changelogs/fragments/winrm-send-input-check.yaml2
-rw-r--r--lib/ansible/plugins/connection/winrm.py23
2 files changed, 19 insertions, 6 deletions
diff --git a/changelogs/fragments/winrm-send-input-check.yaml b/changelogs/fragments/winrm-send-input-check.yaml
new file mode 100644
index 0000000000..50d2a2ee0d
--- /dev/null
+++ b/changelogs/fragments/winrm-send-input-check.yaml
@@ -0,0 +1,2 @@
+bugfixes:
+- winrm - attempt to recover from a WinRM send input failure if possible
diff --git a/lib/ansible/plugins/connection/winrm.py b/lib/ansible/plugins/connection/winrm.py
index 55fb2dbfee..1f38ad4a7c 100644
--- a/lib/ansible/plugins/connection/winrm.py
+++ b/lib/ansible/plugins/connection/winrm.py
@@ -114,6 +114,7 @@ except ImportError:
from ansible.errors import AnsibleError, AnsibleConnectionFailure
from ansible.errors import AnsibleFileNotFound
+from ansible.module_utils.json_utils import _filter_non_json_lines
from ansible.module_utils.parsing.convert_bool import boolean
from ansible.module_utils.six.moves.urllib.parse import urlunsplit
from ansible.module_utils._text import to_bytes, to_native, to_text
@@ -453,7 +454,9 @@ class Connection(ConnectionBase):
self._winrm_send_input(self.protocol, self.shell_id, command_id, data, eof=is_last)
except Exception as ex:
- display.warning("FATAL ERROR DURING FILE TRANSFER: %s" % to_text(ex))
+ display.warning("ERROR DURING WINRM SEND INPUT - attempting to recover: %s %s"
+ % (type(ex).__name__, to_text(ex)))
+ display.debug(traceback.format_exc())
stdin_push_failed = True
# NB: this can hang if the receiver is still running (eg, network failed a Send request but the server's still happy).
@@ -473,11 +476,19 @@ class Connection(ConnectionBase):
display.vvvvvv('WINRM STDERR %s' % to_text(response.std_err), host=self._winrm_host)
if stdin_push_failed:
- stderr = to_bytes(response.std_err, encoding='utf-8')
- if self.is_clixml(stderr):
- stderr = self.parse_clixml_stream(stderr)
-
- raise AnsibleError('winrm send_input failed; \nstdout: %s\nstderr %s' % (to_native(response.std_out), to_native(stderr)))
+ # There are cases where the stdin input failed but the WinRM service still processed it. We attempt to
+ # see if stdout contains a valid json return value so we can ignore this error
+ try:
+ filtered_output, dummy = _filter_non_json_lines(response.std_out)
+ json.loads(filtered_output)
+ except ValueError:
+ # stdout does not contain a return response, stdin input was a fatal error
+ stderr = to_bytes(response.std_err, encoding='utf-8')
+ if self.is_clixml(stderr):
+ stderr = self.parse_clixml_stream(stderr)
+
+ raise AnsibleError('winrm send_input failed; \nstdout: %s\nstderr %s'
+ % (to_native(response.std_out), to_native(stderr)))
return response
except requests.exceptions.ConnectionError as exc: