@ -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):
''' 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):
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):
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 = Fals e, executable = ' /bin/sh ' , in_data = Non e, 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):
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 = Fals e, executable = ' /bin/sh ' , in_data = Non e) :
def exec_command ( self , cmd , in_data = None , sudoable = Fals e) :
''' 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):
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 )