Skip to content

Commit 5f63e84

Browse files
author
Daan Hoogland
committed
Merge branch '4.20'
2 parents 9bcd988 + aca8235 commit 5f63e84

File tree

21 files changed

+218
-145
lines changed

21 files changed

+218
-145
lines changed

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class ApiConstants {
2727
public static final String ACTIVATION_RULE = "activationrule";
2828
public static final String ACTIVITY = "activity";
2929
public static final String ADAPTER_TYPE = "adaptertype";
30+
public static final String ADDITONAL_CONFIG_ENABLED = "additionalconfigenabled";
3031
public static final String ADDRESS = "address";
3132
public static final String ALGORITHM = "algorithm";
3233
public static final String ALIAS = "alias";

api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public void execute() {
7575
response.setInstanceLeaseEnabled((Boolean) capabilities.get(ApiConstants.INSTANCE_LEASE_ENABLED));
7676
response.setExtensionsPath((String)capabilities.get(ApiConstants.EXTENSIONS_PATH));
7777
response.setDynamicScalingEnabled((Boolean) capabilities.get(ApiConstants.DYNAMIC_SCALING_ENABLED));
78+
response.setAdditionalConfigEnabled((Boolean) capabilities.get(ApiConstants.ADDITONAL_CONFIG_ENABLED));
7879
response.setObjectName("capability");
7980
response.setResponseName(getCommandName());
8081
this.setResponseObject(response);

api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ public class CapabilitiesResponse extends BaseResponse {
149149
@Param(description = "true if dynamically scaling for instances is enabled", since = "4.21.0")
150150
private Boolean dynamicScalingEnabled;
151151

152+
@SerializedName(ApiConstants.ADDITONAL_CONFIG_ENABLED)
153+
@Param(description = "true if additional configurations or extraconfig can be passed to Instances", since = "4.20.2")
154+
private Boolean additionalConfigEnabled;
155+
152156
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
153157
this.securityGroupsEnabled = securityGroupsEnabled;
154158
}
@@ -272,4 +276,8 @@ public void setExtensionsPath(String extensionsPath) {
272276
public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) {
273277
this.dynamicScalingEnabled = dynamicScalingEnabled;
274278
}
279+
280+
public void setAdditionalConfigEnabled(Boolean additionalConfigEnabled) {
281+
this.additionalConfigEnabled = additionalConfigEnabled;
282+
}
275283
}

engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,17 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
116116

117117
protected Attribute _updateTimeAttr;
118118

119-
private static final String ORDER_CLUSTERS_NUMBER_OF_VMS_FOR_ACCOUNT_PART1 = "SELECT host.cluster_id, SUM(IF(vm.state='Running' AND vm.account_id = ?, 1, 0)) " +
119+
private static final String ORDER_CLUSTERS_NUMBER_OF_VMS_FOR_ACCOUNT_PART1 = "SELECT host.cluster_id, SUM(IF(vm.state IN ('Running', 'Starting') AND vm.account_id = ?, 1, 0)) " +
120120
"FROM `cloud`.`host` host LEFT JOIN `cloud`.`vm_instance` vm ON host.id = vm.host_id WHERE ";
121121
private static final String ORDER_CLUSTERS_NUMBER_OF_VMS_FOR_ACCOUNT_PART2 = " AND host.type = 'Routing' AND host.removed is null GROUP BY host.cluster_id " +
122122
"ORDER BY 2 ASC ";
123123

124-
private static final String ORDER_PODS_NUMBER_OF_VMS_FOR_ACCOUNT = "SELECT pod.id, SUM(IF(vm.state='Running' AND vm.account_id = ?, 1, 0)) FROM `cloud`.`" +
124+
private static final String ORDER_PODS_NUMBER_OF_VMS_FOR_ACCOUNT = "SELECT pod.id, SUM(IF(vm.state IN ('Running', 'Starting') AND vm.account_id = ?, 1, 0)) FROM `cloud`.`" +
125125
"host_pod_ref` pod LEFT JOIN `cloud`.`vm_instance` vm ON pod.id = vm.pod_id WHERE pod.data_center_id = ? AND pod.removed is null "
126126
+ " GROUP BY pod.id ORDER BY 2 ASC ";
127127

128128
private static final String ORDER_HOSTS_NUMBER_OF_VMS_FOR_ACCOUNT =
129-
"SELECT host.id, SUM(IF(vm.state='Running' AND vm.account_id = ?, 1, 0)) FROM `cloud`.`host` host LEFT JOIN `cloud`.`vm_instance` vm ON host.id = vm.host_id " +
129+
"SELECT host.id, SUM(IF(vm.state IN ('Running', 'Starting') AND vm.account_id = ?, 1, 0)) FROM `cloud`.`host` host LEFT JOIN `cloud`.`vm_instance` vm ON host.id = vm.host_id " +
130130
"WHERE host.data_center_id = ? AND host.type = 'Routing' AND host.removed is null ";
131131

132132
private static final String ORDER_HOSTS_NUMBER_OF_VMS_FOR_ACCOUNT_PART2 = " GROUP BY host.id ORDER BY 2 ASC ";

engine/storage/src/main/java/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@ public DataStore attachHost(DataStore store, HostScope scope, StoragePoolInfo ex
190190
pool.setScope(scope.getScopeType());
191191
pool.setUsedBytes(existingInfo.getCapacityBytes() - existingInfo.getAvailableBytes());
192192
pool.setCapacityBytes(existingInfo.getCapacityBytes());
193-
pool.setStatus(StoragePoolStatus.Up);
193+
if (pool.getStatus() != StoragePoolStatus.Disabled) {
194+
pool.setStatus(StoragePoolStatus.Up);
195+
}
194196
this.dataStoreDao.update(pool.getId(), pool);
195197
this.storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_LOCAL_STORAGE, pool.getUsedBytes());
196198
return dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);

plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5838,11 +5838,20 @@ protected Answer execute(GetVmIpAddressCommand cmd) {
58385838
if (toolsStatus == VirtualMachineToolsStatus.TOOLS_NOT_INSTALLED) {
58395839
details += "Vmware tools not installed.";
58405840
} else {
5841-
ip = guestInfo.getIpAddress();
5842-
if (ip != null) {
5843-
result = true;
5841+
var normalizedMac = cmd.getMacAddress().replaceAll("-", ":");
5842+
for(var guestInfoNic : guestInfo.getNet()) {
5843+
var normalizedNicMac = guestInfoNic.getMacAddress().replaceAll("-", ":");
5844+
if (!result && normalizedNicMac.equalsIgnoreCase(normalizedMac)) {
5845+
result = true;
5846+
details = null;
5847+
for (var ipAddr : guestInfoNic.getIpAddress()) {
5848+
if (NetUtils.isValidIp4(ipAddr) && (cmd.getVmNetworkCidr() == null || NetUtils.isIpWithInCidrRange(ipAddr, cmd.getVmNetworkCidr()))) {
5849+
details = ipAddr;
5850+
}
5851+
}
5852+
break;
5853+
}
58445854
}
5845-
details = ip;
58465855
}
58475856
} else {
58485857
details += "VM " + vmName + " no longer exists on vSphere host: " + hyperHost.getHyperHostName();

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,9 @@ private boolean isKubernetesServiceNetworkOfferingConfigured(DataCenter zone, Lo
430430
logger.warn("Unable to find the network with ID: {} passed for the Kubernetes cluster", networkId);
431431
return false;
432432
}
433+
if (isDirectAccess(network)) {
434+
return true;
435+
}
433436
networkOffering = networkOfferingDao.findById(network.getNetworkOfferingId());
434437
if (networkOffering == null) {
435438
logger.warn("Unable to find the network offering of the network: {} ({}) to be used for provisioning Kubernetes cluster", network.getName(), network.getUuid());
@@ -1870,7 +1873,7 @@ protected Account createProjectKubernetesAccount(final Project project, final St
18701873
try {
18711874
Role role = getProjectKubernetesAccountRole();
18721875
UserAccount userAccount = accountService.createUserAccount(accountName,
1873-
UuidUtils.first(UUID.randomUUID().toString()), PROJECT_KUBERNETES_ACCOUNT_FIRST_NAME,
1876+
UUID.randomUUID().toString(), PROJECT_KUBERNETES_ACCOUNT_FIRST_NAME,
18741877
PROJECT_KUBERNETES_ACCOUNT_LAST_NAME, null, null, accountName, Account.Type.NORMAL, role.getId(),
18751878
project.getDomainId(), null, null, null, null, User.Source.NATIVE);
18761879
projectManager.assignAccountToProject(project, userAccount.getAccountId(), ProjectAccount.Role.Regular,

plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ private HypervisorType getHypervisorType(long hostId) {
504504
@Override
505505
public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) {
506506
DataStore dataStore = dataStoreHelper.attachHost(store, scope, existingInfo);
507-
if(existingInfo.getCapacityBytes() == 0){
507+
if (existingInfo.getCapacityBytes() == 0) {
508508
try {
509509
storageMgr.connectHostToSharedPool(hostDao.findById(scope.getScopeId()), dataStore.getId());
510510
} catch (StorageUnavailableException ex) {

plugins/storage/volume/linstor/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to Linstor CloudStack plugin will be documented in this file
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [2025-10-03]
9+
10+
### Changed
11+
12+
- Revert qcow2 snapshot now use sparse/discard options to convert on thin devices.
13+
814
## [2025-08-05]
915

1016
### Fixed

plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LinstorRevertBackupSnapshotCommandWrapper.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,39 @@
2626
import com.cloud.resource.CommandWrapper;
2727
import com.cloud.resource.ResourceWrapper;
2828
import com.cloud.storage.Storage;
29+
import com.cloud.utils.script.Script;
2930
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
31+
import org.apache.cloudstack.storage.datastore.util.LinstorUtil;
3032
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
3133
import org.apache.cloudstack.storage.to.VolumeObjectTO;
3234
import org.apache.cloudstack.utils.qemu.QemuImg;
3335
import org.apache.cloudstack.utils.qemu.QemuImgException;
3436
import org.apache.cloudstack.utils.qemu.QemuImgFile;
37+
import org.joda.time.Duration;
3538
import org.libvirt.LibvirtException;
3639

3740
@ResourceWrapper(handles = LinstorRevertBackupSnapshotCommand.class)
3841
public final class LinstorRevertBackupSnapshotCommandWrapper
3942
extends CommandWrapper<LinstorRevertBackupSnapshotCommand, CopyCmdAnswer, LibvirtComputingResource>
4043
{
41-
private void convertQCow2ToRAW(final String srcPath, final String dstPath, int waitMilliSeconds)
44+
45+
private void convertQCow2ToRAW(
46+
KVMStoragePool pool, final String srcPath, final String dstUuid, int waitMilliSeconds)
4247
throws LibvirtException, QemuImgException
4348
{
49+
final String dstPath = pool.getPhysicalDisk(dstUuid).getPath();
4450
final QemuImgFile srcQemuFile = new QemuImgFile(
4551
srcPath, QemuImg.PhysicalDiskFormat.QCOW2);
46-
final QemuImg qemu = new QemuImg(waitMilliSeconds);
52+
boolean zeroedDevice = LinstorUtil.resourceSupportZeroBlocks(pool, LinstorUtil.RSC_PREFIX + dstUuid);
53+
if (zeroedDevice)
54+
{
55+
// blockdiscard the device to ensure the device is filled with zeroes
56+
Script blkDiscardScript = new Script("blkdiscard", Duration.millis(waitMilliSeconds));
57+
blkDiscardScript.add("-f");
58+
blkDiscardScript.add(dstPath);
59+
blkDiscardScript.execute();
60+
}
61+
final QemuImg qemu = new QemuImg(waitMilliSeconds, zeroedDevice, true);
4762
final QemuImgFile dstFile = new QemuImgFile(dstPath, QemuImg.PhysicalDiskFormat.RAW);
4863
qemu.convert(srcQemuFile, dstFile);
4964
}
@@ -70,8 +85,9 @@ public CopyCmdAnswer execute(LinstorRevertBackupSnapshotCommand cmd, LibvirtComp
7085
srcDataStore.getUrl() + File.separator + srcFile.getParent());
7186

7287
convertQCow2ToRAW(
88+
linstorPool,
7389
secondaryPool.getLocalPath() + File.separator + srcFile.getName(),
74-
linstorPool.getPhysicalDisk(dst.getPath()).getPath(),
90+
dst.getPath(),
7591
cmd.getWaitInMillSeconds());
7692

7793
final VolumeObjectTO dstVolume = new VolumeObjectTO();

0 commit comments

Comments
 (0)