|
|
|
@ -151,6 +151,9 @@ class Connection(object):
|
|
|
|
|
ssh_cmd = self._password_cmd()
|
|
|
|
|
ssh_cmd += ["ssh", "-C"]
|
|
|
|
|
if not in_data:
|
|
|
|
|
# we can only use tty when we are not pipelining the modules. piping data into /usr/bin/python
|
|
|
|
|
# inside a tty automatically invokes the python interactive-mode but the modules are not
|
|
|
|
|
# compatible with the interactive-mode ("unexpected indent" mainly because of empty lines)
|
|
|
|
|
ssh_cmd += ["-tt"]
|
|
|
|
|
if utils.VERBOSITY > 3:
|
|
|
|
|
ssh_cmd += ["-vvv"]
|
|
|
|
@ -201,30 +204,51 @@ class Connection(object):
|
|
|
|
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
|
stdin = p.stdin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self._send_password()
|
|
|
|
|
|
|
|
|
|
if self.runner.sudo and sudoable and self.runner.sudo_pass:
|
|
|
|
|
# several cases are handled for sudo privileges with password
|
|
|
|
|
# * NOPASSWD (tty & no-tty): detect success_key on stdout
|
|
|
|
|
# * without NOPASSWD:
|
|
|
|
|
# * detect prompt on stdout (tty)
|
|
|
|
|
# * detect prompt on stderr (no-tty)
|
|
|
|
|
fcntl.fcntl(p.stdout, fcntl.F_SETFL,
|
|
|
|
|
fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
|
|
|
|
|
fcntl.fcntl(p.stderr, fcntl.F_SETFL,
|
|
|
|
|
fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
|
|
|
|
|
sudo_output = ''
|
|
|
|
|
if in_data:
|
|
|
|
|
# no terminal => no prompt on output. process is waiting for sudo_pass
|
|
|
|
|
stdin.write(self.runner.sudo_pass + '\n')
|
|
|
|
|
sudo_errput = ''
|
|
|
|
|
|
|
|
|
|
while not sudo_output.endswith(prompt) and success_key not in sudo_output:
|
|
|
|
|
rfd, wfd, efd = select.select([p.stdout], [],
|
|
|
|
|
rfd, wfd, efd = select.select([p.stdout, p.stderr], [],
|
|
|
|
|
[p.stdout], self.runner.timeout)
|
|
|
|
|
if p.stderr in rfd:
|
|
|
|
|
chunk = p.stderr.read()
|
|
|
|
|
if not chunk:
|
|
|
|
|
raise errors.AnsibleError('ssh connection closed waiting for sudo password prompt')
|
|
|
|
|
sudo_errput += chunk
|
|
|
|
|
incorrect_password = gettext.dgettext(
|
|
|
|
|
"sudo", "Sorry, try again.")
|
|
|
|
|
if sudo_errput.strip().endswith("%s%s" % (prompt, incorrect_password)):
|
|
|
|
|
raise errors.AnsibleError('Incorrect sudo password')
|
|
|
|
|
elif sudo_errput.endswith(prompt):
|
|
|
|
|
stdin.write(self.runner.sudo_pass + '\n')
|
|
|
|
|
|
|
|
|
|
if p.stdout in rfd:
|
|
|
|
|
chunk = p.stdout.read()
|
|
|
|
|
if not chunk:
|
|
|
|
|
raise errors.AnsibleError('ssh connection closed waiting for sudo password prompt')
|
|
|
|
|
sudo_output += chunk
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
if not rfd:
|
|
|
|
|
# timeout. wrap up process communication
|
|
|
|
|
stdout = p.communicate()
|
|
|
|
|
raise errors.AnsibleError('ssh connection error waiting for sudo password prompt')
|
|
|
|
|
|
|
|
|
|
if success_key not in sudo_output:
|
|
|
|
|
stdin.write(self.runner.sudo_pass + '\n')
|
|
|
|
|
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
|
|
|
|
|
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) & ~os.O_NONBLOCK)
|
|
|
|
|
# We can't use p.communicate here because the ControlMaster may have stdout open as well
|
|
|
|
|
stdout = ''
|
|
|
|
|
stderr = ''
|
|
|
|
|