diff --git a/lib/ansible/runner/connection_plugins/ssh.py b/lib/ansible/runner/connection_plugins/ssh.py index 3a00e97b2f..ab65e0999a 100644 --- a/lib/ansible/runner/connection_plugins/ssh.py +++ b/lib/ansible/runner/connection_plugins/ssh.py @@ -93,6 +93,22 @@ class Connection(object): os.write(self.wfd, "%s\n" % self.password) os.close(self.wfd) + def not_in_host_file(self, host): + host_file = os.path.expanduser("~/.ssh/known_hosts") + if not os.path.exists(host_file): + print "previous known host file not found" + return True + host_fh = open(host_file) + data = host_fh.read() + host_fh.close() + for line in data.split("\n"): + if line is None or line.find(" ") == -1: + continue + tokens = line.split() + if host in tokens[0]: + return False + return True + def exec_command(self, cmd, tmp_path, sudo_user,sudoable=False, executable='/bin/sh'): ''' run a command on the remote host ''' @@ -109,6 +125,16 @@ class Connection(object): ssh_cmd.append(sudocmd) vvv("EXEC %s" % ssh_cmd, host=self.host) + + not_in_host_file = self.not_in_host_file(self.host) + + if C.HOST_KEY_CHECKING and not_in_host_file: + # lock around the initial SSH connectivity so the user prompt about whether to add + # the host to known hosts is not intermingled with multiprocess output. + KEY_LOCK = self.runner.lockfile + fcntl.lockf(KEY_LOCK, fcntl.LOCK_EX) + + try: # Make sure stdin is a proper (pseudo) pty to avoid: tcgetattr errors import pty @@ -161,6 +187,12 @@ class Connection(object): elif p.poll() is not None: break stdin.close() # close stdin after we read from stdout (see also issue #848) + + if C.HOST_KEY_CHECKING and not_in_host_file: + # lock around the initial SSH connectivity so the user prompt about whether to add + # the host to known hosts is not intermingled with multiprocess output. + KEY_LOCK = self.runner.lockfile + fcntl.lockf(KEY_LOCK, fcntl.LOCK_EX) if p.returncode != 0 and stderr.find('Bad configuration option: ControlPersist') != -1: raise errors.AnsibleError('using -c ssh on certain older ssh versions may not support ControlPersist, set ANSIBLE_SSH_ARGS="" (or ansible_ssh_args in the config file) before running again')