Commit 342bc973 by Toshio Kuratomi

Port chroot conection plugin to the latest v2 connection API.

Also get pipelining working for people who look to chroot as an example
for their own connection plugins

Note: In the latest v2 API, action handles become but chroot doesn't
reliably handle become.  Maybe we need to add a has_become attribute
that the action can display an appropriate error.
parent 056a0203
...@@ -28,7 +28,7 @@ import traceback ...@@ -28,7 +28,7 @@ import traceback
from ansible import constants as C from ansible import constants as C
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
from ansible.utils.path import is_executable from ansible.module_utils.basic import is_executable
from ansible.utils.unicode import to_bytes from ansible.utils.unicode import to_bytes
...@@ -36,11 +36,12 @@ class Connection(ConnectionBase): ...@@ -36,11 +36,12 @@ class Connection(ConnectionBase):
''' Local chroot based connections ''' ''' Local chroot based connections '''
BUFSIZE = 65536 BUFSIZE = 65536
has_pipelining = False has_pipelining = True
transport = 'chroot'
def __init__(self, *args, **kwargs): def __init__(self, play_context, new_stdin, *args, **kwargs):
super(Connection, self).__init__(*args, **kwargs) super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
self.chroot = self._play_context.remote_addr self.chroot = self._play_context.remote_addr
...@@ -60,11 +61,6 @@ class Connection(ConnectionBase): ...@@ -60,11 +61,6 @@ class Connection(ConnectionBase):
if not self.chroot_cmd: if not self.chroot_cmd:
raise AnsibleError("chroot command not found in PATH") raise AnsibleError("chroot command not found in PATH")
@property
def transport(self):
''' used to identify this connection object '''
return 'chroot'
def _connect(self, port=None): def _connect(self, port=None):
''' connect to the chroot; nothing to do here ''' ''' connect to the chroot; nothing to do here '''
...@@ -72,18 +68,13 @@ class Connection(ConnectionBase): ...@@ -72,18 +68,13 @@ class Connection(ConnectionBase):
return self return self
def _generate_cmd(self, executable, cmd): def _generate_cmd(self, cmd, executable):
if executable: # subprocess takes byte strings
local_cmd = [self.chroot_cmd, self.chroot, executable, '-c', cmd] local_cmd = [self.chroot_cmd, self.chroot, executable, '-c']
else: local_cmd.append(cmd)
# Prev to python2.7.3, shlex couldn't handle unicode type strings
cmd = to_bytes(cmd)
cmd = shlex.split(cmd)
local_cmd = [self.chroot_cmd, self.chroot]
local_cmd += cmd
return local_cmd return local_cmd
def _buffered_exec_command(self, cmd, become_user=None, sudoable=False, executable='/bin/sh', in_data=None, stdin=subprocess.PIPE): def _buffered_exec_command(self, cmd, in_data=None, sudoable=False, stdin=subprocess.PIPE):
''' run a command on the chroot. This is only needed for implementing ''' run a command on the chroot. This is only needed for implementing
put_file() get_file() so that we don't have to read the whole file put_file() get_file() so that we don't have to read the whole file
into memory. into memory.
...@@ -91,35 +82,29 @@ class Connection(ConnectionBase): ...@@ -91,35 +82,29 @@ class Connection(ConnectionBase):
compared to exec_command() it looses some niceties like being able to compared to exec_command() it looses some niceties like being able to
return the process's exit code immediately. return the process's exit code immediately.
''' '''
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh'
if sudoable and self._play_context.become and self._play_context.become_method not in self.become_methods_supported: local_cmd = self._generate_cmd(cmd, executable)
raise AnsibleError("Internal Error: this module does not support running commands via %s" % self._play_context.become_method)
if in_data:
raise AnsibleError("Internal Error: this module does not support optimized module pipelining")
# We enter zone as root so we ignore privilege escalation (probably need to fix in case we have to become a specific used [ex: postgres admin])?
local_cmd = self._generate_cmd(executable, cmd)
self._display.vvv("EXEC %s" % (local_cmd), host=self.chroot) self._display.vvv("EXEC %s" % (local_cmd), host=self.chroot)
# FIXME: cwd= needs to be set to the basedir of the playbook, which # FIXME: cwd= needs to be set to the basedir of the playbook, which
# should come from loader, but is not in the connection plugins # should come from loader, but is not in the connection plugins
p = subprocess.Popen(local_cmd, shell=False, p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return p return p
def exec_command(self, cmd, become_user=None, sudoable=False, executable='/bin/sh', in_data=None): def exec_command(self, cmd, in_data=None, sudoable=False):
''' run a command on the chroot ''' ''' run a command on the chroot '''
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
p = self._buffered_exec_command(cmd, become_user, sudoable, executable, in_data) p = self._buffered_exec_command(cmd, in_data, sudoable)
stdout, stderr = p.communicate() stdout, stderr = p.communicate(in_data)
return (p.returncode, stdout, stderr) return (p.returncode, stdout, stderr)
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
''' transfer a file from local to chroot ''' ''' transfer a file from local to chroot '''
super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot) self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot)
...@@ -141,6 +126,7 @@ class Connection(ConnectionBase): ...@@ -141,6 +126,7 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
''' fetch a file from chroot to local ''' ''' fetch a file from chroot to local '''
super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot) self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment