Add parent pid to persistent connection socket path hash (#33518)
* Add parent pid to persistent connection socket path hash Fixes #33192 * Add parent pid in persistent connection socket path hash to avoid using same socket path for multiple simultaneous connection to same remote host. * Ensure unique persistent socket path for each ansible-playbook run * Fix CI failures
This commit is contained in:
parent
08a2338277
commit
2f932d8767
5 changed files with 17 additions and 10 deletions
|
@ -40,7 +40,7 @@ class ConnectionProcess(object):
|
||||||
The connection process wraps around a Connection object that manages
|
The connection process wraps around a Connection object that manages
|
||||||
the connection to a remote device that persists over the playbook
|
the connection to a remote device that persists over the playbook
|
||||||
'''
|
'''
|
||||||
def __init__(self, fd, play_context, socket_path, original_path):
|
def __init__(self, fd, play_context, socket_path, original_path, ansible_playbook_pid=None):
|
||||||
self.play_context = play_context
|
self.play_context = play_context
|
||||||
self.socket_path = socket_path
|
self.socket_path = socket_path
|
||||||
self.original_path = original_path
|
self.original_path = original_path
|
||||||
|
@ -52,6 +52,7 @@ class ConnectionProcess(object):
|
||||||
self.sock = None
|
self.sock = None
|
||||||
|
|
||||||
self.connection = None
|
self.connection = None
|
||||||
|
self._ansible_playbook_pid = ansible_playbook_pid
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
try:
|
try:
|
||||||
|
@ -65,8 +66,8 @@ class ConnectionProcess(object):
|
||||||
# find it now that our cwd is /
|
# find it now that our cwd is /
|
||||||
if self.play_context.private_key_file and self.play_context.private_key_file[0] not in '~/':
|
if self.play_context.private_key_file and self.play_context.private_key_file[0] not in '~/':
|
||||||
self.play_context.private_key_file = os.path.join(self.original_path, self.play_context.private_key_file)
|
self.play_context.private_key_file = os.path.join(self.original_path, self.play_context.private_key_file)
|
||||||
|
self.connection = connection_loader.get(self.play_context.connection, self.play_context, '/dev/null',
|
||||||
self.connection = connection_loader.get(self.play_context.connection, self.play_context, '/dev/null')
|
ansible_playbook_pid=self._ansible_playbook_pid)
|
||||||
self.connection.set_options()
|
self.connection.set_options()
|
||||||
self.connection._connect()
|
self.connection._connect()
|
||||||
self.connection._socket_path = self.socket_path
|
self.connection._socket_path = self.socket_path
|
||||||
|
@ -244,7 +245,8 @@ def main():
|
||||||
|
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
ssh = connection_loader.get('ssh', class_only=True)
|
ssh = connection_loader.get('ssh', class_only=True)
|
||||||
cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user, play_context.connection)
|
ansible_playbook_pid = sys.argv[1]
|
||||||
|
cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user, play_context.connection, ansible_playbook_pid)
|
||||||
|
|
||||||
# create the persistent connection dir if need be and create the paths
|
# create the persistent connection dir if need be and create the paths
|
||||||
# which we will be using later
|
# which we will be using later
|
||||||
|
@ -268,7 +270,7 @@ def main():
|
||||||
try:
|
try:
|
||||||
os.close(r)
|
os.close(r)
|
||||||
wfd = os.fdopen(w, 'w')
|
wfd = os.fdopen(w, 'w')
|
||||||
process = ConnectionProcess(wfd, play_context, socket_path, original_path)
|
process = ConnectionProcess(wfd, play_context, socket_path, original_path, ansible_playbook_pid)
|
||||||
process.start()
|
process.start()
|
||||||
except Exception:
|
except Exception:
|
||||||
messages.append(traceback.format_exc())
|
messages.append(traceback.format_exc())
|
||||||
|
|
|
@ -726,7 +726,7 @@ class TaskExecutor:
|
||||||
|
|
||||||
conn_type = self._play_context.connection
|
conn_type = self._play_context.connection
|
||||||
|
|
||||||
connection = self._shared_loader_obj.connection_loader.get(conn_type, self._play_context, self._new_stdin)
|
connection = self._shared_loader_obj.connection_loader.get(conn_type, self._play_context, self._new_stdin, ansible_playbook_pid=to_text(os.getppid()))
|
||||||
if not connection:
|
if not connection:
|
||||||
raise AnsibleError("the connection plugin '%s' was not found" % conn_type)
|
raise AnsibleError("the connection plugin '%s' was not found" % conn_type)
|
||||||
|
|
||||||
|
@ -800,7 +800,7 @@ class TaskExecutor:
|
||||||
Starts the persistent connection
|
Starts the persistent connection
|
||||||
'''
|
'''
|
||||||
master, slave = pty.openpty()
|
master, slave = pty.openpty()
|
||||||
p = subprocess.Popen(["ansible-connection"], stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
p = subprocess.Popen(["ansible-connection", to_text(os.getppid())], stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
stdin = os.fdopen(master, 'wb', 0)
|
stdin = os.fdopen(master, 'wb', 0)
|
||||||
os.close(slave)
|
os.close(slave)
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,8 @@ class Connection(ConnectionBase):
|
||||||
self._terminal = None
|
self._terminal = None
|
||||||
self._cliconf = None
|
self._cliconf = None
|
||||||
|
|
||||||
|
self._ansible_playbook_pid = kwargs.get('ansible_playbook_pid')
|
||||||
|
|
||||||
if self._play_context.verbosity > 3:
|
if self._play_context.verbosity > 3:
|
||||||
logging.getLogger('paramiko').setLevel(logging.DEBUG)
|
logging.getLogger('paramiko').setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
@ -220,7 +222,8 @@ class Connection(ConnectionBase):
|
||||||
value to None and the _connected value to False
|
value to None and the _connected value to False
|
||||||
'''
|
'''
|
||||||
ssh = connection_loader.get('ssh', class_only=True)
|
ssh = connection_loader.get('ssh', class_only=True)
|
||||||
cp = ssh._create_control_path(self._play_context.remote_addr, self._play_context.port, self._play_context.remote_user, self._play_context.connection)
|
cp = ssh._create_control_path(self._play_context.remote_addr, self._play_context.port, self._play_context.remote_user, self._play_context.connection,
|
||||||
|
self._ansible_playbook_pid)
|
||||||
|
|
||||||
tmp_path = unfrackpath(C.PERSISTENT_CONTROL_PATH_DIR)
|
tmp_path = unfrackpath(C.PERSISTENT_CONTROL_PATH_DIR)
|
||||||
socket_path = unfrackpath(cp % dict(directory=tmp_path))
|
socket_path = unfrackpath(cp % dict(directory=tmp_path))
|
||||||
|
|
|
@ -75,7 +75,7 @@ class Connection(ConnectionBase):
|
||||||
Starts the persistent connection
|
Starts the persistent connection
|
||||||
'''
|
'''
|
||||||
master, slave = pty.openpty()
|
master, slave = pty.openpty()
|
||||||
p = subprocess.Popen(["ansible-connection"], stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
p = subprocess.Popen(["ansible-connection", to_text(os.getppid())], stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
stdin = os.fdopen(master, 'wb', 0)
|
stdin = os.fdopen(master, 'wb', 0)
|
||||||
os.close(slave)
|
os.close(slave)
|
||||||
|
|
||||||
|
|
|
@ -315,11 +315,13 @@ class Connection(ConnectionBase):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_control_path(host, port, user, connection=None):
|
def _create_control_path(host, port, user, connection=None, pid=None):
|
||||||
'''Make a hash for the controlpath based on con attributes'''
|
'''Make a hash for the controlpath based on con attributes'''
|
||||||
pstring = '%s-%s-%s' % (host, port, user)
|
pstring = '%s-%s-%s' % (host, port, user)
|
||||||
if connection:
|
if connection:
|
||||||
pstring += '-%s' % connection
|
pstring += '-%s' % connection
|
||||||
|
if pid:
|
||||||
|
pstring += '-%s' % to_text(pid)
|
||||||
m = hashlib.sha1()
|
m = hashlib.sha1()
|
||||||
m.update(to_bytes(pstring))
|
m.update(to_bytes(pstring))
|
||||||
digest = m.hexdigest()
|
digest = m.hexdigest()
|
||||||
|
|
Loading…
Reference in a new issue