@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);
  }
  private SolidFireUtil.SolidFireVolume createSolidFireVolume(
      VolumeInfo volumeInfo, SolidFireConnection sfConnection) {
    String mVip = sfConnection.getManagementVip();
    int mPort = sfConnection.getManagementPort();
    String clusterAdminUsername = sfConnection.getClusterAdminUsername();
    String clusterAdminPassword = sfConnection.getClusterAdminPassword();

    AccountDetailVO accountDetail =
        _accountDetailsDao.findDetail(volumeInfo.getAccountId(), SolidFireUtil.ACCOUNT_ID);
    long sfAccountId = Long.parseLong(accountDetail.getValue());

    long storagePoolId = volumeInfo.getDataStore().getId();

    final Iops iops;

    Long minIops = volumeInfo.getMinIops();
    Long maxIops = volumeInfo.getMaxIops();

    if (minIops == null || minIops <= 0 || maxIops == null || maxIops <= 0) {
      long defaultMaxIops = getDefaultMaxIops(storagePoolId);

      iops =
          new Iops(
              getDefaultMinIops(storagePoolId),
              defaultMaxIops,
              getDefaultBurstIops(storagePoolId, defaultMaxIops));
    } else {
      iops =
          new Iops(
              volumeInfo.getMinIops(),
              volumeInfo.getMaxIops(),
              getDefaultBurstIops(storagePoolId, volumeInfo.getMaxIops()));
    }

    long sfVolumeId =
        SolidFireUtil.createSolidFireVolume(
            mVip,
            mPort,
            clusterAdminUsername,
            clusterAdminPassword,
            getSolidFireVolumeName(volumeInfo.getName()),
            sfAccountId,
            volumeInfo.getSize(),
            true,
            iops.getMinIops(),
            iops.getMaxIops(),
            iops.getBurstIops());

    return SolidFireUtil.getSolidFireVolume(
        mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfVolumeId);
  }
  @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);
  }