Skip to content

Instantly share code, notes, and snippets.

@cayblood
Created August 27, 2013 09:50
Show Gist options
  • Save cayblood/6351639 to your computer and use it in GitHub Desktop.
Save cayblood/6351639 to your computer and use it in GitHub Desktop.
diff -ru ../ansible/lib/ansible/runner/connection_plugins/ssh.py .env/lib/python2.7/site-packages/ansible/runner/connection_plugins/ssh.py
--- ../ansible/lib/ansible/runner/connection_plugins/ssh.py 2013-08-27 10:03:22.000000000 +0100
+++ .env/lib/python2.7/site-packages/ansible/runner/connection_plugins/ssh.py 2013-08-27 10:42:00.000000000 +0100
@@ -181,65 +181,75 @@
p = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdin = p.stdin
+ try:
+ self._send_password()
- self._send_password()
+ if self.runner.sudo and sudoable and self.runner.sudo_pass:
+ fcntl.fcntl(p.stdout, fcntl.F_SETFL,
+ fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
+ sudo_output = ''
+ while not sudo_output.endswith(prompt):
+ rfd, wfd, efd = select.select([p.stdout], [],
+ [p.stdout], self.runner.timeout)
+ 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:
+ stdout = p.communicate()
+ raise errors.AnsibleError('ssh connection error waiting for sudo password prompt')
+ stdin.write(self.runner.sudo_pass + '\n')
+ fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
+
+ # We can't use p.communicate here because the ControlMaster may have stdout open as well
+ stdout = ''
+ stderr = ''
+ while True:
+ rfd, wfd, efd = select.select([p.stdout, p.stderr], [], [p.stdout, p.stderr], 1)
+
+ # fail early if the sudo password is wrong
+ if self.runner.sudo and sudoable and self.runner.sudo_pass:
+ incorrect_password = gettext.dgettext(
+ "sudo", "Sorry, try again.")
+ if stdout.endswith("%s\r\n%s" % (incorrect_password, prompt)):
+ raise errors.AnsibleError('Incorrect sudo password')
- if self.runner.sudo and sudoable and self.runner.sudo_pass:
- fcntl.fcntl(p.stdout, fcntl.F_SETFL,
- fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
- sudo_output = ''
- while not sudo_output.endswith(prompt):
- rfd, wfd, efd = select.select([p.stdout], [],
- [p.stdout], self.runner.timeout)
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:
- stdout = p.communicate()
- raise errors.AnsibleError('ssh connection error waiting for sudo password prompt')
- stdin.write(self.runner.sudo_pass + '\n')
- fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
-
- # We can't use p.communicate here because the ControlMaster may have stdout open as well
- stdout = ''
- stderr = ''
- while True:
- rfd, wfd, efd = select.select([p.stdout, p.stderr], [], [p.stdout, p.stderr], 1)
-
- # fail early if the sudo password is wrong
- if self.runner.sudo and sudoable and self.runner.sudo_pass:
- incorrect_password = gettext.dgettext(
- "sudo", "Sorry, try again.")
- if stdout.endswith("%s\r\n%s" % (incorrect_password, prompt)):
- raise errors.AnsibleError('Incorrect sudo password')
-
- if p.stdout in rfd:
- dat = os.read(p.stdout.fileno(), 9000)
- stdout += dat
- if dat == '':
- p.wait()
+ dat = os.read(p.stdout.fileno(), 9000)
+ stdout += dat
+ if dat == '':
+ p.wait()
+ break
+ elif p.stderr in rfd:
+ dat = os.read(p.stderr.fileno(), 9000)
+ stderr += dat
+ if dat == '':
+ p.wait()
+ break
+ elif p.poll() is not None:
break
- elif p.stderr in rfd:
- dat = os.read(p.stderr.fileno(), 9000)
- stderr += dat
- if dat == '':
- p.wait()
- break
- 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.
- fcntl.lockf(self.runner.output_lockfile, fcntl.LOCK_UN)
- fcntl.lockf(self.runner.process_lockfile, fcntl.LOCK_UN)
-
- 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')
-
+ 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.
+ fcntl.lockf(self.runner.output_lockfile, fcntl.LOCK_UN)
+ fcntl.lockf(self.runner.process_lockfile, fcntl.LOCK_UN)
+
+ 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')
+ finally:
+ print master
+ if master:
+ try:
+ os.close(master)
+ except:
+ pass
+ try:
+ os.close(slave)
+ except:
+ pass
return (p.returncode, '', stdout, stderr)
def put_file(self, in_path, out_path):
@jimi-c
Copy link

jimi-c commented Aug 27, 2013

Ahh that's interesting, it's not closing the pty. Could you send this as a pull request?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment