-
Notifications
You must be signed in to change notification settings - Fork 0
NFS3 protocol specific snapshot workflows #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
f42552b
8894248
3f0019a
9b79f46
7a0d61e
7c3419e
d2b6a27
c5d5428
3f18c11
723561b
09968db
0a1a9c4
49df4c3
776b9a2
c04e223
186e59b
1020a2c
672d7a4
9c63c61
79730ed
ae96e9b
1b0bba9
7780a93
5bff41f
2abbed6
2340400
ce93705
e1a6465
9138e20
5f9e51c
142e0e6
aa74a5a
55447b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -106,6 +106,10 @@ protected Answer takeDiskOnlyVmSnapshotOfRunningVm(CreateDiskOnlyVmSnapshotComma | |
| return new CreateDiskOnlyVmSnapshotAnswer(cmd, false, errorMsg, null); | ||
| } | ||
| return new CreateDiskOnlyVmSnapshotAnswer(cmd, false, e.getMessage(), null); | ||
| } catch (Exception e) { | ||
| String errorMsg = String.format("Creation of disk-only VM snapshot for VM [%s] failed due to %s.", vmName, e.getMessage()); | ||
| logger.error(errorMsg, e); | ||
| return new CreateDiskOnlyVmSnapshotAnswer(cmd, false, errorMsg, null); | ||
| } finally { | ||
| if (dm != null) { | ||
| try { | ||
|
|
@@ -146,21 +150,13 @@ protected Answer takeDiskOnlyVmSnapshotOfStoppedVm(CreateDiskOnlyVmSnapshotComma | |
| } | ||
| } catch (LibvirtException | QemuImgException e) { | ||
| logger.error("Exception while creating disk-only VM snapshot for VM [{}]. Deleting leftover deltas.", vmName, e); | ||
| for (VolumeObjectTO volumeObjectTO : volumeObjectTos) { | ||
| Pair<Long, String> volSizeAndNewPath = mapVolumeToSnapshotSizeAndNewVolumePath.get(volumeObjectTO.getUuid()); | ||
| PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO) volumeObjectTO.getDataStore(); | ||
| KVMStoragePool kvmStoragePool = storagePoolMgr.getStoragePool(primaryDataStoreTO.getPoolType(), primaryDataStoreTO.getUuid()); | ||
|
|
||
| if (volSizeAndNewPath == null) { | ||
| continue; | ||
| } | ||
| try { | ||
| Files.deleteIfExists(Path.of(kvmStoragePool.getLocalPathFor(volSizeAndNewPath.second()))); | ||
| } catch (IOException ex) { | ||
| logger.warn("Tried to delete leftover snapshot at [{}] failed.", volSizeAndNewPath.second(), ex); | ||
| } | ||
| } | ||
| cleanupLeftoverDeltas(volumeObjectTos, mapVolumeToSnapshotSizeAndNewVolumePath, storagePoolMgr); | ||
| return new Answer(cmd, e); | ||
| } catch (Exception e) { | ||
| logger.error("Unexpected exception while creating disk-only VM snapshot for VM [{}]. Deleting leftover deltas.", vmName, e); | ||
| cleanupLeftoverDeltas(volumeObjectTos, mapVolumeToSnapshotSizeAndNewVolumePath, storagePoolMgr); | ||
| return new CreateDiskOnlyVmSnapshotAnswer(cmd, false, | ||
| String.format("Creation of disk-only VM snapshot for VM [%s] failed due to %s.", vmName, e.getMessage()), null); | ||
| } | ||
|
|
||
| return new CreateDiskOnlyVmSnapshotAnswer(cmd, true, null, mapVolumeToSnapshotSizeAndNewVolumePath); | ||
|
|
@@ -192,6 +188,23 @@ protected Pair<String, Map<String, Pair<Long, String>>> createSnapshotXmlAndNewV | |
| return new Pair<>(snapshotXml, volumeObjectToNewPathMap); | ||
| } | ||
|
|
||
| protected void cleanupLeftoverDeltas(List<VolumeObjectTO> volumeObjectTos, Map<String, Pair<Long, String>> mapVolumeToSnapshotSizeAndNewVolumePath, KVMStoragePoolManager storagePoolMgr) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this refactoring somehow help our plugin functionality? |
||
| for (VolumeObjectTO volumeObjectTO : volumeObjectTos) { | ||
| Pair<Long, String> volSizeAndNewPath = mapVolumeToSnapshotSizeAndNewVolumePath.get(volumeObjectTO.getUuid()); | ||
| PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO) volumeObjectTO.getDataStore(); | ||
| KVMStoragePool kvmStoragePool = storagePoolMgr.getStoragePool(primaryDataStoreTO.getPoolType(), primaryDataStoreTO.getUuid()); | ||
|
|
||
| if (volSizeAndNewPath == null) { | ||
| continue; | ||
| } | ||
| try { | ||
| Files.deleteIfExists(Path.of(kvmStoragePool.getLocalPathFor(volSizeAndNewPath.second()))); | ||
| } catch (IOException ex) { | ||
| logger.warn("Tried to delete leftover snapshot at [{}] failed.", volSizeAndNewPath.second(), ex); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| protected long getFileSize(String path) { | ||
| return new File(path).length(); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,8 @@ | |
| import com.cloud.storage.Volume; | ||
| import com.cloud.storage.VolumeVO; | ||
| import com.cloud.storage.ScopeType; | ||
| import com.cloud.storage.dao.SnapshotDetailsDao; | ||
| import com.cloud.storage.dao.SnapshotDetailsVO; | ||
| import com.cloud.storage.dao.VolumeDao; | ||
| import com.cloud.storage.dao.VolumeDetailsDao; | ||
| import com.cloud.utils.Pair; | ||
|
|
@@ -47,18 +49,22 @@ | |
| 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.command.CreateObjectAnswer; | ||
| 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.feign.model.FileInfo; | ||
| import org.apache.cloudstack.storage.feign.model.Lun; | ||
| import org.apache.cloudstack.storage.service.SANStrategy; | ||
| import org.apache.cloudstack.storage.service.StorageStrategy; | ||
| import org.apache.cloudstack.storage.service.UnifiedSANStrategy; | ||
| import org.apache.cloudstack.storage.service.model.AccessGroup; | ||
| import org.apache.cloudstack.storage.service.model.CloudStackVolume; | ||
| import org.apache.cloudstack.storage.service.model.ProtocolType; | ||
| import org.apache.cloudstack.storage.to.SnapshotObjectTO; | ||
| import org.apache.cloudstack.storage.utils.Constants; | ||
| import org.apache.cloudstack.storage.utils.Utility; | ||
| import org.apache.commons.lang3.StringUtils; | ||
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
|
|
||
|
|
@@ -80,14 +86,16 @@ public class OntapPrimaryDatastoreDriver implements PrimaryDataStoreDriver { | |
| @Inject private VMInstanceDao vmDao; | ||
| @Inject private VolumeDao volumeDao; | ||
| @Inject private VolumeDetailsDao volumeDetailsDao; | ||
| @Inject private SnapshotDetailsDao snapshotDetailsDao; | ||
|
|
||
| @Override | ||
| public Map<String, String> getCapabilities() { | ||
| s_logger.trace("OntapPrimaryDatastoreDriver: getCapabilities: Called"); | ||
| Map<String, String> mapCapabilities = new HashMap<>(); | ||
| // RAW managed initial implementation: snapshot features not yet supported | ||
| // TODO Set it to false once we start supporting snapshot feature | ||
| mapCapabilities.put(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString(), Boolean.FALSE.toString()); | ||
| mapCapabilities.put(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_SNAPSHOT.toString(), Boolean.FALSE.toString()); | ||
| mapCapabilities.put(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString(), Boolean.TRUE.toString()); | ||
| mapCapabilities.put(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_SNAPSHOT.toString(), Boolean.TRUE.toString()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are supporting volume creation from snapshot with this PR?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. volume creation usecase is not yet ready as part of this PR There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to set this as true as we are currently not supporting volume creation from snapshot.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without this property set to true, CloudStack initiates both the snapshot creation and the corresponding copy operation to secondary storage over the data path, as it assumes that snapshots must reside on secondary storage by default.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, with this implementation, snapshots reside in primary storage itself?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I’m trying to explain is that if we don’t keep the second flag set to true, then only the plugin‑created snapshot will remain on the primary. In that case, the orchestrator will call the host agent again to create another snapshot and copy it to the secondary. |
||
| return mapCapabilities; | ||
| } | ||
|
|
||
|
|
@@ -524,7 +532,88 @@ public long getUsedIops(StoragePool storagePool) { | |
|
|
||
| @Override | ||
| public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback) { | ||
| s_logger.info("takeSnapshot : entered with snapshot id: " + snapshot.getId() + " and name: " + snapshot.getName()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lets have an intuitive log message instead of a method entry logger?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you provide a few examples?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of adding an entry log we can add a log post line 544. For example, it could be like |
||
| CreateCmdResult result; | ||
|
|
||
| try { | ||
| VolumeInfo volumeInfo = snapshot.getBaseVolume(); | ||
|
|
||
| VolumeVO volumeVO = volumeDao.findById(volumeInfo.getId()); | ||
| if(volumeVO == null) { | ||
| throw new CloudRuntimeException("takeSnapshot: VolumeVO not found for id: " + volumeInfo.getId()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't add method names in exceptions, as we don't have any cleanup framework before showing them on UI
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand. I was watching such instances, some of which are still overlooked. |
||
| } | ||
|
|
||
| /** we are keeping file path at volumeVO.getPath() */ | ||
|
|
||
| StoragePoolVO storagePool = storagePoolDao.findById(volumeVO.getPoolId()); | ||
| if(storagePool == null) { | ||
| s_logger.error("takeSnapshot : Storage Pool not found for id: " + volumeVO.getPoolId()); | ||
| throw new CloudRuntimeException("takeSnapshot : Storage Pool not found for id: " + volumeVO.getPoolId()); | ||
| } | ||
| Map<String, String> poolDetails = storagePoolDetailsDao.listDetailsKeyPairs(volumeVO.getPoolId()); | ||
| StorageStrategy storageStrategy = Utility.getStrategyByStoragePoolDetails(poolDetails); | ||
|
|
||
| CloudStackVolume cloudStackVolume = null; | ||
| long usedBytes = getUsedBytes(storagePool); | ||
| long capacityBytes = storagePool.getCapacityBytes(); | ||
|
|
||
| // Only proceed for NFS3 protocol | ||
| if (ProtocolType.NFS3.name().equalsIgnoreCase(poolDetails.get(Constants.PROTOCOL))) { | ||
|
sandeeplocharla marked this conversation as resolved.
Outdated
|
||
| Map<String, String> cloudStackVolumeRequestMap = new HashMap<>(); | ||
| cloudStackVolumeRequestMap.put(Constants.VOLUME_UUID, poolDetails.get(Constants.VOLUME_UUID)); | ||
| cloudStackVolumeRequestMap.put(Constants.FILE_PATH, volumeVO.getPath()); | ||
| cloudStackVolume = storageStrategy.getCloudStackVolume(cloudStackVolumeRequestMap); | ||
| if (cloudStackVolume == null || cloudStackVolume.getFile() == null) { | ||
| throw new CloudRuntimeException("takeSnapshot: Failed to get source file to take snapshot"); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we have method names only in loggers and not have them in exceptions? Management server might show this as an error on the UI?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. acknowledged |
||
| } | ||
| s_logger.info("takeSnapshot : entered after getting cloudstack volume with file path: " + cloudStackVolume.getFile().getPath() + " and size: " + cloudStackVolume.getFile().getSize()); | ||
| long fileSize = cloudStackVolume.getFile().getSize(); | ||
| usedBytes += fileSize; | ||
| } | ||
|
piyush5netapp marked this conversation as resolved.
|
||
|
|
||
|
|
||
|
|
||
| if (usedBytes > capacityBytes) { | ||
| throw new CloudRuntimeException("Insufficient space remains in this primary storage to take a snapshot"); | ||
| } | ||
|
|
||
| storagePool.setUsedBytes(usedBytes); | ||
|
|
||
| SnapshotObjectTO snapshotObjectTo = (SnapshotObjectTO)snapshot.getTO(); | ||
|
|
||
| String snapshotName = volumeInfo.getName() + "-" + snapshot.getUuid(); | ||
|
|
||
| int maxSnapshotNameLength = 64; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, we can have more character in snapshot name
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved it to contants for now, will update the length by checking it, if required. |
||
| int trimRequired = snapshotName.length() - maxSnapshotNameLength; | ||
|
|
||
| if (trimRequired > 0) { | ||
| snapshotName = StringUtils.left(volumeInfo.getName(), (volumeInfo.getName().length() - trimRequired)) + "-" + snapshot.getUuid(); | ||
| } | ||
|
|
||
| CloudStackVolume snapCloudStackVolumeRequest = snapshotCloudStackVolumeRequestByProtocol(poolDetails, volumeVO.getPath(), snapshotName); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per our recent discussion, maybe all of this code has to be offloaded to protocol specific strategy class
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we already have it below while calling actual snapshotCloudStackVolume() method. Request preparation we kept here for all the strategy calls.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Part of the discussion was to not create any request calls in driver class, push everything necessary to strategy classes and create the request necessary in the respective strategy class itself. BTW, the AI is on me to move the iSCSI specific request creation also into the respective strategy class. Will plan to pick it up soon but see if you can start this effort with snapshots?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per the implementation, I understand that we intend to follow the current way of handling the code. In which ONTAP specific protocol related changes would be in strategy classes and the cloudstack specific classes such as Driver class, would handle the cloudstack specific code. |
||
| CloudStackVolume cloneCloudStackVolume = storageStrategy.snapshotCloudStackVolume(snapCloudStackVolumeRequest); | ||
|
|
||
| updateSnapshotDetails(snapshot.getId(), volumeInfo.getId(), poolDetails.get(Constants.VOLUME_UUID), cloneCloudStackVolume.getFile().getPath(), volumeVO.getPoolId(), fileSize); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If iSCSI needs different things to be updated in DB, we might get an if-else on protocol here also.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, we have to handle that with iscsi protocol. |
||
|
|
||
| snapshotObjectTo.setPath(Constants.ONTAP_SNAP_ID +"="+cloneCloudStackVolume.getFile().getPath()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is "=" intentional ? |
||
|
|
||
| /** Update size for the storage-pool including snapshot size */ | ||
| storagePoolDao.update(volumeVO.getPoolId(), storagePool); | ||
|
|
||
| CreateObjectAnswer createObjectAnswer = new CreateObjectAnswer(snapshotObjectTo); | ||
|
|
||
| result = new CreateCmdResult(null, createObjectAnswer); | ||
|
|
||
| result.setResult(null); | ||
| } | ||
| catch (Exception ex) { | ||
| s_logger.error("takeSnapshot: Failed due to ", ex); | ||
| result = new CreateCmdResult(null, new CreateObjectAnswer(ex.toString())); | ||
|
|
||
| result.setResult(ex.toString()); | ||
| } | ||
|
|
||
| callback.complete(result); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -622,4 +711,87 @@ private CloudStackVolume createDeleteCloudStackVolumeRequest(StoragePool storage | |
| return cloudStackVolumeDeleteRequest; | ||
|
|
||
| } | ||
|
|
||
| private CloudStackVolume getCloudStackVolumeRequestByProtocol(Map<String, String> details, String filePath) { | ||
| CloudStackVolume cloudStackVolumeRequest = null; | ||
| ProtocolType protocolType = null; | ||
| String protocol = null; | ||
|
|
||
| try { | ||
| protocol = details.get(Constants.PROTOCOL); | ||
| protocolType = ProtocolType.valueOf(protocol); | ||
| } catch (IllegalArgumentException e) { | ||
| throw new CloudRuntimeException("getCloudStackVolumeRequestByProtocol: Protocol: "+ protocol +" is not valid"); | ||
| } | ||
| switch (protocolType) { | ||
| case NFS3: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even this also should be in the respective strategy class itself? |
||
| cloudStackVolumeRequest = new CloudStackVolume(); | ||
| FileInfo fileInfo = new FileInfo(); | ||
| fileInfo.setPath(filePath); | ||
| cloudStackVolumeRequest.setFile(fileInfo); | ||
| String volumeUuid = details.get(Constants.VOLUME_UUID); | ||
| cloudStackVolumeRequest.setFlexVolumeUuid(volumeUuid); | ||
| break; | ||
| default: | ||
| throw new CloudRuntimeException("createCloudStackVolumeRequestByProtocol: Unsupported protocol " + protocol); | ||
| } | ||
| return cloudStackVolumeRequest; | ||
| } | ||
|
|
||
| private CloudStackVolume snapshotCloudStackVolumeRequestByProtocol(Map<String, String> details, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this method is not used anywhere
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am calling this method in takeSnapshot() |
||
| String sourcePath, | ||
| String destinationPath) { | ||
| CloudStackVolume cloudStackVolumeRequest = null; | ||
| ProtocolType protocolType = null; | ||
| String protocol = null; | ||
|
|
||
| try { | ||
| protocol = details.get(Constants.PROTOCOL); | ||
| protocolType = ProtocolType.valueOf(protocol); | ||
| } catch (IllegalArgumentException e) { | ||
| throw new CloudRuntimeException("getCloudStackVolumeRequestByProtocol: Protocol: "+ protocol +" is not valid"); | ||
| } | ||
| switch (protocolType) { | ||
| case NFS3: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, this was addressed elaborately in our discussion.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please take a relook? This was also planned to be pushed onto the strategy classes to be dealt with according to the requirement |
||
| cloudStackVolumeRequest = new CloudStackVolume(); | ||
| FileInfo fileInfo = new FileInfo(); | ||
| fileInfo.setPath(sourcePath); | ||
| cloudStackVolumeRequest.setFile(fileInfo); | ||
| String volumeUuid = details.get(Constants.VOLUME_UUID); | ||
| cloudStackVolumeRequest.setFlexVolumeUuid(volumeUuid); | ||
| cloudStackVolumeRequest.setDestinationPath(destinationPath); | ||
| break; | ||
| default: | ||
| throw new CloudRuntimeException("createCloudStackVolumeRequestByProtocol: Unsupported protocol " + protocol); | ||
|
|
||
| } | ||
| return cloudStackVolumeRequest; | ||
| } | ||
|
|
||
| /** | ||
| * | ||
| * @param csSnapshotId: generated snapshot id from cloudstack | ||
| * @param csVolumeId: Source CS volume id | ||
| * @param ontapVolumeUuid: storage flexvolume id | ||
| * @param ontapNewSnapshot: generated snapshot id from ONTAP | ||
| * @param storagePoolId: primary storage pool id | ||
| * @param ontapSnapSize: Size of snapshot CS volume(LUN/file) | ||
| */ | ||
| private void updateSnapshotDetails(long csSnapshotId, long csVolumeId, String ontapVolumeUuid, String ontapNewSnapshot, long storagePoolId, long ontapSnapSize) { | ||
|
piyush5netapp marked this conversation as resolved.
Outdated
|
||
| SnapshotDetailsVO snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.SRC_CS_VOLUME_ID, String.valueOf(csVolumeId), false); | ||
| snapshotDetailsDao.persist(snapshotDetail); | ||
|
|
||
| snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.BASE_ONTAP_FV_ID, String.valueOf(ontapVolumeUuid), false); | ||
| snapshotDetailsDao.persist(snapshotDetail); | ||
|
|
||
| snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.ONTAP_SNAP_ID, String.valueOf(ontapNewSnapshot), false); | ||
| snapshotDetailsDao.persist(snapshotDetail); | ||
|
|
||
| snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.PRIMARY_POOL_ID, String.valueOf(storagePoolId), false); | ||
| snapshotDetailsDao.persist(snapshotDetail); | ||
|
|
||
| snapshotDetail = new SnapshotDetailsVO(csSnapshotId, Constants.ONTAP_SNAP_SIZE, String.valueOf(ontapSnapSize), false); | ||
| snapshotDetailsDao.persist(snapshotDetail); | ||
| } | ||
|
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.