This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.20 by this push:
     new d98511dddd8 Update physical size for the snapshots of the volumes on 
ceph primary storage (#12465)
d98511dddd8 is described below

commit d98511dddd86206c15c23b09e5180a931fd1c54e
Author: Suresh Kumar Anaparti <[email protected]>
AuthorDate: Fri Jan 30 15:21:38 2026 +0530

    Update physical size for the snapshots of the volumes on ceph primary 
storage (#12465)
---
 .../cloudstack/storage/to/SnapshotObjectTO.java    |  2 -
 .../storage/snapshot/SnapshotObject.java           |  5 +-
 .../kvm/resource/LibvirtComputingResource.java     | 15 +++--
 .../kvm/storage/KVMStorageProcessor.java           | 69 ++++++++++++++++------
 4 files changed, 62 insertions(+), 29 deletions(-)

diff --git 
a/core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java 
b/core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
index 76b93909b8c..9d64ab84121 100644
--- a/core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
+++ b/core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
@@ -44,9 +44,7 @@ public class SnapshotObjectTO extends DownloadableObjectTO 
implements DataTO {
     private Long physicalSize = (long) 0;
     private long accountId;
 
-
     public SnapshotObjectTO() {
-
     }
 
     public SnapshotObjectTO(SnapshotInfo snapshot) {
diff --git 
a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
 
b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
index 7602a142f88..df7e476cc20 100644
--- 
a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
+++ 
b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
@@ -358,13 +358,16 @@ public class SnapshotObject implements SnapshotInfo {
             if (answer instanceof CreateObjectAnswer) {
                 SnapshotObjectTO snapshotTO = 
(SnapshotObjectTO)((CreateObjectAnswer)answer).getData();
                 snapshotStore.setInstallPath(snapshotTO.getPath());
+                if (snapshotTO.getPhysicalSize() != null && 
snapshotTO.getPhysicalSize() > 0L) {
+                    
snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
+                }
                 snapshotStoreDao.update(snapshotStore.getId(), snapshotStore);
             } else if (answer instanceof CopyCmdAnswer) {
                 SnapshotObjectTO snapshotTO = 
(SnapshotObjectTO)((CopyCmdAnswer)answer).getNewData();
                 snapshotStore.setInstallPath(snapshotTO.getPath());
                 if (snapshotTO.getPhysicalSize() != null) {
                     // For S3 delta snapshot, physical size is currently not 
set
-                snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
+                    
snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
                 }
                 if (snapshotTO.getParentSnapshotPath() == null) {
                     snapshotStore.setParentSnapshotId(0L);
diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index c7b2747a777..054ef44bbe7 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -1836,7 +1836,7 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
         for (final String ifNamePattern : ifNamePatterns) {
             commonPattern.append("|(").append(ifNamePattern).append(".*)");
         }
-        if(fname.matches(commonPattern.toString())) {
+        if (fname.matches(commonPattern.toString())) {
             return true;
         }
         return false;
@@ -2128,11 +2128,10 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
         final Pattern pattern = 
Pattern.compile("(\\D+)(\\d+)(\\D*)(\\d*)(\\D*)(\\d*)");
         final Matcher matcher = pattern.matcher(pif);
         LOGGER.debug("getting broadcast uri for pif " + pif + " and bridge " + 
brName);
-        if(matcher.find()) {
+        if (matcher.find()) {
             if (brName.startsWith("brvx")){
                 return 
BroadcastDomainType.Vxlan.toUri(matcher.group(2)).toString();
-            }
-            else{
+            } else {
                 if (!matcher.group(6).isEmpty()) {
                     return 
BroadcastDomainType.Vlan.toUri(matcher.group(6)).toString();
                 } else if (!matcher.group(4).isEmpty()) {
@@ -3331,7 +3330,7 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
                 } else if (volume.getType() == Volume.Type.DATADISK) {
                     final KVMPhysicalDisk physicalDisk = 
storagePoolManager.getPhysicalDisk(store.getPoolType(), store.getUuid(), 
data.getPath());
                     final KVMStoragePool pool = physicalDisk.getPool();
-                    if(StoragePoolType.RBD.equals(pool.getType())) {
+                    if (StoragePoolType.RBD.equals(pool.getType())) {
                         final int devId = volume.getDiskSeq().intValue();
                         final String device = mapRbdDevice(physicalDisk);
                         if (device != null) {
@@ -4777,7 +4776,7 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
         }
 
         for (int i = 0; i < memoryStats.length; i++) {
-            if(memoryStats[i].getTag() == UNUSEDMEMORY) {
+            if (memoryStats[i].getTag() == UNUSEDMEMORY) {
                 freeMemory = memoryStats[i].getValue();
                 break;
             }
@@ -5243,12 +5242,12 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
         return hypervisorType;
     }
 
-    public String mapRbdDevice(final KVMPhysicalDisk disk){
+    public String mapRbdDevice(final KVMPhysicalDisk disk) {
         final KVMStoragePool pool = disk.getPool();
         //Check if rbd image is already mapped
         final String[] splitPoolImage = disk.getPath().split("/");
         String device = Script.runSimpleBashScript("rbd showmapped | grep 
\""+splitPoolImage[0]+"[ ]*"+splitPoolImage[1]+"\" | grep -o \"[^ ]*[ ]*$\"");
-        if(device == null) {
+        if (device == null) {
             //If not mapped, map and return mapped device
             Script.runSimpleBashScript("rbd map " + disk.getPath() + " --id " 
+ pool.getAuthUserName());
             device = Script.runSimpleBashScript("rbd showmapped | grep 
\""+splitPoolImage[0]+"[ ]*"+splitPoolImage[1]+"\" | grep -o \"[^ ]*[ ]*$\"");
diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
index 87ca531bb74..52740cead27 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
@@ -43,6 +43,9 @@ import java.util.stream.Collectors;
 
 import javax.naming.ConfigurationException;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.cloudstack.agent.directdownload.DirectDownloadAnswer;
 import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand;
 import org.apache.cloudstack.direct.download.DirectDownloadHelper;
@@ -305,7 +308,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
                 newTemplate.setPath(primaryVol.getName());
                 newTemplate.setSize(primaryVol.getSize());
 
-                if(List.of(
+                if (List.of(
                     StoragePoolType.RBD,
                     StoragePoolType.PowerFlex,
                     StoragePoolType.Linstor,
@@ -696,7 +699,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
                 templateContent += "snapshot.name=" + dateFormat.format(date) 
+ System.getProperty("line.separator");
 
 
-                try(FileOutputStream templFo = new 
FileOutputStream(templateProp);){
+                try (FileOutputStream templFo = new 
FileOutputStream(templateProp);) {
                     templFo.write(templateContent.getBytes());
                     templFo.flush();
                 } catch (final IOException e) {
@@ -761,11 +764,9 @@ public class KVMStorageProcessor implements 
StorageProcessor {
 
         if (srcData instanceof VolumeObjectTO) {
             isVolume = true;
-        }
-        else if (srcData instanceof SnapshotObjectTO) {
+        } else if (srcData instanceof SnapshotObjectTO) {
             isVolume = false;
-        }
-        else {
+        } else {
             return new CopyCmdAnswer("unsupported object type");
         }
 
@@ -831,8 +832,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
 
             if (isVolume) {
                 templateContent += "volume.name=" + dateFormat.format(date) + 
System.getProperty("line.separator");
-            }
-            else {
+            } else {
                 templateContent += "snapshot.name=" + dateFormat.format(date) 
+ System.getProperty("line.separator");
             }
 
@@ -870,8 +870,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
         } catch (Exception ex) {
             if (isVolume) {
                 logger.debug("Failed to create template from volume: ", ex);
-            }
-            else {
+            } else {
                 logger.debug("Failed to create template from snapshot: ", ex);
             }
 
@@ -1034,7 +1033,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
                     q.convert(srcFile, destFile);
 
                     final File snapFile = new File(snapshotFile);
-                    if(snapFile.exists()) {
+                    if (snapFile.exists()) {
                         size = snapFile.length();
                     }
 
@@ -1067,7 +1066,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
                     return new CopyCmdAnswer(result);
                 }
                 final File snapFile = new File(snapshotDestPath + "/" + 
descName);
-                if(snapFile.exists()){
+                if (snapFile.exists()) {
                     size = snapFile.length();
                 }
             }
@@ -1406,7 +1405,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
                     if (resource.getHypervisorType() == 
Hypervisor.HypervisorType.LXC) {
                         final String device = 
resource.mapRbdDevice(attachingDisk);
                         if (device != null) {
-                            logger.debug("RBD device on host is: "+device);
+                            logger.debug("RBD device on host is: " + device);
                             attachingDisk.setPath(device);
                         }
                     }
@@ -1433,11 +1432,11 @@ public class KVMStorageProcessor implements 
StorageProcessor {
                 }
                 diskdef.setSerial(serial);
                 if (attachingPool.getType() == StoragePoolType.RBD) {
-                    if(resource.getHypervisorType() == 
Hypervisor.HypervisorType.LXC){
+                    if (resource.getHypervisorType() == 
Hypervisor.HypervisorType.LXC) {
                         // For LXC, map image to host and then attach to Vm
                         final String device = 
resource.mapRbdDevice(attachingDisk);
                         if (device != null) {
-                            logger.debug("RBD device on host is: "+device);
+                            logger.debug("RBD device on host is: " + device);
                             diskdef.defBlockBasedDisk(device, devId, busT);
                         } else {
                             throw new InternalErrorException("Error while 
mapping disk "+attachingDisk.getPath()+" on host");
@@ -1507,7 +1506,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
                 if ((iopsWriteRateMaxLength != null) && 
(iopsWriteRateMaxLength > 0)) {
                     diskdef.setIopsWriteRateMaxLength(iopsWriteRateMaxLength);
                 }
-                if(cacheMode != null) {
+                if (cacheMode != null) {
                     
diskdef.setCacheMode(DiskDef.DiskCacheMode.valueOf(cacheMode.toUpperCase()));
                 }
 
@@ -1690,7 +1689,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
             }
 
             final VolumeObjectTO newVol = new VolumeObjectTO();
-            if(vol != null) {
+            if (vol != null) {
                 newVol.setPath(vol.getName());
                 if (vol.getQemuEncryptFormat() != null) {
                     
newVol.setEncryptFormat(vol.getQemuEncryptFormat().toString());
@@ -1793,6 +1792,7 @@ public class KVMStorageProcessor implements 
StorageProcessor {
 
             String diskPath = disk.getPath();
             String snapshotPath = diskPath + File.separator + snapshotName;
+            Long snapshotSize = null;
             if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && 
!primaryPool.isExternalSnapshot()) {
 
                 validateAvailableSizeOnPoolToTakeVolumeSnapshot(primaryPool, 
disk);
@@ -1853,6 +1853,11 @@ public class KVMStorageProcessor implements 
StorageProcessor {
                         logger.debug("Attempting to create RBD snapshot " + 
disk.getName() + "@" + snapshotName);
                         image.snapCreate(snapshotName);
 
+                        long rbdSnapshotSize = 
getRbdSnapshotSize(primaryPool.getSourceDir(), disk.getName(), snapshotName, 
primaryPool.getSourceHost(), primaryPool.getAuthUserName(), 
primaryPool.getAuthSecret());
+                        if (rbdSnapshotSize > 0) {
+                            snapshotSize = rbdSnapshotSize;
+                        }
+
                         rbd.close(image);
                         r.ioCtxDestroy(io);
                     } catch (final Exception e) {
@@ -1876,8 +1881,11 @@ public class KVMStorageProcessor implements 
StorageProcessor {
             }
 
             final SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
-
             newSnapshot.setPath(snapshotPath);
+            if (snapshotSize != null) {
+                newSnapshot.setPhysicalSize(snapshotSize);
+            }
+
             return new CreateObjectAnswer(newSnapshot);
         } catch (CloudRuntimeException | LibvirtException | IOException ex) {
             String errorMsg = String.format("Failed take snapshot for volume 
[%s], in VM [%s], due to [%s].", volume, vmName, ex.getMessage());
@@ -1888,6 +1896,31 @@ public class KVMStorageProcessor implements 
StorageProcessor {
         }
     }
 
+    private long getRbdSnapshotSize(String poolPath, String diskName, String 
snapshotName, String rbdMonitor, String authUser, String authSecret) {
+        logger.debug("Get RBD snapshot size for {}/{}@{}", poolPath, diskName, 
snapshotName);
+        //cmd: rbd du <pool>/<disk-name>@<snapshot-name> --format json 
--mon-host <monitor-host> --id <user> --key <key> 2>/dev/null
+        String snapshotDetailsInJson = 
Script.runSimpleBashScript(String.format("rbd du %s/%s@%s --format json 
--mon-host %s --id %s --key %s 2>/dev/null", poolPath, diskName, snapshotName, 
rbdMonitor, authUser, authSecret));
+        if (StringUtils.isNotBlank(snapshotDetailsInJson)) {
+            ObjectMapper mapper = new ObjectMapper();
+            try {
+                JsonNode root = mapper.readTree(snapshotDetailsInJson);
+                for (JsonNode image : root.path("images")) {
+                    if (snapshotName.equals(image.path("snapshot").asText())) {
+                        long usedSizeInBytes = 
image.path("used_size").asLong();
+                        logger.debug("RBD snapshot {}/{}@{} used size in 
bytes: {}", poolPath, diskName, snapshotName, usedSizeInBytes);
+                        return usedSizeInBytes;
+                    }
+                }
+            } catch (JsonProcessingException e) {
+                logger.error("Unable to get the RBD snapshot size, RBD 
snapshot cmd output: {}", snapshotDetailsInJson, e);
+            }
+        } else {
+                logger.warn("Failed to get RBD snapshot size for {}/{}@{} - no 
output for RBD snapshot cmd", poolPath, diskName, snapshotName);
+        }
+
+        return 0;
+    }
+
     protected void 
deleteFullVmSnapshotAfterConvertingItToExternalDiskSnapshot(Domain vm, String 
snapshotName, VolumeObjectTO volume, String vmName) throws LibvirtException {
         logger.debug(String.format("Deleting full Instance Snapshot [%s] of 
Instance [%s] as we already converted it to an external disk Snapshot of the 
volume [%s].", snapshotName, vmName,
                 volume));

Reply via email to