This is an automated email from the ASF dual-hosted git repository. dahn pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push: new fa85a75bc88 Log previous and new value of configuration when reset/update API is called (#10769) fa85a75bc88 is described below commit fa85a75bc88bc8d98d8b859038db7a931736d803 Author: Manoj Kumar <manojkr.it...@gmail.com> AuthorDate: Wed Jun 4 15:36:25 2025 +0530 Log previous and new value of configuration when reset/update API is called (#10769) --- .../cloud/configuration/ConfigurationManager.java | 6 +- .../configuration/ConfigurationManagerImpl.java | 72 ++++++++++++++-------- .../ConfigurationManagerImplTest.java | 16 ++--- .../cloud/vpc/MockConfigurationManagerImpl.java | 3 +- 4 files changed, 61 insertions(+), 36 deletions(-) diff --git a/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java b/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java index f172bead7aa..859d1176213 100644 --- a/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java +++ b/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java @@ -77,12 +77,14 @@ public interface ConfigurationManager { /** * Updates a configuration entry with a new value - * * @param userId * @param name + * @param category * @param value + * @param scope + * @param id */ - String updateConfiguration(long userId, String name, String category, String value, String scope, Long id); + String updateConfiguration(long userId, String name, String category, String value, ConfigKey.Scope scope, Long id); // /** // * Creates a new service offering diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index ecc72e907c2..908f3d7dad0 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -713,7 +713,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public String updateConfiguration(final long userId, final String name, final String category, String value, final String scope, final Long resourceId) { + public String updateConfiguration(final long userId, final String name, final String category, String value, ConfigKey.Scope scope, final Long resourceId) { final String validationMsg = validateConfigurationValue(name, value, scope); if (validationMsg != null) { logger.error("Invalid value [{}] for configuration [{}] due to [{}].", value, name, validationMsg); @@ -724,15 +724,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // corresponding details table, // if scope is mentioned as global or not mentioned then it is normal // global parameter updation - if (scope != null && !scope.isEmpty() && !ConfigKey.Scope.Global.toString().equalsIgnoreCase(scope)) { + if (scope != null && !ConfigKey.Scope.Global.equals(scope)) { boolean valueEncrypted = shouldEncryptValue(category); if (valueEncrypted) { value = DBEncryptionUtil.encrypt(value); } ApiCommandResourceType resourceType; - ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope); - switch (scopeVal) { + switch (scope) { case Zone: final DataCenterVO zone = _zoneDao.findById(resourceId); if (zone == null) { @@ -831,9 +830,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati CallContext.current().setEventResourceType(resourceType); CallContext.current().setEventResourceId(resourceId); - CallContext.current().setEventDetails(String.format(" Name: %s, New Value: %s, Scope: %s", name, value, scope)); + CallContext.current().setEventDetails(String.format(" Name: %s, New Value: %s, Scope: %s", name, value, scope.name())); - _configDepot.invalidateConfigCache(name, scopeVal, resourceId); + _configDepot.invalidateConfigCache(name, scope, resourceId); return valueEncrypted ? DBEncryptionUtil.decrypt(value) : value; } @@ -999,40 +998,40 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return _configDao.findByName(name); } - String scope = null; + ConfigKey.Scope scope = null; Long id = null; int paramCountCheck = 0; if (zoneId != null) { - scope = ConfigKey.Scope.Zone.toString(); + scope = ConfigKey.Scope.Zone; id = zoneId; paramCountCheck++; } if (clusterId != null) { - scope = ConfigKey.Scope.Cluster.toString(); + scope = ConfigKey.Scope.Cluster; id = clusterId; paramCountCheck++; } if (accountId != null) { Account account = _accountMgr.getAccount(accountId); _accountMgr.checkAccess(caller, null, false, account); - scope = ConfigKey.Scope.Account.toString(); + scope = ConfigKey.Scope.Account; id = accountId; paramCountCheck++; } if (domainId != null) { _accountMgr.checkAccess(caller, _domainDao.findById(domainId)); - scope = ConfigKey.Scope.Domain.toString(); + scope = ConfigKey.Scope.Domain; id = domainId; paramCountCheck++; } if (storagepoolId != null) { - scope = ConfigKey.Scope.StoragePool.toString(); + scope = ConfigKey.Scope.StoragePool; id = storagepoolId; paramCountCheck++; } if (imageStoreId != null) { - scope = ConfigKey.Scope.ImageStore.toString(); + scope = ConfigKey.Scope.ImageStore; id = imageStoreId; paramCountCheck++; } @@ -1046,8 +1045,15 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (value.isEmpty() || value.equals("null")) { value = (id == null) ? null : ""; } + + String currentValueInScope = getConfigurationValueInScope(config, name, scope, id); final String updatedValue = updateConfiguration(userId, name, category, value, scope, id); if (value == null && updatedValue == null || updatedValue.equalsIgnoreCase(value)) { + logger.debug("Config: {} value is updated from: {} to {} for scope: {}", name, + encryptEventValueIfConfigIsEncrypted(config, currentValueInScope), + encryptEventValueIfConfigIsEncrypted(config, value), + scope != null ? scope : ConfigKey.Scope.Global.name()); + return _configDao.findByName(name); } else { throw new CloudRuntimeException("Unable to update configuration parameter " + name); @@ -1109,7 +1115,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati configScope = config.getScopes(); } - String scope = ""; + String scopeVal = ""; Map<String, Long> scopeMap = new LinkedHashMap<>(); Long id = null; @@ -1125,22 +1131,23 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati ParamCountPair paramCountPair = getParamCount(scopeMap); id = paramCountPair.getId(); paramCountCheck = paramCountPair.getParamCount(); - scope = paramCountPair.getScope(); + scopeVal = paramCountPair.getScope(); if (paramCountCheck > 1) { throw new InvalidParameterValueException("cannot handle multiple IDs, provide only one ID corresponding to the scope"); } - if (scope != null) { - ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope); - if (!scope.equals(ConfigKey.Scope.Global.toString()) && !configScope.contains(scopeVal)) { + if (scopeVal != null) { + ConfigKey.Scope scope = ConfigKey.Scope.valueOf(scopeVal); + if (!scopeVal.equals(ConfigKey.Scope.Global.toString()) && !configScope.contains(scope)) { throw new InvalidParameterValueException("Invalid scope id provided for the parameter " + name); } } String newValue = null; - ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope); - switch (scopeVal) { + ConfigKey.Scope scope = ConfigKey.Scope.valueOf(scopeVal); + String currentValueInScope = getConfigurationValueInScope(config, name, scope, id); + switch (scope) { case Zone: final DataCenterVO zone = _zoneDao.findById(id); if (zone == null) { @@ -1225,12 +1232,28 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; } - _configDepot.invalidateConfigCache(name, scopeVal, id); + logger.debug("Config: {} value is updated from: {} to {} for scope: {}", name, + encryptEventValueIfConfigIsEncrypted(config, currentValueInScope), + encryptEventValueIfConfigIsEncrypted(config, newValue), scope); + + _configDepot.invalidateConfigCache(name, scope, id); CallContext.current().setEventDetails(" Name: " + name + " New Value: " + (name.toLowerCase().contains("password") ? "*****" : defaultValue == null ? "" : defaultValue)); return new Pair<Configuration, String>(_configDao.findByName(name), newValue); } + private String getConfigurationValueInScope(ConfigurationVO config, String name, ConfigKey.Scope scope, Long id) { + String configValue; + if (scope == null || ConfigKey.Scope.Global.equals(scope)) { + configValue = config.getValue(); + } else { + ConfigKey<?> configKey = _configDepot.get(name); + Object currentValue = configKey.valueInScope(scope, id); + configValue = currentValue != null ? currentValue.toString() : null; + } + return configValue; + } + /** * Validates whether a value is valid for the specified configuration. This includes type and range validation. * @param name name of the configuration. @@ -1238,7 +1261,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati * @param scope scope of the configuration. * @return null if the value is valid; otherwise, returns an error message. */ - protected String validateConfigurationValue(String name, String value, String scope) { + protected String validateConfigurationValue(String name, String value, ConfigKey.Scope scope) { final ConfigurationVO cfg = _configDao.findByName(name); if (cfg == null) { logger.error("Missing configuration variable " + name + " in configuration table"); @@ -1248,10 +1271,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati List<ConfigKey.Scope> configScope = cfg.getScopes(); if (scope != null) { - ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope); - if (!configScope.contains(scopeVal) && + if (!configScope.contains(scope) && !(ENABLE_ACCOUNT_SETTINGS_FOR_DOMAIN.value() && configScope.contains(ConfigKey.Scope.Account) && - scope.equals(ConfigKey.Scope.Domain.toString()))) { + ConfigKey.Scope.Domain.equals(scope))) { logger.error("Invalid scope id provided for the parameter " + name); return "Invalid scope id provided for the parameter " + name; } diff --git a/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java b/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java index 9b988c0058f..5b0f10f8508 100644 --- a/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java +++ b/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java @@ -459,7 +459,7 @@ public class ConfigurationManagerImplTest { @Test public void testValidateInvalidConfiguration() { Mockito.doReturn(null).when(configDao).findByName(Mockito.anyString()); - String msg = configurationManagerImplSpy.validateConfigurationValue("test.config.name", "testvalue", ConfigKey.Scope.Global.toString()); + String msg = configurationManagerImplSpy.validateConfigurationValue("test.config.name", "testvalue", ConfigKey.Scope.Global); Assert.assertEquals("Invalid configuration variable.", msg); } @@ -468,7 +468,7 @@ public class ConfigurationManagerImplTest { ConfigurationVO cfg = mock(ConfigurationVO.class); when(cfg.getScopes()).thenReturn(List.of(ConfigKey.Scope.Account)); Mockito.doReturn(cfg).when(configDao).findByName(Mockito.anyString()); - String msg = configurationManagerImplSpy.validateConfigurationValue("test.config.name", "testvalue", ConfigKey.Scope.Domain.toString()); + String msg = configurationManagerImplSpy.validateConfigurationValue("test.config.name", "testvalue", ConfigKey.Scope.Domain); Assert.assertEquals("Invalid scope id provided for the parameter test.config.name", msg); } @@ -480,7 +480,7 @@ public class ConfigurationManagerImplTest { Mockito.doReturn(cfg).when(configDao).findByName(Mockito.anyString()); Mockito.doReturn(configKey).when(configurationManagerImplSpy._configDepot).get(configKey.key()); - String result = configurationManagerImplSpy.validateConfigurationValue(configKey.key(), "11", configKey.getScopes().get(0).name()); + String result = configurationManagerImplSpy.validateConfigurationValue(configKey.key(), "11", configKey.getScopes().get(0)); Assert.assertNotNull(result); } @@ -492,7 +492,7 @@ public class ConfigurationManagerImplTest { ConfigKey<Integer> configKey = UnmanagedVMsManager.ThreadsOnKVMHostToImportVMwareVMFiles; Mockito.doReturn(cfg).when(configDao).findByName(Mockito.anyString()); Mockito.doReturn(configKey).when(configurationManagerImplSpy._configDepot).get(configKey.key()); - String msg = configurationManagerImplSpy.validateConfigurationValue(configKey.key(), "10", configKey.getScopes().get(0).name()); + String msg = configurationManagerImplSpy.validateConfigurationValue(configKey.key(), "10", configKey.getScopes().get(0)); Assert.assertNull(msg); } @@ -505,7 +505,7 @@ public class ConfigurationManagerImplTest { Mockito.doReturn(configKey).when(configurationManagerImplSpy._configDepot).get(configKey.key()); configurationManagerImplSpy.populateConfigValuesForValidationSet(); - String result = configurationManagerImplSpy.validateConfigurationValue(configKey.key(), "0", configKey.getScopes().get(0).name()); + String result = configurationManagerImplSpy.validateConfigurationValue(configKey.key(), "0", configKey.getScopes().get(0)); Assert.assertNotNull(result); } @@ -518,7 +518,7 @@ public class ConfigurationManagerImplTest { Mockito.doReturn(cfg).when(configDao).findByName(Mockito.anyString()); Mockito.doReturn(configKey).when(configurationManagerImplSpy._configDepot).get(configKey.key()); configurationManagerImplSpy.populateConfigValuesForValidationSet(); - String msg = configurationManagerImplSpy.validateConfigurationValue(configKey.key(), "9", configKey.getScopes().get(0).name()); + String msg = configurationManagerImplSpy.validateConfigurationValue(configKey.key(), "9", configKey.getScopes().get(0)); Assert.assertNull(msg); } @@ -633,14 +633,14 @@ public class ConfigurationManagerImplTest { @Test public void validateConfigurationValueTestValidatesValueType() { Mockito.when(configKeyMock.type()).thenReturn(Integer.class); - configurationManagerImplSpy.validateConfigurationValue("validate.type", "100", ConfigKey.Scope.Global.name()); + configurationManagerImplSpy.validateConfigurationValue("validate.type", "100", ConfigKey.Scope.Global); Mockito.verify(configurationManagerImplSpy).validateValueType("100", Integer.class); } @Test public void validateConfigurationValueTestValidatesValueRange() { Mockito.when(configKeyMock.type()).thenReturn(Integer.class); - configurationManagerImplSpy.validateConfigurationValue("validate.range", "100", ConfigKey.Scope.Global.name()); + configurationManagerImplSpy.validateConfigurationValue("validate.range", "100", ConfigKey.Scope.Global); Mockito.verify(configurationManagerImplSpy).validateValueRange("validate.range", "100", Integer.class, null); } diff --git a/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java index d4f3569cb57..cdd902bcebd 100644 --- a/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -82,6 +82,7 @@ import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; import org.apache.cloudstack.config.Configuration; +import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO; import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpRange; @@ -497,7 +498,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu * @see com.cloud.configuration.ConfigurationManager#updateConfiguration(long, java.lang.String, java.lang.String, java.lang.String) */ @Override - public String updateConfiguration(long userId, String name, String category, String value, String scope, Long resourceId) { + public String updateConfiguration(long userId, String name, String category, String value, ConfigKey.Scope scope, Long resourceId) { // TODO Auto-generated method stub return null; }