Copilot commented on code in PR #11298:
URL: https://github.com/apache/cloudstack/pull/11298#discussion_r2232753228
##########
plugins/storage/volume/primera/src/main/java/org/apache/cloudstack/storage/datastore/adapter/primera/PrimeraAdapter.java:
##########
@@ -288,39 +288,94 @@ public void delete(ProviderAdapterContext context,
ProviderAdapterDataObject req
@Override
public ProviderVolume copy(ProviderAdapterContext context,
ProviderAdapterDataObject sourceVolumeInfo,
- ProviderAdapterDataObject targetVolumeInfo) {
+ ProviderAdapterDataObject targetVolumeInfo, Long newSize) {
+ // Log the start of the copy operation with source volume details
+ logger.debug("PrimeraAdapter: Starting volume copy operation - source
volume: '{}', target volume: '{}', requested new size: {} bytes ({} MiB)",
+ sourceVolumeInfo.getExternalName(),
targetVolumeInfo.getName(), newSize, newSize / PrimeraAdapter.BYTES_IN_MiB);
+
+ // Flag to determine copy method: online copy (direct clone) vs
offline copy (with resize)
+ boolean onlineCopy = true;
PrimeraVolumeCopyRequest request = new PrimeraVolumeCopyRequest();
PrimeraVolumeCopyRequestParameters parms = new
PrimeraVolumeCopyRequestParameters();
assert sourceVolumeInfo.getExternalName() != null: "External provider
name not provided on copy request to Primera volume provider";
- // if we have no external name, treat it as a new volume
+ // Generate external name for target volume if not already set
if (targetVolumeInfo.getExternalName() == null) {
targetVolumeInfo.setExternalName(ProviderVolumeNamer.generateObjectName(context,
targetVolumeInfo));
+ logger.debug("PrimeraAdapter: Generated external name '{}' for
target volume", targetVolumeInfo.getExternalName());
}
ProviderVolume sourceVolume = this.getVolume(context,
sourceVolumeInfo);
if (sourceVolume == null) {
throw new RuntimeException("Source volume " +
sourceVolumeInfo.getExternalUuid() + " with provider name " +
sourceVolumeInfo.getExternalName() + " not found on storage provider");
}
+ // Determine copy method based on size difference
+ // Online copy: Direct clone without size change (faster, immediate)
+ // Offline copy: Copy with potential resize (slower, requires task
completion wait)
+ Long sourceSize = sourceVolume.getAllocatedSizeInBytes();
+ if (newSize == null || sourceSize == null ||
!newSize.equals(sourceSize)) {
+ logger.debug("PrimeraAdapter: Volume size change detected (source:
{} bytes, target: {} bytes) - using offline copy method",
+ sourceSize, newSize);
+ onlineCopy = false;
+ } else {
+ logger.debug("PrimeraAdapter: No size change required (both {}
bytes) - using online copy method for faster cloning", newSize);
+ }
+
+ // Check if target volume already exists on the storage provider
ProviderVolume targetVolume = this.getVolume(context,
targetVolumeInfo);
if (targetVolume == null) {
- this.create(context, targetVolumeInfo, null,
sourceVolume.getAllocatedSizeInBytes());
+ if (!onlineCopy) {
+ // For offline copy, pre-create the target volume with the
desired size
+ logger.debug("PrimeraAdapter: Offline copy mode - pre-creating
target volume '{}' with size {} bytes",
+ targetVolumeInfo.getName(),
sourceVolume.getAllocatedSizeInBytes());
+ this.create(context, targetVolumeInfo, null,
sourceVolume.getAllocatedSizeInBytes());
Review Comment:
For offline copy mode, the target volume is being created with the source
volume size instead of the newSize parameter. This contradicts the logic that
offline copy is used when sizes differ, and the target should be created with
the desired newSize.
```suggestion
targetVolumeInfo.getName(), newSize);
this.create(context, targetVolumeInfo, null, newSize);
```
##########
plugins/storage/volume/primera/src/main/java/org/apache/cloudstack/storage/datastore/adapter/primera/PrimeraAdapter.java:
##########
@@ -288,39 +288,94 @@ public void delete(ProviderAdapterContext context,
ProviderAdapterDataObject req
@Override
public ProviderVolume copy(ProviderAdapterContext context,
ProviderAdapterDataObject sourceVolumeInfo,
- ProviderAdapterDataObject targetVolumeInfo) {
+ ProviderAdapterDataObject targetVolumeInfo, Long newSize) {
+ // Log the start of the copy operation with source volume details
+ logger.debug("PrimeraAdapter: Starting volume copy operation - source
volume: '{}', target volume: '{}', requested new size: {} bytes ({} MiB)",
+ sourceVolumeInfo.getExternalName(),
targetVolumeInfo.getName(), newSize, newSize / PrimeraAdapter.BYTES_IN_MiB);
+
+ // Flag to determine copy method: online copy (direct clone) vs
offline copy (with resize)
+ boolean onlineCopy = true;
PrimeraVolumeCopyRequest request = new PrimeraVolumeCopyRequest();
PrimeraVolumeCopyRequestParameters parms = new
PrimeraVolumeCopyRequestParameters();
assert sourceVolumeInfo.getExternalName() != null: "External provider
name not provided on copy request to Primera volume provider";
- // if we have no external name, treat it as a new volume
+ // Generate external name for target volume if not already set
if (targetVolumeInfo.getExternalName() == null) {
targetVolumeInfo.setExternalName(ProviderVolumeNamer.generateObjectName(context,
targetVolumeInfo));
+ logger.debug("PrimeraAdapter: Generated external name '{}' for
target volume", targetVolumeInfo.getExternalName());
}
ProviderVolume sourceVolume = this.getVolume(context,
sourceVolumeInfo);
if (sourceVolume == null) {
throw new RuntimeException("Source volume " +
sourceVolumeInfo.getExternalUuid() + " with provider name " +
sourceVolumeInfo.getExternalName() + " not found on storage provider");
}
+ // Determine copy method based on size difference
+ // Online copy: Direct clone without size change (faster, immediate)
+ // Offline copy: Copy with potential resize (slower, requires task
completion wait)
+ Long sourceSize = sourceVolume.getAllocatedSizeInBytes();
+ if (newSize == null || sourceSize == null ||
!newSize.equals(sourceSize)) {
+ logger.debug("PrimeraAdapter: Volume size change detected (source:
{} bytes, target: {} bytes) - using offline copy method",
+ sourceSize, newSize);
+ onlineCopy = false;
+ } else {
+ logger.debug("PrimeraAdapter: No size change required (both {}
bytes) - using online copy method for faster cloning", newSize);
+ }
+
+ // Check if target volume already exists on the storage provider
ProviderVolume targetVolume = this.getVolume(context,
targetVolumeInfo);
if (targetVolume == null) {
- this.create(context, targetVolumeInfo, null,
sourceVolume.getAllocatedSizeInBytes());
+ if (!onlineCopy) {
+ // For offline copy, pre-create the target volume with the
desired size
+ logger.debug("PrimeraAdapter: Offline copy mode - pre-creating
target volume '{}' with size {} bytes",
+ targetVolumeInfo.getName(),
sourceVolume.getAllocatedSizeInBytes());
+ this.create(context, targetVolumeInfo, null,
sourceVolume.getAllocatedSizeInBytes());
+ } else {
+ // For online copy, the target volume will be created
automatically during the clone operation
+ logger.debug("PrimeraAdapter: Online copy mode - target volume
'{}' will be created automatically during clone operation",
+ targetVolumeInfo.getName());
+ }
+ } else {
+ logger.warn("PrimeraAdapter: Target volume '{}' already exists on
storage provider - proceeding with copy operation",
+ targetVolumeInfo.getExternalName());
}
parms.setDestVolume(targetVolumeInfo.getExternalName());
- parms.setOnline(false);
- parms.setPriority(1);
+ if (onlineCopy) {
+ // Online copy configuration: immediate clone with deduplication
and compression
+ parms.setOnline(true);
+ parms.setDestCPG(cpg);
+ parms.setTpvv(false);
+ parms.setReduce(true);
+ logger.debug("PrimeraAdapter: Configuring online copy -
destination CPG: '{}', deduplication enabled, thin provisioning disabled", cpg);
+ } else {
+ // Offline copy configuration: background task with high priority
+ parms.setOnline(false);
+ parms.setPriority(1); // Set high priority for faster completion
+ logger.debug("PrimeraAdapter: Configuring offline copy with high
priority for target volume '{}'", targetVolumeInfo.getName());
+ }
+
+ // Set request parameters and initiate the copy operation
request.setParameters(parms);
PrimeraTaskReference taskref = POST("/volumes/" +
sourceVolumeInfo.getExternalName(), request, new
TypeReference<PrimeraTaskReference>() {});
if (taskref == null) {
+ logger.error("PrimeraAdapter: Failed to initiate copy operation -
no task reference returned from storage provider");
throw new RuntimeException("Unable to retrieve task used to copy
to newly created volume");
}
- waitForTaskToComplete(taskref.getTaskid(), "copy volume " +
sourceVolumeInfo.getExternalName() + " to " +
- targetVolumeInfo.getExternalName(), taskWaitTimeoutMs);
+ // Handle task completion based on copy method
+ if (!onlineCopy) {
+ // Offline copy requires waiting for task completion
+ logger.debug("PrimeraAdapter: Offline copy initiated - waiting for
task completion (TaskID: {})", taskref.getTaskid());
+ waitForTaskToComplete(taskref.getTaskid(), "copy volume " +
sourceVolumeInfo.getExternalName() + " to " +
+ targetVolumeInfo.getExternalName(), taskWaitTimeoutMs);
+ logger.debug("PrimeraAdapter: Offline copy operation completed
successfully");
+ } else {
Review Comment:
[nitpick] The waitForTaskToComplete call is only executed for offline copy,
but it should be within the offline copy conditional block for better code
organization and readability.
```suggestion
if (onlineCopy) {
```
##########
plugins/storage/volume/flasharray/src/main/java/org/apache/cloudstack/storage/datastore/adapter/flasharray/FlashArrayAdapter.java:
##########
@@ -367,7 +367,8 @@ public ProviderSnapshot getSnapshot(ProviderAdapterContext
context, ProviderAdap
@Override
public ProviderVolume copy(ProviderAdapterContext context,
ProviderAdapterDataObject sourceDataObject,
- ProviderAdapterDataObject destDataObject) {
+ ProviderAdapterDataObject destDataObject, Long newSize) {
+ // Add new parameter as newSize to match method declaration but not
used anywhere
Review Comment:
[nitpick] The comment indicates the newSize parameter is not implemented
yet. Consider adding a TODO comment or proper documentation about the planned
implementation to make the intention clearer for future development.
```suggestion
// TODO: The newSize parameter is currently unused. It may be
implemented in the future
// to allow resizing the destination volume during the copy
operation.
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]