This is an automated email from the ASF dual-hosted git repository.
sureshanaparti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 5cac4f6c448 added online/offline copy method for Primera storage
adapter (#11298)
5cac4f6c448 is described below
commit 5cac4f6c4485e25e5f4c09efd181c3f3f72125f2
Author: shrikantjoshi-hpe <[email protected]>
AuthorDate: Sun Aug 3 12:31:37 2025 +0530
added online/offline copy method for Primera storage adapter (#11298)
---
.../storage/datastore/adapter/ProviderAdapter.java | 3 +-
.../driver/AdaptiveDataStoreDriverImpl.java | 3 +-
.../adapter/flasharray/FlashArrayAdapter.java | 3 +-
.../datastore/adapter/primera/PrimeraAdapter.java | 69 +++++++++++++++++++---
4 files changed, 68 insertions(+), 10 deletions(-)
diff --git
a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/adapter/ProviderAdapter.java
b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/adapter/ProviderAdapter.java
index 9c0db25d52e..5851ee44d2e 100644
---
a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/adapter/ProviderAdapter.java
+++
b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/adapter/ProviderAdapter.java
@@ -87,8 +87,9 @@ public interface ProviderAdapter {
/**
* Copy a source object to a destination volume. The source object can be
a Volume, Snapshot, or Template
+ * @param newSize the desired size in bytes for the destination volume
(supports resize-during-copy)
*/
- public ProviderVolume copy(ProviderAdapterContext context,
ProviderAdapterDataObject sourceVolume, ProviderAdapterDataObject targetVolume);
+ public ProviderVolume copy(ProviderAdapterContext context,
ProviderAdapterDataObject sourceVolume, ProviderAdapterDataObject targetVolume,
Long newSize);
/**
* Make a device-specific snapshot of the provided volume
diff --git
a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/driver/AdaptiveDataStoreDriverImpl.java
b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/driver/AdaptiveDataStoreDriverImpl.java
index e573f453a6c..40d99526394 100644
---
a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/driver/AdaptiveDataStoreDriverImpl.java
+++
b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/driver/AdaptiveDataStoreDriverImpl.java
@@ -337,7 +337,8 @@ public class AdaptiveDataStoreDriverImpl extends
CloudStackPrimaryDataStoreDrive
ProviderAdapterDataObject sourceIn =
newManagedDataObject(srcdata, storagePool);
ProviderAdapterDataObject destIn =
newManagedDataObject(destdata, storagePool);
- outVolume = api.copy(context, sourceIn, destIn);
+ // Call provider adapter copy method with destination size
parameter for resize-during-copy support
+ outVolume = api.copy(context, sourceIn, destIn,
destdata.getSize());
// populate this data - it may be needed later
destIn.setExternalName(outVolume.getExternalName());
diff --git
a/plugins/storage/volume/flasharray/src/main/java/org/apache/cloudstack/storage/datastore/adapter/flasharray/FlashArrayAdapter.java
b/plugins/storage/volume/flasharray/src/main/java/org/apache/cloudstack/storage/datastore/adapter/flasharray/FlashArrayAdapter.java
index 715379daf86..41125f3e113 100644
---
a/plugins/storage/volume/flasharray/src/main/java/org/apache/cloudstack/storage/datastore/adapter/flasharray/FlashArrayAdapter.java
+++
b/plugins/storage/volume/flasharray/src/main/java/org/apache/cloudstack/storage/datastore/adapter/flasharray/FlashArrayAdapter.java
@@ -367,7 +367,8 @@ public class FlashArrayAdapter implements ProviderAdapter {
@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
// private ManagedVolume copy(ManagedVolume sourceVolume, String
destNamespace,
// String destName) {
if (sourceDataObject == null || sourceDataObject.getExternalName() ==
null
diff --git
a/plugins/storage/volume/primera/src/main/java/org/apache/cloudstack/storage/datastore/adapter/primera/PrimeraAdapter.java
b/plugins/storage/volume/primera/src/main/java/org/apache/cloudstack/storage/datastore/adapter/primera/PrimeraAdapter.java
index 036144103b1..ee6b710efa6 100644
---
a/plugins/storage/volume/primera/src/main/java/org/apache/cloudstack/storage/datastore/adapter/primera/PrimeraAdapter.java
+++
b/plugins/storage/volume/primera/src/main/java/org/apache/cloudstack/storage/datastore/adapter/primera/PrimeraAdapter.java
@@ -288,15 +288,22 @@ public class PrimeraAdapter implements ProviderAdapter {
@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);
@@ -304,23 +311,71 @@ public class PrimeraAdapter implements ProviderAdapter {
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 {
+ // Online copy completes immediately
+ logger.debug("PrimeraAdapter: Online copy operation completed
successfully (TaskID: {})", taskref.getTaskid());
+ }
return this.getVolume(context, targetVolumeInfo);
}