mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Move connection plugins to using global display
This commit is contained in:
parent
318bfbb207
commit
aa4f213cb5
11 changed files with 192 additions and 131 deletions
|
@ -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,17 +29,23 @@ 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
|
||||||
# which leaves room for the TCP/IP header. We set this to a
|
# which leaves room for the TCP/IP header. We set this to a
|
||||||
# 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,25 +68,25 @@ 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)
|
||||||
if not self.validate_user():
|
if not self.validate_user():
|
||||||
# the accelerated daemon was started with a
|
# the accelerated daemon was started with a
|
||||||
# different remote_user. The above command
|
# different remote_user. The above command
|
||||||
# should have caused the accelerate daemon to
|
# should have caused the accelerate daemon to
|
||||||
# shutdown, so we'll reconnect.
|
# shutdown, so we'll reconnect.
|
||||||
|
@ -97,37 +103,37 @@ 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")
|
||||||
|
|
||||||
def validate_user(self):
|
def validate_user(self):
|
||||||
'''
|
'''
|
||||||
Checks the remote uid of the accelerated daemon vs. the
|
Checks the remote uid of the accelerated daemon vs. the
|
||||||
one specified for this play and will cause the accel
|
one specified for this play and will cause the accel
|
||||||
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',
|
||||||
|
@ -180,11 +186,11 @@ class Connection(ConnectionBase):
|
||||||
data = keyczar_encrypt(self.key, data)
|
data = keyczar_encrypt(self.key, data)
|
||||||
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)
|
||||||
|
|
||||||
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
|
||||||
# ({"pong":"true"}) rather than the response we want.
|
# ({"pong":"true"}) rather than the response we want.
|
||||||
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)
|
||||||
|
@ -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)
|
||||||
|
@ -271,7 +277,7 @@ class Connection(ConnectionBase):
|
||||||
out = base64.b64decode(response['data'])
|
out = base64.b64decode(response['data'])
|
||||||
fh.write(out)
|
fh.write(out)
|
||||||
bytes += len(out)
|
bytes += len(out)
|
||||||
# send an empty response back to signify we
|
# send an empty response back to signify we
|
||||||
# received the last chunk without errors
|
# received the last chunk without errors
|
||||||
data = jsonify(dict())
|
data = jsonify(dict())
|
||||||
data = keyczar_encrypt(self.key, data)
|
data = keyczar_encrypt(self.key, 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,15 +82,15 @@ 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
|
||||||
|
|
||||||
def get_zone_path(self):
|
def get_zone_path(self):
|
||||||
#solaris10vm# zoneadm -z cswbuild list -p
|
#solaris10vm# zoneadm -z cswbuild list -p
|
||||||
#-:cswbuild:installed:/zones/cswbuild:479f3c4b-d0c6-e97b-cd04-fd58f2c0238e:native:shared
|
#-:cswbuild:installed:/zones/cswbuild:479f3c4b-d0c6-e97b-cd04-fd58f2c0238e:native:shared
|
||||||
process = subprocess.Popen([self.zoneadm_cmd, '-z', self.zone, 'list', '-p'],
|
process = subprocess.Popen([self.zoneadm_cmd, '-z', self.zone, 'list', '-p'],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
|
@ -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):
|
||||||
|
@ -113,11 +119,11 @@ class Connection(ConnectionBase):
|
||||||
# -c. Not sure why as cmd could contain shell metachars (like
|
# -c. Not sure why as cmd could contain shell metachars (like
|
||||||
# cmd = "mkdir -p $HOME/pathname && echo $HOME/pathname") which
|
# cmd = "mkdir -p $HOME/pathname && echo $HOME/pathname") which
|
||||||
# probably wouldn't work without a shell. Get someone to test that
|
# probably wouldn't work without a shell. Get someone to test that
|
||||||
# this connection plugin works and then we can remove this note
|
# this connection plugin works and then we can remove this note
|
||||||
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…
Reference in a new issue