private void deleteInstance(@NotNull final VmwareCloudInstance instance) {
   if (instance.getErrorInfo() == null) {
     LOG.info("Will delete instance " + instance.getName());
     final VmwareInstance vmInstance;
     try {
       vmInstance = myApiConnector.getInstanceDetails(instance.getName());
       myAsyncTaskExecutor.executeAsync(
           vmInstance.deleteInstance(),
           new ImageStatusTaskWrapper(instance) {
             @Override
             public void onSuccess() {
               removeInstance(instance.getName());
             }
           });
     } catch (VmwareCheckedCloudException e) {
       LOG.warn("An exception during deleting instance " + instance.getName(), e);
       instance.updateErrors(TypedCloudErrorInfo.fromException(e));
     }
   } else {
     LOG.warn(
         String.format(
             "Won't delete instance %s with error: %s (%s)",
             instance.getName(),
             instance.getErrorInfo().getMessage(),
             instance.getErrorInfo().getDetailedMessage()));
   }
 }
  public void terminateInstance(@NotNull final VmwareCloudInstance instance) {

    LOG.info("Stopping instance " + instance.getName());
    instance.setStatus(InstanceStatus.SCHEDULED_TO_STOP);
    myAsyncTaskExecutor.executeAsync(
        new VmwareTaskWrapper(
            new Callable<Task>() {
              public Task call() throws Exception {
                return myApiConnector.stopInstance(instance);
              }
            },
            "Stop " + instance.getName()),
        new ImageStatusTaskWrapper(instance) {

          @Override
          public void onComplete() {
            instance.setStatus(InstanceStatus.STOPPED);
            if (myImageDetails
                .getBehaviour()
                .isDeleteAfterStop()) { // we only destroy proper instances.
              deleteInstance(instance);
            }
          }
        });
  }
  @Override
  public synchronized VmwareCloudInstance startNewInstance(
      @NotNull final CloudInstanceUserData cloudInstanceUserData) throws QuotaException {
    try {
      final VmwareCloudInstance instance = getOrCreateInstance();
      if (instance == null) {
        return null;
      }
      boolean willClone = !myApiConnector.checkVirtualMachineExists(instance.getName());
      LOG.info("Will clone for " + instance.getName() + ": " + willClone);
      if (willClone && myImageDetails.getMaxInstances() <= myInstances.size()) {
        throw new QuotaException(
            String.format(
                "Cannot clone '%s' into '%s' - limit exceeded",
                myImageDetails.getSourceName(), instance.getName()));
      }
      instance.setStatus(InstanceStatus.SCHEDULED_TO_START);
      if (!myInstances.containsKey(instance.getName())) {
        addInstance(instance);
      }
      if (willClone) {
        myAsyncTaskExecutor.executeAsync(
            new VmwareTaskWrapper(
                new Callable<Task>() {
                  public Task call() throws Exception {
                    return myApiConnector.cloneAndStartVm(
                        instance, myImageDetails.getResourcePoolId(), myImageDetails.getFolderId());
                  }
                },
                "Clone and start instance " + instance.getName()),
            new ImageStatusTaskWrapper(instance) {
              @Override
              public void onSuccess() {
                reconfigureVmTask(instance, cloudInstanceUserData);
              }

              @Override
              public void onError(final Throwable th) {
                super.onError(th);
                removeInstance(instance.getName());
              }
            });
      } else {
        startVM(instance, cloudInstanceUserData);
      }
      return instance;
    } catch (QuotaException e) {
      throw e;
    } catch (VmwareCheckedCloudException e) {
      throw new CloudException("Unable to start new instance: " + e.toString());
    }
  }
 private synchronized void startVM(
     @NotNull final VmwareCloudInstance instance,
     @NotNull final CloudInstanceUserData cloudInstanceUserData) {
   instance.setStatus(InstanceStatus.STARTING);
   myAsyncTaskExecutor.executeAsync(
       new VmwareTaskWrapper(
           new Callable<Task>() {
             public Task call() throws Exception {
               return myApiConnector.startInstance(
                   instance, instance.getName(), cloudInstanceUserData);
             }
           },
           "Start instance " + instance.getName()),
       new ImageStatusTaskWrapper(instance) {
         @Override
         public void onSuccess() {
           reconfigureVmTask(instance, cloudInstanceUserData);
         }
       });
 }
 private synchronized void reconfigureVmTask(
     @NotNull final VmwareCloudInstance instance,
     @NotNull final CloudInstanceUserData cloudInstanceUserData) {
   myAsyncTaskExecutor.executeAsync(
       new VmwareTaskWrapper(
           new Callable<Task>() {
             public Task call() throws Exception {
               return myApiConnector.reconfigureInstance(
                   instance, instance.getName(), cloudInstanceUserData);
             }
           },
           "Reconfigure " + instance.getName()),
       new ImageStatusTaskWrapper(instance) {
         @Override
         public void onSuccess() {
           instance.setStatus(InstanceStatus.RUNNING);
           instance.updateErrors();
           LOG.info("Instance started successfully");
         }
       });
 }