Support delegation in strategy plugin

The strategy plugin previously did not support container detection
when the delegate_to host was a container. This adds support for
delegating tasks to other containers, so the strategy will perform
the same container vars lookups so the SSH connection is toward the
physical host of the container, and the command is wrapped with
lxc-attach based on the container_name.

Co-Authored-By: Jimmy McCrory <jimmy.mccrory@gmail.com>
Change-Id: I56d8afddbccf01f2944d2fdd505b601a4b048374
This commit is contained in:
Logan V 2017-04-07 09:37:53 -05:00 committed by Jimmy McCrory
parent 5e1828ce6e
commit d8c0341ab8
2 changed files with 31 additions and 39 deletions

View File

@ -46,11 +46,18 @@ class Connection(SSH.Connection):
super(Connection, self).__init__(*args, **kwargs) super(Connection, self).__init__(*args, **kwargs)
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
self.vars = self._play_context._attributes['vars'] if hasattr(self._play_context, 'chroot_path'):
self.chroot_path = self.vars.get('chroot_path') self.chroot_path = self._play_context.chroot_path
self.container_name = self.vars.get('container_name') else:
self.physical_host = self.vars.get('physical_host') self.chroot_path = None
self.physical_hostname = self.vars.get('physical_hostname') if hasattr(self._play_context, 'container_name'):
self.container_name = self._play_context.container_name
else:
self.container_name = None
if hasattr(self._play_context, 'physical_host'):
self.physical_host = self._play_context.physical_host
else:
self.physical_host = None
if self._container_check() or self._chroot_check(): if self._container_check() or self._chroot_check():
self.host = self._play_context.remote_addr = self.physical_host self.host = self._play_context.remote_addr = self.physical_host
@ -68,11 +75,11 @@ class Connection(SSH.Connection):
return super(Connection, self).exec_command(cmd, in_data, sudoable) return super(Connection, self).exec_command(cmd, in_data, sudoable)
def _chroot_check(self): def _chroot_check(self):
if self.chroot_path: if self.chroot_path is not None:
SSH.display.vvv(u'chroot_path: "%s"' % self.chroot_path) SSH.display.vvv(u'chroot_path: "%s"' % self.chroot_path)
if self.physical_hostname: if self.physical_host is not None:
SSH.display.vvv( SSH.display.vvv(
u'physical_hostname: "%s"' % self.physical_hostname u'physical_host: "%s"' % self.physical_host
) )
SSH.display.vvv(u'chroot confirmed') SSH.display.vvv(u'chroot confirmed')
return True return True
@ -80,13 +87,13 @@ class Connection(SSH.Connection):
return False return False
def _container_check(self): def _container_check(self):
if self.container_name: if self.container_name is not None:
SSH.display.vvv(u'container_name: "%s"' % self.container_name) SSH.display.vvv(u'container_name: "%s"' % self.container_name)
if self.physical_hostname: if self.physical_host is not None:
SSH.display.vvv( SSH.display.vvv(
u'physical_hostname: "%s"' % self.physical_hostname u'physical_host: "%s"' % self.physical_host
) )
if self.container_name != self.physical_hostname: if self.container_name != self.physical_host:
SSH.display.vvv(u'Container confirmed') SSH.display.vvv(u'Container confirmed')
return True return True

View File

@ -26,6 +26,16 @@ LINEAR = imp.load_source(
os.path.join(os.path.dirname(strategy.__file__), 'linear.py') os.path.join(os.path.dirname(strategy.__file__), 'linear.py')
) )
# NOTICE(jmccrory): The play_context is imported so that additional container
# specific variables can be made available to connection
# plugins.
import ansible.playbook.play_context
ansible.playbook.play_context.MAGIC_VARIABLE_MAPPING.update({'physical_host':
('physical_host',)})
ansible.playbook.play_context.MAGIC_VARIABLE_MAPPING.update({'container_name':
('inventory_hostname',)})
ansible.playbook.play_context.MAGIC_VARIABLE_MAPPING.update({'chroot_path':
('chroot_path',)})
class StrategyModule(LINEAR.StrategyModule): class StrategyModule(LINEAR.StrategyModule):
"""Notes about this strategy. """Notes about this strategy.
@ -94,15 +104,14 @@ class StrategyModule(LINEAR.StrategyModule):
def _queue_task(self, host, task, task_vars, play_context): def _queue_task(self, host, task, task_vars, play_context):
"""Queue a task to be sent to the worker. """Queue a task to be sent to the worker.
Modify the playbook_context to support adding attributes for remote Modify the playbook_context to disable pipelining and use the paramiko
LXC containers or remote chroots. transport method when a task is being delegated.
""" """
templar = LINEAR.Templar(loader=self._loader, variables=task_vars) templar = LINEAR.Templar(loader=self._loader, variables=task_vars)
if not self._check_when(host, task, templar, task_vars): if not self._check_when(host, task, templar, task_vars):
return return
_play_context = copy.deepcopy(play_context) _play_context = copy.deepcopy(play_context)
_vars = _play_context._attributes['vars']
if task.delegate_to: if task.delegate_to:
# If a task uses delegation change the play_context # If a task uses delegation change the play_context
# to use paramiko with pipelining disabled for this # to use paramiko with pipelining disabled for this
@ -129,30 +138,6 @@ class StrategyModule(LINEAR.StrategyModule):
host=host, host=host,
caplevel=0 caplevel=0
) )
else:
physical_host = _vars.get('physical_host')
if not physical_host:
physical_host = task_vars.get('physical_host')
if physical_host:
ph = self._inventory.get_host(physical_host)
ansible_host = ph.vars.get('ansible_host')
if not ansible_host:
ansible_host = ph.vars.get('ansible_host')
if ansible_host:
_vars['physical_host'] = ansible_host
_vars['physical_hostname'] = physical_host
container_name = _vars.get('container_name')
if not container_name:
container_name = task_vars.get('container_name')
if container_name:
_vars['container_name'] = container_name
chroot_path = _vars.get('chroot_path')
if not chroot_path:
chroot_path = task_vars.get('chroot_path')
if chroot_path:
_vars['chroot_path'] = chroot_path
return super(StrategyModule, self)._queue_task( return super(StrategyModule, self)._queue_task(
host, host,