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()));
   }
 }
  @NotNull
  protected synchronized VmwareCloudInstance getOrCreateInstance()
      throws VmwareCheckedCloudException {
    if (!canStartNewInstance()) {
      throw new QuotaException("Unable to start more instances of image " + getName());
    }

    if (myImageDetails.getBehaviour().isUseOriginal()) {
      LOG.info("Won't create a new instance - using original");
      return myInstances.get(myImageDetails.getSourceName());
    }

    final String latestSnapshotName =
        myApiConnector.getLatestSnapshot(
            myImageDetails.getSourceName(), myImageDetails.getSnapshotName());
    if (!myImageDetails.useCurrentVersion() && latestSnapshotName == null) {
      updateErrors(new TypedCloudErrorInfo("No such snapshot: " + getSnapshotName()));
      throw new VmwareCheckedCloudException(
          "Unable to find snapshot: " + myImageDetails.getSnapshotName());
    }

    if (!myImageDetails.getBehaviour().isDeleteAfterStop()) {
      // on demand clone
      final Map<String, VmwareInstance> vmClones = myApiConnector.listImageInstances(this);

      // start an existsing one.
      final VmwareInstance imageVm =
          myApiConnector.getInstanceDetails(myImageDetails.getSourceName());
      for (VmwareInstance vmInstance : vmClones.values()) {
        if (vmInstance.getInstanceStatus() == InstanceStatus.STOPPED) {

          final String vmName = vmInstance.getName();
          final VmwareCloudInstance instance = myInstances.get(vmName);

          if (instance == null) {
            LOG.warn("Unable to find instance " + vmName + " in myInstances.");
            continue;
          }

          // checking if this instance is already starting.
          if (instance.getStatus() != InstanceStatus.STOPPED) continue;

          if (myImageDetails.useCurrentVersion()) {
            if (imageVm.getChangeVersion() == null
                || !imageVm.getChangeVersion().equals(vmInstance.getChangeVersion())) {
              LOG.info(
                  String.format(
                      "Change version for %s is outdated: '%s' vs '%s'",
                      vmName, vmInstance.getChangeVersion(), imageVm.getChangeVersion()));
              deleteInstance(instance);
              continue;
            }
          } else {
            final String snapshotName = vmInstance.getSnapshotName();
            if (latestSnapshotName != null && !latestSnapshotName.equals(snapshotName)) {
              LOG.info(
                  String.format(
                      "VM %s Snapshot is not the latest one: '%s' vs '%s'",
                      vmName, snapshotName, latestSnapshotName));
              deleteInstance(instance);
              continue;
            }
          }
          LOG.info("Will use existing VM with name " + vmName);
          return instance;
        }
      }
    }
    // wasn't able to find an existing candidate, so will clone into a new VM
    final String newVmName = generateNewVmName();
    LOG.info("Will create a new VM with name " + newVmName);
    return new VmwareCloudInstance(this, newVmName, latestSnapshotName);
  }