Skip to content

Commit 30d3066

Browse files
Merge branch '4.20' into 4.22
2 parents ef60aa5 + 6bed3d4 commit 30d3066

File tree

11 files changed

+138
-76
lines changed

11 files changed

+138
-76
lines changed

api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Objects;
2020
import java.util.stream.Stream;
2121

22+
import com.cloud.utils.exception.CloudRuntimeException;
2223
import org.apache.cloudstack.api.ACL;
2324
import org.apache.cloudstack.api.APICommand;
2425
import org.apache.cloudstack.api.ApiConstants;
@@ -39,7 +40,6 @@
3940
import com.cloud.exception.ResourceAllocationException;
4041
import com.cloud.exception.ResourceUnavailableException;
4142
import com.cloud.uservm.UserVm;
42-
import com.cloud.utils.exception.CloudRuntimeException;
4343
import com.cloud.vm.VirtualMachine;
4444

4545
@APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts an Instance based on a service offering, disk offering, and Template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class},

api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.cloud.exception.ResourceUnavailableException;
2222
import com.cloud.user.Account;
2323
import com.cloud.uservm.UserVm;
24+
import com.cloud.utils.StringUtils;
2425
import com.cloud.utils.exception.CloudRuntimeException;
2526
import com.cloud.utils.net.Dhcp;
2627
import com.cloud.vm.VirtualMachine;
@@ -44,7 +45,6 @@
4445
import org.apache.cloudstack.context.CallContext;
4546
import org.apache.cloudstack.vm.lease.VMLeaseManager;
4647
import org.apache.commons.lang3.EnumUtils;
47-
import org.apache.commons.lang3.StringUtils;
4848

4949
import java.util.Collection;
5050
import java.util.HashMap;
@@ -168,6 +168,9 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction,
168168
/////////////////////////////////////////////////////
169169

170170
public String getDisplayName() {
171+
if (StringUtils.isBlank(displayName)) {
172+
displayName = name;
173+
}
171174
return displayName;
172175
}
173176

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
@@ -48,9 +48,7 @@ public class SnapshotObjectTO extends DownloadableObjectTO implements DataTO {
4848
private Long physicalSize = (long) 0;
4949
private long accountId;
5050

51-
5251
public SnapshotObjectTO() {
53-
5452
}
5553

5654
@Override

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
@@ -398,13 +398,16 @@ public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answe
398398
if (answer instanceof CreateObjectAnswer) {
399399
SnapshotObjectTO snapshotTO = (SnapshotObjectTO)((CreateObjectAnswer)answer).getData();
400400
snapshotStore.setInstallPath(snapshotTO.getPath());
401+
if (snapshotTO.getPhysicalSize() != null && snapshotTO.getPhysicalSize() > 0L) {
402+
snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
403+
}
401404
snapshotStoreDao.update(snapshotStore.getId(), snapshotStore);
402405
} else if (answer instanceof CopyCmdAnswer) {
403406
SnapshotObjectTO snapshotTO = (SnapshotObjectTO)((CopyCmdAnswer)answer).getNewData();
404407
snapshotStore.setInstallPath(snapshotTO.getPath());
405408
if (snapshotTO.getPhysicalSize() != null) {
406409
// For S3 delta snapshot, physical size is currently not set
407-
snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
410+
snapshotStore.setPhysicalSize(snapshotTO.getPhysicalSize());
408411
}
409412
if (snapshotTO.getParentSnapshotPath() == null) {
410413
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
@@ -1969,7 +1969,7 @@ protected static boolean isInterface(final String fname) {
19691969
for (final String ifNamePattern : ifNamePatterns) {
19701970
commonPattern.append("|(").append(ifNamePattern).append(".*)");
19711971
}
1972-
if(fname.matches(commonPattern.toString())) {
1972+
if (fname.matches(commonPattern.toString())) {
19731973
return true;
19741974
}
19751975
return false;
@@ -2496,11 +2496,10 @@ private String getBroadcastUriFromBridge(final String brName) {
24962496
final Pattern pattern = Pattern.compile("(\\D+)(\\d+)(\\D*)(\\d*)(\\D*)(\\d*)");
24972497
final Matcher matcher = pattern.matcher(pif);
24982498
LOGGER.debug("getting broadcast uri for pif " + pif + " and bridge " + brName);
2499-
if(matcher.find()) {
2499+
if (matcher.find()) {
25002500
if (brName.startsWith("brvx")){
25012501
return BroadcastDomainType.Vxlan.toUri(matcher.group(2)).toString();
2502-
}
2503-
else{
2502+
} else {
25042503
if (!matcher.group(6).isEmpty()) {
25052504
return BroadcastDomainType.Vlan.toUri(matcher.group(6)).toString();
25062505
} else if (!matcher.group(4).isEmpty()) {
@@ -3730,7 +3729,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
37303729
} else if (volume.getType() == Volume.Type.DATADISK) {
37313730
final KVMPhysicalDisk physicalDisk = storagePoolManager.getPhysicalDisk(store.getPoolType(), store.getUuid(), data.getPath());
37323731
final KVMStoragePool pool = physicalDisk.getPool();
3733-
if(StoragePoolType.RBD.equals(pool.getType())) {
3732+
if (StoragePoolType.RBD.equals(pool.getType())) {
37343733
final int devId = volume.getDiskSeq().intValue();
37353734
final String device = mapRbdDevice(physicalDisk);
37363735
if (device != null) {
@@ -5188,7 +5187,7 @@ protected long getMemoryFreeInKBs(Domain dm) throws LibvirtException {
51885187
}
51895188

51905189
for (int i = 0; i < memoryStats.length; i++) {
5191-
if(memoryStats[i].getTag() == UNUSEDMEMORY) {
5190+
if (memoryStats[i].getTag() == UNUSEDMEMORY) {
51925191
freeMemory = memoryStats[i].getValue();
51935192
break;
51945193
}
@@ -5760,12 +5759,12 @@ public HypervisorType getHypervisorType(){
57605759
return hypervisorType;
57615760
}
57625761

5763-
public String mapRbdDevice(final KVMPhysicalDisk disk){
5762+
public String mapRbdDevice(final KVMPhysicalDisk disk) {
57645763
final KVMStoragePool pool = disk.getPool();
57655764
//Check if rbd image is already mapped
57665765
final String[] splitPoolImage = disk.getPath().split("/");
57675766
String device = Script.runSimpleBashScript("rbd showmapped | grep \""+splitPoolImage[0]+"[ ]*"+splitPoolImage[1]+"\" | grep -o \"[^ ]*[ ]*$\"");
5768-
if(device == null) {
5767+
if (device == null) {
57695768
//If not mapped, map and return mapped device
57705769
Script.runSimpleBashScript("rbd map " + disk.getPath() + " --id " + pool.getAuthUserName());
57715770
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: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555

5656
import com.cloud.agent.api.Command;
5757
import com.cloud.hypervisor.kvm.resource.LibvirtXMLParser;
58+
import com.fasterxml.jackson.core.JsonProcessingException;
59+
import com.fasterxml.jackson.databind.JsonNode;
60+
import com.fasterxml.jackson.databind.ObjectMapper;
5861
import org.apache.cloudstack.agent.directdownload.DirectDownloadAnswer;
5962
import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand;
6063
import org.apache.cloudstack.direct.download.DirectDownloadHelper;
@@ -365,6 +368,16 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
365368
newTemplate.setPath(primaryVol.getName());
366369
newTemplate.setSize(primaryVol.getSize());
367370
newTemplate.setFormat(getFormat(primaryPool.getType()));
371+
372+
if (List.of(
373+
StoragePoolType.RBD,
374+
StoragePoolType.PowerFlex,
375+
StoragePoolType.Linstor,
376+
StoragePoolType.FiberChannel).contains(primaryPool.getType())) {
377+
newTemplate.setFormat(ImageFormat.RAW);
378+
} else {
379+
newTemplate.setFormat(ImageFormat.QCOW2);
380+
}
368381
data = newTemplate;
369382
} else if (destData.getObjectType() == DataObjectType.VOLUME) {
370383
final VolumeObjectTO volumeObjectTO = new VolumeObjectTO();
@@ -752,7 +765,7 @@ public Answer createTemplateFromVolume(final CopyCommand cmd) {
752765
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
753766

754767

755-
try(FileOutputStream templFo = new FileOutputStream(templateProp);){
768+
try (FileOutputStream templFo = new FileOutputStream(templateProp);) {
756769
templFo.write(templateContent.getBytes());
757770
templFo.flush();
758771
} catch (final IOException e) {
@@ -817,11 +830,9 @@ private Answer createTemplateFromVolumeOrSnapshot(CopyCommand cmd) {
817830

818831
if (srcData instanceof VolumeObjectTO) {
819832
isVolume = true;
820-
}
821-
else if (srcData instanceof SnapshotObjectTO) {
833+
} else if (srcData instanceof SnapshotObjectTO) {
822834
isVolume = false;
823-
}
824-
else {
835+
} else {
825836
return new CopyCmdAnswer("unsupported object type");
826837
}
827838

@@ -887,8 +898,7 @@ else if (srcData instanceof SnapshotObjectTO) {
887898

888899
if (isVolume) {
889900
templateContent += "volume.name=" + dateFormat.format(date) + System.getProperty("line.separator");
890-
}
891-
else {
901+
} else {
892902
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
893903
}
894904

@@ -926,8 +936,7 @@ else if (srcData instanceof SnapshotObjectTO) {
926936
} catch (Exception ex) {
927937
if (isVolume) {
928938
logger.debug("Failed to create template from volume: ", ex);
929-
}
930-
else {
939+
} else {
931940
logger.debug("Failed to create template from snapshot: ", ex);
932941
}
933942

@@ -1088,7 +1097,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10881097
q.convert(srcFile, destFile);
10891098

10901099
final File snapFile = new File(snapshotFile);
1091-
if(snapFile.exists()) {
1100+
if (snapFile.exists()) {
10921101
size = snapFile.length();
10931102
}
10941103

@@ -1121,7 +1130,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
11211130
return new CopyCmdAnswer(result);
11221131
}
11231132
final File snapFile = new File(snapshotDestPath + "/" + descName);
1124-
if(snapFile.exists()){
1133+
if (snapFile.exists()) {
11251134
size = snapFile.length();
11261135
}
11271136
}
@@ -1460,7 +1469,7 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
14601469
if (resource.getHypervisorType() == Hypervisor.HypervisorType.LXC) {
14611470
final String device = resource.mapRbdDevice(attachingDisk);
14621471
if (device != null) {
1463-
logger.debug("RBD device on host is: "+device);
1472+
logger.debug("RBD device on host is: " + device);
14641473
attachingDisk.setPath(device);
14651474
}
14661475
}
@@ -1487,11 +1496,11 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
14871496
}
14881497
diskdef.setSerial(serial);
14891498
if (attachingPool.getType() == StoragePoolType.RBD) {
1490-
if(resource.getHypervisorType() == Hypervisor.HypervisorType.LXC){
1499+
if (resource.getHypervisorType() == Hypervisor.HypervisorType.LXC) {
14911500
// For LXC, map image to host and then attach to Vm
14921501
final String device = resource.mapRbdDevice(attachingDisk);
14931502
if (device != null) {
1494-
logger.debug("RBD device on host is: "+device);
1503+
logger.debug("RBD device on host is: " + device);
14951504
diskdef.defBlockBasedDisk(device, devId, busT);
14961505
} else {
14971506
throw new InternalErrorException("Error while mapping disk "+attachingDisk.getPath()+" on host");
@@ -1561,7 +1570,7 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
15611570
if ((iopsWriteRateMaxLength != null) && (iopsWriteRateMaxLength > 0)) {
15621571
diskdef.setIopsWriteRateMaxLength(iopsWriteRateMaxLength);
15631572
}
1564-
if(cacheMode != null) {
1573+
if (cacheMode != null) {
15651574
diskdef.setCacheMode(DiskDef.DiskCacheMode.valueOf(cacheMode.toUpperCase()));
15661575
}
15671576

@@ -1748,7 +1757,7 @@ public Answer createVolume(final CreateObjectCommand cmd) {
17481757
}
17491758

17501759
final VolumeObjectTO newVol = new VolumeObjectTO();
1751-
if(vol != null) {
1760+
if (vol != null) {
17521761
newVol.setPath(vol.getName());
17531762
if (vol.getQemuEncryptFormat() != null) {
17541763
newVol.setEncryptFormat(vol.getQemuEncryptFormat().toString());
@@ -1853,8 +1862,11 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
18531862
}
18541863
} else {
18551864
if (primaryPool.getType() == StoragePoolType.RBD) {
1856-
takeRbdVolumeSnapshotOfStoppedVm(primaryPool, disk, snapshotName);
1865+
Long snapshotSize = takeRbdVolumeSnapshotOfStoppedVm(primaryPool, disk, snapshotName);
18571866
newSnapshot.setPath(snapshotPath);
1867+
if (snapshotSize != null) {
1868+
newSnapshot.setPhysicalSize(snapshotSize);
1869+
}
18581870
} else if (primaryPool.getType() == StoragePoolType.CLVM) {
18591871
CreateObjectAnswer result = takeClvmVolumeSnapshotOfStoppedVm(disk, snapshotName);
18601872
if (result != null) return result;
@@ -2306,7 +2318,8 @@ private CreateObjectAnswer takeClvmVolumeSnapshotOfStoppedVm(KVMPhysicalDisk dis
23062318
* barriers properly (>2.6.32) this won't be any different then pulling the power
23072319
* cord out of a running machine.
23082320
*/
2309-
private void takeRbdVolumeSnapshotOfStoppedVm(KVMStoragePool primaryPool, KVMPhysicalDisk disk, String snapshotName) {
2321+
private Long takeRbdVolumeSnapshotOfStoppedVm(KVMStoragePool primaryPool, KVMPhysicalDisk disk, String snapshotName) {
2322+
Long snapshotSize = null;
23102323
try {
23112324
Rados r = radosConnect(primaryPool);
23122325

@@ -2317,11 +2330,43 @@ private void takeRbdVolumeSnapshotOfStoppedVm(KVMStoragePool primaryPool, KVMPhy
23172330
logger.debug("Attempting to create RBD snapshot {}@{}", disk.getName(), snapshotName);
23182331
image.snapCreate(snapshotName);
23192332

2333+
image.snapCreate(snapshotName);
2334+
long rbdSnapshotSize = getRbdSnapshotSize(primaryPool.getSourceDir(), disk.getName(), snapshotName, primaryPool.getSourceHost(), primaryPool.getAuthUserName(), primaryPool.getAuthSecret());
2335+
if (rbdSnapshotSize > 0) {
2336+
snapshotSize = rbdSnapshotSize;
2337+
}
2338+
23202339
rbd.close(image);
23212340
r.ioCtxDestroy(io);
23222341
} catch (final Exception e) {
23232342
logger.error("A RBD snapshot operation on [{}] failed. The error was: {}", disk.getName(), e.getMessage(), e);
23242343
}
2344+
return snapshotSize;
2345+
}
2346+
2347+
private long getRbdSnapshotSize(String poolPath, String diskName, String snapshotName, String rbdMonitor, String authUser, String authSecret) {
2348+
logger.debug("Get RBD snapshot size for {}/{}@{}", poolPath, diskName, snapshotName);
2349+
//cmd: rbd du <pool>/<disk-name>@<snapshot-name> --format json --mon-host <monitor-host> --id <user> --key <key> 2>/dev/null
2350+
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));
2351+
if (StringUtils.isNotBlank(snapshotDetailsInJson)) {
2352+
ObjectMapper mapper = new ObjectMapper();
2353+
try {
2354+
JsonNode root = mapper.readTree(snapshotDetailsInJson);
2355+
for (JsonNode image : root.path("images")) {
2356+
if (snapshotName.equals(image.path("snapshot").asText())) {
2357+
long usedSizeInBytes = image.path("used_size").asLong();
2358+
logger.debug("RBD snapshot {}/{}@{} used size in bytes: {}", poolPath, diskName, snapshotName, usedSizeInBytes);
2359+
return usedSizeInBytes;
2360+
}
2361+
}
2362+
} catch (JsonProcessingException e) {
2363+
logger.error("Unable to get the RBD snapshot size, RBD snapshot cmd output: {}", snapshotDetailsInJson, e);
2364+
}
2365+
} else {
2366+
logger.warn("Failed to get RBD snapshot size for {}/{}@{} - no output for RBD snapshot cmd", poolPath, diskName, snapshotName);
2367+
}
2368+
2369+
return 0;
23252370
}
23262371

23272372
/**

server/src/main/java/com/cloud/api/ApiResponseHelper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4445,7 +4445,7 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord, Map<String, Se
44454445
} else if (usageRecord.getUsageType() == UsageTypes.BACKUP) {
44464446
resourceType = ResourceObjectType.Backup;
44474447
final StringBuilder builder = new StringBuilder();
4448-
builder.append("Backup usage of size ").append(usageRecord.getUsageDisplay());
4448+
builder.append("Backup usage");
44494449
if (vmInstance != null) {
44504450
resourceId = vmInstance.getId();
44514451
usageRecResponse.setResourceName(vmInstance.getInstanceName());
@@ -4458,9 +4458,12 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord, Map<String, Se
44584458
.append(" (").append(backupOffering.getUuid()).append(", user ad-hoc/scheduled backup allowed: ")
44594459
.append(backupOffering.isUserDrivenBackupAllowed()).append(")");
44604460
}
4461-
44624461
}
4462+
builder.append(" with size ").append(toHumanReadableSize(usageRecord.getSize()));
4463+
builder.append(" and with virtual size ").append(toHumanReadableSize(usageRecord.getVirtualSize()));
44634464
usageRecResponse.setDescription(builder.toString());
4465+
usageRecResponse.setSize(usageRecord.getSize());
4466+
usageRecResponse.setVirtualSize(usageRecord.getVirtualSize());
44644467
} else if (usageRecord.getUsageType() == UsageTypes.VM_SNAPSHOT) {
44654468
resourceType = ResourceObjectType.VMSnapshot;
44664469
VMSnapshotVO vmSnapshotVO = null;

0 commit comments

Comments
 (0)