Merge branch 'ghi11438-errorprone-fixes' of https://github.com/apache/cloudstack into ghi11438-errorprone-fixes

This commit is contained in:
Pearl Dsilva 2026-02-04 09:50:47 -05:00
commit 1c18ca8f7a
8 changed files with 117 additions and 65 deletions

View File

@ -56,7 +56,6 @@ import org.apache.cloudstack.context.CallContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.agent.api.LogLevel;
import com.cloud.event.EventTypes;
@ -74,6 +73,7 @@ import com.cloud.template.VirtualMachineTemplate;
import com.cloud.uservm.UserVm;
import com.cloud.utils.net.Dhcp;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.StringUtils;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VmDetailConstants;
@ -298,6 +298,9 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
}
public String getDisplayName() {
if (StringUtils.isEmpty(displayName)) {
displayName = name;
}
return displayName;
}

View File

@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cloud.utils.StringUtils;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.ApiArgValidator;
@ -159,6 +160,9 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction,
/////////////////////////////////////////////////////
public String getDisplayName() {
if (StringUtils.isBlank(displayName)) {
displayName = name;
}
return displayName;
}

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) {
@ -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 \"[^ ]*[ ]*$\"");

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

View File

@ -1,17 +1,17 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
@ -24,7 +24,7 @@
v-for="filter in this.searchFilters"
:key="filter.key + filter.value"
>
<a-col v-if="!['page', 'pagesize', 'q', 'keyword', 'tags'].includes(filter.key)">
<a-col v-if="!['page', 'pagesize', 'q', 'keyword', 'tags', 'projectid'].includes(filter.key)">
<a-tag
v-if="!filter.isTag"
closable
@ -175,6 +175,7 @@ export default {
immediate: true,
handler (newFilters) {
const clonedFilters = newFilters.map(filter => ({ ...filter }))
this.searchFilters = clonedFilters.map(f => ({ ...f }))
const promises = []
for (let idx = 0; idx < clonedFilters.length; idx++) {
const filter = clonedFilters[idx]
@ -188,9 +189,10 @@ export default {
resolve()
} else {
this.getSearchFilters(filter.key, filter.value).then((value) => {
const displayValue = (value !== undefined && value !== null && value !== '') ? value : filter.value
clonedFilters[idx] = {
key: filter.key,
value: value,
value: displayValue,
isTag: filter.isTag
}
resolve()

View File

@ -17,7 +17,10 @@
<template>
<div>
<a-affix :offsetTop="this.$store.getters.shutdownTriggered ? 103 : 78">
<a-affix
:key="'affix-' + showSearchFilters"
:offsetTop="this.$store.getters.shutdownTriggered ? 103 : 78"
>
<a-card class="breadcrumb-card" style="z-index: 10">
<a-row>
<a-col :span="device === 'mobile' ? 24 : 12" style="padding-left: 12px; margin-top: 10px">
@ -107,11 +110,11 @@
</a-col>
</a-row>
<a-row
v-if="!dataView && $config.showSearchFilters"
style="min-height: 36px; padding-top: 12px;"
v-if="showSearchFilters"
style="min-height: 36px; padding-top: 12px; padding-left: 12px;"
>
<search-filter
:filters="getActiveFilters()"
:filters="activeFiltersList"
:apiName="apiName"
@removeFilter="removeFilter"
/>
@ -687,6 +690,37 @@ export default {
}
},
computed: {
activeFiltersList () {
const queryParams = Object.assign({}, this.$route.query)
const activeFilters = []
for (const filter in queryParams) {
if (this.$route.name === 'host' && filter === 'type') {
continue
}
if (!filter.startsWith('tags[')) {
activeFilters.push({
key: filter,
value: queryParams[filter],
isTag: false
})
} else if (filter.endsWith('].key')) {
const tagIdx = filter.split('[')[1].split(']')[0]
const tagKey = queryParams[`tags[${tagIdx}].key`]
const tagValue = queryParams[`tags[${tagIdx}].value`]
activeFilters.push({
key: tagKey,
value: tagValue,
isTag: true,
tagIdx: tagIdx
})
}
}
return activeFilters
},
showSearchFilters () {
const excludedKeys = ['page', 'pagesize', 'q', 'keyword', 'tags', 'projectid']
return !this.dataView && this.$config.showSearchFilters && this.activeFiltersList.some(f => !excludedKeys.includes(f.key))
},
hasSelected () {
return this.selectedRowKeys.length > 0
},
@ -1138,30 +1172,6 @@ export default {
eventBus.emit('action-closing', { action: this.currentAction })
this.closeAction()
},
getActiveFilters () {
const queryParams = Object.assign({}, this.$route.query)
const activeFilters = []
for (const filter in queryParams) {
if (!filter.startsWith('tags[')) {
activeFilters.push({
key: filter,
value: queryParams[filter],
isTag: false
})
} else if (filter.endsWith('].key')) {
const tagIdx = filter.split('[')[1].split(']')[0]
const tagKey = queryParams[`tags[${tagIdx}].key`]
const tagValue = queryParams[`tags[${tagIdx}].value`]
activeFilters.push({
key: tagKey,
value: tagValue,
isTag: true,
tagIdx: tagIdx
})
}
}
return activeFilters
},
removeFilter (filter) {
const queryParams = Object.assign({}, this.$route.query)
if (filter.isTag) {