From 96992d3d640967b62ca5e323890ca4052d05b072 Mon Sep 17 00:00:00 2001 From: Manoj Kumar Date: Wed, 24 Sep 2025 13:58:24 +0530 Subject: [PATCH 1/5] server: Fix vpclimit count for listAcccount API response (#11686) --- .../org/apache/cloudstack/api/response/AccountResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java index 6fc098295f6..d761d7c0394 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java @@ -464,7 +464,7 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou @Override public void setVpcLimit(String vpcLimit) { - this.vpcLimit = networkLimit; + this.vpcLimit = vpcLimit; } @Override From c24d2b88f6bff2a13b21cad8fc25ebf367c726be Mon Sep 17 00:00:00 2001 From: dahn Date: Wed, 24 Sep 2025 11:30:04 +0200 Subject: [PATCH 2/5] LDAP: honour nested groups for MSAD (#11696) --- .../org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java | 8 ++++++-- .../org/apache/cloudstack/ldap/LdapConfiguration.java | 5 ++++- .../apache/cloudstack/ldap/OpenLdapUserManagerImpl.java | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java index 552d5969a9e..e96606dca2f 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java @@ -93,10 +93,14 @@ public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements Ld } protected String getMemberOfAttribute(final Long domainId) { + String rc; if(_ldapConfiguration.isNestedGroupsEnabled(domainId)) { - return MICROSOFT_AD_NESTED_MEMBERS_FILTER; + rc = MICROSOFT_AD_NESTED_MEMBERS_FILTER; } else { - return MICROSOFT_AD_MEMBERS_FILTER; + rc = MICROSOFT_AD_MEMBERS_FILTER; } + logger.trace("using memberOf filter = {} for domain with id {}", rc, domainId); + + return rc; } } diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapConfiguration.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapConfiguration.java index 6a62ad8d99d..87ff2d0a2ac 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapConfiguration.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapConfiguration.java @@ -27,9 +27,12 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import com.cloud.utils.Pair; import org.apache.cloudstack.ldap.dao.LdapConfigurationDao; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class LdapConfiguration implements Configurable{ private final static String factory = "com.sun.jndi.ldap.LdapCtxFactory"; + protected Logger logger = LogManager.getLogger(getClass()); private static final ConfigKey ldapReadTimeout = new ConfigKey( Long.class, @@ -325,7 +328,7 @@ public class LdapConfiguration implements Configurable{ try { provider = LdapUserManager.Provider.valueOf(ldapProvider.valueIn(domainId).toUpperCase()); } catch (IllegalArgumentException ex) { - //openldap is the default + logger.warn("no LDAP provider found for domain {}, using openldap as default", domainId); provider = LdapUserManager.Provider.OPENLDAP; } return provider; diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java index 4c125af2ea6..d0b6bc4bd34 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java @@ -63,7 +63,7 @@ public class OpenLdapUserManagerImpl implements LdapUserManager { final String firstname = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getFirstnameAttribute(domainId)); final String lastname = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getLastnameAttribute(domainId)); final String principal = result.getNameInNamespace(); - final List memberships = LdapUtils.getAttributeValues(attributes, _ldapConfiguration.getUserMemberOfAttribute(domainId)); + final List memberships = LdapUtils.getAttributeValues(attributes, getMemberOfAttribute(domainId)); String domain = principal.replace("cn=" + LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getCommonNameAttribute()) + ",", ""); domain = domain.replace("," + _ldapConfiguration.getBaseDn(domainId), ""); @@ -87,7 +87,7 @@ public class OpenLdapUserManagerImpl implements LdapUserManager { usernameFilter.append((username == null ? "*" : LdapUtils.escapeLDAPSearchFilter(username))); usernameFilter.append(")"); - String memberOfAttribute = _ldapConfiguration.getUserMemberOfAttribute(domainId); + String memberOfAttribute = getMemberOfAttribute(domainId); StringBuilder ldapGroupsFilter = new StringBuilder(); // this should get the trustmaps for this domain List ldapGroups = getMappedLdapGroups(domainId); From 36cfd76ce199ce159f496b27f9ed080488b96427 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 24 Sep 2025 13:53:27 +0200 Subject: [PATCH 3/5] KVM: fix delete vm snapshot if it does not exist with a Stopped vm (#11687) * KVM: fix delete vm snapshot if it does not exist with a Stopped vm * update 11687 --- .../wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java index 58a74d6e0f6..9f1b264ff71 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteVMSnapshotCommandWrapper.java @@ -40,6 +40,7 @@ import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Volume; +import com.cloud.utils.StringUtils; import com.cloud.utils.script.Script; @ResourceWrapper(handles = DeleteVMSnapshotCommand.class) @@ -104,7 +105,7 @@ public final class LibvirtDeleteVMSnapshotCommandWrapper extends CommandWrapper< commands.add(new String[]{Script.getExecutableAbsolutePath("awk"), "-F", " ", "{print $2}"}); commands.add(new String[]{Script.getExecutableAbsolutePath("grep"), "^" + sanitizeBashCommandArgument(cmd.getTarget().getSnapshotName()) + "$"}); String qemu_img_snapshot = Script.executePipedCommands(commands, 0).second(); - if (qemu_img_snapshot == null) { + if (StringUtils.isEmpty(qemu_img_snapshot)) { logger.info("Cannot find snapshot " + cmd.getTarget().getSnapshotName() + " in file " + rootDisk.getPath() + ", return true"); return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs()); } From 318a4f2b6ece664c6bee923fc2b10828190d7203 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 26 Sep 2025 20:25:11 +0200 Subject: [PATCH 4/5] server: set download volume format to qcow2 for KVM volumes (#11198) --- .../hypervisor/kvm/storage/KVMStorageProcessor.java | 2 +- .../driver/CloudStackImageStoreDriverImpl.java | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index 4ea8d1e80fb..91d5cf81d6f 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -587,7 +587,7 @@ public class KVMStorageProcessor implements StorageProcessor { try { final String volumeName = UUID.randomUUID().toString(); - final String destVolumeName = volumeName + "." + destFormat.getFileExtension(); + final String destVolumeName = volumeName + "." + ImageFormat.QCOW2.getFileExtension(); final KVMPhysicalDisk volume = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), srcVolumePath); volume.setFormat(PhysicalDiskFormat.valueOf(srcFormat.toString())); diff --git a/plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java b/plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java index d9a12d382ba..179d68efea7 100644 --- a/plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java +++ b/plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java @@ -23,7 +23,9 @@ import java.util.UUID; import javax.inject.Inject; import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand; +import com.cloud.agent.api.to.DataObjectType; import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Upload; import com.cloud.utils.StringUtils; @@ -72,7 +74,14 @@ public class CloudStackImageStoreDriverImpl extends NfsImageStoreDriverImpl { } if (format != null) { - objectNameInUrl = objectNameInUrl + "." + format.getFileExtension(); + if (dataObject.getTO() != null + && DataObjectType.VOLUME.equals(dataObject.getTO().getObjectType()) + && HypervisorType.KVM.equals(dataObject.getTO().getHypervisorType())) { + // Fix: The format of KVM volumes on image store is qcow2 + objectNameInUrl = objectNameInUrl + "." + ImageFormat.QCOW2.getFileExtension(); + } else { + objectNameInUrl = objectNameInUrl + "." + format.getFileExtension(); + } } else if (installPath.lastIndexOf(".") != -1) { objectNameInUrl = objectNameInUrl + "." + installPath.substring(installPath.lastIndexOf(".") + 1); } From 5dfeb79c63ccd4e3364dd1ba1ef0254b9bf54a96 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Sat, 27 Sep 2025 01:36:36 +0200 Subject: [PATCH 5/5] systemvm: fix failed to get script version when patch system vm or router (#10962) This is a regression of #9900 prior to this PR ``` 2025-06-05 12:28:53,992 DEBUG [cloud.agent.Agent] (AgentRequest-Handler-1:[]) (logid:) Processing command: com.cloud.agent.api.PatchSystemVmCommand 2025-06-05 12:29:25,959 DEBUG [resource.wrapper.LibvirtPatchSystemVmCommandWrapper] (AgentRequest-Handler-1:[]) (logid:) Patch result of systemVM s-368-VM: /root 2025-06-05 12:29:25,961 WARN [resource.wrapper.LibvirtPatchSystemVmCommandWrapper] (AgentRequest-Handler-1:[]) (logid:) Failed to get the latest script version 2025-06-05 12:29:25,962 DEBUG [cloud.agent.Agent] (AgentRequest-Handler-1:[]) (logid:) Seq 2-7450361158554357406: { Ans: , MgmtId: 32986204472275, via: 2, Ver: v1, Flags: 10, [{"com.cloud.agent.api.PatchSystemVmAnswer":{"templateVersion":"Cloudstack Release 4.20.1 Wed May 14 05:22:13 PM UTC 2025","scriptsVersion":"5ebc6ded1a3880732363c1cdbbd54cfb ``` with this PR ``` 2025-06-05 12:42:46,219 DEBUG [cloud.agent.Agent] (AgentRequest-Handler-2:[]) (logid:) Request:Seq 2-7450361158554357463: { Cmd , MgmtId: 32986204472275, via: 2, Ver: v1, Flags: 100011, [{"com.cloud.agent.api.PatchSystemVmCommand":{"forced":"true","accessDetails":{"router.ip":"169.254.151.188","router.name":"s-368-VM"},"wait":"0","bypassHostMaintenance":"false"}}] } 2025-06-05 12:42:46,220 DEBUG [cloud.agent.Agent] (AgentRequest-Handler-2:[]) (logid:) Processing command: com.cloud.agent.api.PatchSystemVmCommand 2025-06-05 12:43:18,083 DEBUG [resource.wrapper.LibvirtPatchSystemVmCommandWrapper] (AgentRequest-Handler-2:[]) (logid:) Patch result of systemVM s-368-VM: /root 2025-06-05 12:43:18,083 DEBUG [cloud.agent.Agent] (AgentRequest-Handler-2:[]) (logid:) Seq 2-7450361158554357463: { Ans: , MgmtId: 32986204472275, via: 2, Ver: v1, Flags: 10, [{"com.cloud.agent.api.PatchSystemVmAnswer":{"templateVersion":"Cloudstack Release 4.20.1 Wed May 14 05:22:13 PM UTC 2025","scriptsVersion":"5ebc6ded1a3880732363c1cdbbd54cfb","result":"true","details":"Successfully patched systemVM s-368-VM ","wait":"0","bypassHostMaintenance":"false"}}] } ``` --- systemvm/patch-sysvms.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index f24136155f8..7d026c20b9d 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -124,8 +124,10 @@ patch_systemvm() { echo "Restored keystore file and certs using backup" >> $logfile 2>&1 fi - # Import global cacerts into 'cloud' service's keystore - keytool -importkeystore -srckeystore /etc/ssl/certs/java/cacerts -destkeystore /usr/local/cloud/systemvm/certs/realhostip.keystore -srcstorepass changeit -deststorepass vmops.com -noprompt || true + if [ "$TYPE" = "consoleproxy" ] || [ "$TYPE" = "secstorage" ]; then + # Import global cacerts into 'cloud' service's keystore + keytool -importkeystore -srckeystore /etc/ssl/certs/java/cacerts -destkeystore /usr/local/cloud/systemvm/certs/realhostip.keystore -srcstorepass changeit -deststorepass vmops.com -noprompt 2>/dev/null || true + fi update_checksum $newpath/cloud-scripts.tgz