Move connection plugins to using global display

pull/12547/merge
Toshio Kuratomi 9 years ago
parent 318bfbb207
commit aa4f213cb5

@ -22,7 +22,6 @@ __metaclass__ = type
import fcntl import fcntl
import gettext import gettext
import select
import os import os
from abc import ABCMeta, abstractmethod, abstractproperty from abc import ABCMeta, abstractmethod, abstractproperty
@ -68,6 +67,7 @@ class ConnectionBase(with_metaclass(ABCMeta, object)):
self._play_context = play_context self._play_context = play_context
if not hasattr(self, '_new_stdin'): if not hasattr(self, '_new_stdin'):
self._new_stdin = new_stdin self._new_stdin = new_stdin
# Backwards compat: self._display isn't really needed, just import the global display and use that.
if not hasattr(self, '_display'): if not hasattr(self, '_display'):
self._display = display self._display = display
if not hasattr(self, '_connected'): if not hasattr(self, '_connected'):
@ -220,11 +220,11 @@ class ConnectionBase(with_metaclass(ABCMeta, object)):
def connection_lock(self): def connection_lock(self):
f = self._play_context.connection_lockfd f = self._play_context.connection_lockfd
self._display.vvvv('CONNECTION: pid %d waiting for lock on %d' % (os.getpid(), f)) display.vvvv('CONNECTION: pid %d waiting for lock on %d' % (os.getpid(), f))
fcntl.lockf(f, fcntl.LOCK_EX) fcntl.lockf(f, fcntl.LOCK_EX)
self._display.vvvv('CONNECTION: pid %d acquired lock on %d' % (os.getpid(), f)) display.vvvv('CONNECTION: pid %d acquired lock on %d' % (os.getpid(), f))
def connection_unlock(self): def connection_unlock(self):
f = self._play_context.connection_lockfd f = self._play_context.connection_lockfd
fcntl.lockf(f, fcntl.LOCK_UN) fcntl.lockf(f, fcntl.LOCK_UN)
self._display.vvvv('CONNECTION: pid %d released lock on %d' % (os.getpid(), f)) display.vvvv('CONNECTION: pid %d released lock on %d' % (os.getpid(), f))

@ -29,10 +29,15 @@ from ansible import constants as C
from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleConnectionFailure from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleConnectionFailure
from ansible.parsing.utils.jsonify import jsonify from ansible.parsing.utils.jsonify import jsonify
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
from ansible.plugins.connection.ssh import Connection as SSHConnection
from ansible.plugins.connection.paramiko_ssh import Connection as ParamikoConnection
from ansible.utils.encrypt import key_for_hostname, keyczar_encrypt, keyczar_decrypt from ansible.utils.encrypt import key_for_hostname, keyczar_encrypt, keyczar_decrypt
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
# the chunk size to read and send, assuming mtu 1500 and # the chunk size to read and send, assuming mtu 1500 and
# leaving room for base64 (+33%) encoding and header (8 bytes) # leaving room for base64 (+33%) encoding and header (8 bytes)
# ((1400-8)/4)*3) = 1044 # ((1400-8)/4)*3) = 1044
@ -40,6 +45,7 @@ from ansible.utils.encrypt import key_for_hostname, keyczar_encrypt, keyczar_dec
# multiple of the value to speed up file reads. # multiple of the value to speed up file reads.
CHUNK_SIZE=1044*20 CHUNK_SIZE=1044*20
class Connection(ConnectionBase): class Connection(ConnectionBase):
''' raw socket accelerated connection ''' ''' raw socket accelerated connection '''
@ -62,20 +68,20 @@ class Connection(ConnectionBase):
tries = 3 tries = 3
self.conn = socket.socket() self.conn = socket.socket()
self.conn.settimeout(C.ACCELERATE_CONNECT_TIMEOUT) self.conn.settimeout(C.ACCELERATE_CONNECT_TIMEOUT)
self._display.vvvv("attempting connection to %s via the accelerated port %d" % (self._play_context.remote_addr,self._play_context.accelerate_port)) display.vvvv("attempting connection to %s via the accelerated port %d" % (self._play_context.remote_addr,self._play_context.accelerate_port))
while tries > 0: while tries > 0:
try: try:
self.conn.connect((self._play_context.remote_addr,self._play_context.accelerate_port)) self.conn.connect((self._play_context.remote_addr,self._play_context.accelerate_port))
break break
except socket.error: except socket.error:
self._display.vvvv("connection to %s failed, retrying..." % self._play_context.remote_addr) display.vvvv("connection to %s failed, retrying..." % self._play_context.remote_addr)
time.sleep(0.1) time.sleep(0.1)
tries -= 1 tries -= 1
if tries == 0: if tries == 0:
self._display.vvv("Could not connect via the accelerated connection, exceeded # of tries") display.vvv("Could not connect via the accelerated connection, exceeded # of tries")
raise AnsibleConnectionFailure("Failed to connect to %s on the accelerated port %s" % (self._play_context.remote_addr, self._play_context.accelerate_port)) raise AnsibleConnectionFailure("Failed to connect to %s on the accelerated port %s" % (self._play_context.remote_addr, self._play_context.accelerate_port))
elif wrong_user: elif wrong_user:
self._display.vvv("Restarting daemon with a different remote_user") display.vvv("Restarting daemon with a different remote_user")
raise AnsibleError("The accelerated daemon was started on the remote with a different user") raise AnsibleError("The accelerated daemon was started on the remote with a different user")
self.conn.settimeout(C.ACCELERATE_TIMEOUT) self.conn.settimeout(C.ACCELERATE_TIMEOUT)
@ -97,25 +103,25 @@ class Connection(ConnectionBase):
header_len = 8 # size of a packed unsigned long long header_len = 8 # size of a packed unsigned long long
data = b"" data = b""
try: try:
self._display.vvvv("%s: in recv_data(), waiting for the header" % self._play_context.remote_addr) display.vvvv("%s: in recv_data(), waiting for the header" % self._play_context.remote_addr)
while len(data) < header_len: while len(data) < header_len:
d = self.conn.recv(header_len - len(data)) d = self.conn.recv(header_len - len(data))
if not d: if not d:
self._display.vvvv("%s: received nothing, bailing out" % self._play_context.remote_addr) display.vvvv("%s: received nothing, bailing out" % self._play_context.remote_addr)
return None return None
data += d data += d
self._display.vvvv("%s: got the header, unpacking" % self._play_context.remote_addr) display.vvvv("%s: got the header, unpacking" % self._play_context.remote_addr)
data_len = struct.unpack('!Q',data[:header_len])[0] data_len = struct.unpack('!Q',data[:header_len])[0]
data = data[header_len:] data = data[header_len:]
self._display.vvvv("%s: data received so far (expecting %d): %d" % (self._play_context.remote_addr,data_len,len(data))) display.vvvv("%s: data received so far (expecting %d): %d" % (self._play_context.remote_addr,data_len,len(data)))
while len(data) < data_len: while len(data) < data_len:
d = self.conn.recv(data_len - len(data)) d = self.conn.recv(data_len - len(data))
if not d: if not d:
self._display.vvvv("%s: received nothing, bailing out" % self._play_context.remote_addr) display.vvvv("%s: received nothing, bailing out" % self._play_context.remote_addr)
return None return None
self._display.vvvv("%s: received %d bytes" % (self._play_context.remote_addr, len(d))) display.vvvv("%s: received %d bytes" % (self._play_context.remote_addr, len(d)))
data += d data += d
self._display.vvvv("%s: received all of the data, returning" % self._play_context.remote_addr) display.vvvv("%s: received all of the data, returning" % self._play_context.remote_addr)
return data return data
except socket.timeout: except socket.timeout:
raise AnsibleError("timed out while waiting to receive data") raise AnsibleError("timed out while waiting to receive data")
@ -127,7 +133,7 @@ class Connection(ConnectionBase):
daemon to exit if they don't match daemon to exit if they don't match
''' '''
self._display.vvvv("%s: sending request for validate_user" % self._play_context.remote_addr) display.vvvv("%s: sending request for validate_user" % self._play_context.remote_addr)
data = dict( data = dict(
mode='validate_user', mode='validate_user',
username=self._play_context.remote_user, username=self._play_context.remote_user,
@ -137,7 +143,7 @@ class Connection(ConnectionBase):
if self.send_data(data): if self.send_data(data):
raise AnsibleError("Failed to send command to %s" % self._play_context.remote_addr) raise AnsibleError("Failed to send command to %s" % self._play_context.remote_addr)
self._display.vvvv("%s: waiting for validate_user response" % self._play_context.remote_addr) display.vvvv("%s: waiting for validate_user response" % self._play_context.remote_addr)
while True: while True:
# we loop here while waiting for the response, because a # we loop here while waiting for the response, because a
# long running command may cause us to receive keepalive packets # long running command may cause us to receive keepalive packets
@ -149,10 +155,10 @@ class Connection(ConnectionBase):
response = json.loads(response) response = json.loads(response)
if "pong" in response: if "pong" in response:
# it's a keepalive, go back to waiting # it's a keepalive, go back to waiting
self._display.vvvv("%s: received a keepalive packet" % self._play_context.remote_addr) display.vvvv("%s: received a keepalive packet" % self._play_context.remote_addr)
continue continue
else: else:
self._display.vvvv("%s: received the validate_user response: %s" % (self._play_context.remote_addr, response)) display.vvvv("%s: received the validate_user response: %s" % (self._play_context.remote_addr, response))
break break
if response.get('failed'): if response.get('failed'):
@ -169,7 +175,7 @@ class Connection(ConnectionBase):
if in_data: if in_data:
raise AnsibleError("Internal Error: this module does not support optimized module pipelining") raise AnsibleError("Internal Error: this module does not support optimized module pipelining")
self._display.vvv("EXEC COMMAND %s" % cmd) display.vvv("EXEC COMMAND %s" % cmd)
data = dict( data = dict(
mode='command', mode='command',
@ -192,10 +198,10 @@ class Connection(ConnectionBase):
response = json.loads(response) response = json.loads(response)
if "pong" in response: if "pong" in response:
# it's a keepalive, go back to waiting # it's a keepalive, go back to waiting
self._display.vvvv("%s: received a keepalive packet" % self._play_context.remote_addr) display.vvvv("%s: received a keepalive packet" % self._play_context.remote_addr)
continue continue
else: else:
self._display.vvvv("%s: received the response" % self._play_context.remote_addr) display.vvvv("%s: received the response" % self._play_context.remote_addr)
break break
return (response.get('rc', None), response.get('stdout', ''), response.get('stderr', '')) return (response.get('rc', None), response.get('stdout', ''), response.get('stderr', ''))
@ -203,7 +209,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
''' transfer a file from local to remote ''' ''' transfer a file from local to remote '''
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
if not os.path.exists(in_path): if not os.path.exists(in_path):
raise AnsibleFileNotFound("file or module does not exist: %s" % in_path) raise AnsibleFileNotFound("file or module does not exist: %s" % in_path)
@ -211,10 +217,10 @@ class Connection(ConnectionBase):
fd = file(in_path, 'rb') fd = file(in_path, 'rb')
fstat = os.stat(in_path) fstat = os.stat(in_path)
try: try:
self._display.vvv("PUT file is %d bytes" % fstat.st_size) display.vvv("PUT file is %d bytes" % fstat.st_size)
last = False last = False
while fd.tell() <= fstat.st_size and not last: while fd.tell() <= fstat.st_size and not last:
self._display.vvvv("file position currently %ld, file size is %ld" % (fd.tell(), fstat.st_size)) display.vvvv("file position currently %ld, file size is %ld" % (fd.tell(), fstat.st_size))
data = fd.read(CHUNK_SIZE) data = fd.read(CHUNK_SIZE)
if fd.tell() >= fstat.st_size: if fd.tell() >= fstat.st_size:
last = True last = True
@ -237,7 +243,7 @@ class Connection(ConnectionBase):
raise AnsibleError("failed to put the file in the requested location") raise AnsibleError("failed to put the file in the requested location")
finally: finally:
fd.close() fd.close()
self._display.vvvv("waiting for final response after PUT") display.vvvv("waiting for final response after PUT")
response = self.recv_data() response = self.recv_data()
if not response: if not response:
raise AnsibleError("Failed to get a response from %s" % self._play_context.remote_addr) raise AnsibleError("Failed to get a response from %s" % self._play_context.remote_addr)
@ -249,7 +255,7 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
''' save a remote file to the specified path ''' ''' save a remote file to the specified path '''
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
data = dict(mode='fetch', in_path=in_path) data = dict(mode='fetch', in_path=in_path)
data = jsonify(data) data = jsonify(data)
@ -285,7 +291,7 @@ class Connection(ConnectionBase):
# point in the future or we may just have the put/fetch # point in the future or we may just have the put/fetch
# operations not send back a final response at all # operations not send back a final response at all
response = self.recv_data() response = self.recv_data()
self._display.vvv("FETCH wrote %d bytes to %s" % (bytes, out_path)) display.vvv("FETCH wrote %d bytes to %s" % (bytes, out_path))
fh.close() fh.close()
def close(self): def close(self):
@ -295,4 +301,3 @@ class Connection(ConnectionBase):
self.conn.close() self.conn.close()
except: except:
pass pass

@ -31,6 +31,12 @@ from ansible.errors import AnsibleError
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
from ansible.module_utils.basic import is_executable from ansible.module_utils.basic import is_executable
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
BUFSIZE = 65536 BUFSIZE = 65536
@ -70,7 +76,7 @@ class Connection(ConnectionBase):
''' connect to the chroot; nothing to do here ''' ''' connect to the chroot; nothing to do here '''
super(Connection, self)._connect() super(Connection, self)._connect()
if not self._connected: if not self._connected:
self._display.vvv("THIS IS A LOCAL CHROOT DIR", host=self.chroot) display.vvv("THIS IS A LOCAL CHROOT DIR", host=self.chroot)
self._connected = True self._connected = True
def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE): def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
@ -84,7 +90,7 @@ class Connection(ConnectionBase):
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh' executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh'
local_cmd = [self.chroot_cmd, self.chroot, executable, '-c', cmd] local_cmd = [self.chroot_cmd, self.chroot, executable, '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self.chroot) display.vvv("EXEC %s" % (local_cmd), host=self.chroot)
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin, p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -116,7 +122,7 @@ class Connection(ConnectionBase):
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) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot)
out_path = pipes.quote(self._prefix_login_path(out_path)) out_path = pipes.quote(self._prefix_login_path(out_path))
try: try:
@ -138,7 +144,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) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot)
in_path = pipes.quote(self._prefix_login_path(in_path)) in_path = pipes.quote(self._prefix_login_path(in_path))
try: try:

@ -37,8 +37,16 @@ import ansible.constants as C
from ansible.errors import AnsibleError, AnsibleFileNotFound from ansible.errors import AnsibleError, AnsibleFileNotFound
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
BUFSIZE = 65536 BUFSIZE = 65536
class Connection(ConnectionBase): class Connection(ConnectionBase):
''' Local docker based connections ''' ''' Local docker based connections '''
@ -103,7 +111,7 @@ class Connection(ConnectionBase):
""" Connect to the container. Nothing to do """ """ Connect to the container. Nothing to do """
super(Connection, self)._connect() super(Connection, self)._connect()
if not self._connected: if not self._connected:
self._display.vvv("ESTABLISH DOCKER CONNECTION FOR USER: {0}".format( display.vvv("ESTABLISH DOCKER CONNECTION FOR USER: {0}".format(
self._play_context.remote_user, host=self._play_context.remote_addr) self._play_context.remote_user, host=self._play_context.remote_addr)
) )
self._connected = True self._connected = True
@ -116,7 +124,7 @@ class Connection(ConnectionBase):
# -i is needed to keep stdin open which allows pipelining to work # -i is needed to keep stdin open which allows pipelining to work
local_cmd = [self.docker_cmd, "exec", '-i', self._play_context.remote_addr, executable, '-c', cmd] local_cmd = [self.docker_cmd, "exec", '-i', self._play_context.remote_addr, executable, '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self._play_context.remote_addr) display.vvv("EXEC %s" % (local_cmd), host=self._play_context.remote_addr)
p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE, p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -140,7 +148,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
""" Transfer a file from local to docker container """ """ Transfer a file from local to docker container """
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
out_path = self._prefix_login_path(out_path) out_path = self._prefix_login_path(out_path)
if not os.path.exists(in_path): if not os.path.exists(in_path):
@ -175,7 +183,7 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
""" Fetch a file from container to local. """ """ Fetch a file from container to local. """
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
in_path = self._prefix_login_path(in_path) in_path = self._prefix_login_path(in_path)
# out_path is the final file path, but docker takes a directory, not a # out_path is the final file path, but docker takes a directory, not a

@ -31,6 +31,12 @@ 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
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
BUFSIZE = 65536 BUFSIZE = 65536
@ -58,7 +64,7 @@ class Connection(ConnectionBase):
self.jls_cmd = self._search_executable('jls') self.jls_cmd = self._search_executable('jls')
self.jexec_cmd = self._search_executable('jexec') self.jexec_cmd = self._search_executable('jexec')
if not self.jail in self.list_jails(): if self.jail not in self.list_jails():
raise AnsibleError("incorrect jail name %s" % self.jail) raise AnsibleError("incorrect jail name %s" % self.jail)
@staticmethod @staticmethod
@ -90,7 +96,7 @@ class Connection(ConnectionBase):
''' connect to the jail; nothing to do here ''' ''' connect to the jail; nothing to do here '''
super(Connection, self)._connect() super(Connection, self)._connect()
if not self._connected: if not self._connected:
self._display.vvv("THIS IS A LOCAL JAIL DIR", host=self.jail) display.vvv("THIS IS A LOCAL JAIL DIR", host=self.jail)
self._connected = True self._connected = True
def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE): def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
@ -104,7 +110,7 @@ class Connection(ConnectionBase):
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh' executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh'
local_cmd = [self.jexec_cmd, self.jail, executable, '-c', cmd] local_cmd = [self.jexec_cmd, self.jail, executable, '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self.jail) display.vvv("EXEC %s" % (local_cmd), host=self.jail)
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin, p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -143,7 +149,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
''' transfer a file from local to jail ''' ''' transfer a file from local to jail '''
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.jail) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.jail)
out_path = pipes.quote(self._prefix_login_path(out_path)) out_path = pipes.quote(self._prefix_login_path(out_path))
try: try:
@ -165,7 +171,7 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
''' fetch a file from jail to local ''' ''' fetch a file from jail to local '''
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.jail) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.jail)
in_path = pipes.quote(self._prefix_login_path(in_path)) in_path = pipes.quote(self._prefix_login_path(in_path))
try: try:

@ -31,6 +31,12 @@ 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
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
BUFSIZE = 65536 BUFSIZE = 65536
@ -70,7 +76,7 @@ class Connection(ConnectionBase):
''' connect to the lxc; nothing to do here ''' ''' connect to the lxc; nothing to do here '''
super(Connection, self)._connect() super(Connection, self)._connect()
if not self._connected: if not self._connected:
self._display.vvv("THIS IS A LOCAL LXC DIR", host=self.lxc) display.vvv("THIS IS A LOCAL LXC DIR", host=self.lxc)
self._connected = True self._connected = True
def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE): def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
@ -84,7 +90,7 @@ class Connection(ConnectionBase):
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh' executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh'
local_cmd = [self.virsh, '-q', '-c', 'lxc:///', 'lxc-enter-namespace', self.lxc, '--', executable , '-c', cmd] local_cmd = [self.virsh, '-q', '-c', 'lxc:///', 'lxc-enter-namespace', self.lxc, '--', executable , '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self.lxc) display.vvv("EXEC %s" % (local_cmd), host=self.lxc)
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin, p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -116,7 +122,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
''' transfer a file from local to lxc ''' ''' transfer a file from local to lxc '''
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.lxc) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.lxc)
out_path = pipes.quote(self._prefix_login_path(out_path)) out_path = pipes.quote(self._prefix_login_path(out_path))
try: try:
@ -138,7 +144,7 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
''' fetch a file from lxc to local ''' ''' fetch a file from lxc to local '''
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.lxc) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.lxc)
in_path = pipes.quote(self._prefix_login_path(in_path)) in_path = pipes.quote(self._prefix_login_path(in_path))
try: try:

@ -18,7 +18,6 @@
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import traceback
import os import os
import shutil import shutil
import subprocess import subprocess
@ -31,6 +30,14 @@ import ansible.constants as C
from ansible.errors import AnsibleError, AnsibleFileNotFound from ansible.errors import AnsibleError, AnsibleFileNotFound
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
class Connection(ConnectionBase): class Connection(ConnectionBase):
''' Local based connections ''' ''' Local based connections '''
@ -48,7 +55,7 @@ class Connection(ConnectionBase):
self._play_context.remote_user = getpass.getuser() self._play_context.remote_user = getpass.getuser()
if not self._connected: if not self._connected:
self._display.vvv("ESTABLISH LOCAL CONNECTION FOR USER: {0}".format(self._play_context.remote_user, host=self._play_context.remote_addr)) display.vvv("ESTABLISH LOCAL CONNECTION FOR USER: {0}".format(self._play_context.remote_user, host=self._play_context.remote_addr))
self._connected = True self._connected = True
return self return self
@ -57,15 +64,15 @@ class Connection(ConnectionBase):
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable) super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
self._display.debug("in local.exec_command()") display.debug("in local.exec_command()")
if in_data: if in_data:
raise AnsibleError("Internal Error: this module does not support optimized module pipelining") raise AnsibleError("Internal Error: this module does not support optimized module pipelining")
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else None executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else None
self._display.vvv("{0} EXEC {1}".format(self._play_context.remote_addr, cmd)) display.vvv("{0} EXEC {1}".format(self._play_context.remote_addr, cmd))
# FIXME: cwd= needs to be set to the basedir of the playbook # FIXME: cwd= needs to be set to the basedir of the playbook
self._display.debug("opening command with Popen()") display.debug("opening command with Popen()")
p = subprocess.Popen( p = subprocess.Popen(
cmd, cmd,
shell=isinstance(cmd, basestring), shell=isinstance(cmd, basestring),
@ -74,7 +81,7 @@ class Connection(ConnectionBase):
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
) )
self._display.debug("done running command with Popen()") display.debug("done running command with Popen()")
if self._play_context.prompt and sudoable: if self._play_context.prompt and sudoable:
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK) fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
@ -99,11 +106,11 @@ class Connection(ConnectionBase):
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK) 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) fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) & ~os.O_NONBLOCK)
self._display.debug("getting output with communicate()") display.debug("getting output with communicate()")
stdout, stderr = p.communicate() stdout, stderr = p.communicate()
self._display.debug("done communicating") display.debug("done communicating")
self._display.debug("done with local.exec_command()") display.debug("done with local.exec_command()")
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):
@ -111,7 +118,7 @@ class Connection(ConnectionBase):
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("{0} PUT {1} TO {2}".format(self._play_context.remote_addr, in_path, out_path)) display.vvv("{0} PUT {1} TO {2}".format(self._play_context.remote_addr, in_path, out_path))
if not os.path.exists(in_path): if not os.path.exists(in_path):
raise AnsibleFileNotFound("file or module does not exist: {0}".format(in_path)) raise AnsibleFileNotFound("file or module does not exist: {0}".format(in_path))
try: try:
@ -126,7 +133,7 @@ class Connection(ConnectionBase):
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("{0} FETCH {1} TO {2}".format(self._play_context.remote_addr, in_path, out_path)) display.vvv("{0} FETCH {1} TO {2}".format(self._play_context.remote_addr, in_path, out_path))
self.put_file(in_path, out_path) self.put_file(in_path, out_path)
def close(self): def close(self):

@ -26,14 +26,11 @@ __metaclass__ = type
import warnings import warnings
import os import os
import pipes
import socket import socket
import random
import logging import logging
import tempfile import tempfile
import traceback import traceback
import fcntl import fcntl
import re
import sys import sys
from termios import tcflush, TCIFLUSH from termios import tcflush, TCIFLUSH
@ -46,6 +43,13 @@ from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNo
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
from ansible.utils.path import makedirs_safe from ansible.utils.path import makedirs_safe
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
AUTHENTICITY_MSG=""" AUTHENTICITY_MSG="""
paramiko: The authenticity of host '%s' can't be established. paramiko: The authenticity of host '%s' can't be established.
The %s key fingerprint is %s. The %s key fingerprint is %s.
@ -114,6 +118,7 @@ class MyAddPolicy(object):
SSH_CONNECTION_CACHE = {} SSH_CONNECTION_CACHE = {}
SFTP_CONNECTION_CACHE = {} SFTP_CONNECTION_CACHE = {}
class Connection(ConnectionBase): class Connection(ConnectionBase):
''' SSH based connections with Paramiko ''' ''' SSH based connections with Paramiko '''
@ -140,7 +145,7 @@ class Connection(ConnectionBase):
raise AnsibleError("paramiko is not installed") raise AnsibleError("paramiko is not installed")
port = self._play_context.port or 22 port = self._play_context.port or 22
self._display.vvv("ESTABLISH CONNECTION FOR USER: %s on PORT %s TO %s" % (self._play_context.remote_user, port, self._play_context.remote_addr), host=self._play_context.remote_addr) display.vvv("ESTABLISH CONNECTION FOR USER: %s on PORT %s TO %s" % (self._play_context.remote_user, port, self._play_context.remote_addr), host=self._play_context.remote_addr)
ssh = paramiko.SSHClient() ssh = paramiko.SSHClient()
@ -214,7 +219,7 @@ class Connection(ConnectionBase):
if C.PARAMIKO_PTY: if C.PARAMIKO_PTY:
chan.get_pty(term=os.getenv('TERM', 'vt100'), width=int(os.getenv('COLUMNS', 0)), height=int(os.getenv('LINES', 0))) chan.get_pty(term=os.getenv('TERM', 'vt100'), width=int(os.getenv('COLUMNS', 0)), height=int(os.getenv('LINES', 0)))
self._display.vvv("EXEC %s" % cmd, host=self._play_context.remote_addr) display.vvv("EXEC %s" % cmd, host=self._play_context.remote_addr)
no_prompt_out = '' no_prompt_out = ''
no_prompt_err = '' no_prompt_err = ''
@ -225,7 +230,7 @@ class Connection(ConnectionBase):
if self._play_context.prompt: if self._play_context.prompt:
passprompt = False passprompt = False
while True: while True:
self._display.debug('Waiting for Privilege Escalation input') display.debug('Waiting for Privilege Escalation input')
if self.check_become_success(become_output): if self.check_become_success(become_output):
break break
elif self.check_password_prompt(become_output): elif self.check_password_prompt(become_output):
@ -233,7 +238,7 @@ class Connection(ConnectionBase):
break break
chunk = chan.recv(bufsize) chunk = chan.recv(bufsize)
self._display.debug("chunk is: %s" % chunk) display.debug("chunk is: %s" % chunk)
if not chunk: if not chunk:
if 'unknown user' in become_output: if 'unknown user' in become_output:
raise AnsibleError( 'user %s does not exist' % self._play_context.become_user) raise AnsibleError( 'user %s does not exist' % self._play_context.become_user)
@ -262,7 +267,7 @@ class Connection(ConnectionBase):
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
if not os.path.exists(in_path): if not os.path.exists(in_path):
raise AnsibleFileNotFound("file or module does not exist: %s" % in_path) raise AnsibleFileNotFound("file or module does not exist: %s" % in_path)
@ -291,7 +296,7 @@ class Connection(ConnectionBase):
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
try: try:
self.sftp = self._connect_sftp() self.sftp = self._connect_sftp()
@ -305,7 +310,6 @@ class Connection(ConnectionBase):
def _any_keys_added(self): def _any_keys_added(self):
added_any = False
for hostname, keys in iteritems(self.ssh._host_keys): for hostname, keys in iteritems(self.ssh._host_keys):
for keytype, key in iteritems(keys): for keytype, key in iteritems(keys):
added_this_time = getattr(key, '_added_by_ansible_this_time', False) added_this_time = getattr(key, '_added_by_ansible_this_time', False)
@ -402,4 +406,3 @@ class Connection(ConnectionBase):
fcntl.lockf(KEY_LOCK, fcntl.LOCK_UN) fcntl.lockf(KEY_LOCK, fcntl.LOCK_UN)
self.ssh.close() self.ssh.close()

@ -34,8 +34,16 @@ from ansible.plugins.connection import ConnectionBase
from ansible.utils.path import unfrackpath, makedirs_safe from ansible.utils.path import unfrackpath, makedirs_safe
from ansible.utils.unicode import to_bytes, to_unicode from ansible.utils.unicode import to_bytes, to_unicode
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
SSHPASS_AVAILABLE = None SSHPASS_AVAILABLE = None
class Connection(ConnectionBase): class Connection(ConnectionBase):
''' ssh based connections ''' ''' ssh based connections '''
@ -109,7 +117,7 @@ class Connection(ConnectionBase):
explanation of why they were added. explanation of why they were added.
""" """
self._command += args self._command += args
self._display.vvvvv('SSH: ' + explanation + ': (%s)' % ')('.join(args), host=self._play_context.remote_addr) display.vvvvv('SSH: ' + explanation + ': (%s)' % ')('.join(args), host=self._play_context.remote_addr)
def _build_command(self, binary, *other_args): def _build_command(self, binary, *other_args):
''' '''
@ -242,7 +250,7 @@ class Connection(ConnectionBase):
just hang forever waiting for more commands.) just hang forever waiting for more commands.)
''' '''
self._display.debug('Sending initial data') display.debug('Sending initial data')
try: try:
fh.write(in_data) fh.write(in_data)
@ -250,7 +258,7 @@ class Connection(ConnectionBase):
except (OSError, IOError): except (OSError, IOError):
raise AnsibleConnectionFailure('SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh') raise AnsibleConnectionFailure('SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh')
self._display.debug('Sent initial data (%d bytes)' % len(in_data)) display.debug('Sent initial data (%d bytes)' % len(in_data))
# Used by _run() to kill processes on failures # Used by _run() to kill processes on failures
@staticmethod @staticmethod
@ -277,20 +285,20 @@ class Connection(ConnectionBase):
for l in chunk.splitlines(True): for l in chunk.splitlines(True):
suppress_output = False suppress_output = False
# self._display.debug("Examining line (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n'))) # display.debug("Examining line (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n')))
if self._play_context.prompt and self.check_password_prompt(l): if self._play_context.prompt and self.check_password_prompt(l):
self._display.debug("become_prompt: (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n'))) display.debug("become_prompt: (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n')))
self._flags['become_prompt'] = True self._flags['become_prompt'] = True
suppress_output = True suppress_output = True
elif self._play_context.success_key and self.check_become_success(l): elif self._play_context.success_key and self.check_become_success(l):
self._display.debug("become_success: (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n'))) display.debug("become_success: (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n')))
self._flags['become_success'] = True self._flags['become_success'] = True
suppress_output = True suppress_output = True
elif sudoable and self.check_incorrect_password(l): elif sudoable and self.check_incorrect_password(l):
self._display.debug("become_error: (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n'))) display.debug("become_error: (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n')))
self._flags['become_error'] = True self._flags['become_error'] = True
elif sudoable and self.check_missing_password(l): elif sudoable and self.check_missing_password(l):
self._display.debug("become_nopasswd_error: (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n'))) display.debug("become_nopasswd_error: (source=%s, state=%s): '%s'" % (source, state, l.rstrip('\r\n')))
self._flags['become_nopasswd_error'] = True self._flags['become_nopasswd_error'] = True
if not suppress_output: if not suppress_output:
@ -314,7 +322,7 @@ class Connection(ConnectionBase):
''' '''
display_cmd = map(pipes.quote, cmd[:-1]) + [cmd[-1]] display_cmd = map(pipes.quote, cmd[:-1]) + [cmd[-1]]
self._display.vvv('SSH: EXEC {0}'.format(' '.join(display_cmd)), host=self.host) display.vvv('SSH: EXEC {0}'.format(' '.join(display_cmd)), host=self.host)
# Start the given command. If we don't need to pipeline data, we can try # Start the given command. If we don't need to pipeline data, we can try
# to use a pseudo-tty (ssh will have been invoked with -tt). If we are # to use a pseudo-tty (ssh will have been invoked with -tt). If we are
@ -364,12 +372,12 @@ class Connection(ConnectionBase):
# We're requesting escalation with a password, so we have to # We're requesting escalation with a password, so we have to
# wait for a password prompt. # wait for a password prompt.
state = states.index('awaiting_prompt') state = states.index('awaiting_prompt')
self._display.debug('Initial state: %s: %s' % (states[state], self._play_context.prompt)) display.debug('Initial state: %s: %s' % (states[state], self._play_context.prompt))
elif self._play_context.become and self._play_context.success_key: elif self._play_context.become and self._play_context.success_key:
# We're requesting escalation without a password, so we have to # We're requesting escalation without a password, so we have to
# detect success/failure before sending any initial data. # detect success/failure before sending any initial data.
state = states.index('awaiting_escalation') state = states.index('awaiting_escalation')
self._display.debug('Initial state: %s: %s' % (states[state], self._play_context.success_key)) display.debug('Initial state: %s: %s' % (states[state], self._play_context.success_key))
# We store accumulated stdout and stderr output from the process here, # We store accumulated stdout and stderr output from the process here,
# but strip any privilege escalation prompt/confirmation lines first. # but strip any privilege escalation prompt/confirmation lines first.
@ -415,14 +423,14 @@ class Connection(ConnectionBase):
if chunk == '': if chunk == '':
rpipes.remove(p.stdout) rpipes.remove(p.stdout)
tmp_stdout += chunk tmp_stdout += chunk
self._display.debug("stdout chunk (state=%s):\n>>>%s<<<\n" % (state, chunk)) display.debug("stdout chunk (state=%s):\n>>>%s<<<\n" % (state, chunk))
if p.stderr in rfd: if p.stderr in rfd:
chunk = p.stderr.read() chunk = p.stderr.read()
if chunk == '': if chunk == '':
rpipes.remove(p.stderr) rpipes.remove(p.stderr)
tmp_stderr += chunk tmp_stderr += chunk
self._display.debug("stderr chunk (state=%s):\n>>>%s<<<\n" % (state, chunk)) display.debug("stderr chunk (state=%s):\n>>>%s<<<\n" % (state, chunk))
# We examine the output line-by-line until we have negotiated any # We examine the output line-by-line until we have negotiated any
# privilege escalation prompt and subsequent success/error message. # privilege escalation prompt and subsequent success/error message.
@ -446,7 +454,7 @@ class Connection(ConnectionBase):
# If we see a privilege escalation prompt, we send the password. # If we see a privilege escalation prompt, we send the password.
if states[state] == 'awaiting_prompt' and self._flags['become_prompt']: if states[state] == 'awaiting_prompt' and self._flags['become_prompt']:
self._display.debug('Sending become_pass in response to prompt') display.debug('Sending become_pass in response to prompt')
stdin.write(self._play_context.become_pass + '\n') stdin.write(self._play_context.become_pass + '\n')
self._flags['become_prompt'] = False self._flags['become_prompt'] = False
state += 1 state += 1
@ -456,23 +464,23 @@ class Connection(ConnectionBase):
if states[state] == 'awaiting_escalation': if states[state] == 'awaiting_escalation':
if self._flags['become_success']: if self._flags['become_success']:
self._display.debug('Escalation succeeded') display.debug('Escalation succeeded')
self._flags['become_success'] = False self._flags['become_success'] = False
state += 1 state += 1
elif self._flags['become_error']: elif self._flags['become_error']:
self._display.debug('Escalation failed') display.debug('Escalation failed')
self._terminate_process(p) self._terminate_process(p)
self._flags['become_error'] = False self._flags['become_error'] = False
raise AnsibleError('Incorrect %s password' % self._play_context.become_method) raise AnsibleError('Incorrect %s password' % self._play_context.become_method)
elif self._flags['become_nopasswd_error']: elif self._flags['become_nopasswd_error']:
self._display.debug('Escalation requires password') display.debug('Escalation requires password')
self._terminate_process(p) self._terminate_process(p)
self._flags['become_nopasswd_error'] = False self._flags['become_nopasswd_error'] = False
raise AnsibleError('Missing %s password' % self._play_context.become_method) raise AnsibleError('Missing %s password' % self._play_context.become_method)
elif self._flags['become_prompt']: elif self._flags['become_prompt']:
# This shouldn't happen, because we should see the "Sorry, # This shouldn't happen, because we should see the "Sorry,
# try again" message first. # try again" message first.
self._display.debug('Escalation prompt repeated') display.debug('Escalation prompt repeated')
self._terminate_process(p) self._terminate_process(p)
self._flags['become_prompt'] = False self._flags['become_prompt'] = False
raise AnsibleError('Incorrect %s password' % self._play_context.become_method) raise AnsibleError('Incorrect %s password' % self._play_context.become_method)
@ -501,7 +509,7 @@ class Connection(ConnectionBase):
# written to stderr between the time we called select() and when # written to stderr between the time we called select() and when
# we learned that the process had finished. # we learned that the process had finished.
if not p.stdout in rpipes: if p.stdout not in rpipes:
timeout = 0 timeout = 0
continue continue
@ -537,7 +545,7 @@ class Connection(ConnectionBase):
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable) super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
self._display.vvv("ESTABLISH SSH CONNECTION FOR USER: {0}".format(self._play_context.remote_user), host=self._play_context.remote_addr) display.vvv("ESTABLISH SSH CONNECTION FOR USER: {0}".format(self._play_context.remote_user), host=self._play_context.remote_addr)
# we can only use tty when we are not pipelining the modules. piping # we can only use tty when we are not pipelining the modules. piping
# data into /usr/bin/python inside a tty automatically invokes the # data into /usr/bin/python inside a tty automatically invokes the
@ -593,7 +601,7 @@ class Connection(ConnectionBase):
else: else:
msg = "ssh_retry: attempt: %d, caught exception(%s) from cmd (%s), pausing for %d seconds" % (attempt, e, cmd_summary, pause) msg = "ssh_retry: attempt: %d, caught exception(%s) from cmd (%s), pausing for %d seconds" % (attempt, e, cmd_summary, pause)
self._display.vv(msg) display.vv(msg)
time.sleep(pause) time.sleep(pause)
continue continue
@ -605,7 +613,7 @@ class Connection(ConnectionBase):
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT {0} TO {1}".format(in_path, out_path), host=self.host) display.vvv("PUT {0} TO {1}".format(in_path, out_path), host=self.host)
if not os.path.exists(in_path): if not os.path.exists(in_path):
raise AnsibleFileNotFound("file or module does not exist: {0}".format(in_path)) raise AnsibleFileNotFound("file or module does not exist: {0}".format(in_path))
@ -630,7 +638,7 @@ class Connection(ConnectionBase):
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH {0} TO {1}".format(in_path, out_path), host=self.host) display.vvv("FETCH {0} TO {1}".format(in_path, out_path), host=self.host)
# scp and sftp require square brackets for IPv6 addresses, but # scp and sftp require square brackets for IPv6 addresses, but
# accept them for hostnames and IPv4 addresses too. # accept them for hostnames and IPv4 addresses too.

@ -42,13 +42,19 @@ try:
except ImportError: except ImportError:
pass pass
from ansible import constants as C from ansible.errors import AnsibleFileNotFound
from ansible.errors import AnsibleConnectionFailure, AnsibleFileNotFound
from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection import ConnectionBase
from ansible.plugins import shell_loader
from ansible.utils.path import makedirs_safe from ansible.utils.path import makedirs_safe
from ansible.utils.unicode import to_bytes, to_unicode, to_str from ansible.utils.unicode import to_bytes, to_unicode, to_str
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
class Connection(ConnectionBase): class Connection(ConnectionBase):
'''WinRM connections over HTTP/HTTPS.''' '''WinRM connections over HTTP/HTTPS.'''
@ -111,7 +117,7 @@ class Connection(ConnectionBase):
''' '''
Establish a WinRM connection over HTTP/HTTPS. Establish a WinRM connection over HTTP/HTTPS.
''' '''
self._display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" % \ display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
(self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host) (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)
netloc = '%s:%d' % (self._winrm_host, self._winrm_port) netloc = '%s:%d' % (self._winrm_host, self._winrm_port)
endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', '')) endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
@ -120,7 +126,7 @@ class Connection(ConnectionBase):
if transport == 'kerberos' and not HAVE_KERBEROS: if transport == 'kerberos' and not HAVE_KERBEROS:
errors.append('kerberos: the python kerberos library is not installed') errors.append('kerberos: the python kerberos library is not installed')
continue continue
self._display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host) display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
try: try:
protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs) protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs)
protocol.send_message('') protocol.send_message('')
@ -137,7 +143,7 @@ class Connection(ConnectionBase):
elif code == 411: elif code == 411:
return protocol return protocol
errors.append('%s: %s' % (transport, err_msg)) errors.append('%s: %s' % (transport, err_msg))
self._display.vvvvv('WINRM CONNECTION ERROR: %s\n%s' % (err_msg, traceback.format_exc()), host=self._winrm_host) display.vvvvv('WINRM CONNECTION ERROR: %s\n%s' % (err_msg, traceback.format_exc()), host=self._winrm_host)
if errors: if errors:
raise AnsibleError(', '.join(errors)) raise AnsibleError(', '.join(errors))
else: else:
@ -145,9 +151,9 @@ class Connection(ConnectionBase):
def _winrm_exec(self, command, args=(), from_exec=False): def _winrm_exec(self, command, args=(), from_exec=False):
if from_exec: if from_exec:
self._display.vvvvv("WINRM EXEC %r %r" % (command, args), host=self._winrm_host) display.vvvvv("WINRM EXEC %r %r" % (command, args), host=self._winrm_host)
else: else:
self._display.vvvvvv("WINRM EXEC %r %r" % (command, args), host=self._winrm_host) display.vvvvvv("WINRM EXEC %r %r" % (command, args), host=self._winrm_host)
if not self.protocol: if not self.protocol:
self.protocol = self._winrm_connect() self.protocol = self._winrm_connect()
if not self.shell_id: if not self.shell_id:
@ -157,11 +163,11 @@ class Connection(ConnectionBase):
command_id = self.protocol.run_command(self.shell_id, to_bytes(command), map(to_bytes, args)) command_id = self.protocol.run_command(self.shell_id, to_bytes(command), map(to_bytes, args))
response = Response(self.protocol.get_command_output(self.shell_id, command_id)) response = Response(self.protocol.get_command_output(self.shell_id, command_id))
if from_exec: if from_exec:
self._display.vvvvv('WINRM RESULT %r' % to_unicode(response), host=self._winrm_host) display.vvvvv('WINRM RESULT %r' % to_unicode(response), host=self._winrm_host)
else: else:
self._display.vvvvvv('WINRM RESULT %r' % to_unicode(response), host=self._winrm_host) display.vvvvvv('WINRM RESULT %r' % to_unicode(response), host=self._winrm_host)
self._display.vvvvvv('WINRM STDOUT %s' % to_unicode(response.std_out), host=self._winrm_host) display.vvvvvv('WINRM STDOUT %s' % to_unicode(response.std_out), host=self._winrm_host)
self._display.vvvvvv('WINRM STDERR %s' % to_unicode(response.std_err), host=self._winrm_host) display.vvvvvv('WINRM STDERR %s' % to_unicode(response.std_err), host=self._winrm_host)
return response return response
finally: finally:
if command_id: if command_id:
@ -192,12 +198,12 @@ class Connection(ConnectionBase):
if '-EncodedCommand' in cmd_parts: if '-EncodedCommand' in cmd_parts:
encoded_cmd = cmd_parts[cmd_parts.index('-EncodedCommand') + 1] encoded_cmd = cmd_parts[cmd_parts.index('-EncodedCommand') + 1]
decoded_cmd = to_unicode(base64.b64decode(encoded_cmd).decode('utf-16-le')) decoded_cmd = to_unicode(base64.b64decode(encoded_cmd).decode('utf-16-le'))
self._display.vvv("EXEC %s" % decoded_cmd, host=self._winrm_host) display.vvv("EXEC %s" % decoded_cmd, host=self._winrm_host)
else: else:
self._display.vvv("EXEC %s" % cmd, host=self._winrm_host) display.vvv("EXEC %s" % cmd, host=self._winrm_host)
try: try:
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True) result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True)
except Exception as e: except Exception:
traceback.print_exc() traceback.print_exc()
raise AnsibleError("failed to exec cmd %s" % cmd) raise AnsibleError("failed to exec cmd %s" % cmd)
result.std_out = to_bytes(result.std_out) result.std_out = to_bytes(result.std_out)
@ -207,7 +213,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
out_path = self._shell._unquote(out_path) out_path = self._shell._unquote(out_path)
self._display.vvv('PUT "%s" TO "%s"' % (in_path, out_path), host=self._winrm_host) display.vvv('PUT "%s" TO "%s"' % (in_path, out_path), host=self._winrm_host)
if not os.path.exists(in_path): if not os.path.exists(in_path):
raise AnsibleFileNotFound('file or module does not exist: "%s"' % in_path) raise AnsibleFileNotFound('file or module does not exist: "%s"' % in_path)
with open(in_path) as in_file: with open(in_path) as in_file:
@ -235,7 +241,7 @@ class Connection(ConnectionBase):
out_path = out_path + '.ps1' out_path = out_path + '.ps1'
b64_data = base64.b64encode(out_data) b64_data = base64.b64encode(out_data)
script = script_template % (self._shell._escape(out_path), offset, b64_data, in_size) script = script_template % (self._shell._escape(out_path), offset, b64_data, in_size)
self._display.vvvvv('WINRM PUT "%s" to "%s" (offset=%d size=%d)' % (in_path, out_path, offset, len(out_data)), host=self._winrm_host) display.vvvvv('WINRM PUT "%s" to "%s" (offset=%d size=%d)' % (in_path, out_path, offset, len(out_data)), host=self._winrm_host)
cmd_parts = self._shell._encode_script(script, as_list=True) cmd_parts = self._shell._encode_script(script, as_list=True)
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:]) result = self._winrm_exec(cmd_parts[0], cmd_parts[1:])
if result.status_code != 0: if result.status_code != 0:
@ -248,7 +254,7 @@ class Connection(ConnectionBase):
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
in_path = self._shell._unquote(in_path) in_path = self._shell._unquote(in_path)
out_path = out_path.replace('\\', '/') out_path = out_path.replace('\\', '/')
self._display.vvv('FETCH "%s" TO "%s"' % (in_path, out_path), host=self._winrm_host) display.vvv('FETCH "%s" TO "%s"' % (in_path, out_path), host=self._winrm_host)
buffer_size = 2**19 # 0.5MB chunks buffer_size = 2**19 # 0.5MB chunks
makedirs_safe(os.path.dirname(out_path)) makedirs_safe(os.path.dirname(out_path))
out_file = None out_file = None
@ -277,7 +283,7 @@ class Connection(ConnectionBase):
Exit 1; Exit 1;
} }
''' % dict(buffer_size=buffer_size, path=self._shell._escape(in_path), offset=offset) ''' % dict(buffer_size=buffer_size, path=self._shell._escape(in_path), offset=offset)
self._display.vvvvv('WINRM FETCH "%s" to "%s" (offset=%d)' % (in_path, out_path, offset), host=self._winrm_host) display.vvvvv('WINRM FETCH "%s" to "%s" (offset=%d)' % (in_path, out_path, offset), host=self._winrm_host)
cmd_parts = self._shell._encode_script(script, as_list=True) cmd_parts = self._shell._encode_script(script, as_list=True)
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:]) result = self._winrm_exec(cmd_parts[0], cmd_parts[1:])
if result.status_code != 0: if result.status_code != 0:

@ -32,6 +32,12 @@ 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
try:
from __main__ import display
display = display
except ImportError:
from ansible.utils.display import Display
display = Display()
BUFSIZE = 65536 BUFSIZE = 65536
@ -59,7 +65,7 @@ class Connection(ConnectionBase):
self.zoneadm_cmd = self._search_executable('zoneadm') self.zoneadm_cmd = self._search_executable('zoneadm')
self.zlogin_cmd = self._search_executable('zlogin') self.zlogin_cmd = self._search_executable('zlogin')
if not self.zone in self.list_zones(): if self.zone not in self.list_zones():
raise AnsibleError("incorrect zone name %s" % self.zone) raise AnsibleError("incorrect zone name %s" % self.zone)
@staticmethod @staticmethod
@ -76,10 +82,10 @@ class Connection(ConnectionBase):
zones = [] zones = []
for l in process.stdout.readlines(): for l in process.stdout.readlines():
# 1:work:running:/zones/work:3126dc59-9a07-4829-cde9-a816e4c5040e:native:shared # 1:work:running:/zones/work:3126dc59-9a07-4829-cde9-a816e4c5040e:native:shared
s = l.split(':') s = l.split(':')
if s[1] != 'global': if s[1] != 'global':
zones.append(s[1]) zones.append(s[1])
return zones return zones
@ -98,7 +104,7 @@ class Connection(ConnectionBase):
''' connect to the zone; nothing to do here ''' ''' connect to the zone; nothing to do here '''
super(Connection, self)._connect() super(Connection, self)._connect()
if not self._connected: if not self._connected:
self._display.vvv("THIS IS A LOCAL ZONE DIR", host=self.zone) display.vvv("THIS IS A LOCAL ZONE DIR", host=self.zone)
self._connected = True self._connected = True
def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE): def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
@ -117,7 +123,7 @@ class Connection(ConnectionBase):
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh' executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else '/bin/sh'
local_cmd = [self.zlogin_cmd, self.zone, executable, '-c', cmd] local_cmd = [self.zlogin_cmd, self.zone, executable, '-c', cmd]
self._display.vvv("EXEC %s" % (local_cmd), host=self.zone) display.vvv("EXEC %s" % (local_cmd), host=self.zone)
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin, p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -156,7 +162,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
''' transfer a file from local to zone ''' ''' transfer a file from local to zone '''
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.zone) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.zone)
out_path = pipes.quote(self._prefix_login_path(out_path)) out_path = pipes.quote(self._prefix_login_path(out_path))
try: try:
@ -178,7 +184,7 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
''' fetch a file from zone to local ''' ''' fetch a file from zone to local '''
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.zone) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.zone)
in_path = pipes.quote(self._prefix_login_path(in_path)) in_path = pipes.quote(self._prefix_login_path(in_path))
try: try:

Loading…
Cancel
Save