From 94c93e533f533206611ed70934b5819d7a318289 Mon Sep 17 00:00:00 2001 From: Kevin Carter Date: Wed, 11 Jul 2018 16:19:39 -0500 Subject: [PATCH] Correct severe performance problem When running our plugins we're seeing a severe performance impact in the ansible run-time. As it turns out, within the linear strategy we're looping over all physical hosts in an environment and pulling address information out to store as a task variable. This action causes all tasks to reload all {group,host}_vars for all hosts and that repetitive action results in a massive slowdown, especially when there are many hosts within the inventory. Results from a normal OSA playbook run on 50 hosts: time openstack-ansible openstack-hosts-setup.yml --forks 15 real 37m44.263s user 35m30.984s sys 2m23.252s Results with the strategy plugin disabled on 50 hosts: time ANSIBLE_STRATEGY_PLUGINS=false openstack-ansible openstack-hosts-setup.yml --forks 15 real 5m8.641s user 6m30.792s sys 1m32.512s This change scopes the physical host look up to the task and target host and adds conditionals around the process to ensure we're not forcing a lookup that has no chance of succeeding. Results with this patch applied on 50 hosts and no forks: time openstack-ansible openstack-hosts-setup.yml real 6m40.573s user 7m53.336s sys 1m25.828s Should anything like this come up again debug statements have been added to the method so that we can enable verbose mode and know what is being parsed. Change-Id: I76af71ffe19b2a8afb18ed731f1362a4e399c613 Signed-off-by: Kevin Carter --- strategy/linear.py | 48 ++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/strategy/linear.py b/strategy/linear.py index 4dcf40d9..0454c62b 100644 --- a/strategy/linear.py +++ b/strategy/linear.py @@ -125,23 +125,39 @@ class StrategyModule(LINEAR.StrategyModule): _play_context = copy.deepcopy(play_context) - try: - groups = self._inventory.get_groups_dict() - except AttributeError: - groups = self._inventory.get_group_dict() - physical_hosts = groups.get('hosts', groups.get('all', {})) - physical_host_addrs = {} - for physical_host in physical_hosts: - physical_host_vars = self._variable_manager.get_vars( - host=self._inventory.get_host(physical_host) + pha = task_vars['physical_host_addrs'] = dict() + physical_host_item = host.vars.get('physical_host') + if physical_host_item: + LINEAR.display.verbose( + u'The "physical_host" variable was found.', + host=host, + caplevel=0 ) - physical_host_templar = LINEAR.Templar(loader=self._loader, - variables=physical_host_vars) - physical_host_addr = physical_host_templar.template( - physical_host_vars.get('ansible_host', - physical_host)) - physical_host_addrs[physical_host] = physical_host_addr - task_vars['physical_host_addrs'] = physical_host_addrs + ph = self._inventory.get_host(physical_host_item) + if ph: + LINEAR.display.verbose( + u'The "physical_host" variable of "%s" has been found to' + u' have a corresponding host entry in inventory.' + % physical_host_item, + host=host, + caplevel=0 + ) + physical_host_vars = self._variable_manager.get_vars(host=ph) + for item in ['ansible_host', 'container_address', 'address']: + addr = physical_host_vars.get(item) + if addr: + LINEAR.display.verbose( + u'The "physical_host" variable of "%s" terminates' + u' at "%s" using the host variable "%s".' % ( + physical_host_item, + addr, + item + ), + host=host, + caplevel=0 + ) + pha[ph.name] = addr + break if task.delegate_to: # If a task uses delegation change the play_context