From 74a252d0a57472b60f7e4ca08f2ace1063660551 Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Wed, 18 May 2016 14:06:13 -0400 Subject: [PATCH] More playbook executor compatibility fixes With some earlier changes, continuing to forward failed hosts on to the iterator with each TQM run() call was causing plays with max_fail_pct set to fail, as hosts which failed in previous plays were counting those old failures against the % calculation. Also changed the linear strategy's calculation to use the internal failed list, rather than the iterator, as this now represents the hosts failed during the current run only. --- lib/ansible/executor/task_queue_manager.py | 14 +++++++++++--- lib/ansible/plugins/strategy/linear.py | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/ansible/executor/task_queue_manager.py b/lib/ansible/executor/task_queue_manager.py index ba4970ed662..8373264ef18 100644 --- a/lib/ansible/executor/task_queue_manager.py +++ b/lib/ansible/executor/task_queue_manager.py @@ -236,13 +236,16 @@ class TaskQueueManager: start_at_done = self._start_at_done, ) - # because the TQM may survive multiple play runs, we start by - # marking any hosts as failed in the iterator here which may - # have been marked as failed in previous runs. + # Because the TQM may survive multiple play runs, we start by marking + # any hosts as failed in the iterator here which may have been marked + # as failed in previous runs. Then we clear the internal list of failed + # hosts so we know what failed this round. for host_name in self._failed_hosts.keys(): host = self._inventory.get_host(host_name) iterator.mark_host_failed(host) + self.clear_failed_hosts() + # during initialization, the PlayContext will clear the start_at_task # field to signal that a matching task was found, so check that here # and remember it so we don't try to skip tasks on future plays @@ -251,6 +254,11 @@ class TaskQueueManager: # and run the play using the strategy and cleanup on way out play_return = strategy.run(iterator, play_context) + + # now re-save the hosts that failed from the iterator to our internal list + for host_name in iterator.get_failed_hosts(): + self._failed_hosts[host_name] = True + self._cleanup_processes() return play_return diff --git a/lib/ansible/plugins/strategy/linear.py b/lib/ansible/plugins/strategy/linear.py index 0b8f0318c64..2d3396a3b20 100644 --- a/lib/ansible/plugins/strategy/linear.py +++ b/lib/ansible/plugins/strategy/linear.py @@ -367,7 +367,7 @@ class StrategyModule(StrategyBase): if iterator._play.max_fail_percentage is not None and len(results) > 0: percentage = iterator._play.max_fail_percentage / 100.0 - if (len(iterator.get_failed_hosts()) / len(results)) > percentage: + if (len(self._tqm._failed_hosts) / len(results)) > percentage: for host in hosts_left: # don't double-mark hosts, or the iterator will potentially # fail them out of the rescue/always states