summaryrefslogtreecommitdiff
path: root/lib/ansible/plugins/connection/ssh.py
diff options
context:
space:
mode:
authorToshio Kuratomi <toshio@fedoraproject.org>2015-12-03 08:01:05 -0800
committerToshio Kuratomi <toshio@fedoraproject.org>2015-12-03 08:01:05 -0800
commite201a255d17a72b338be92b8db881effb79b5ece (patch)
tree5ccab78637b70d820479703150671079ce5e3bac /lib/ansible/plugins/connection/ssh.py
parentfbb63d66e79a772642aea4db050401cc89332fac (diff)
downloadansible-e201a255d17a72b338be92b8db881effb79b5ece.tar.gz
Revert "Make sudo+requiretty and ANSIBLE_PIPELINING work together"
This reverts commit f488de85997079f480d504f73537e3e33ff2495b. Reverting for now due to hard to pin down bugs: #13410 #13411
Diffstat (limited to 'lib/ansible/plugins/connection/ssh.py')
-rw-r--r--lib/ansible/plugins/connection/ssh.py43
1 files changed, 32 insertions, 11 deletions
diff --git a/lib/ansible/plugins/connection/ssh.py b/lib/ansible/plugins/connection/ssh.py
index 607dcd667f..debe36bd32 100644
--- a/lib/ansible/plugins/connection/ssh.py
+++ b/lib/ansible/plugins/connection/ssh.py
@@ -241,7 +241,7 @@ class Connection(ConnectionBase):
return self._command
- def _send_initial_data(self, fh, in_data, tty=False):
+ def _send_initial_data(self, fh, in_data):
'''
Writes initial data to the stdin filehandle of the subprocess and closes
it. (The handle must be closed; otherwise, for example, "sftp -b -" will
@@ -252,8 +252,6 @@ class Connection(ConnectionBase):
try:
fh.write(in_data)
- if tty:
- fh.write("__EOF__942d747a0772c3284ffb5920e234bd57__\n")
fh.close()
except (OSError, IOError):
raise AnsibleConnectionFailure('SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh')
@@ -316,7 +314,7 @@ class Connection(ConnectionBase):
return ''.join(output), remainder
- def _run(self, cmd, in_data, sudoable=True, tty=False):
+ def _run(self, cmd, in_data, sudoable=True):
'''
Starts the command and communicates with it until it ends.
'''
@@ -324,10 +322,25 @@ class Connection(ConnectionBase):
display_cmd = map(pipes.quote, cmd[:-1]) + [cmd[-1]]
display.vvv('SSH: EXEC {0}'.format(' '.join(display_cmd)), host=self.host)
- # Start the given command.
+ # Start the given command. If we don't need to pipeline data, we can try
+ # to use a pseudo-tty (ssh will have been invoked with -tt). If we are
+ # pipelining data, or can't create a pty, we fall back to using plain
+ # old pipes.
- p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- stdin = p.stdin
+ p = None
+ if not in_data:
+ try:
+ # Make sure stdin is a proper pty to avoid tcgetattr errors
+ master, slave = pty.openpty()
+ p = subprocess.Popen(cmd, stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdin = os.fdopen(master, 'w', 0)
+ os.close(slave)
+ except (OSError, IOError):
+ p = None
+
+ if not p:
+ p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdin = p.stdin
# If we are using SSH password authentication, write the password into
# the pipe we opened in _build_command.
@@ -390,7 +403,7 @@ class Connection(ConnectionBase):
# before we call select.
if states[state] == 'ready_to_send' and in_data:
- self._send_initial_data(stdin, in_data, tty)
+ self._send_initial_data(stdin, in_data)
state += 1
while True:
@@ -488,7 +501,7 @@ class Connection(ConnectionBase):
if states[state] == 'ready_to_send':
if in_data:
- self._send_initial_data(stdin, in_data, tty)
+ self._send_initial_data(stdin, in_data)
state += 1
# Now we're awaiting_exit: has the child process exited? If it has,
@@ -544,9 +557,17 @@ class Connection(ConnectionBase):
display.vvv("ESTABLISH SSH CONNECTION FOR USER: {0}".format(self._play_context.remote_user), host=self._play_context.remote_addr)
- cmd = self._build_command('ssh', '-tt', self.host, cmd)
+ # 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)
+
+ if in_data:
+ cmd = self._build_command('ssh', self.host, cmd)
+ else:
+ cmd = self._build_command('ssh', '-tt', self.host, cmd)
- (returncode, stdout, stderr) = self._run(cmd, in_data, sudoable=sudoable, tty=True)
+ (returncode, stdout, stderr) = self._run(cmd, in_data, sudoable=sudoable)
return (returncode, stdout, stderr)