2012-06-17 11:35:59 +00:00
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
import os
2014-05-23 15:06:09 +00:00
import re
2012-06-17 11:35:59 +00:00
import subprocess
import shlex
import pipes
import random
import select
import fcntl
2013-08-02 16:08:02 +00:00
import hmac
2013-03-27 20:41:54 +00:00
import pwd
2013-08-08 15:02:52 +00:00
import gettext
2013-09-16 21:19:39 +00:00
import pty
2013-08-02 16:08:02 +00:00
from hashlib import sha1
2012-08-15 00:13:02 +00:00
import ansible . constants as C
2012-08-09 01:09:14 +00:00
from ansible . callbacks import vvv
2012-06-17 11:35:59 +00:00
from ansible import errors
2013-01-10 05:50:56 +00:00
from ansible import utils
2012-06-17 11:35:59 +00:00
2012-08-18 14:52:24 +00:00
class Connection ( object ) :
2012-06-17 11:35:59 +00:00
''' ssh based connections '''
2013-04-05 18:42:18 +00:00
def __init__ ( self , runner , host , port , user , password , private_key_file , * args , * * kwargs ) :
2012-06-17 11:35:59 +00:00
self . runner = runner
self . host = host
2013-08-18 21:08:35 +00:00
self . ipv6 = ' : ' in self . host
2012-06-17 11:35:59 +00:00
self . port = port
2014-05-13 09:29:19 +00:00
self . user = str ( user )
2013-02-10 22:22:18 +00:00
self . password = password
2013-03-19 16:28:43 +00:00
self . private_key_file = private_key_file
2013-08-02 16:08:02 +00:00
self . HASHED_KEY_MAGIC = " |1| "
2014-01-15 21:44:28 +00:00
self . has_pipelining = True
2012-06-17 11:35:59 +00:00
2013-09-03 15:59:50 +00:00
fcntl . lockf ( self . runner . process_lockfile , fcntl . LOCK_EX )
self . cp_dir = utils . prepare_writeable_dir ( ' $HOME/.ansible/cp ' , mode = 0700 )
fcntl . lockf ( self . runner . process_lockfile , fcntl . LOCK_UN )
2012-06-17 11:35:59 +00:00
def connect ( self ) :
''' connect to the remote host '''
2012-07-15 16:29:53 +00:00
2013-02-10 22:22:18 +00:00
vvv ( " ESTABLISH CONNECTION FOR USER: %s " % self . user , host = self . host )
2012-08-11 21:33:34 +00:00
2012-06-26 18:59:42 +00:00
self . common_args = [ ]
2012-08-15 00:13:02 +00:00
extra_args = C . ANSIBLE_SSH_ARGS
2012-06-17 11:35:59 +00:00
if extra_args is not None :
Clean a bit more the ssh_args configuration
If someone add ssh_args = " " to his .ansible.cfg, it will result into
strange failure later :
<server.example.org> ESTABLISH CONNECTION FOR USER: misc
<server.example.org> REMOTE_MODULE ping
<server.example.org> EXEC ['ssh', '-C', '-tt', '-q', ' ', '-o', 'KbdInteractiveAuthentication=no',
'-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no',
'-o', 'ConnectTimeout=10', 'server.example.org', "/bin/sh -c 'mkdir -p /tmp/ansible-tmp-1397947711.21-5932460998838
&& chmod a+rx /tmp/ansible-tmp-1397947711.21-5932460998838 && echo /tmp/ansible-tmp-1397947711.21-5932460998838'"]
server.example.org | FAILED => SSH encountered an unknown error during the connection. We recommend you re-run the
command using -vvvv, which will enable SSH debugging output to help diagnose the issue
The root cause is the empty string between -q and -o, who kinda break mkdir.
2014-04-19 22:47:00 +00:00
# make sure there is no empty string added as this can produce weird errors
self . common_args + = [ x . strip ( ) for x in shlex . split ( extra_args ) if x . strip ( ) ]
2012-06-19 19:58:24 +00:00
else :
self . common_args + = [ " -o " , " ControlMaster=auto " ,
" -o " , " ControlPersist=60s " ,
2014-10-22 22:45:02 +00:00
" -o " , " ControlPath= \" %s \" " % ( C . ANSIBLE_SSH_CONTROL_PATH % dict ( directory = self . cp_dir ) ) ]
2013-08-20 17:03:50 +00:00
cp_in_use = False
cp_path_set = False
for arg in self . common_args :
2014-01-23 15:02:17 +00:00
if " ControlPersist " in arg :
2013-08-20 17:03:50 +00:00
cp_in_use = True
2014-01-23 15:02:17 +00:00
if " ControlPath " in arg :
2013-08-20 17:03:50 +00:00
cp_path_set = True
if cp_in_use and not cp_path_set :
2014-10-22 22:45:02 +00:00
self . common_args + = [ " -o " , " ControlPath= \" %s \" " % ( C . ANSIBLE_SSH_CONTROL_PATH % dict ( directory = self . cp_dir ) ) ]
2013-07-03 20:47:20 +00:00
if not C . HOST_KEY_CHECKING :
self . common_args + = [ " -o " , " StrictHostKeyChecking=no " ]
2012-06-26 18:59:42 +00:00
if self . port is not None :
self . common_args + = [ " -o " , " Port= %d " % ( self . port ) ]
2013-03-19 16:28:43 +00:00
if self . private_key_file is not None :
2014-06-10 19:39:47 +00:00
self . common_args + = [ " -o " , " IdentityFile= \" %s \" " % os . path . expanduser ( self . private_key_file ) ]
2013-03-19 16:28:43 +00:00
elif self . runner . private_key_file is not None :
2014-06-10 19:39:47 +00:00
self . common_args + = [ " -o " , " IdentityFile= \" %s \" " % os . path . expanduser ( self . runner . private_key_file ) ]
2013-02-10 22:22:18 +00:00
if self . password :
2012-11-27 09:51:35 +00:00
self . common_args + = [ " -o " , " GSSAPIAuthentication=no " ,
" -o " , " PubkeyAuthentication=no " ]
else :
self . common_args + = [ " -o " , " KbdInteractiveAuthentication=no " ,
2013-09-06 08:29:43 +00:00
" -o " , " PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey " ,
2012-11-27 09:51:35 +00:00
" -o " , " PasswordAuthentication=no " ]
2014-07-21 15:32:43 +00:00
if self . user != pwd . getpwuid ( os . geteuid ( ) ) [ 0 ] :
self . common_args + = [ " -o " , " User= " + self . user ]
2013-02-10 22:22:18 +00:00
self . common_args + = [ " -o " , " ConnectTimeout= %d " % self . runner . timeout ]
2012-06-17 11:35:59 +00:00
return self
2014-03-21 20:52:07 +00:00
def _run ( self , cmd , indata ) :
if indata :
# do not use pseudo-pty
p = subprocess . Popen ( cmd , stdin = subprocess . PIPE ,
stdout = subprocess . PIPE , stderr = subprocess . PIPE )
stdin = p . stdin
else :
# try to use upseudo-pty
try :
# Make sure stdin is a proper (pseudo) 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 :
p = subprocess . Popen ( cmd , stdin = subprocess . PIPE ,
stdout = subprocess . PIPE , stderr = subprocess . PIPE )
stdin = p . stdin
return ( p , stdin )
2012-11-16 22:42:19 +00:00
def _password_cmd ( self ) :
2013-02-10 22:22:18 +00:00
if self . password :
2012-11-16 22:42:19 +00:00
try :
p = subprocess . Popen ( [ " sshpass " ] , stdin = subprocess . PIPE ,
stdout = subprocess . PIPE , stderr = subprocess . PIPE )
p . communicate ( )
except OSError :
2013-07-19 13:09:04 +00:00
raise errors . AnsibleError ( " to use the ' ssh ' connection type with passwords, you must install the sshpass program " )
2012-11-16 22:42:19 +00:00
( self . rfd , self . wfd ) = os . pipe ( )
return [ " sshpass " , " -d %d " % self . rfd ]
return [ ]
def _send_password ( self ) :
2013-02-10 22:22:18 +00:00
if self . password :
2012-11-16 22:42:19 +00:00
os . close ( self . rfd )
2013-02-10 22:22:18 +00:00
os . write ( self . wfd , " %s \n " % self . password )
2012-11-16 22:42:19 +00:00
os . close ( self . wfd )
2014-03-26 19:55:54 +00:00
def _communicate ( self , p , stdin , indata , su = False , sudoable = False , prompt = None ) :
2014-03-21 20:52:07 +00:00
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 )
# We can't use p.communicate here because the ControlMaster may have stdout open as well
stdout = ' '
stderr = ' '
rpipes = [ p . stdout , p . stderr ]
if indata :
try :
stdin . write ( indata )
stdin . close ( )
except :
raise errors . AnsibleError ( ' SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh ' )
2014-02-25 23:02:42 +00:00
# Read stdout/stderr from process
2014-03-21 20:52:07 +00:00
while True :
rfd , wfd , efd = select . select ( rpipes , [ ] , rpipes , 1 )
# fail early if the sudo/su password is wrong
2014-01-30 13:54:03 +00:00
if self . runner . sudo and sudoable :
if 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 stdout . endswith ( prompt ) :
raise errors . AnsibleError ( ' Missing sudo password ' )
2014-03-21 20:52:07 +00:00
2014-03-31 11:20:00 +00:00
if self . runner . su and su and self . runner . su_pass :
2014-03-21 20:52:07 +00:00
incorrect_password = gettext . dgettext (
" su " , " Sorry " )
if stdout . endswith ( " %s \r \n %s " % ( incorrect_password , prompt ) ) :
raise errors . AnsibleError ( ' Incorrect su password ' )
if p . stdout in rfd :
dat = os . read ( p . stdout . fileno ( ) , 9000 )
stdout + = dat
if dat == ' ' :
rpipes . remove ( p . stdout )
if p . stderr in rfd :
dat = os . read ( p . stderr . fileno ( ) , 9000 )
stderr + = dat
if dat == ' ' :
rpipes . remove ( p . stderr )
2014-02-25 23:02:42 +00:00
# only break out if no pipes are left to read or
# the pipes are completely read and
# the process is terminated
2014-03-21 20:52:07 +00:00
if ( not rpipes or not rfd ) and p . poll ( ) is not None :
break
2014-02-25 23:02:42 +00:00
# No pipes are left to read but process is not yet terminated
# Only then it is safe to wait for the process to be finished
# NOTE: Actually p.poll() is always None here if rpipes is empty
2014-03-21 20:52:07 +00:00
elif not rpipes and p . poll ( ) == None :
p . wait ( )
2014-02-25 23:02:42 +00:00
# The process is terminated. Since no pipes to read from are
# left, there is no need to call select() again.
2014-03-21 20:52:07 +00:00
break
2014-02-25 23:02:42 +00:00
# close stdin after process is terminated and stdout/stderr are read
# completely (see also issue #848)
stdin . close ( )
2014-03-21 20:52:07 +00:00
return ( p . returncode , stdout , stderr )
2013-07-04 20:03:17 +00:00
def not_in_host_file ( self , host ) :
2014-01-28 20:10:13 +00:00
if ' USER ' in os . environ :
2014-02-24 21:05:03 +00:00
user_host_file = os . path . expandvars ( " ~$ {USER} /.ssh/known_hosts " )
2014-01-28 20:10:13 +00:00
else :
2014-02-24 21:05:03 +00:00
user_host_file = " ~/.ssh/known_hosts "
user_host_file = os . path . expanduser ( user_host_file )
host_file_list = [ ]
host_file_list . append ( user_host_file )
host_file_list . append ( " /etc/ssh/ssh_known_hosts " )
host_file_list . append ( " /etc/ssh/ssh_known_hosts2 " )
hfiles_not_found = 0
for hf in host_file_list :
if not os . path . exists ( hf ) :
hfiles_not_found + = 1
2013-07-04 20:03:17 +00:00
continue
2014-04-02 10:42:07 +00:00
try :
host_fh = open ( hf )
except IOError , e :
hfiles_not_found + = 1
continue
2014-04-02 12:57:54 +00:00
else :
2014-04-02 10:42:07 +00:00
data = host_fh . read ( )
host_fh . close ( )
2014-02-24 21:05:03 +00:00
for line in data . split ( " \n " ) :
2014-01-23 15:02:17 +00:00
if line is None or " " not in line :
2013-08-02 16:08:02 +00:00
continue
2014-02-24 21:05:03 +00:00
tokens = line . split ( )
if tokens [ 0 ] . find ( self . HASHED_KEY_MAGIC ) == 0 :
# this is a hashed known host entry
try :
( kn_salt , kn_host ) = tokens [ 0 ] [ len ( self . HASHED_KEY_MAGIC ) : ] . split ( " | " , 2 )
hash = hmac . new ( kn_salt . decode ( ' base64 ' ) , digestmod = sha1 )
hash . update ( host )
if hash . digest ( ) == kn_host . decode ( ' base64 ' ) :
return False
except :
# invalid hashed host key, skip it
continue
else :
# standard host file entry
if host in tokens [ 0 ] :
return False
if ( hfiles_not_found == len ( host_file_list ) ) :
2014-03-18 16:14:56 +00:00
vvv ( " EXEC previous known host file not found for %s " % host )
2013-07-04 20:03:17 +00:00
return True
2014-01-21 01:19:03 +00:00
def exec_command ( self , cmd , tmp_path , sudo_user = None , sudoable = False , executable = ' /bin/sh ' , in_data = None , su_user = None , su = False ) :
2012-06-17 11:35:59 +00:00
''' run a command on the remote host '''
2012-11-16 22:42:19 +00:00
ssh_cmd = self . _password_cmd ( )
2014-01-15 21:44:28 +00:00
ssh_cmd + = [ " ssh " , " -C " ]
if not in_data :
# 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)
ssh_cmd + = [ " -tt " ]
2013-09-19 10:58:54 +00:00
if utils . VERBOSITY > 3 :
ssh_cmd + = [ " -vvv " ]
else :
ssh_cmd + = [ " -q " ]
ssh_cmd + = self . common_args
2013-08-18 21:08:35 +00:00
if self . ipv6 :
ssh_cmd + = [ ' -6 ' ]
ssh_cmd + = [ self . host ]
2012-11-16 22:42:19 +00:00
2014-01-21 01:19:03 +00:00
if su and su_user :
sudocmd , prompt , success_key = utils . make_su_cmd ( su_user , executable , cmd )
ssh_cmd . append ( sudocmd )
elif not self . runner . sudo or not sudoable :
2014-04-01 07:23:52 +00:00
prompt = None
2013-01-08 16:45:37 +00:00
if executable :
ssh_cmd . append ( executable + ' -c ' + pipes . quote ( cmd ) )
else :
ssh_cmd . append ( cmd )
2012-12-23 18:17:07 +00:00
else :
2014-09-27 15:39:49 +00:00
sudocmd , prompt , success_key = utils . make_sudo_cmd ( self . runner . sudo_exe , sudo_user , executable , cmd )
2013-01-10 05:50:56 +00:00
ssh_cmd . append ( sudocmd )
2012-11-16 22:42:19 +00:00
2014-09-03 19:04:14 +00:00
vvv ( " EXEC %s " % ' ' . join ( ssh_cmd ) , host = self . host )
2013-07-04 20:03:17 +00:00
not_in_host_file = self . not_in_host_file ( self . host )
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.
2013-07-04 22:17:45 +00:00
fcntl . lockf ( self . runner . process_lockfile , fcntl . LOCK_EX )
fcntl . lockf ( self . runner . output_lockfile , fcntl . LOCK_EX )
2014-01-21 01:19:03 +00:00
2014-01-15 21:44:28 +00:00
# create process
2014-03-21 20:52:07 +00:00
( p , stdin ) = self . _run ( ssh_cmd , in_data )
2012-11-16 22:42:19 +00:00
self . _send_password ( )
2014-09-05 13:42:31 +00:00
no_prompt_out = ' '
no_prompt_err = ' '
2014-01-21 01:19:03 +00:00
if ( self . runner . sudo and sudoable and self . runner . sudo_pass ) or \
( self . runner . su and su and self . runner . su_pass ) :
2014-01-15 21:44:28 +00:00
# several cases are handled for sudo privileges with password
# * NOPASSWD (tty & no-tty): detect success_key on stdout
# * without NOPASSWD:
# * detect prompt on stdout (tty)
# * detect prompt on stderr (no-tty)
2012-11-16 22:42:19 +00:00
fcntl . fcntl ( p . stdout , fcntl . F_SETFL ,
fcntl . fcntl ( p . stdout , fcntl . F_GETFL ) | os . O_NONBLOCK )
2014-01-15 21:44:28 +00:00
fcntl . fcntl ( p . stderr , fcntl . F_SETFL ,
fcntl . fcntl ( p . stderr , fcntl . F_GETFL ) | os . O_NONBLOCK )
2012-11-22 19:06:30 +00:00
sudo_output = ' '
2014-01-15 21:44:28 +00:00
sudo_errput = ' '
2014-05-23 15:06:09 +00:00
while True :
if success_key in sudo_output or \
( self . runner . sudo_pass and sudo_output . endswith ( prompt ) ) or \
2014-08-21 18:09:32 +00:00
( self . runner . su_pass and utils . su_prompts . check_su_prompt ( sudo_output ) ) :
2014-05-23 15:06:09 +00:00
break
2014-01-15 21:44:28 +00:00
rfd , wfd , efd = select . select ( [ p . stdout , p . stderr ] , [ ] ,
2012-11-16 22:42:19 +00:00
[ p . stdout ] , self . runner . timeout )
2014-01-15 21:44:28 +00:00
if p . stderr in rfd :
chunk = p . stderr . read ( )
if not chunk :
2014-01-21 01:19:03 +00:00
raise errors . AnsibleError ( ' ssh connection closed waiting for sudo or su password prompt ' )
2014-01-15 21:44:28 +00:00
sudo_errput + = chunk
incorrect_password = gettext . dgettext (
" sudo " , " Sorry, try again. " )
if sudo_errput . strip ( ) . endswith ( " %s %s " % ( prompt , incorrect_password ) ) :
raise errors . AnsibleError ( ' Incorrect sudo password ' )
elif sudo_errput . endswith ( prompt ) :
stdin . write ( self . runner . sudo_pass + ' \n ' )
2012-11-16 22:42:19 +00:00
if p . stdout in rfd :
chunk = p . stdout . read ( )
if not chunk :
2014-01-21 01:19:03 +00:00
raise errors . AnsibleError ( ' ssh connection closed waiting for sudo or su password prompt ' )
2012-11-16 22:42:19 +00:00
sudo_output + = chunk
2014-01-15 21:44:28 +00:00
if not rfd :
# timeout. wrap up process communication
2012-11-16 22:42:19 +00:00
stdout = p . communicate ( )
2014-01-21 01:19:03 +00:00
raise errors . AnsibleError ( ' ssh connection error waiting for sudo or su password prompt ' )
2014-01-15 21:44:28 +00:00
2013-10-30 18:18:35 +00:00
if success_key not in sudo_output :
2014-01-21 01:19:03 +00:00
if sudoable :
stdin . write ( self . runner . sudo_pass + ' \n ' )
elif su :
stdin . write ( self . runner . su_pass + ' \n ' )
2014-09-05 13:42:31 +00:00
else :
no_prompt_out + = sudo_output
no_prompt_err + = sudo_errput
2013-07-17 15:17:13 +00:00
2014-04-01 07:23:52 +00:00
( returncode , stdout , stderr ) = self . _communicate ( p , stdin , in_data , su = su , sudoable = sudoable , prompt = prompt )
2014-01-21 01:19:03 +00:00
2013-07-04 20:03:17 +00:00
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.
2013-07-04 22:17:45 +00:00
fcntl . lockf ( self . runner . output_lockfile , fcntl . LOCK_UN )
fcntl . lockf ( self . runner . process_lockfile , fcntl . LOCK_UN )
2014-01-23 15:02:17 +00:00
controlpersisterror = ' Bad configuration option: ControlPersist ' in stderr or \
' unknown configuration option: ControlPersist ' in stderr
2014-01-08 21:50:40 +00:00
if C . HOST_KEY_CHECKING :
if ssh_cmd [ 0 ] == " sshpass " and p . returncode == 6 :
2014-01-08 22:25:50 +00:00
raise errors . AnsibleError ( ' Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host \' s fingerprint to your known_hosts file to manage this host. ' )
2014-01-08 21:50:40 +00:00
2013-11-22 17:13:24 +00:00
if p . returncode != 0 and controlpersisterror :
2014-04-19 22:35:10 +00:00
raise errors . AnsibleError ( ' using -c ssh on certain older ssh versions may not support ControlPersist, set ANSIBLE_SSH_ARGS= " " (or ssh_args in [ssh_connection] section of the config file) before running again ' )
2014-03-26 23:40:50 +00:00
if p . returncode == 255 and ( in_data or self . runner . module_name == ' raw ' ) :
2014-01-15 21:44:28 +00:00
raise errors . AnsibleError ( ' SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh ' )
2012-08-07 00:07:02 +00:00
2014-09-05 13:42:31 +00:00
return ( p . returncode , ' ' , no_prompt_out + stdout , no_prompt_err + stderr )
2012-06-17 11:35:59 +00:00
def put_file ( self , in_path , out_path ) :
''' transfer a file from local to remote '''
2012-08-09 01:09:14 +00:00
vvv ( " PUT %s TO %s " % ( in_path , out_path ) , host = self . host )
2012-06-17 11:35:59 +00:00
if not os . path . exists ( in_path ) :
raise errors . AnsibleFileNotFound ( " file or module does not exist: %s " % in_path )
2012-11-16 22:42:19 +00:00
cmd = self . _password_cmd ( )
2013-08-18 21:08:35 +00:00
host = self . host
if self . ipv6 :
host = ' [ %s ] ' % host
2012-11-05 22:25:40 +00:00
if C . DEFAULT_SCP_IF_SSH :
2012-11-16 22:42:19 +00:00
cmd + = [ " scp " ] + self . common_args
2013-08-18 21:08:35 +00:00
cmd + = [ in_path , host + " : " + pipes . quote ( out_path ) ]
2012-11-16 22:42:19 +00:00
indata = None
2012-11-05 22:25:40 +00:00
else :
2013-08-18 21:08:35 +00:00
cmd + = [ " sftp " ] + self . common_args + [ host ]
2013-07-20 22:28:11 +00:00
indata = " put %s %s \n " % ( pipes . quote ( in_path ) , pipes . quote ( out_path ) )
2012-11-16 22:42:19 +00:00
2014-03-21 20:52:07 +00:00
( p , stdin ) = self . _run ( cmd , indata )
2012-11-16 22:42:19 +00:00
self . _send_password ( )
2014-03-21 20:52:07 +00:00
( returncode , stdout , stderr ) = self . _communicate ( p , stdin , indata )
if returncode != 0 :
2012-06-17 11:35:59 +00:00
raise errors . AnsibleError ( " failed to transfer file to %s : \n %s \n %s " % ( out_path , stdout , stderr ) )
def fetch_file ( self , in_path , out_path ) :
''' fetch a file from remote to local '''
2012-08-09 01:09:14 +00:00
vvv ( " FETCH %s TO %s " % ( in_path , out_path ) , host = self . host )
2012-11-16 22:42:19 +00:00
cmd = self . _password_cmd ( )
2013-08-18 21:08:35 +00:00
host = self . host
if self . ipv6 :
host = ' [ %s ] ' % host
2012-11-05 22:25:40 +00:00
if C . DEFAULT_SCP_IF_SSH :
2012-11-16 22:42:19 +00:00
cmd + = [ " scp " ] + self . common_args
2013-08-18 21:08:35 +00:00
cmd + = [ host + " : " + in_path , out_path ]
2012-11-16 22:42:19 +00:00
indata = None
2012-11-05 22:25:40 +00:00
else :
2013-08-18 21:08:35 +00:00
cmd + = [ " sftp " ] + self . common_args + [ host ]
2012-11-16 22:42:19 +00:00
indata = " get %s %s \n " % ( in_path , out_path )
p = subprocess . Popen ( cmd , stdin = subprocess . PIPE ,
stdout = subprocess . PIPE , stderr = subprocess . PIPE )
self . _send_password ( )
stdout , stderr = p . communicate ( indata )
2012-06-17 11:35:59 +00:00
if p . returncode != 0 :
raise errors . AnsibleError ( " failed to transfer file from %s : \n %s \n %s " % ( in_path , stdout , stderr ) )
def close ( self ) :
2012-07-15 16:29:53 +00:00
''' not applicable since we ' re executing openssh binaries '''
2012-06-17 11:35:59 +00:00
pass
2012-07-15 16:29:53 +00:00