def _get_serialized_batches(self, play): ''' 把主机列表分批次 ''' all_hosts = self.inventory.get_hosts(play.hosts) all_hosts_len = len(all_hosts) serial_batch_list = play.serial if len(serial_batch_list) == 0: serial_batch_list = [-1] cur_item = 0 serialized_batches = [] while len(all_hosts) > 0: serial = pct_to_int(serial_batch_list[cur_item], all_hosts_len) if serial <= 0: serialized_batches.append(all_hosts) break else: play_hosts = [] for x in range(serial): print(x) if len(all_hosts) > 0: play_hosts.append(all_hosts.pop(0)) serialized_batches.append(play_hosts) cur_item += 1 if cur_item > len(serial_batch_list) - 1: cur_item = len(serial_batch_list) - 1 return serialized_batches
def _get_serialized_batches(self, play): ''' Returns a list of hosts subdivided into batches based on the serial size specified in the play and a list of 0 and 1 values, used to ignore or not unreachable hosts during the play. ''' # make sure we have a unique list of hosts all_hosts = self._inventory.get_hosts(play.hosts, order=play.order) all_hosts_len = len(all_hosts) # Extract serial batch list serial_batch_list = [ i[0] if isinstance(i, list) else i for i in play.serial ] # ignore_unreachable_list contains 0,1 value, if 0, host unreachable are counted as failed, othewise # are not counted as failed. If a value is not 0 or 1, we pass 0 as standard ignore_unreachable_list = [ i[1] if isinstance(i, list) and i[1] == 1 else 0 for i in play.serial ] # the serial value can be listed as a scalar or a list of # scalars, so we make sure it's a list here if len(serial_batch_list) == 0: serial_batch_list = [-1] cur_item = 0 serialized_batches = [] ignore_unreachable = [] while len(all_hosts) > 0: # get the serial value from current item in the list serial = pct_to_int(serial_batch_list[cur_item], all_hosts_len) # if the serial count was not specified or is invalid, default to # a list of all hosts, otherwise grab a chunk of the hosts equal # to the current serial item size if serial <= 0: serialized_batches.append(all_hosts) ignore_unreachable.append(0) break else: play_hosts = [] for x in range(serial): if len(all_hosts) > 0: play_hosts.append(all_hosts.pop(0)) serialized_batches.append(play_hosts) ignore_unreachable.append(ignore_unreachable_list[cur_item]) # increment the current batch list item number, and if we've hit # the end keep using the last element until we've consumed all of # the hosts in the inventory cur_item += 1 if cur_item > len(serial_batch_list) - 1: cur_item = len(serial_batch_list) - 1 return serialized_batches, ignore_unreachable
def test_pct_to_int(self): self.assertEqual(pct_to_int(1, 100), 1) self.assertEqual(pct_to_int(-1, 100), -1) self.assertEqual(pct_to_int("1%", 10), 1) self.assertEqual(pct_to_int("1%", 10, 0), 0) self.assertEqual(pct_to_int("1", 100), 1) self.assertEqual(pct_to_int("10%", 100), 10)
def _get_serialized_batches(self, play): ''' Returns a list of hosts, subdivided into batches based on the serial size specified in the play. ''' # make sure we have a unique list of hosts all_hosts = self._inventory.get_hosts(play.hosts) all_hosts_len = len(all_hosts) # the serial value can be listed as a scalar or a list of # scalars, so we make sure it's a list here serial_batch_list = play.serial if len(serial_batch_list) == 0: serial_batch_list = [-1] cur_item = 0 serialized_batches = [] while len(all_hosts) > 0: # get the serial value from current item in the list serial = pct_to_int(serial_batch_list[cur_item], all_hosts_len) # if the serial count was not specified or is invalid, default to # a list of all hosts, otherwise grab a chunk of the hosts equal # to the current serial item size if serial <= 0: serialized_batches.append(all_hosts) break else: play_hosts = [] for x in range(serial): if len(all_hosts) > 0: play_hosts.append(all_hosts.pop(0)) serialized_batches.append(play_hosts) # increment the current batch list item number, and if we've hit # the end keep using the last element until we've consumed all of # the hosts in the inventory cur_item += 1 if cur_item > len(serial_batch_list) - 1: cur_item = len(serial_batch_list) - 1 return serialized_batches
def run(self, play): ''' Iterates over the roles/tasks in a play, using the given (or default) strategy for queueing tasks. The default is the linear strategy, which operates like classic Ansible by keeping all hosts in lock-step with a given task (meaning no hosts move on to the next task until all hosts are done with the current task). ''' if not self._callbacks_loaded: self.load_callbacks() all_vars = self._variable_manager.get_vars(play=play) warn_if_reserved(all_vars) templar = Templar(loader=self._loader, variables=all_vars) new_play = play.copy() new_play.post_validate(templar) new_play.handlers = new_play.compile_roles_handlers( ) + new_play.handlers self.hostvars = HostVars( inventory=self._inventory, variable_manager=self._variable_manager, loader=self._loader, ) # Fork # of forks, # of hosts or serial, whichever is lowest num_hosts = len( self._inventory.get_hosts(new_play.hosts, ignore_restrictions=True)) max_serial = 0 if new_play.serial: # the play has not been post_validated here, so we may need # to convert the scalar value to a list at this point serial_items = new_play.serial if not isinstance(serial_items, list): serial_items = [serial_items] max_serial = max([pct_to_int(x, num_hosts) for x in serial_items]) contenders = [self._options.forks, max_serial, num_hosts] contenders = [v for v in contenders if v is not None and v > 0] self._initialize_processes(min(contenders)) play_context = PlayContext(new_play, self._options, self.passwords, self._connection_lockfile.fileno()) for callback_plugin in self._callback_plugins: if hasattr(callback_plugin, 'set_play_context'): callback_plugin.set_play_context(play_context) self.send_callback('v2_playbook_on_play_start', new_play) # initialize the shared dictionary containing the notified handlers self._initialize_notified_handlers(new_play) # load the specified strategy (or the default linear one) strategy = strategy_loader.get(new_play.strategy, self) if strategy is None: raise AnsibleError("Invalid play strategy specified: %s" % new_play.strategy, obj=play._ds) # build the iterator iterator = PlayIterator( inventory=self._inventory, play=new_play, play_context=play_context, variable_manager=self._variable_manager, all_vars=all_vars, 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. 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 if getattr(self._options, 'start_at_task', None) is not None and play_context.start_at_task is None: self._start_at_done = True # 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 strategy.cleanup() self._cleanup_processes() return play_return
def run(self, play): ''' Iterates over the roles/tasks in a play, using the given (or default) strategy for queueing tasks. The default is the linear strategy, which operates like classic Ansible by keeping all hosts in lock-step with a given task (meaning no hosts move on to the next task until all hosts are done with the current task). ''' if not self._callbacks_loaded: self.load_callbacks() all_vars = self._variable_manager.get_vars(loader=self._loader, play=play) templar = Templar(loader=self._loader, variables=all_vars) new_play = play.copy() new_play.post_validate(templar) new_play.handlers = new_play.compile_roles_handlers() + new_play.handlers self.hostvars = HostVars( inventory=self._inventory, variable_manager=self._variable_manager, loader=self._loader, ) # Fork # of forks, # of hosts or serial, whichever is lowest num_hosts = len(self._inventory.get_hosts(new_play.hosts, ignore_restrictions=True)) max_serial = 0 if new_play.serial: # the play has not been post_validated here, so we may need # to convert the scalar value to a list at this point serial_items = new_play.serial if not isinstance(serial_items, list): serial_items = [serial_items] max_serial = max([pct_to_int(x, num_hosts) for x in serial_items]) contenders = [self._options.forks, max_serial, num_hosts] contenders = [v for v in contenders if v is not None and v > 0] self._initialize_processes(min(contenders)) play_context = PlayContext(new_play, self._options, self.passwords, self._connection_lockfile.fileno()) for callback_plugin in self._callback_plugins: if hasattr(callback_plugin, 'set_play_context'): callback_plugin.set_play_context(play_context) self.send_callback('v2_playbook_on_play_start', new_play) # initialize the shared dictionary containing the notified handlers self._initialize_notified_handlers(new_play) # load the specified strategy (or the default linear one) strategy = strategy_loader.get(new_play.strategy, self) if strategy is None: raise AnsibleError("Invalid play strategy specified: %s" % new_play.strategy, obj=play._ds) # build the iterator iterator = PlayIterator( inventory=self._inventory, play=new_play, play_context=play_context, variable_manager=self._variable_manager, all_vars=all_vars, 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. 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 if getattr(self._options, 'start_at_task', None) is not None and play_context.start_at_task is None: self._start_at_done = True # 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 strategy.cleanup() self._cleanup_processes() return play_return
def _get_serialized_batches(self, play): ''' Returns a list of hosts, subdivided into batches based on the serial size specified in the play. ''' # make sure we have a unique list of hosts all_hosts = self.inventory.get_hosts(play.hosts) all_hosts_len = len(all_hosts) # the serial value can be listed as a scalar or a list of # scalars, so we make sure it's a list here serial_batch_list = play.serial if len(serial_batch_list) == 0: serial_batch_list = [-1] cur_item = 0 serialized_batches = [] while len(all_hosts) > 0: # get the serial value from current item in the list serial = pct_to_int(serial_batch_list[cur_item], all_hosts_len) # if the serial count was not specified or is invalid, default to # a list of all hosts, otherwise grab a chunk of the hosts equal # to the current serial item size if serial <= 0: serialized_batches.append(all_hosts) break else: play_hosts = [] for x in range(serial): if len(all_hosts) > 0: play_hosts.append(all_hosts.pop(0)) serialized_batches.append(play_hosts) # increment the current batch list item number, and if we've hit # the end keep using the last element until we've consumed all of # the hosts in the inventory cur_item += 1 if cur_item > len(serial_batch_list) - 1: cur_item = len(serial_batch_list) - 1 return serialized_batches # # def get_playbook_result(self): # self.results_raw = {'skipped': {}, 'failed': {}, 'ok': {}, "status": {}, 'unreachable': {}, "changed": {}} # for host, result in self.callback.task_ok.items(): # self.results_raw['ok'][host] = result # # for host, result in self.callback.task_failed.items(): # self.results_raw['failed'][host] = result # # for host, result in self.callback.task_status.items(): # self.results_raw['status'][host] = result # # # for host, result in self.callback.task_changed.items(): # # self.results_raw['changed'][host] = result # # for host, result in self.callback.task_skipped.items(): # self.results_raw['skipped'][host] = result # # for host, result in self.callback.task_unreachable.items(): # self.results_raw['unreachable'][host] = result # return self.results_raw