protected Void createTemplateCallback(
      AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> callback,
      TemplateOpContext<TemplateApiResult> context) {
    TemplateObject template = context.getTemplate();
    AsyncCompletionCallback<TemplateApiResult> parentCallback = context.getParentCallback();
    TemplateApiResult result = new TemplateApiResult(template);
    CreateCmdResult callbackResult = callback.getResult();
    if (callbackResult.isFailed()) {
      template.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
      result.setResult(callbackResult.getResult());
      if (parentCallback != null) {
        parentCallback.complete(result);
      }
      return null;
    }

    try {
      template.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
    } catch (Exception e) {
      result.setResult(e.toString());
      if (parentCallback != null) {
        parentCallback.complete(result);
      }
      return null;
    }

    if (parentCallback != null) {
      parentCallback.complete(result);
    }
    return null;
  }
  protected Void createTemplateAsyncCallback(
      AsyncCallbackDispatcher<? extends BaseImageStoreDriverImpl, DownloadAnswer> callback,
      CreateContext<CreateCmdResult> context) {
    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Performing image store createTemplate async callback");
    }
    DownloadAnswer answer = callback.getResult();
    DataObject obj = context.data;
    DataStore store = obj.getDataStore();

    TemplateDataStoreVO tmpltStoreVO =
        _templateStoreDao.findByStoreTemplate(store.getId(), obj.getId());
    if (tmpltStoreVO != null) {
      if (tmpltStoreVO.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
        if (s_logger.isDebugEnabled()) {
          s_logger.debug(
              "Template is already in DOWNLOADED state, ignore further incoming DownloadAnswer");
        }
        return null;
      }
      TemplateDataStoreVO updateBuilder = _templateStoreDao.createForUpdate();
      updateBuilder.setDownloadPercent(answer.getDownloadPct());
      updateBuilder.setDownloadState(answer.getDownloadStatus());
      updateBuilder.setLastUpdated(new Date());
      updateBuilder.setErrorString(answer.getErrorString());
      updateBuilder.setJobId(answer.getJobId());
      updateBuilder.setLocalDownloadPath(answer.getDownloadPath());
      updateBuilder.setInstallPath(answer.getInstallPath());
      updateBuilder.setSize(answer.getTemplateSize());
      updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
      _templateStoreDao.update(tmpltStoreVO.getId(), updateBuilder);
      // update size in vm_template table
      VMTemplateVO tmlptUpdater = _templateDao.createForUpdate();
      tmlptUpdater.setSize(answer.getTemplateSize());
      _templateDao.update(obj.getId(), tmlptUpdater);
    }

    AsyncCompletionCallback<CreateCmdResult> caller = context.getParentCallback();

    if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR
        || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED
        || answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) {
      CreateCmdResult result = new CreateCmdResult(null, null);
      result.setSuccess(false);
      result.setResult(answer.getErrorString());
      caller.complete(result);
    } else if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
      if (answer.getCheckSum() != null) {
        VMTemplateVO templateDaoBuilder = _templateDao.createForUpdate();
        templateDaoBuilder.setChecksum(answer.getCheckSum());
        _templateDao.update(obj.getId(), templateDaoBuilder);
      }

      CreateCmdResult result = new CreateCmdResult(null, null);
      caller.complete(result);
    }
    return null;
  }
  @Override
  public void createAsync(
      DataStore dataStore,
      DataObject dataObject,
      AsyncCompletionCallback<CreateCmdResult> callback) {
    String iqn = null;
    String errMsg = null;

    if (dataObject.getType() == DataObjectType.VOLUME) {
      VolumeInfo volumeInfo = (VolumeInfo) dataObject;
      AccountVO account = _accountDao.findById(volumeInfo.getAccountId());
      String sfAccountName = getSfAccountName(account.getUuid(), account.getAccountId());

      long storagePoolId = dataStore.getId();
      SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);

      if (!sfAccountExists(sfAccountName, sfConnection)) {
        SolidFireUtil.SolidFireAccount sfAccount =
            createSolidFireAccount(sfAccountName, sfConnection);

        updateCsDbWithAccountInfo(account.getId(), sfAccount);
      }

      SolidFireUtil.SolidFireVolume sfVolume = createSolidFireVolume(volumeInfo, sfConnection);

      iqn = sfVolume.getIqn();

      VolumeVO volume = this._volumeDao.findById(volumeInfo.getId());

      volume.set_iScsiName(iqn);
      volume.setFolder(String.valueOf(sfVolume.getId()));
      volume.setPoolType(StoragePoolType.IscsiLUN);
      volume.setPoolId(storagePoolId);

      _volumeDao.update(volume.getId(), volume);

      StoragePoolVO storagePool = _storagePoolDao.findById(dataStore.getId());

      long capacityBytes = storagePool.getCapacityBytes();
      long usedBytes = storagePool.getUsedBytes();

      usedBytes += volumeInfo.getSize();

      storagePool.setUsedBytes(usedBytes > capacityBytes ? capacityBytes : usedBytes);

      _storagePoolDao.update(storagePoolId, storagePool);
    } else {
      errMsg = "Invalid DataObjectType (" + dataObject.getType() + ") passed to createAsync";
    }

    // path = iqn
    // size is pulled from DataObject instance, if errMsg is null
    CreateCmdResult result = new CreateCmdResult(iqn, new Answer(null, errMsg == null, errMsg));

    result.setResult(errMsg);

    callback.complete(result);
  }
  @Override
  public void createTemplateAsync(
      TemplateInfo template, DataStore store, AsyncCompletionCallback<TemplateApiResult> callback) {
    // persist template_store_ref entry
    TemplateObject templateOnStore = (TemplateObject) store.create(template);
    // update template_store_ref and template state
    try {
      templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested);
    } catch (Exception e) {
      TemplateApiResult result = new TemplateApiResult(templateOnStore);
      result.setResult(e.toString());
      result.setSuccess(false);
      if (callback != null) {
        callback.complete(result);
      }
      return;
    }

    try {
      TemplateOpContext<TemplateApiResult> context =
          new TemplateOpContext<TemplateApiResult>(callback, templateOnStore, null);

      AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller =
          AsyncCallbackDispatcher.create(this);
      caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context);
      store.getDriver().createAsync(store, templateOnStore, caller);
    } catch (CloudRuntimeException ex) {
      // clean up already persisted template_store_ref entry in case of createTemplateCallback is
      // never called
      TemplateDataStoreVO templateStoreVO =
          _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId());
      if (templateStoreVO != null) {
        TemplateInfo tmplObj = _templateFactory.getTemplate(template, store);
        tmplObj.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
      }
      TemplateApiResult result = new TemplateApiResult(template);
      result.setResult(ex.getMessage());
      if (callback != null) {
        callback.complete(result);
      }
    }
  }
 @Override
 public void downloadTemplateToStorage(
     DataObject template, AsyncCompletionCallback<DownloadAnswer> callback) {
   if (template != null) {
     long templateId = template.getId();
     DataStore store = template.getDataStore();
     if (isTemplateUpdateable(templateId, store.getId())) {
       if (template.getUri() != null) {
         initiateTemplateDownload(template, callback);
       } else {
         s_logger.info("Template url is null, cannot download");
         DownloadAnswer ans = new DownloadAnswer("Template url is null", Status.UNKNOWN);
         callback.complete(ans);
       }
     } else {
       s_logger.info("Template download is already in progress or already downloaded");
       DownloadAnswer ans =
           new DownloadAnswer(
               "Template download is already in progress or already downloaded", Status.UNKNOWN);
       callback.complete(ans);
     }
   }
 }
    @Override
    public void run() {
      try {
        Answer answer = new Answer(cmd, false, "unknown command");
        /*if (cmd instanceof CopyTemplateToPrimaryStorageCmd) {
            answer = new CopyTemplateToPrimaryStorageAnswer(cmd, UUID.randomUUID().toString());
        } else if (cmd instanceof CreateVolumeFromBaseImageCommand) {
            answer = new CreateVolumeAnswer(cmd, UUID.randomUUID().toString());
        }*/

        callback.complete(answer);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  @Override
  public void deleteAsync(
      DataStore dataStore, DataObject dataObject, AsyncCompletionCallback<CommandResult> callback) {
    String errMsg = null;

    if (dataObject.getType() == DataObjectType.VOLUME) {
      VolumeInfo volumeInfo = (VolumeInfo) dataObject;
      AccountVO account = _accountDao.findById(volumeInfo.getAccountId());
      AccountDetailVO accountDetails =
          _accountDetailsDao.findDetail(account.getAccountId(), SolidFireUtil.ACCOUNT_ID);
      long sfAccountId = Long.parseLong(accountDetails.getValue());

      long storagePoolId = dataStore.getId();
      SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);

      deleteSolidFireVolume(volumeInfo, sfConnection);

      _volumeDao.deleteVolumesByInstance(volumeInfo.getId());

      //            if (!sfAccountHasVolume(sfAccountId, sfConnection)) {
      //                // delete the account from the SolidFire SAN
      //                deleteSolidFireAccount(sfAccountId, sfConnection);
      //
      //                // delete the info in the account_details table
      //                // that's related to the SolidFire account
      //                _accountDetailsDao.deleteDetails(account.getAccountId());
      //            }

      StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);

      long usedBytes = storagePool.getUsedBytes();

      usedBytes -= volumeInfo.getSize();

      storagePool.setUsedBytes(usedBytes < 0 ? 0 : usedBytes);

      _storagePoolDao.update(storagePoolId, storagePool);
    } else {
      errMsg = "Invalid DataObjectType (" + dataObject.getType() + ") passed to deleteAsync";
    }

    CommandResult result = new CommandResult();

    result.setResult(errMsg);

    callback.complete(result);
  }
 @Override
 public void deleteAsync(
     DataStore dataStore, DataObject data, AsyncCompletionCallback<CommandResult> callback) {
   CommandResult result = new CommandResult();
   try {
     DeleteCommand cmd = new DeleteCommand(data.getTO());
     EndPoint ep = _epSelector.select(data);
     Answer answer = ep.sendMessage(cmd);
     if (answer != null && !answer.getResult()) {
       result.setResult(answer.getDetails());
     }
   } catch (Exception ex) {
     s_logger.debug("Unable to destoy " + data.getType().toString() + ": " + data.getId(), ex);
     result.setResult(ex.toString());
   }
   callback.complete(result);
 }