Skip to content

Commit 0efc5f7

Browse files
Update physical size for the snapshots on ceph primary
1 parent f1f779a commit 0efc5f7

File tree

4 files changed

+81
-29
lines changed

4 files changed

+81
-29
lines changed

core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ public class SnapshotObjectTO extends DownloadableObjectTO implements DataTO {
4444
private Long physicalSize = (long) 0;
4545
private long accountId;
4646

47-
4847
public SnapshotObjectTO() {
49-
5048
}
5149

5250
public SnapshotObjectTO(SnapshotInfo snapshot) {

engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotObject.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,13 +358,16 @@ public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answe
358358
if (answer instanceof CreateObjectAnswer) {
359359
SnapshotObjectTO snapshotTO = (SnapshotObjectTO)((CreateObjectAnswer)answer).getData();
360360
snapshotStore.setInstallPath(snapshotTO.getPath());
361+
if (snapshotTO.getPhysicalSize() != null && snapshotTO.getPhysicalSize() > 0L) {
362+
snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
363+
}
361364
snapshotStoreDao.update(snapshotStore.getId(), snapshotStore);
362365
} else if (answer instanceof CopyCmdAnswer) {
363366
SnapshotObjectTO snapshotTO = (SnapshotObjectTO)((CopyCmdAnswer)answer).getNewData();
364367
snapshotStore.setInstallPath(snapshotTO.getPath());
365368
if (snapshotTO.getPhysicalSize() != null) {
366369
// For S3 delta snapshot, physical size is currently not set
367-
snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
370+
snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
368371
}
369372
if (snapshotTO.getParentSnapshotPath() == null) {
370373
snapshotStore.setParentSnapshotId(0L);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,7 +1836,7 @@ protected static boolean isInterface(final String fname) {
18361836
for (final String ifNamePattern : ifNamePatterns) {
18371837
commonPattern.append("|(").append(ifNamePattern).append(".*)");
18381838
}
1839-
if(fname.matches(commonPattern.toString())) {
1839+
if (fname.matches(commonPattern.toString())) {
18401840
return true;
18411841
}
18421842
return false;
@@ -2128,11 +2128,10 @@ private String getBroadcastUriFromBridge(final String brName) {
21282128
final Pattern pattern = Pattern.compile("(\\D+)(\\d+)(\\D*)(\\d*)(\\D*)(\\d*)");
21292129
final Matcher matcher = pattern.matcher(pif);
21302130
LOGGER.debug("getting broadcast uri for pif " + pif + " and bridge " + brName);
2131-
if(matcher.find()) {
2131+
if (matcher.find()) {
21322132
if (brName.startsWith("brvx")){
21332133
return BroadcastDomainType.Vxlan.toUri(matcher.group(2)).toString();
2134-
}
2135-
else{
2134+
} else {
21362135
if (!matcher.group(6).isEmpty()) {
21372136
return BroadcastDomainType.Vlan.toUri(matcher.group(6)).toString();
21382137
} else if (!matcher.group(4).isEmpty()) {
@@ -3331,7 +3330,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
33313330
} else if (volume.getType() == Volume.Type.DATADISK) {
33323331
final KVMPhysicalDisk physicalDisk = storagePoolManager.getPhysicalDisk(store.getPoolType(), store.getUuid(), data.getPath());
33333332
final KVMStoragePool pool = physicalDisk.getPool();
3334-
if(StoragePoolType.RBD.equals(pool.getType())) {
3333+
if (StoragePoolType.RBD.equals(pool.getType())) {
33353334
final int devId = volume.getDiskSeq().intValue();
33363335
final String device = mapRbdDevice(physicalDisk);
33373336
if (device != null) {
@@ -4778,7 +4777,7 @@ protected long getMemoryFreeInKBs(Domain dm) throws LibvirtException {
47784777
}
47794778

47804779
for (int i = 0; i < memoryStats.length; i++) {
4781-
if(memoryStats[i].getTag() == UNUSEDMEMORY) {
4780+
if (memoryStats[i].getTag() == UNUSEDMEMORY) {
47824781
freeMemory = memoryStats[i].getValue();
47834782
break;
47844783
}
@@ -5244,12 +5243,12 @@ public HypervisorType getHypervisorType(){
52445243
return hypervisorType;
52455244
}
52465245

5247-
public String mapRbdDevice(final KVMPhysicalDisk disk){
5246+
public String mapRbdDevice(final KVMPhysicalDisk disk) {
52485247
final KVMStoragePool pool = disk.getPool();
52495248
//Check if rbd image is already mapped
52505249
final String[] splitPoolImage = disk.getPath().split("/");
52515250
String device = Script.runSimpleBashScript("rbd showmapped | grep \""+splitPoolImage[0]+"[ ]*"+splitPoolImage[1]+"\" | grep -o \"[^ ]*[ ]*$\"");
5252-
if(device == null) {
5251+
if (device == null) {
52535252
//If not mapped, map and return mapped device
52545253
Script.runSimpleBashScript("rbd map " + disk.getPath() + " --id " + pool.getAuthUserName());
52555254
device = Script.runSimpleBashScript("rbd showmapped | grep \""+splitPoolImage[0]+"[ ]*"+splitPoolImage[1]+"\" | grep -o \"[^ ]*[ ]*$\"");

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343

4444
import javax.naming.ConfigurationException;
4545

46+
import com.ceph.rbd.jna.RbdImageInfo;
47+
import com.fasterxml.jackson.core.JsonProcessingException;
48+
import com.fasterxml.jackson.databind.JsonNode;
49+
import com.fasterxml.jackson.databind.ObjectMapper;
4650
import org.apache.cloudstack.agent.directdownload.DirectDownloadAnswer;
4751
import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand;
4852
import org.apache.cloudstack.direct.download.DirectDownloadHelper;
@@ -305,7 +309,7 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
305309
newTemplate.setPath(primaryVol.getName());
306310
newTemplate.setSize(primaryVol.getSize());
307311

308-
if(List.of(
312+
if (List.of(
309313
StoragePoolType.RBD,
310314
StoragePoolType.PowerFlex,
311315
StoragePoolType.Linstor,
@@ -696,7 +700,7 @@ public Answer createTemplateFromVolume(final CopyCommand cmd) {
696700
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
697701

698702

699-
try(FileOutputStream templFo = new FileOutputStream(templateProp);){
703+
try (FileOutputStream templFo = new FileOutputStream(templateProp);) {
700704
templFo.write(templateContent.getBytes());
701705
templFo.flush();
702706
} catch (final IOException e) {
@@ -761,11 +765,9 @@ private Answer createTemplateFromVolumeOrSnapshot(CopyCommand cmd) {
761765

762766
if (srcData instanceof VolumeObjectTO) {
763767
isVolume = true;
764-
}
765-
else if (srcData instanceof SnapshotObjectTO) {
768+
} else if (srcData instanceof SnapshotObjectTO) {
766769
isVolume = false;
767-
}
768-
else {
770+
} else {
769771
return new CopyCmdAnswer("unsupported object type");
770772
}
771773

@@ -831,8 +833,7 @@ else if (srcData instanceof SnapshotObjectTO) {
831833

832834
if (isVolume) {
833835
templateContent += "volume.name=" + dateFormat.format(date) + System.getProperty("line.separator");
834-
}
835-
else {
836+
} else {
836837
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
837838
}
838839

@@ -870,8 +871,7 @@ else if (srcData instanceof SnapshotObjectTO) {
870871
} catch (Exception ex) {
871872
if (isVolume) {
872873
logger.debug("Failed to create template from volume: ", ex);
873-
}
874-
else {
874+
} else {
875875
logger.debug("Failed to create template from snapshot: ", ex);
876876
}
877877

@@ -1034,7 +1034,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10341034
q.convert(srcFile, destFile);
10351035

10361036
final File snapFile = new File(snapshotFile);
1037-
if(snapFile.exists()) {
1037+
if (snapFile.exists()) {
10381038
size = snapFile.length();
10391039
}
10401040

@@ -1067,7 +1067,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10671067
return new CopyCmdAnswer(result);
10681068
}
10691069
final File snapFile = new File(snapshotDestPath + "/" + descName);
1070-
if(snapFile.exists()){
1070+
if (snapFile.exists()) {
10711071
size = snapFile.length();
10721072
}
10731073
}
@@ -1404,7 +1404,7 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
14041404
if (resource.getHypervisorType() == Hypervisor.HypervisorType.LXC) {
14051405
final String device = resource.mapRbdDevice(attachingDisk);
14061406
if (device != null) {
1407-
logger.debug("RBD device on host is: "+device);
1407+
logger.debug("RBD device on host is: " + device);
14081408
attachingDisk.setPath(device);
14091409
}
14101410
}
@@ -1441,11 +1441,11 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
14411441
}
14421442
diskdef.setSerial(serial);
14431443
if (attachingPool.getType() == StoragePoolType.RBD) {
1444-
if(resource.getHypervisorType() == Hypervisor.HypervisorType.LXC){
1444+
if (resource.getHypervisorType() == Hypervisor.HypervisorType.LXC) {
14451445
// For LXC, map image to host and then attach to Vm
14461446
final String device = resource.mapRbdDevice(attachingDisk);
14471447
if (device != null) {
1448-
logger.debug("RBD device on host is: "+device);
1448+
logger.debug("RBD device on host is: " + device);
14491449
diskdef.defBlockBasedDisk(device, devId, busT);
14501450
} else {
14511451
throw new InternalErrorException("Error while mapping disk "+attachingDisk.getPath()+" on host");
@@ -1515,7 +1515,7 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
15151515
if ((iopsWriteRateMaxLength != null) && (iopsWriteRateMaxLength > 0)) {
15161516
diskdef.setIopsWriteRateMaxLength(iopsWriteRateMaxLength);
15171517
}
1518-
if(cacheMode != null) {
1518+
if (cacheMode != null) {
15191519
diskdef.setCacheMode(DiskDef.DiskCacheMode.valueOf(cacheMode.toUpperCase()));
15201520
}
15211521

@@ -1675,7 +1675,7 @@ public Answer createVolume(final CreateObjectCommand cmd) {
16751675
}
16761676

16771677
final VolumeObjectTO newVol = new VolumeObjectTO();
1678-
if(vol != null) {
1678+
if (vol != null) {
16791679
newVol.setPath(vol.getName());
16801680
if (vol.getQemuEncryptFormat() != null) {
16811681
newVol.setEncryptFormat(vol.getQemuEncryptFormat().toString());
@@ -1778,6 +1778,7 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
17781778

17791779
String diskPath = disk.getPath();
17801780
String snapshotPath = diskPath + File.separator + snapshotName;
1781+
Long snapshotSize = null;
17811782
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) {
17821783

17831784
validateAvailableSizeOnPoolToTakeVolumeSnapshot(primaryPool, disk);
@@ -1838,6 +1839,27 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
18381839
logger.debug("Attempting to create RBD snapshot " + disk.getName() + "@" + snapshotName);
18391840
image.snapCreate(snapshotName);
18401841

1842+
RbdImageInfo imageInfo = image.stat();
1843+
logger.debug("RBD image " + image.getName() + " info - size: " + imageInfo.size + ", obj_size: " + imageInfo.obj_size + ", num_objs: " + imageInfo.num_objs);
1844+
1845+
long rbdSnapshotSize = getRdbSnapshotSize(primaryPool.getSourceDir(), disk.getName(), snapshotName, primaryPool.getSourceHost(), primaryPool.getAuthUserName(), primaryPool.getAuthSecret());
1846+
if (rbdSnapshotSize > 0) {
1847+
snapshotSize = rbdSnapshotSize;
1848+
}
1849+
1850+
List<RbdSnapInfo> snapInfo = image.snapList();
1851+
for (RbdSnapInfo snap : snapInfo) {
1852+
logger.debug("RBD snap info - id: " + snap.id + ", name:" + snap.name + ", size: " + snap.size);
1853+
}
1854+
1855+
final RbdImage imageSnap = rbd.open(disk.getName(), snapshotName);
1856+
imageSnap.stat();
1857+
logger.debug("RBD image snapshot " + image.getName() + " info - size: " + imageInfo.size + ", obj_size: " + imageInfo.obj_size + ", num_objs: " + imageInfo.num_objs);
1858+
1859+
final RbdImage snap = rbd.open(disk.getName() + "@" + snapshotName);
1860+
snap.stat();
1861+
logger.debug("RBD snapshot " + image.getName() + " info - size: " + imageInfo.size + ", obj_size: " + imageInfo.obj_size + ", num_objs: " + imageInfo.num_objs);
1862+
18411863
rbd.close(image);
18421864
r.ioCtxDestroy(io);
18431865
} catch (final Exception e) {
@@ -1861,8 +1883,11 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
18611883
}
18621884

18631885
final SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
1864-
18651886
newSnapshot.setPath(snapshotPath);
1887+
if (snapshotSize != null) {
1888+
newSnapshot.setPhysicalSize(snapshotSize);
1889+
}
1890+
18661891
return new CreateObjectAnswer(newSnapshot);
18671892
} catch (CloudRuntimeException | LibvirtException | IOException ex) {
18681893
String errorMsg = String.format("Failed take snapshot for volume [%s], in VM [%s], due to [%s].", volume, vmName, ex.getMessage());
@@ -1873,6 +1898,33 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
18731898
}
18741899
}
18751900

1901+
private long getRdbSnapshotSize(String poolPath, String diskName, String snapshotName, String rbdMonitor, String authUser, String authSecret) {
1902+
logger.debug("Get RBD snapshot size for {}/{}@{}", poolPath, diskName, snapshotName);
1903+
//rbd du cloudstack/e29110ce-ffab-4a27-b2ad-6d87905039d8@d2e2d6d5-ff66-46f1-be7b-76e0504e965d --format json --pretty-format
1904+
//rbd du cloudstack/e29110ce-ffab-4a27-b2ad-6d87905039d8@d2e2d6d5-ff66-46f1-be7b-76e0504e965d --format json --mon-host 10.0.33.201 --id cloudstack --key AQApZshoQKVHCxAA42Bb8kBoUyLH2cEcFbd2jQ== 2>/dev/null
1905+
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));
1906+
if (StringUtils.isNotBlank(snapshotDetailsInJson)) {
1907+
logger.debug("RBD snapshot size for {}/{}@{} cmd output: ", poolPath, diskName, snapshotName, snapshotDetailsInJson);
1908+
ObjectMapper mapper = new ObjectMapper();
1909+
try {
1910+
JsonNode root = mapper.readTree(snapshotDetailsInJson);
1911+
for (JsonNode image : root.path("images")) {
1912+
if (snapshotName.equals(image.path("snapshot").asText())) {
1913+
long usedSizeInBytes = image.path("used_size").asLong();
1914+
if (usedSizeInBytes > 0) {
1915+
logger.debug("RBD snapshot {}/{}@{} used size in bytes: {}", poolPath, diskName, snapshotName, usedSizeInBytes);
1916+
return usedSizeInBytes;
1917+
}
1918+
}
1919+
}
1920+
} catch (JsonProcessingException e) {
1921+
logger.error("Unable to get the RBD snapshot size", e);
1922+
}
1923+
}
1924+
1925+
return 0;
1926+
}
1927+
18761928
protected void deleteFullVmSnapshotAfterConvertingItToExternalDiskSnapshot(Domain vm, String snapshotName, VolumeObjectTO volume, String vmName) throws LibvirtException {
18771929
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,
18781930
volume));

0 commit comments

Comments
 (0)