Reduce interactions by nearly 50%

The container interactions require a couple interactions to address the
container namespace as well as pad the pathing when transmitting a file.
This change reduces those interactions by nearly half for a single task
by storing information about a target container instead of looking it up
for every interaction.

Example file transfer:
  > Before this PR: http://paste.openstack.org/show/691341/
  > After this PR: http://paste.openstack.org/show/691338/

In the example we can see the "Before" runnins 20 commands to transfer
a file to a target while the "After" is running only 11.

Example command:
  > Before: http://paste.openstack.org/show/691343/
  > After: http://paste.openstack.org/show/691344/

In the command example we can see the "Before" is running 10 commands
to run a single command task while the "After" is running only 6.

This change will improve general ansible performance by cutting down the
number of operations needed to be completed to execute any one task.

Change-Id: Ia8405ec5c3b55ed3f7f134c4882d337c5e0b625f
Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
(cherry picked from commit 9dc4ce2a04)
This commit is contained in:
Kevin Carter 2018-03-05 00:40:19 -06:00
parent 2472c81eb3
commit 35727b8eb8
1 changed files with 33 additions and 22 deletions

View File

@ -78,6 +78,9 @@ class Connection(SSH.Connection):
if self._play_context.remote_user:
self.container_user = self._play_context.remote_user
# Store the container pid for multi-use
self.container_pid = None
def set_host_overrides(self, host, hostvars=None, templar=None):
if self._container_check() or self._chroot_check():
physical_host_addrs = host.get_vars().get('physical_host_addrs', {})
@ -90,17 +93,10 @@ class Connection(SSH.Connection):
if self._container_check():
# Remote user is normally set, but if it isn't, then default to 'root'
self.container_user = 'root'
if self._play_context.remote_user:
self.container_user = self._play_context.remote_user
# NOTE(hwoarang) It is important to connect to the container
# without inheriting the host environment as that would interfere
# with running commands and services inside the container. However,
# it is also important to create a sensible environment within the
# container because certain commands and services expect some
# enviromental variables to be set properly. The best way to do
# that would be to execute the commands in a login shell
else:
self.container_user = 'root'
# NOTE(hwoarang): the shlex_quote method is necessary here because
# we need to properly quote the cmd as it's being passed as argument
# to the -c su option. The Ansible ssh class has already
@ -132,7 +128,7 @@ class Connection(SSH.Connection):
SSH.shlex_quote(cmd)
)
if self._chroot_check():
elif self._chroot_check():
chroot_command = 'chroot %s' % self.chroot_path
cmd = '%s %s' % (chroot_command, cmd)
@ -169,6 +165,15 @@ class Connection(SSH.Connection):
return False
def _pid_lookup(self, subdir=None):
"""Lookup the container pid return padding.
The container pid path will be set and returned to the
function. If this is a new lookup, the method will run
a lookup command and set the "self.container_pid" variable
so that a container lookup is not required on a subsequent
command within the same task.
"""
pid_path = """/proc/%s"""
if self.container_tech == 'nspawn':
lookup_command = (
u"machinectl show %s | awk -F'=' '/Leader/ {print $2}'"
@ -188,20 +193,26 @@ class Connection(SSH.Connection):
else:
return 1, ''
args = ('ssh', self.host, lookup_command)
returncode, stdout, _ = self._run(
self._build_command(*args),
in_data=None,
sudoable=False
)
pid_path = os.path.join(
pid_path % SSH.to_text(stdout.strip()),
subdir
)
return returncode, pid_path
if not self.container_pid:
args = ('ssh', self.host, lookup_command)
returncode, stdout, _ = self._run(
self._build_command(*args),
in_data=None,
sudoable=False
)
self.container_pid = stdout.strip()
pid_path = os.path.join(
pid_path % SSH.to_text(self.container_pid),
subdir
)
return returncode, pid_path
else:
return 0, os.path.join(
pid_path % SSH.to_text(self.container_pid),
subdir
)
def _container_path_pad(self, path):
returncode, pid_path = self._pid_lookup()
if returncode == 0:
pad = os.path.join(