/**
   * loads the provisioning driver class and sets it up.
   *
   * @throws CLIException Indicates the configured could not be found and instantiated
   */
  private void createProvisioningDriver() throws CLIException {
    try {
      provisioning =
          (ProvisioningDriver) Class.forName(cloud.getConfiguration().getClassName()).newInstance();
    } catch (final ClassNotFoundException e) {
      throw new CLIException(
          "Failed to load provisioning class for cloud: "
              + cloud.getName()
              + ". Class not found: "
              + cloud.getConfiguration().getClassName(),
          e);
    } catch (final Exception e) {
      throw new CLIException("Failed to load provisioning class for cloud: " + cloud.getName(), e);
    }
    if (provisioning instanceof ProvisioningDriverClassContextAware) {
      final ProvisioningDriverClassContextAware contextAware =
          (ProvisioningDriverClassContextAware) provisioning;
      contextAware.setProvisioningDriverClassContext(new DefaultProvisioningDriverClassContext());
    }

    provisioning.addListener(new CliProvisioningDriverListener());
    final String serviceName = null;
    provisioning.setConfig(
        cloud, cloud.getConfiguration().getManagementMachineTemplate(), true, serviceName);
  }
  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;
  }
 private void stopManagementMachines() {
   try {
     provisioning.stopManagementMachines();
   } catch (final CloudProvisioningException e) {
     // log a warning, don't throw an exception on this failure
     logger.warning(
         "Failed to clean management machines after provisioning failure, reported error: "
             + e.getMessage());
   } catch (final TimeoutException e) {
     // log a warning, don't throw an exception on this failure
     logger.warning(
         "Failed to clean management machines after provisioning failure, the operation timed out ("
             + e.getMessage()
             + ")");
   }
 }
  private void destroyManagementServers(final long timeout, final TimeUnit timeoutUnit)
      throws CLIException, InterruptedException, TimeoutException {

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

    if (!force) {

      if (!adminFacade.isConnected()) {
        throw new CLIException("Please connect to the cloud before tearing down");
      }
      uninstallApplications(end);

    } else {

      if (adminFacade.isConnected()) {
        try {
          uninstallApplications(end);
        } catch (final InterruptedException e) {
          throw e;
        } catch (final TimeoutException e) {
          logger.fine(
              "Failed to uninstall applications. Shut down of management machines will continue");
        } catch (final CLIException e) {
          logger.fine(
              "Failed to uninstall applications. Shut down of management machines will continue");
        }
      } else {
        logger.info(
            "Teardown performed without connection to the cloud, only management machines will be "
                + "terminated.");
      }
    }

    logger.info("Terminating cloud machines");

    try {
      provisioning.stopManagementMachines();
    } catch (final CloudProvisioningException e) {
      throw new CLIException(
          "Failed to shut down management machine during tear down of cloud: " + e.getMessage(), e);
    }
    adminFacade.disconnect();
  }
  /**
   * 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;
    }
  }