Skip to content

Commit 1020a2c

Browse files
CSTACKEX-18_2: using flexvolume snapshot even for CS volume snapshot workflow
1 parent 186e59b commit 1020a2c

File tree

6 files changed

+1053
-151
lines changed

6 files changed

+1053
-151
lines changed

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java

Lines changed: 15 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import com.cloud.storage.Volume;
3030
import com.cloud.storage.VolumeVO;
3131
import com.cloud.storage.ScopeType;
32-
import com.cloud.storage.dao.SnapshotDetailsDao;
33-
import com.cloud.storage.dao.SnapshotDetailsVO;
3432
import com.cloud.storage.dao.VolumeDao;
3533
import com.cloud.storage.dao.VolumeDetailsDao;
3634
import com.cloud.utils.Pair;
@@ -49,22 +47,18 @@
4947
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
5048
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
5149
import org.apache.cloudstack.storage.command.CommandResult;
52-
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
5350
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
5451
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
5552
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
56-
import org.apache.cloudstack.storage.feign.model.FileInfo;
5753
import org.apache.cloudstack.storage.feign.model.Lun;
5854
import org.apache.cloudstack.storage.service.SANStrategy;
5955
import org.apache.cloudstack.storage.service.StorageStrategy;
6056
import org.apache.cloudstack.storage.service.UnifiedSANStrategy;
6157
import org.apache.cloudstack.storage.service.model.AccessGroup;
6258
import org.apache.cloudstack.storage.service.model.CloudStackVolume;
6359
import org.apache.cloudstack.storage.service.model.ProtocolType;
64-
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
6560
import org.apache.cloudstack.storage.utils.Constants;
6661
import org.apache.cloudstack.storage.utils.Utility;
67-
import org.apache.commons.lang3.StringUtils;
6862
import org.apache.logging.log4j.LogManager;
6963
import org.apache.logging.log4j.Logger;
7064

@@ -86,16 +80,17 @@ public class OntapPrimaryDatastoreDriver implements PrimaryDataStoreDriver {
8680
@Inject private VMInstanceDao vmDao;
8781
@Inject private VolumeDao volumeDao;
8882
@Inject private VolumeDetailsDao volumeDetailsDao;
89-
@Inject private SnapshotDetailsDao snapshotDetailsDao;
9083

9184
@Override
9285
public Map<String, String> getCapabilities() {
9386
s_logger.trace("OntapPrimaryDatastoreDriver: getCapabilities: Called");
9487
Map<String, String> mapCapabilities = new HashMap<>();
95-
// RAW managed initial implementation: snapshot features not yet supported
96-
// TODO Set it to false once we start supporting snapshot feature
97-
mapCapabilities.put(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString(), Boolean.TRUE.toString());
98-
mapCapabilities.put(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_SNAPSHOT.toString(), Boolean.TRUE.toString());
88+
// Snapshot operations are handled by OntapSnapshotStrategy (volume-level)
89+
// and OntapVMSnapshotStrategy (VM-level) using native ONTAP FlexVol snapshots.
90+
// These capabilities are set to FALSE so that StorageSystemSnapshotStrategy
91+
// does not attempt to handle ONTAP volumes through the driver path.
92+
mapCapabilities.put(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString(), Boolean.FALSE.toString());
93+
mapCapabilities.put(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_SNAPSHOT.toString(), Boolean.FALSE.toString());
9994
return mapCapabilities;
10095
}
10196

@@ -532,84 +527,15 @@ public long getUsedIops(StoragePool storagePool) {
532527

533528
@Override
534529
public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback) {
535-
s_logger.info("takeSnapshot : entered with snapshot id: " + snapshot.getId() + " and name: " + snapshot.getName());
536-
CreateCmdResult result;
537-
538-
try {
539-
VolumeInfo volumeInfo = snapshot.getBaseVolume();
540-
541-
VolumeVO volumeVO = volumeDao.findById(volumeInfo.getId());
542-
if(volumeVO == null) {
543-
throw new CloudRuntimeException("takeSnapshot: VolumeVO not found for id: " + volumeInfo.getId());
544-
}
545-
546-
/** we are keeping file path at volumeVO.getPath() */
547-
548-
StoragePoolVO storagePool = storagePoolDao.findById(volumeVO.getPoolId());
549-
if(storagePool == null) {
550-
s_logger.error("takeSnapshot : Storage Pool not found for id: " + volumeVO.getPoolId());
551-
throw new CloudRuntimeException("takeSnapshot : Storage Pool not found for id: " + volumeVO.getPoolId());
552-
}
553-
Map<String, String> poolDetails = storagePoolDetailsDao.listDetailsKeyPairs(volumeVO.getPoolId());
554-
StorageStrategy storageStrategy = Utility.getStrategyByStoragePoolDetails(poolDetails);
555-
556-
CloudStackVolume cloudStackVolume = null;
557-
long usedBytes = getUsedBytes(storagePool);
558-
long capacityBytes = storagePool.getCapacityBytes();
559-
long fileSize = 0l;
560-
// Only proceed for NFS3 protocol
561-
if (ProtocolType.NFS3.name().equalsIgnoreCase(poolDetails.get(Constants.PROTOCOL))) {
562-
Map<String, String> cloudStackVolumeRequestMap = new HashMap<>();
563-
cloudStackVolumeRequestMap.put(Constants.VOLUME_UUID, poolDetails.get(Constants.VOLUME_UUID));
564-
cloudStackVolumeRequestMap.put(Constants.FILE_PATH, volumeVO.getPath());
565-
cloudStackVolume = storageStrategy.getCloudStackVolume(cloudStackVolumeRequestMap);
566-
if (cloudStackVolume == null || cloudStackVolume.getFile() == null) {
567-
throw new CloudRuntimeException("Failed to get source file to take snapshot");
568-
}
569-
s_logger.info("takeSnapshot : entered after getting cloudstack volume with file path: " + cloudStackVolume.getFile().getPath() + " and size: " + cloudStackVolume.getFile().getSize());
570-
fileSize = cloudStackVolume.getFile().getSize();
571-
usedBytes += fileSize;
572-
}
573-
574-
if (usedBytes > capacityBytes) {
575-
throw new CloudRuntimeException("Insufficient space remains in this primary storage to take a snapshot");
576-
}
577-
578-
storagePool.setUsedBytes(usedBytes);
579-
580-
SnapshotObjectTO snapshotObjectTo = (SnapshotObjectTO)snapshot.getTO();
581-
582-
String snapshotName = volumeInfo.getName() + "-" + snapshot.getUuid();
583-
584-
int trimRequired = snapshotName.length() - Constants.MAX_SNAPSHOT_NAME_LENGTH;
585-
586-
if (trimRequired > 0) {
587-
snapshotName = StringUtils.left(volumeInfo.getName(), (volumeInfo.getName().length() - trimRequired)) + "-" + snapshot.getUuid();
588-
}
589-
590-
CloudStackVolume snapCloudStackVolumeRequest = snapshotCloudStackVolumeRequestByProtocol(poolDetails, volumeVO.getPath(), snapshotName);
591-
CloudStackVolume cloneCloudStackVolume = storageStrategy.snapshotCloudStackVolume(snapCloudStackVolumeRequest);
592-
593-
updateSnapshotDetails(snapshot.getId(), volumeInfo.getId(), poolDetails.get(Constants.VOLUME_UUID), cloneCloudStackVolume.getFile().getPath(), volumeVO.getPoolId(), fileSize);
594-
595-
snapshotObjectTo.setPath(Constants.ONTAP_SNAP_ID +"="+cloneCloudStackVolume.getFile().getPath());
596-
597-
/** Update size for the storage-pool including snapshot size */
598-
storagePoolDao.update(volumeVO.getPoolId(), storagePool);
599-
600-
CreateObjectAnswer createObjectAnswer = new CreateObjectAnswer(snapshotObjectTo);
601-
602-
result = new CreateCmdResult(null, createObjectAnswer);
603-
604-
result.setResult(null);
605-
}
606-
catch (Exception ex) {
607-
s_logger.error("takeSnapshot: Failed due to ", ex);
608-
result = new CreateCmdResult(null, new CreateObjectAnswer(ex.toString()));
609-
610-
result.setResult(ex.toString());
611-
}
612-
530+
// Snapshot operations are now handled by OntapSnapshotStrategy which intercepts
531+
// at the strategy layer before the driver is ever called. This method should
532+
// not be reached for ONTAP volumes. If it is, fail explicitly.
533+
s_logger.error("takeSnapshot: This driver method should not be called. " +
534+
"Snapshot operations for ONTAP are handled by OntapSnapshotStrategy. " +
535+
"Snapshot id: " + snapshot.getId());
536+
CreateCmdResult result = new CreateCmdResult(null, new Answer(null, false,
537+
"takeSnapshot not supported via driver path; use OntapSnapshotStrategy"));
538+
result.setResult("takeSnapshot not supported via driver path");
613539
callback.complete(result);
614540
}
615541

@@ -709,60 +635,4 @@ private CloudStackVolume createDeleteCloudStackVolumeRequest(StoragePool storage
709635

710636
}
711637

712-
private CloudStackVolume snapshotCloudStackVolumeRequestByProtocol(Map<String, String> details,
713-
String sourcePath,
714-
String destinationPath) {
715-
CloudStackVolume cloudStackVolumeRequest = null;
716-
ProtocolType protocolType = null;
717-
String protocol = null;
718-
719-
try {
720-
protocol = details.get(Constants.PROTOCOL);
721-
protocolType = ProtocolType.valueOf(protocol);
722-
} catch (IllegalArgumentException e) {
723-
throw new CloudRuntimeException("getCloudStackVolumeRequestByProtocol: Protocol: "+ protocol +" is not valid");
724-
}
725-
switch (protocolType) {
726-
case NFS3:
727-
cloudStackVolumeRequest = new CloudStackVolume();
728-
FileInfo fileInfo = new FileInfo();
729-
fileInfo.setPath(sourcePath);
730-
cloudStackVolumeRequest.setFile(fileInfo);
731-
String volumeUuid = details.get(Constants.VOLUME_UUID);
732-
cloudStackVolumeRequest.setFlexVolumeUuid(volumeUuid);
733-
cloudStackVolumeRequest.setDestinationPath(destinationPath);
734-
break;
735-
default:
736-
throw new CloudRuntimeException("createCloudStackVolumeRequestByProtocol: Unsupported protocol " + protocol);
737-
738-
}
739-
return cloudStackVolumeRequest;
740-
}
741-
742-
/**
743-
*
744-
* @param csSnapshotId: generated snapshot id from cloudstack
745-
* @param csVolumeId: Source CS volume id
746-
* @param ontapVolumeUuid: storage flexvolume id
747-
* @param ontapNewSnapshot: generated snapshot id from ONTAP
748-
* @param storagePoolId: primary storage pool id
749-
* @param ontapSnapSize: Size of snapshot CS volume(LUN/file)
750-
*/
751-
private void updateSnapshotDetails(long csSnapshotId, long csVolumeId, String ontapVolumeUuid, String ontapNewSnapshot, long storagePoolId, long ontapSnapSize) {
752-
SnapshotDetailsVO snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.SRC_CS_VOLUME_ID, String.valueOf(csVolumeId), false);
753-
snapshotDetailsDao.persist(snapshotDetail);
754-
755-
snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.BASE_ONTAP_FV_ID, String.valueOf(ontapVolumeUuid), false);
756-
snapshotDetailsDao.persist(snapshotDetail);
757-
758-
snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.ONTAP_SNAP_ID, String.valueOf(ontapNewSnapshot), false);
759-
snapshotDetailsDao.persist(snapshotDetail);
760-
761-
snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.PRIMARY_POOL_ID, String.valueOf(storagePoolId), false);
762-
snapshotDetailsDao.persist(snapshotDetail);
763-
764-
snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.ONTAP_SNAP_SIZE, String.valueOf(ontapSnapSize), false);
765-
snapshotDetailsDao.persist(snapshotDetail);
766-
}
767-
768638
}

0 commit comments

Comments
 (0)