From a928ea4d937de6d54b42f455705c262100b72022 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Tue, 27 Nov 2018 16:48:57 -0500 Subject: [PATCH] [stable-2.7] Reboot - Fix errors when using Paramiko connection (#49002) Different connection plugins return different data when throwing exceptions. The Paramiko connection plugin does not return a text sting, which caused an exception. The ssh connection plugin returns multi-line errors, which makes the debug logs harder to read. Only return the last line in that case in order to make the logs more readable. When experiencing a connection failure, reset the connection. Add reset() to paramiko_ssh Indicate thet conection state is False when running close(). This is needed by the ensure_connected() decorator to work properly. Co-authored-by: Matt Martz (cherry picked from commit 5eb7f5781e) Co-authored-by: Sam Doran --- lib/ansible/plugins/action/reboot.py | 11 ++++++++++- lib/ansible/plugins/connection/paramiko_ssh.py | 7 ++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/ansible/plugins/action/reboot.py b/lib/ansible/plugins/action/reboot.py index fe22b92adb9..160ef9bce11 100644 --- a/lib/ansible/plugins/action/reboot.py +++ b/lib/ansible/plugins/action/reboot.py @@ -175,6 +175,11 @@ class ActionModule(ActionBase): display.debug('%s: %s success' % (self._task.action, action_desc)) return except Exception as e: + if isinstance(e, AnsibleConnectionFailure): + try: + self._connection.reset() + except AnsibleConnectionFailure: + pass # Use exponential backoff with a max timout, plus a little bit of randomness random_int = random.randint(0, 1000) / 1000 fail_sleep = 2 ** fail_count + random_int @@ -182,8 +187,12 @@ class ActionModule(ActionBase): fail_sleep = max_fail_sleep + random_int if action_desc: + try: + error = to_text(e).splitlines()[-1] + except TypeError as e: + error = to_text(e) display.debug("{0}: {1} fail '{2}', retrying in {3:.4} seconds...".format(self._task.action, action_desc, - to_text(e).splitlines()[-1], fail_sleep)) + error, fail_sleep)) fail_count += 1 time.sleep(fail_sleep) diff --git a/lib/ansible/plugins/connection/paramiko_ssh.py b/lib/ansible/plugins/connection/paramiko_ssh.py index 1c02b9c0e7d..36d7f0c0b50 100644 --- a/lib/ansible/plugins/connection/paramiko_ssh.py +++ b/lib/ansible/plugins/connection/paramiko_ssh.py @@ -530,6 +530,10 @@ class Connection(ConnectionBase): f.close() + def reset(self): + self.close() + self._connect() + def close(self): ''' terminate the connection ''' @@ -587,7 +591,7 @@ class Connection(ConnectionBase): os.rename(tmp_keyfile.name, self.keyfile) - except: + except Exception: # unable to save keys, including scenario when key was invalid # and caught earlier @@ -595,3 +599,4 @@ class Connection(ConnectionBase): fcntl.lockf(KEY_LOCK, fcntl.LOCK_UN) self.ssh.close() + self._connected = False