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)
self.args = args
self.kwargs = kwargs
self.vars = self._play_context._attributes['vars']
self.chroot_path = self.vars.get('chroot_path')
self.container_name = self.vars.get('container_name')
self.physical_host = self.vars.get('physical_host')
self.physical_hostname = self.vars.get('physical_hostname')
if hasattr(self._play_context, 'chroot_path'):
self.chroot_path = self._play_context.chroot_path
else:
self.chroot_path = None
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():
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)
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)
if self.physical_hostname:
if self.physical_host is not None:
SSH.display.vvv(
u'physical_hostname: "%s"' % self.physical_hostname
u'physical_host: "%s"' % self.physical_host
)
SSH.display.vvv(u'chroot confirmed')
return True
@ -80,13 +87,13 @@ class Connection(SSH.Connection):
return False
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)
if self.physical_hostname:
if self.physical_host is not None:
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')
return True

View File

@ -26,6 +26,16 @@ LINEAR = imp.load_source(
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):
"""Notes about this strategy.
@ -94,15 +104,14 @@ class StrategyModule(LINEAR.StrategyModule):
def _queue_task(self, host, task, task_vars, play_context):
"""Queue a task to be sent to the worker.
Modify the playbook_context to support adding attributes for remote
LXC containers or remote chroots.
Modify the playbook_context to disable pipelining and use the paramiko
transport method when a task is being delegated.
"""
templar = LINEAR.Templar(loader=self._loader, variables=task_vars)
if not self._check_when(host, task, templar, task_vars):
return
_play_context = copy.deepcopy(play_context)
_vars = _play_context._attributes['vars']
if task.delegate_to:
# If a task uses delegation change the play_context
# to use paramiko with pipelining disabled for this
@ -129,30 +138,6 @@ class StrategyModule(LINEAR.StrategyModule):
host=host,
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(
host,