This commit is contained in:
Suresh Kumar Anaparti 2026-01-22 14:27:55 +00:00 committed by GitHub
commit 0de590ca75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 62 additions and 29 deletions

View File

@ -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) {

View File

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

View File

@ -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) {
@ -4778,7 +4777,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;
}
@ -5244,12 +5243,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 \"[^ ]*[ ]*$\"");

View File

@ -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();
}
}
@ -1404,7 +1403,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);
}
}
@ -1441,11 +1440,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");
@ -1515,7 +1514,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()));
}
@ -1675,7 +1674,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());
@ -1778,6 +1777,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);
@ -1838,6 +1838,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) {
@ -1861,8 +1866,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());
@ -1873,6 +1881,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));