Coverage for lib/ansible/executor/play_iterator.py : 53%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com> # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# Make coding more python3-ish
except ImportError: from ansible.utils.display import Display display = Display()
return "HostState(%r)" % self._blocks
except IndexError: return "UNKNOWN STATE"
else: ret = [] for i in (1, 2, 4, 8): if n & i: ret.append(states[i]) return "|".join(ret)
"rescue child state? (%s), always child state? (%s), did rescue? %s, did start at task? %s" % ( self.cur_block, self.cur_regular_task, self.cur_rescue_task, self.cur_always_task, _run_state_to_string(self.run_state), _failed_state_to_string(self.fail_state), self.pending_setup, self.tasks_child_state, self.rescue_child_state, self.always_child_state, self.did_rescue, self.did_start_at_task, ))
if not isinstance(other, HostState): return False
for attr in ('_blocks', 'cur_block', 'cur_regular_task', 'cur_rescue_task', 'cur_always_task', 'run_state', 'fail_state', 'pending_setup', 'cur_dep_chain', 'tasks_child_state', 'rescue_child_state', 'always_child_state'): if getattr(self, attr) != getattr(other, attr): return False
return True
return self._blocks[self.cur_block]
new_state.cur_dep_chain = self.cur_dep_chain[:] new_state.rescue_child_state = self.rescue_child_state.copy() new_state.always_child_state = self.always_child_state.copy()
# the primary running states for the play iteration
# the failure states for the play iteration, which are powers # of 2 as they may be or'ed together in certain circumstances
# Default options to gather
# Retrieve subset to gather gather_subset = self._play.gather_subset # Retrieve timeout for gather gather_timeout = self._play.gather_timeout # Retrieve fact_path fact_path = self._play.fact_path
'gather_subset': gather_subset, } setup_task.args['fact_path'] = fact_path # short circuit fact gathering if the entire playbook is conditional setup_task.when = self._play._included_conditional[:]
self.cache_block_tasks(handler_block)
# if we're looking to start at a specific task, iterate through # the tasks for this host until we find the specified task while True: (s, task) = self.get_next_task_for_host(host, peek=True) if s.run_state == self.ITERATING_COMPLETE: break if task.name == play_context.start_at_task or fnmatch.fnmatch(task.name, play_context.start_at_task) or \ task.get_name() == play_context.start_at_task or fnmatch.fnmatch(task.get_name(), play_context.start_at_task): start_at_matched = True break else: self.get_next_task_for_host(host)
# finally, reset the host's state to ITERATING_SETUP if start_at_matched: self._host_states[host.name].did_start_at_task = True self._host_states[host.name].run_state = self.ITERATING_SETUP
# we have our match, so clear the start_at_task field on the # play context to flag that we've started at a task (and future # plays won't try to advance) play_context.start_at_task = None
# Since we're using the PlayIterator to carry forward failed hosts, # in the event that a previous host was not in the current inventory # we create a stub state for it now self._host_states[host.name] = HostState(blocks=[])
# now a noop, we've changed the way we do caching and finding of # original task entries, but just in case any 3rd party strategies # are using this we're leaving it here for now
display.debug("host %s is done iterating, returning" % host.name) return (s, None)
# try and find the next task, given the current state. # try to get the current block from the list of blocks, and # if we run past the end of the list we know we're done with # this block
# First, we check to see if we were pending setup. If not, this is # the first trip through ITERATING_SETUP, so we set the pending_setup # flag and try to determine if we do in fact want to gather facts for # the specified host.
# Gather facts if the default is 'smart' and we have not yet # done it for this host; or if 'explicit' and the play sets # gather_facts to True; or if 'implicit' and the play does # NOT explicitly set gather_facts to False.
(gathering == 'explicit' and boolean(self._play.gather_facts, strict=False)) or \ (gathering == 'smart' and implied and not (self._variable_manager._fact_cache.get(host.name, {}).get('module_setup', False))): # The setup block is always self._blocks[0], as we inject it # during the play compilation in __init__ above. setup_block = self._blocks[0] if setup_block.has_tasks() and len(setup_block.block) > 0: task = setup_block.block[0] else: # This is the second trip through ITERATING_SETUP, so we clear # the flag and move onto the next block in the list while setting # the run state to ITERATING_TASKS
# clear the pending setup flag, since we're past that and it didn't fail state.pending_setup = False
# First, we check for a child task state that is not failed, and if we # have one recurse into it for the next task. If we're done with the child # state, we clear it and drop back to getting the next task from the list. # failed child state, so clear it and move into the rescue portion state.tasks_child_state = None self._set_failed_state(state) else: # get the next task recursively # we're done with the child state, so clear it and continue # back to the top of the loop to get the next task else: # First here, we check to see if we've failed anywhere down the chain # of states we have, and if so we move onto the rescue portion. Otherwise, # we check to see if we've moved past the end of the list of tasks. If so, # we move into the always portion of the block, otherwise we get the next # task from the list. state.run_state = self.ITERATING_RESCUE else: # if the current task is actually a child block, create a child # state for us to recurse into on the next pass # since we've created the child state, clear the task # so we can pick up the child state on the next pass
# The process here is identical to ITERATING_TASKS, except instead # we move into the always portion of the block. if host.name in self._play._removed_hosts: self._play._removed_hosts.remove(host.name)
if state.rescue_child_state: (state.rescue_child_state, task) = self._get_next_task_from_state(state.rescue_child_state, host=host, peek=peek, in_child=True) if self._check_failed_state(state.rescue_child_state): state.rescue_child_state = None self._set_failed_state(state) else: if task is None or state.rescue_child_state.run_state == self.ITERATING_COMPLETE: state.rescue_child_state = None continue else: if state.fail_state & self.FAILED_RESCUE == self.FAILED_RESCUE: state.run_state = self.ITERATING_ALWAYS elif state.cur_rescue_task >= len(block.rescue): if len(block.rescue) > 0: state.fail_state = self.FAILED_NONE state.run_state = self.ITERATING_ALWAYS state.did_rescue = True else: task = block.rescue[state.cur_rescue_task] if isinstance(task, Block) or state.rescue_child_state is not None: state.rescue_child_state = HostState(blocks=[task]) state.rescue_child_state.run_state = self.ITERATING_TASKS task = None state.cur_rescue_task += 1
# And again, the process here is identical to ITERATING_TASKS, except # instead we either move onto the next block in the list, or we set the # run state to ITERATING_COMPLETE in the event of any errors, or when we # have hit the end of the list of blocks. (state.always_child_state, task) = self._get_next_task_from_state(state.always_child_state, host=host, peek=peek, in_child=True) if self._check_failed_state(state.always_child_state): state.always_child_state = None self._set_failed_state(state) else: if task is None or state.always_child_state.run_state == self.ITERATING_COMPLETE: state.always_child_state = None continue else: state.run_state = self.ITERATING_COMPLETE else:
# we're advancing blocks, so if this was an end-of-role block we # mark the current role complete else: state.always_child_state = HostState(blocks=[task]) state.always_child_state.run_state = self.ITERATING_TASKS task = None
elif state.run_state == self.ITERATING_COMPLETE: return (state, None)
# if something above set the task, break out of the loop now
if state.run_state == self.ITERATING_SETUP: state.fail_state |= self.FAILED_SETUP state.run_state = self.ITERATING_COMPLETE elif state.run_state == self.ITERATING_TASKS: if state.tasks_child_state is not None: state.tasks_child_state = self._set_failed_state(state.tasks_child_state) else: state.fail_state |= self.FAILED_TASKS if state._blocks[state.cur_block].rescue: state.run_state = self.ITERATING_RESCUE elif state._blocks[state.cur_block].always: state.run_state = self.ITERATING_ALWAYS else: state.run_state = self.ITERATING_COMPLETE elif state.run_state == self.ITERATING_RESCUE: if state.rescue_child_state is not None: state.rescue_child_state = self._set_failed_state(state.rescue_child_state) else: state.fail_state |= self.FAILED_RESCUE if state._blocks[state.cur_block].always: state.run_state = self.ITERATING_ALWAYS else: state.run_state = self.ITERATING_COMPLETE elif state.run_state == self.ITERATING_ALWAYS: if state.always_child_state is not None: state.always_child_state = self._set_failed_state(state.always_child_state) else: state.fail_state |= self.FAILED_ALWAYS state.run_state = self.ITERATING_COMPLETE return state
s = self.get_host_state(host) display.debug("marking host %s failed, current state: %s" % (host, s)) s = self._set_failed_state(s) display.debug("^ failed state is now: %s" % s) self._host_states[host.name] = s self._play._removed_hosts.append(host.name)
return True return True if state.run_state == self.ITERATING_RESCUE and state.fail_state & self.FAILED_RESCUE == 0: return False elif state.run_state == self.ITERATING_ALWAYS and state.fail_state & self.FAILED_ALWAYS == 0: return False else: return not state.did_rescue cur_block = self._blocks[state.cur_block] if len(cur_block.rescue) > 0 and state.fail_state & self.FAILED_RESCUE == 0: return False else: return True
# now a noop because we've changed the way we do caching return (None, None)
# if we've failed at all, or if the task list is empty, just return the current state return state
else: elif state.run_state == self.ITERATING_RESCUE: if state.rescue_child_state: state.rescue_child_state = self._insert_tasks_into_state(state.rescue_child_state, task_list) else: target_block = state._blocks[state.cur_block].copy(exclude_parent=True) before = target_block.rescue[:state.cur_rescue_task] after = target_block.rescue[state.cur_rescue_task:] target_block.rescue = before + task_list + after state._blocks[state.cur_block] = target_block elif state.run_state == self.ITERATING_ALWAYS: if state.always_child_state: state.always_child_state = self._insert_tasks_into_state(state.always_child_state, task_list) else: target_block = state._blocks[state.cur_block].copy(exclude_parent=True) before = target_block.always[:state.cur_always_task] after = target_block.always[state.cur_always_task:] target_block.always = before + task_list + after state._blocks[state.cur_block] = target_block
|