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