# Buggy code
def close(self):
    """terminate the connection"""

    cache_key = self._cache_key()
    SSH_CONNECTION_CACHE.pop(cache_key, None)
    SFTP_CONNECTION_CACHE.pop(cache_key, None)

    if self.sftp is not None:
        self.sftp.close()

    if C.HOST_KEY_CHECKING and C.PARAMIKO_RECORD_HOST_KEYS and self._any_keys_added():
        # add any new SSH host keys -- warning -- this could be slow
        # (This doesn't acquire the connection lock because it needs
        # to exclude only other known_hosts writers, not connections
        # that are starting up.)
        lockfile = self.keyfile.replace("known_hosts", ".known_hosts.lock")
        dirname = os.path.dirname(self.keyfile)
        makedirs_safe(dirname)

        KEY_LOCK = open(lockfile, "w")
        fcntl.lockf(KEY_LOCK, fcntl.LOCK_EX)

        try:
            # just in case any were added recently

            self.ssh.load_system_host_keys()
            self.ssh._host_keys.update(self.ssh._system_host_keys)

            # gather information about the current key file, so
            # we can ensure the new file has the correct mode/owner

            key_dir = os.path.dirname(self.keyfile)
            key_stat = os.stat(self.keyfile)

            # Save the new keys to a temporary file and move it into place
            # rather than rewriting the file. We set delete=False because
            # the file will be moved into place rather than cleaned up.

            tmp_keyfile = tempfile.NamedTemporaryFile(dir=key_dir, delete=False)
            os.chmod(tmp_keyfile.name, key_stat.st_mode & 0o7777)
            os.chown(tmp_keyfile.name, key_stat.st_uid, key_stat.st_gid)

            self._save_ssh_host_keys(tmp_keyfile.name)
            tmp_keyfile.close()

            os.rename(tmp_keyfile.name, self.keyfile)

        except:
            # unable to save keys, including scenario when key was invalid
            # and caught earlier
            traceback.print_exc()
            pass
        fcntl.lockf(KEY_LOCK, fcntl.LOCK_UN)

    self.ssh.close()


# Traceback (OSError)
[ec2-user@some_host ~]$ ansible all -m ping

paramiko: The authenticity of host 'some_other_host_a' can't be established.
The ssh-rsa key fingerprint is some_fingerprint.
Are you sure you want to continue connecting (yes/no)?
yes

paramiko: The authenticity of host 'some_other_host_b' can't be established.
The ssh-rsa key fingerprint is some_other_fingerprint.
Are you sure you want to continue connecting (yes/no)?
Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/paramiko_ssh.py", line 393, in close
key_stat = os.stat(self.keyfile)
OSError: [Errno 2] No such file or directory: '/home/ec2-user/.ssh/known_hosts'

some_other_host_a | success >> {
"changed": false,
"ping": "pong"
}

Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/ansible/runner/connection_plugins/paramiko_ssh.py", line 393, in close
key_stat = os.stat(self.keyfile)
OSError: [Errno 2] No such file or directory: '/home/ec2-user/.ssh/known_hosts'
some_other_host_b | success >> {
"changed": false,
"ping": "pong"
}

# Fixed code
def close(self):
    """terminate the connection"""

    cache_key = self._cache_key()
    SSH_CONNECTION_CACHE.pop(cache_key, None)
    SFTP_CONNECTION_CACHE.pop(cache_key, None)

    if self.sftp is not None:
        self.sftp.close()

    if C.HOST_KEY_CHECKING and C.PARAMIKO_RECORD_HOST_KEYS and self._any_keys_added():
        # add any new SSH host keys -- warning -- this could be slow
        # (This doesn't acquire the connection lock because it needs
        # to exclude only other known_hosts writers, not connections
        # that are starting up.)
        lockfile = self.keyfile.replace("known_hosts", ".known_hosts.lock")
        dirname = os.path.dirname(self.keyfile)
        makedirs_safe(dirname)

        KEY_LOCK = open(lockfile, "w")
        fcntl.lockf(KEY_LOCK, fcntl.LOCK_EX)

        try:
            # just in case any were added recently

            self.ssh.load_system_host_keys()
            self.ssh._host_keys.update(self.ssh._system_host_keys)

            # gather information about the current key file, so
            # we can ensure the new file has the correct mode/owner

            key_dir = os.path.dirname(self.keyfile)
            if os.path.exists(self.keyfile):
                key_stat = os.stat(self.keyfile)
                mode = key_stat.st_mode
                uid = key_stat.st_uid
                gid = key_stat.st_gid
            else:
                mode = 33188
                uid = os.getuid()
                gid = os.getgid()

            # Save the new keys to a temporary file and move it into place
            # rather than rewriting the file. We set delete=False because
            # the file will be moved into place rather than cleaned up.

            tmp_keyfile = tempfile.NamedTemporaryFile(dir=key_dir, delete=False)
            os.chmod(tmp_keyfile.name, mode & 0o7777)
            os.chown(tmp_keyfile.name, uid, gid)

            self._save_ssh_host_keys(tmp_keyfile.name)
            tmp_keyfile.close()

            os.rename(tmp_keyfile.name, self.keyfile)

        except:
            # unable to save keys, including scenario when key was invalid
            # and caught earlier
            traceback.print_exc()
            pass
        fcntl.lockf(KEY_LOCK, fcntl.LOCK_UN)

    self.ssh.close()