Fixing bugs in strategies

* Don't filter hosts remaining based on their failed state. Instead rely
  on the PlayIterator to return None/ITERATING_COMPLETE when the host is
  failed.
* In the free strategy, make sure we wait outside the host loop for all
  pending results to be processed.
* Use the internal _set_failed_state() instead of manually setting things
  when a failed child state is hit

Fixes #15623
pull/15759/head
James Cammarata 9 years ago
parent 4574a0e82d
commit 506e6255b2

@ -326,8 +326,7 @@ class PlayIterator:
if self._check_failed_state(state.tasks_child_state): if self._check_failed_state(state.tasks_child_state):
# failed child state, so clear it and move into the rescue portion # failed child state, so clear it and move into the rescue portion
state.tasks_child_state = None state.tasks_child_state = None
state.fail_state |= self.FAILED_TASKS self._set_failed_state(state)
state.run_state = self.ITERATING_RESCUE
else: else:
# get the next task recursively # get the next task recursively
if task is None or state.tasks_child_state.run_state == self.ITERATING_COMPLETE: if task is None or state.tasks_child_state.run_state == self.ITERATING_COMPLETE:
@ -365,8 +364,7 @@ class PlayIterator:
(state.rescue_child_state, task) = self._get_next_task_from_state(state.rescue_child_state, host=host, peek=peek) (state.rescue_child_state, task) = self._get_next_task_from_state(state.rescue_child_state, host=host, peek=peek)
if self._check_failed_state(state.rescue_child_state): if self._check_failed_state(state.rescue_child_state):
state.rescue_child_state = None state.rescue_child_state = None
state.fail_state |= self.FAILED_RESCUE self._set_failed_state(state)
state.run_state = self.ITERATING_ALWAYS
else: else:
if task is None or state.rescue_child_state.run_state == self.ITERATING_COMPLETE: if task is None or state.rescue_child_state.run_state == self.ITERATING_COMPLETE:
state.rescue_child_state = None state.rescue_child_state = None
@ -396,8 +394,7 @@ class PlayIterator:
(state.always_child_state, task) = self._get_next_task_from_state(state.always_child_state, host=host, peek=peek) (state.always_child_state, task) = self._get_next_task_from_state(state.always_child_state, host=host, peek=peek)
if self._check_failed_state(state.always_child_state): if self._check_failed_state(state.always_child_state):
state.always_child_state = None state.always_child_state = None
state.fail_state |= self.FAILED_ALWAYS self._set_failed_state(state)
state.run_state = self.ITERATING_COMPLETE
else: else:
if task is None or state.always_child_state.run_state == self.ITERATING_COMPLETE: if task is None or state.always_child_state.run_state == self.ITERATING_COMPLETE:
state.always_child_state = None state.always_child_state = None
@ -466,7 +463,9 @@ class PlayIterator:
def mark_host_failed(self, host): def mark_host_failed(self, host):
s = self.get_host_state(host) s = self.get_host_state(host)
display.debug("marking host %s failed, current state: %s" % (host, s))
s = self._set_failed_state(s) s = self._set_failed_state(s)
display.debug("^ failed state is now: %s" % s)
self._host_states[host.name] = s self._host_states[host.name] = s
def get_failed_hosts(self): def get_failed_hosts(self):

@ -58,7 +58,7 @@ class StrategyModule(StrategyBase):
work_to_do = True work_to_do = True
while work_to_do and not self._tqm._terminated: while work_to_do and not self._tqm._terminated:
hosts_left = [host for host in self._inventory.get_hosts(iterator._play.hosts) if host.name not in self._tqm._unreachable_hosts and not iterator.is_failed(host)] hosts_left = [host for host in self._inventory.get_hosts(iterator._play.hosts) if host.name not in self._tqm._unreachable_hosts]
if len(hosts_left) == 0: if len(hosts_left) == 0:
self._tqm.send_callback('v2_playbook_on_no_hosts_remaining') self._tqm.send_callback('v2_playbook_on_no_hosts_remaining')
result = False result = False
@ -191,6 +191,9 @@ class StrategyModule(StrategyBase):
# pause briefly so we don't spin lock # pause briefly so we don't spin lock
time.sleep(0.001) time.sleep(0.001)
# collect all the final results
results = self._wait_on_pending_results(iterator)
# run the base class run() method, which executes the cleanup function # run the base class run() method, which executes the cleanup function
# and runs any outstanding handlers which have been triggered # and runs any outstanding handlers which have been triggered
return super(StrategyModule, self).run(iterator, play_context, result) return super(StrategyModule, self).run(iterator, play_context, result)

@ -163,7 +163,7 @@ class StrategyModule(StrategyBase):
try: try:
display.debug("getting the remaining hosts for this loop") display.debug("getting the remaining hosts for this loop")
hosts_left = [host for host in self._inventory.get_hosts(iterator._play.hosts) if host.name not in self._tqm._unreachable_hosts and not iterator.is_failed(host)] hosts_left = [host for host in self._inventory.get_hosts(iterator._play.hosts) if host.name not in self._tqm._unreachable_hosts]
display.debug("done getting the remaining hosts for this loop") display.debug("done getting the remaining hosts for this loop")
# queue up this task for each host in the inventory # queue up this task for each host in the inventory

Loading…
Cancel
Save