content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  package org.apache.cloudstack.storage.datastore.driver;
  
  import static org.apache.cloudstack.storage.datastore.util.NexentaUtil.NexentaPluginParameters;
  
  import java.util.Map;
  
  import javax.inject.Inject;
  
  import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
  import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
  import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
  import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
  import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
  import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
  import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
  import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
  import org.apache.cloudstack.storage.command.CommandResult;
  import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
  import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
  import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
  import org.apache.cloudstack.storage.datastore.util.NexentaStorAppliance;
  import org.apache.cloudstack.storage.datastore.util.NexentaStorAppliance.NexentaStorZvol;
  import org.apache.cloudstack.storage.datastore.util.NexentaUtil;
  import org.apache.logging.log4j.Logger;
  import org.apache.logging.log4j.LogManager;
  
  import com.cloud.agent.api.Answer;
  import com.cloud.agent.api.to.DataObjectType;
  import com.cloud.agent.api.to.DataStoreTO;
  import com.cloud.agent.api.to.DataTO;
  import com.cloud.host.Host;
  import com.cloud.storage.Storage;
  import com.cloud.storage.Storage.StoragePoolType;
  import com.cloud.storage.StoragePool;
  import com.cloud.storage.Volume;
  import com.cloud.storage.VolumeVO;
  import com.cloud.storage.dao.VolumeDao;
  import com.cloud.user.dao.AccountDao;
  import com.cloud.utils.Pair;
  
  public class NexentaPrimaryDataStoreDriver implements PrimaryDataStoreDriver {
      protected Logger logger = LogManager.getLogger(getClass());
  
      @Override
      public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore) {
          return false;  //To change body of implemented methods use File | Settings | File Templates.
      }
  
      @Override
      public void revokeAccess(DataObject dataObject, Host host, DataStore dataStore) {
          //To change body of implemented methods use File | Settings | File Templates.
      }
  
      @Override
      public long getUsedBytes(StoragePool storagePool) {
          return 0;
      }
  
      @Override
      public long getUsedIops(StoragePool storagePool) {
          return 0;
      }
  
      @Override
      public long getDataObjectSizeIncludingHypervisorSnapshotReserve(DataObject dataObject, StoragePool pool) {
          return 0;
      }
  
      @Override
      public long getBytesRequiredForTemplate(TemplateInfo templateInfo, StoragePool storagePool) {
          return 0;
      }
  
      @Inject
      private VolumeDao _volumeDao;
      @Inject
      PrimaryDataStoreDao _storagePoolDao;
      @Inject
      private StoragePoolDetailsDao _storagePoolDetailsDao;
      @Inject
      private AccountDao _accountDao;
  
      @Override
      public Map<String, String> getCapabilities() {
          return null;
      }
  
      @Override
      public ChapInfo getChapInfo(DataObject dataObject) {
          return null;
      }
  
      @Override
      public DataTO getTO(DataObject data) {
          return null;
      }
  
      @Override
      public DataStoreTO getStoreTO(DataStore store) {
          return null;
      }
  
      private NexentaStorAppliance getNexentaStorAppliance(long storagePoolId) {
          NexentaPluginParameters parameters = new NexentaPluginParameters();
  
          parameters.setNmsUrl(_storagePoolDetailsDao.findDetail(storagePoolId, NexentaUtil.NMS_URL).getValue());
          parameters.setVolume(_storagePoolDetailsDao.findDetail(storagePoolId, NexentaUtil.VOLUME).getValue());
          parameters.setStorageType(_storagePoolDetailsDao.findDetail(storagePoolId, NexentaUtil.STORAGE_TYPE).getValue());
          parameters.setStorageHost(_storagePoolDetailsDao.findDetail(storagePoolId, NexentaUtil.STORAGE_HOST).getValue());
          parameters.setStoragePort(_storagePoolDetailsDao.findDetail(storagePoolId, NexentaUtil.STORAGE_PORT).getValue());
          parameters.setStoragePath(_storagePoolDetailsDao.findDetail(storagePoolId, NexentaUtil.STORAGE_PATH).getValue());
          parameters.setSparseVolumes(_storagePoolDetailsDao.findDetail(storagePoolId, NexentaUtil.SPARSE_VOLUMES).getValue());
          parameters.setVolumeBlockSize(_storagePoolDetailsDao.findDetail(storagePoolId, NexentaUtil.VOLUME_BLOCK_SIZE).getValue());
  
          return new NexentaStorAppliance(parameters);
      }
  
      @Override
      public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback) {}
  
      @Override
      public void revertSnapshot(SnapshotInfo snapshot, SnapshotInfo snapshotOnPrimaryStore, AsyncCompletionCallback<CommandResult> callback) {}
  
      @Override
      public void createAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback<CreateCmdResult> callback) {
          String iqn = null;
          String errorMessage = null;
  
          if (dataObject.getType() != DataObjectType.VOLUME) {
              errorMessage = "Invalid DataObjectType (" + dataObject.getType() + ") passed to createAsync";
          } else {
              VolumeInfo volumeInfo = (VolumeInfo) dataObject;
  
              long storagePoolId = dataStore.getId();
              NexentaStorAppliance appliance = getNexentaStorAppliance(storagePoolId);
  
              // TODO: maybe we should use md5(volume name) as volume name
              NexentaStorZvol zvol = (NexentaStorZvol) appliance.createVolume(volumeInfo.getName(), volumeInfo.getSize());
              iqn = zvol.getIqn();
  
              VolumeVO volume = this._volumeDao.findById(volumeInfo.getId());
              volume.set_iScsiName(iqn);
              volume.setFolder(zvol.getName());
              volume.setPoolType(Storage.StoragePoolType.IscsiLUN);
              volume.setPoolId(storagePoolId);
              _volumeDao.update(volume.getId(), volume);
  
              StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);
              long capacityBytes = storagePool.getCapacityBytes();
              long usedBytes = storagePool.getUsedBytes();
              usedBytes += volumeInfo.getSize();
              storagePool.setUsedBytes(usedBytes > capacityBytes ? capacityBytes : usedBytes);
              _storagePoolDao.update(storagePoolId, storagePool);
          }
  
          CreateCmdResult result = new CreateCmdResult(iqn, new Answer(null, errorMessage == null, errorMessage));
          result.setResult(errorMessage);
          callback.complete(result);
      }
  
      @Override
      public void deleteAsync(DataStore store, DataObject data, AsyncCompletionCallback<CommandResult> callback) {
          String errorMessage = null;
          if (data.getType() == DataObjectType.VOLUME) {
              VolumeInfo volumeInfo = (VolumeInfo) data;
              long storagePoolId = store.getId();
              NexentaStorAppliance appliance = getNexentaStorAppliance(storagePoolId);
              StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);
  
  
  
  //            _storagePoolDao.update(stoagePoolId);
          } else {
              errorMessage = String.format(
                      "Invalid DataObjectType(%s) passed to deleteAsync",
                      data.getType());
          }
          CommandResult result = new CommandResult();
          result.setResult(errorMessage);
          callback.complete(result);
      }
  
      @Override
      public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {}
  
      @Override
      public void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
      }
  
      @Override
      public boolean canCopy(DataObject srcData, DataObject destData) {
          return false;
      }
  
      @Override
      public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) {}
  
      @Override
      public void handleQualityOfServiceForVolumeMigration(VolumeInfo volumeInfo, QualityOfServiceState qualityOfServiceState) {}
  
      @Override
      public boolean canProvideStorageStats() {
          return false;
      }
  
      @Override
      public boolean canProvideVolumeStats() {
          return false;
      }
  
      @Override
      public Pair<Long, Long> getVolumeStats(StoragePool storagePool, String volumeId) {
          return null;
      }
  
      @Override
      public Pair<Long, Long> getStorageStats(StoragePool storagePool) {
          return null;
      }
  
      @Override
      public boolean canHostAccessStoragePool(Host host, StoragePool pool) {
          return true;
      }
  
      @Override
      public boolean isVmInfoNeeded() {
          return false;
      }
  
      @Override
      public void provideVmInfo(long vmId, long volumeId) {
      }
  
      @Override
      public boolean isVmTagsNeeded(String tagKey) {
          return false;
      }
  
      @Override
      public void provideVmTags(long vmId, long volumeId, String tagValue) {
      }
  
      @Override
      public boolean isStorageSupportHA(StoragePoolType type) {
          return false;
      }
  
      @Override
      public void detachVolumeFromAllStorageNodes(Volume volume) {
      }
  
      @Override
      public boolean volumesRequireGrantAccessWhenUsed() {
          return true;
      }
  }
  