Create n clients to run in a pool.

def CreateClientPool(n):
  """Create n clients to run in a pool."""
  clients = []

  # Load previously stored clients.
  try:
    certificates = []
    with open(flags.FLAGS.cert_file, "rb") as fd:
      # Certificates are base64-encoded, so that we can use new-lines as
      # separators.
      for l in fd:
        cert = rdf_crypto.RSAPrivateKey(initializer=base64.b64decode(l))
        certificates.append(cert)

    for certificate in certificates[:n]:
      clients.append(
          PoolGRRClient(
              private_key=certificate,
              ca_cert=config.CONFIG["CA.certificate"],
              fast_poll=flags.FLAGS.fast_poll,
              send_foreman_request=flags.FLAGS.send_foreman_request,
          ))

    clients_loaded = True
  except (IOError, EOFError):
    clients_loaded = False

  if clients_loaded and len(clients) < n:
    raise RuntimeError(
        "Loaded %d clients, but expected %d." % (len(clients), n))

  while len(clients) < n:
    # Generate a new RSA key pair for each client.
    bits = config.CONFIG["Client.rsa_key_length"]
    key = rdf_crypto.RSAPrivateKey.GenerateKey(bits=bits)
    clients.append(
        PoolGRRClient(private_key=key, ca_cert=config.CONFIG["CA.certificate"]))

  # Start all the clients now.
  for c in clients:
    c.start()

  start_time = time.time()
  try:
    if flags.FLAGS.enroll_only:
      while True:
        time.sleep(1)
        enrolled = len([x for x in clients if x.enrolled])

        if enrolled == n:
          logging.info("All clients enrolled, exiting.")
          break

        else:
          logging.info("%s: Enrolled %d/%d clients.", int(time.time()),
                       enrolled, n)
    else:
      try:
        while True:
          time.sleep(100)
      except KeyboardInterrupt:
        pass

  finally:
    # Stop all pool clients.
    for cl in clients:
      cl.Stop()

  # Note: code below is going to be executed after SIGTERM is sent to this
  # process.
  logging.info("Pool done in %s seconds.", time.time() - start_time)

  # The way benchmarking is supposed to work is that we execute poolclient with
  # --enroll_only flag, it dumps the certificates to the flags.FLAGS.cert_file.
  # Then, all further poolclient invocations just read private keys back
  # from that file. Therefore if private keys were loaded from
  # flags.FLAGS.cert_file, then there's no need to rewrite it again with the
  # same data.
  if not clients_loaded:
    logging.info("Saving certificates.")
    with open(flags.FLAGS.cert_file, "wb") as fd:
      # We're base64-encoding ceritificates so that we can use new-lines
      # as separators.
      b64_certs = [
          base64.b64encode(x.private_key.SerializeToString()) for x in clients
      ]
      fd.write("\n".join(b64_certs))