diff --git a/lib/ansible/plugins/connections/local.py b/lib/ansible/plugins/connections/local.py index 74df551f13..3655cb5b6d 100644 --- a/lib/ansible/plugins/connections/local.py +++ b/lib/ansible/plugins/connections/local.py @@ -22,8 +22,8 @@ import traceback import os import shutil import subprocess -#import select -#import fcntl +import select +import fcntl import ansible.constants as C @@ -51,18 +51,17 @@ class Connection(ConnectionBase): def exec_command(self, cmd, tmp_path, in_data=None, sudoable=True): ''' run a command on the local host ''' - super(Connection, self).exec_command(cmd, tmp_path, in_data=in_data) + super(Connection, self).exec_command(cmd, tmp_path, in_data=in_data, sudoable=sudoable) debug("in local.exec_command()") - # su requires to be run from a terminal, and therefore isn't supported here (yet?) - #if self._connection_info.su: - # raise AnsibleError("Internal Error: this module does not support running commands via su") if in_data: raise AnsibleError("Internal Error: this module does not support optimized module pipelining") - executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else None + if sudoable: + cmd, self.prompt, self.success_key = self._connection_info.make_become_cmd(cmd) + self._display.vvv("{0} EXEC {1}".format(self._connection_info.remote_addr, cmd)) # FIXME: cwd= needs to be set to the basedir of the playbook debug("opening command with Popen()") @@ -76,31 +75,28 @@ class Connection(ConnectionBase): ) debug("done running command with Popen()") - # FIXME: more su/sudo stuff - #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) - # fcntl.fcntl(p.stderr, fcntl.F_SETFL, - # fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK) - # sudo_output = '' - # while not sudo_output.endswith(prompt) and success_key not in sudo_output: - # rfd, wfd, efd = select.select([p.stdout, p.stderr], [], - # [p.stdout, p.stderr], self.runner.timeout) - # if p.stdout in rfd: - # chunk = p.stdout.read() - # elif p.stderr in rfd: - # chunk = p.stderr.read() - # else: - # stdout, stderr = p.communicate() - # raise AnsibleError('timeout waiting for sudo password prompt:\n' + sudo_output) - # if not chunk: - # stdout, stderr = p.communicate() - # raise AnsibleError('sudo output closed while waiting for password prompt:\n' + sudo_output) - # sudo_output += chunk - # if success_key not in sudo_output: - # p.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) + if self.prompt: + 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) + become_output = '' + while not self.check_become_success(become_output) and not self.check_password_prompt(become_output): + + rfd, wfd, efd = select.select([p.stdout, p.stderr], [], [p.stdout, p.stderr], self._connection_info.timeout) + if p.stdout in rfd: + chunk = p.stdout.read() + elif p.stderr in rfd: + chunk = p.stderr.read() + else: + stdout, stderr = p.communicate() + raise AnsibleError('timeout waiting for privilege escalation password prompt:\n' + become_output) + if not chunk: + stdout, stderr = p.communicate() + raise AnsibleError('privilege output closed while waiting for password prompt:\n' + become_output) + become_output += chunk + if not self.check_become_success(become_output): + p.stdin.write(self._connection_info.become_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) debug("getting output with communicate()") stdout, stderr = p.communicate()