Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncComplet
* - DATA or ROOT snapshot → new attachable data volume (ROOT is never bootable
* via this path; bootable recovery is createTemplate(snapshotid) → deploy).
* - Backend: iSCSI → POST /api/storage/luns (clone.source in .snapshot/);
* NFS → POST /api/storage/file/clone with snapshot.name.
* NFS → POST /api/storage/file/clone with source_path
* ./.snapshot/<snapshot-name>/<source-file>.
* - IOPS: the new volume's min/max (snapshot values, or the root offering when one
* is supplied). Applied here; the temporary template clone does not get a policy.
*
Expand Down Expand Up @@ -517,7 +518,8 @@ private Long getSnapshotIdForCloning(long volumeId) {
* {@code createTemplate(snapshotid)} then deploy.</li>
* <li><b>iSCSI</b> — {@code POST /api/storage/luns} with
* {@code clone.source.name=/vol/&lt;fv&gt;/.snapshot/&lt;snap&gt;/&lt;lun&gt;}</li>
* <li><b>NFS3</b> — {@code POST /api/storage/file/clone} with {@code snapshot.name}</li>
* <li><b>NFS3</b> — {@code POST /api/storage/file/clone} with
* {@code source_path=./.snapshot/&lt;snapshot-name&gt;/&lt;source-file&gt;}</li>
* <li><b>Not this path</b> — in-place revert ({@code revertSnapshot}); VM/instance snapshots;
* secondary-storage archive restore.</li>
* </ul>
Expand Down Expand Up @@ -2390,14 +2392,17 @@ private CloudStackVolume createCloneFileFromSnapshotRequest(StoragePoolVO storag
String flexVolName = details.get(OntapStorageConstants.VOLUME_NAME);

FileInfo file = new FileInfo();
file.setPath(OntapStorageUtils.toFlexVolRelativePath(sourceVolumePath, flexVolName));
// FlexVol-relative source path, for example "<source-file-uuid>".
String relativeSourcePath = OntapStorageUtils.toFlexVolRelativePath(sourceVolumePath, flexVolName);
Comment thread
sp16743 marked this conversation as resolved.
Resolved
// Path assigned to file.setPath(), for example "./.snapshot/<snapshot-name>/<source-file-uuid>".
file.setPath(OntapStorageConstants.DOT + OntapStorageConstants.SNAPSHOT_PATH_SEGMENT + snapshotName
+ OntapStorageConstants.SLASH + relativeSourcePath);

CloudStackVolume request = new CloudStackVolume();
request.setDatastoreId(String.valueOf(storagePool.getId()));
request.setVolumeInfo(volumeInfo);
request.setFile(file);
request.setDestinationPath(OntapStorageUtils.toFlexVolRelativePath(volumeInfo.getUuid(), flexVolName));
request.setSnapshotName(snapshotName);
Comment thread
sandeeplocharla marked this conversation as resolved.
Resolved
return request;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,6 @@ public FileCloneRequest(String flexVolUuid, String flexVolName, String sourcePat
this.destinationPath = destinationPath;
}

public FileCloneRequest(String flexVolUuid, String flexVolName, String sourcePath, String destinationPath,
String snapshotName) {
this(flexVolUuid, flexVolName, sourcePath, destinationPath);
if (snapshotName != null && !snapshotName.isEmpty()) {
this.snapshot = new SnapshotRef(snapshotName);
}
}

public VolumeRef getVolume() {
return volume;
}
Expand Down Expand Up @@ -177,7 +169,6 @@ public void setName(String name) {
public String toString() {
return "FileCloneRequest{volume=" + (volume != null ? volume.getUuid() : null)
+ ", sourcePath=" + sourcePath
+ ", destinationPath=" + destinationPath
+ ", snapshot=" + (snapshot != null ? snapshot.getName() : null) + "}";
+ ", destinationPath=" + destinationPath + "}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -934,8 +934,9 @@ abstract public CloudStackVolume createTemplateCache(StoragePoolVO storagePool,
* <ul>
* <li><b>SAN</b> — {@code lun.clone.source.name} set to
* {@code /vol/&lt;fv&gt;/.snapshot/&lt;snap&gt;/&lt;lun&gt;}</li>
* <li><b>NAS</b> — {@link CloudStackVolume#getSnapshotName()} set; it is sent as
* {@code snapshot.name} on {@code POST /api/storage/file/clone}</li>
* <li><b>NAS</b> — {@code file.path} set to
* {@code ./.snapshot/&lt;snapshot-name&gt;/&lt;source-file&gt;} and sent as
* {@code source_path} on {@code POST /api/storage/file/clone}</li>
* </ul>
*
* @param cloudstackVolume describes the clone to create; the source is carried in the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ public void deleteCloudStackVolume(CloudStackVolume cloudstackVolume) {
* Clones a file inside the FlexVolume using ONTAP's file clone API.
*
* <p>The source is taken from {@code file.path} and the destination from
* {@code destinationPath}, both relative to the root of the FlexVolume backing the pool.
* When {@code snapshotName} is set, the source is read from that FlexVolume snapshot.</p>
* {@code destinationPath}, both relative to the root of the FlexVolume backing the pool.</p>
*/
@Override
public CloudStackVolume cloneCloudStackVolume(CloudStackVolume cloudstackVolume) {
Expand All @@ -203,12 +202,11 @@ public CloudStackVolume cloneCloudStackVolume(CloudStackVolume cloudstackVolume)
}
String sourcePath = cloudstackVolume.getFile().getPath();
String destinationPath = cloudstackVolume.getDestinationPath();
String snapshotName = cloudstackVolume.getSnapshotName();

logger.info("cloneCloudStackVolume: Cloning file [{}] to [{}] in FlexVol [{}] from snapshot [{}]",
sourcePath, destinationPath, flexVolName, snapshotName);
logger.info("cloneCloudStackVolume: Cloning file [{}] to [{}] in FlexVol [{}]",
sourcePath, destinationPath, flexVolName);
try {
FileCloneRequest request = new FileCloneRequest(flexVolUuid, flexVolName, sourcePath, destinationPath, snapshotName);
FileCloneRequest request = new FileCloneRequest(flexVolUuid, flexVolName, sourcePath, destinationPath);
Comment thread
sp16743 marked this conversation as resolved.
Resolved
JobResponse jobResponse = nasFeignClient.cloneFile(getAuthHeader(), request);
pollJobIfPresent(jobResponse, "clone file [" + sourcePath + "] to [" + destinationPath + "]");

Expand All @@ -221,7 +219,6 @@ public CloudStackVolume cloneCloudStackVolume(CloudStackVolume cloudstackVolume)
clonedCloudStackVolume.setFile(clonedFile);
clonedCloudStackVolume.setDatastoreId(cloudstackVolume.getDatastoreId());
clonedCloudStackVolume.setVolumeInfo(cloudstackVolume.getVolumeInfo());
clonedCloudStackVolume.setSnapshotName(snapshotName);
return clonedCloudStackVolume;
} catch (FeignException e) {
logger.error("FeignException occurred while cloning file [{}], Status: {}, Exception: {}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ public class CloudStackVolume {
*/
private String destinationPath;

/**
* ONTAP FlexVolume snapshot name when cloning a new file/LUN from a snapshot
* (create-volume-from-snapshot). Null for live clones (e.g. template cache).
*/
private String snapshotName;

Comment thread
sp16743 marked this conversation as resolved.
Resolved
private DataObject volumeInfo; // This is needed as we need DataObject to be passed to agent to create volume

public FileInfo getFile() {
Expand Down Expand Up @@ -107,12 +101,4 @@ public void setDestinationPath(String destinationPath) {
this.destinationPath = destinationPath;
}

public String getSnapshotName() {
return snapshotName;
}

public void setSnapshotName(String snapshotName) {
this.snapshotName = snapshotName;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1236,9 +1236,8 @@ void testCreateAsync_VolumeClonedFromSnapshot_NfsSuccess() {
ArgumentCaptor<CloudStackVolume> requestCaptor = ArgumentCaptor.forClass(CloudStackVolume.class);
verify(nasStrategy).cloneCloudStackVolume(requestCaptor.capture());
CloudStackVolume request = requestCaptor.getValue();
assertEquals("source-file-uuid", request.getFile().getPath());
assertEquals("./.snapshot/snap_cs200/source-file-uuid", request.getFile().getPath());
assertEquals("new-volume-uuid", request.getDestinationPath());
assertEquals("snap_cs200", request.getSnapshotName());
assertEquals("1", request.getDatastoreId());
verify(nasStrategy, never()).createCloudStackVolume(any());
}
Expand Down Expand Up @@ -3461,9 +3460,9 @@ void testCopyAsync_NfsTemporarySnapshotCopy_SetsFilePath() {

ArgumentCaptor<CloudStackVolume> requestCaptor = ArgumentCaptor.forClass(CloudStackVolume.class);
verify(nasStrategy).cloneCloudStackVolume(requestCaptor.capture());
assertEquals("source-file-uuid", requestCaptor.getValue().getFile().getPath());
assertEquals("./.snapshot/snap_cs200/source-file-uuid",
requestCaptor.getValue().getFile().getPath());
assertEquals("tmp-volume-uuid", requestCaptor.getValue().getDestinationPath());
assertEquals("snap_cs200", requestCaptor.getValue().getSnapshotName());

assertEquals("tmp-volume-uuid", dbVolume.getPath());
assertEquals(Storage.ImageFormat.QCOW2, dbVolume.getFormat());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1176,11 +1176,10 @@ public void testCloneCloudStackVolume_Success() {
assertEquals("volume-uuid", captor.getValue().getDestinationPath());
assertEquals("flexvol1", captor.getValue().getVolume().getName());
assertEquals("flexvol-uuid-1", captor.getValue().getVolume().getUuid());
assertNull(captor.getValue().getSnapshot());
}

@Test
public void testCloneCloudStackVolume_SnapshotSource_SendsSnapshotName() {
public void testCloneCloudStackVolume_SnapshotSource_UsesSnapshotSourcePath() {
VolumeObject volumeObject = mock(VolumeObject.class);
VolumeVO volumeVO = mock(VolumeVO.class);
when(volumeObject.getId()).thenReturn(100L);
Expand All @@ -1193,26 +1192,22 @@ public void testCloneCloudStackVolume_SnapshotSource_SendsSnapshotName() {
when(storagePoolDetailsDao.listDetailsKeyPairs(1L)).thenReturn(details);

FileInfo source = new FileInfo();
source.setPath("source-file-uuid");
source.setPath("./.snapshot/snap_cs200/source-file-uuid");
CloudStackVolume request = new CloudStackVolume();
request.setDatastoreId("1");
request.setVolumeInfo(volumeObject);
request.setFile(source);
request.setDestinationPath("new-volume-uuid");
request.setSnapshotName("snap_cs200");

when(nasFeignClient.cloneFile(anyString(), any(FileCloneRequest.class))).thenReturn(new JobResponse());

CloudStackVolume result = strategy.cloneCloudStackVolume(request);

assertEquals("new-volume-uuid", result.getFile().getPath());
assertEquals("snap_cs200", result.getSnapshotName());
ArgumentCaptor<FileCloneRequest> captor = ArgumentCaptor.forClass(FileCloneRequest.class);
verify(nasFeignClient).cloneFile(anyString(), captor.capture());
assertEquals("source-file-uuid", captor.getValue().getSourcePath());
assertEquals("./.snapshot/snap_cs200/source-file-uuid", captor.getValue().getSourcePath());
assertEquals("new-volume-uuid", captor.getValue().getDestinationPath());
assertNotNull(captor.getValue().getSnapshot());
assertEquals("snap_cs200", captor.getValue().getSnapshot().getName());
}

@Test
Expand Down
Loading