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);
     }

Reply via email to