private MachineDetails[] createManagementServers(final long timeout, final TimeUnit timeoutUnit)
      throws CLIException {
    MachineDetails[] servers;
    try {
      servers = provisioning.startManagementMachines(timeout, timeoutUnit);
    } catch (final CloudProvisioningException e) {
      final CLIStatusException cliStatusException =
          new CLIStatusException(
              e, CloudifyErrorMessages.CLOUD_API_ERROR.getName(), e.getMessage());
      throw cliStatusException;
    } catch (final TimeoutException e) {
      throw new CLIException(
          "Cloudify bootstrap on provider "
              + this.cloud.getProvider().getProvider()
              + " timed-out. "
              + "Please try to run again using the –timeout option.",
          e);
    }

    if (servers.length == 0) {
      throw new IllegalArgumentException(
          "Received zero management servers from provisioning implementation");
    }
    return servers;
  }
  /**
   * Bootstraps and waits until the management machines are running, or until the timeout is
   * reached.
   *
   * @param securityProfile set security profile (nonsecure/secure/ssl)
   * @param username The username for a secure connection to the server
   * @param password The password for a secure connection to the server
   * @param keystorePassword The password to the keystore to set on the rest server
   * @param timeout The number of {@link TimeUnit}s to wait before timing out
   * @param timeoutUnit The time unit to use (seconds, minutes etc.)
   * @throws InstallerException Indicates the provisioning driver failed to start management
   *     machines or that the management processes failed to start
   * @throws CLIException Indicates a basic failure or a time out. a detailed message is included
   * @throws InterruptedException Indicates a thread was interrupted while waiting
   */
  public void bootstrapCloudAndWait(
      final String securityProfile,
      final String username,
      final String password,
      final String keystorePassword,
      final long timeout,
      final TimeUnit timeoutUnit)
      throws InstallerException, CLIException, InterruptedException {

    final long end = System.currentTimeMillis() + timeoutUnit.toMillis(timeout);

    createProvisioningDriver();

    // Start the cloud machines!!!
    MachineDetails[] servers;
    try {
      servers = provisioning.startManagementMachines(timeout, timeoutUnit);
    } catch (final CloudProvisioningException e) {
      final CLIStatusException cliStatusException =
          new CLIStatusException(
              e, CloudifyErrorMessages.CLOUD_API_ERROR.getName(), e.getMessage());
      throw cliStatusException;
    } catch (final TimeoutException e) {
      throw new CLIException(
          "Cloudify bootstrap on provider "
              + this.cloud.getProvider().getProvider()
              + " timed-out. "
              + "Please try to run again using the –timeout option.",
          e);
    }

    // from this point on - close machines if an exception is thrown (to
    // avoid leaks).
    try {

      // log details in FINE
      if (logger.isLoggable(Level.FINE)) {
        for (final MachineDetails server : servers) {
          logServerDetails(server);
        }
      }

      validateServers(servers);

      // Start the management agents and other processes
      if (servers[0].isAgentRunning()) {
        // must be using existing machines.
        throw new IllegalStateException(
            "Cloud bootstrapper found existing management machines with the same name. "
                + "Please shut them down before continuing");
      }

      startManagememntProcesses(servers, securityProfile, keystorePassword, end);

      if (!isNoWebServices()) {
        final Integer restPort =
            getRestPort(
                cloud.getConfiguration().getComponents().getRest().getPort(),
                ShellUtils.isSecureConnection(securityProfile));
        final Integer webuiPort =
            getWebuiPort(
                cloud.getConfiguration().getComponents().getWebui().getPort(),
                ShellUtils.isSecureConnection(securityProfile));
        waitForManagementWebServices(
            ShellUtils.isSecureConnection(securityProfile),
            username,
            password,
            restPort,
            webuiPort,
            end,
            servers);
      }

    } catch (final IOException e) {
      stopManagementMachines();
      throw new CLIException(
          "Cloudify bootstrap on provider "
              + this.cloud.getProvider().getProvider()
              + " failed. Reason: "
              + e.getMessage(),
          e);
    } catch (final URISyntaxException e) {
      stopManagementMachines();
      throw new CLIException("Bootstrap-cloud failed. Reason: " + e.getMessage(), e);
    } catch (final TimeoutException e) {
      stopManagementMachines();
      throw new CLIException(
          "Cloudify bootstrap on provider "
              + this.cloud.getProvider().getProvider()
              + " timed-out. "
              + "Please try to run again using the –timeout option.",
          e);
    } catch (final CLIException e) {
      stopManagementMachines();
      throw e;
    } catch (final InstallerException e) {
      stopManagementMachines();
      throw e;
    } catch (final InterruptedException e) {
      stopManagementMachines();
      throw e;
    }
  }