Skip to content

Commit

Permalink
Support delegation in strategy plugin
Browse files Browse the repository at this point in the history
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
  • Loading branch information
logan2211 and jimmymccrory committed Apr 21, 2017
1 parent 5e1828c commit d8c0341
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 39 deletions.
31 changes: 19 additions & 12 deletions connection/ssh.py
Expand Up @@ -46,11 +46,18 @@ def __init__(self, *args, **kwargs):
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

Expand All @@ -68,25 +75,25 @@ def exec_command(self, cmd, in_data=None, sudoable=True):
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

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

Expand Down
39 changes: 12 additions & 27 deletions strategy/linear.py
Expand Up @@ -26,6 +26,16 @@
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.
Expand Down Expand Up @@ -94,15 +104,14 @@ def _check_when(host, task, templar, task_vars):
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
Expand All @@ -129,30 +138,6 @@ def _queue_task(self, host, task, task_vars, play_context):
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,
Expand Down

0 comments on commit d8c0341

Please sign in to comment.