code: def _run_single_op(state, op_hash):
      '''
      Run a single operation for all servers. Can be configured to run in serial.
      '''
      op_meta = state.op_meta[op_hash]
      op_types = []
      if op_meta['serial']:
          op_types.append('serial')
      if op_meta['run_once']:
          op_types.append('run once')
      logger.info('{0} {1} {2}'.format(
          click.style('--> Starting{0}operation:'.format(
              ' {0} '.format(', '.join(op_types)) if op_types else ' ',
          ), 'blue'),
          click.style(', '.join(op_meta['names']), bold=True),
          tuple(op_meta['args']) if op_meta['args'] else '',
      ))
      failed_hosts = set()
      if op_meta['serial']:
          with progress_spinner(state.inventory) as progress:
              for host in state.inventory:
                  result = _run_server_op(state, host, op_hash)
                  progress(host)
                  if not result:
                      failed_hosts.add(host)
      else:
          batches = [state.inventory]
          if op_meta['parallel']:
              parallel = op_meta['parallel']
              hosts = list(state.inventory)
              batches = [
                  hosts[i:i + parallel]
                  for i in range(0, len(hosts), parallel)
              ]
          for batch in batches:
              with progress_spinner(batch) as progress:
                  greenlet_to_host = {
                      state.pool.spawn(_run_server_op, state, host, op_hash): host
                      for host in batch
                  }
                  for greenlet in gevent.iwait(greenlet_to_host.keys()):
                      host = greenlet_to_host[greenlet]
                      progress(host)
                  for greenlet, host in six.iteritems(greenlet_to_host):
                      if not greenlet.get():
                          failed_hosts.add(host)
      if not op_meta['ignore_errors']:
          state.fail_hosts(failed_hosts)
      if pyinfra.is_cli:
          print()