mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
framework/config,server: configkey caching (#9628)
Added caching for ConfigKey value retrievals based on the Caffeine in-memory caching library. https://github.com/ben-manes/caffeine Currently, expire time for a cache is 30s and each update of the config key invalidates the cache. On any update or reset of the configuration, cache automatically invalidates for it. Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
parent
787acfd172
commit
31b0ed0a18
@ -43,7 +43,6 @@ import java.util.stream.Collectors;
|
|||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
|
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
|
||||||
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
||||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||||
@ -1256,12 +1255,10 @@ public class VirtualMachineManagerImplTest {
|
|||||||
ConfigKey configKey = VirtualMachineManager.VmMetadataManufacturer;
|
ConfigKey configKey = VirtualMachineManager.VmMetadataManufacturer;
|
||||||
this.configDepotImpl = (ConfigDepotImpl)ReflectionTestUtils.getField(configKey, "s_depot");
|
this.configDepotImpl = (ConfigDepotImpl)ReflectionTestUtils.getField(configKey, "s_depot");
|
||||||
ConfigDepotImpl configDepot = Mockito.mock(ConfigDepotImpl.class);
|
ConfigDepotImpl configDepot = Mockito.mock(ConfigDepotImpl.class);
|
||||||
ScopedConfigStorage storage = Mockito.mock(ScopedConfigStorage.class);
|
Mockito.when(configDepot.getConfigStringValue(Mockito.eq(configKey.key()),
|
||||||
Mockito.when(storage.getConfigValue(Mockito.anyLong(), Mockito.eq(configKey))).thenReturn(manufacturer);
|
Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn(manufacturer);
|
||||||
Mockito.when(storage.getConfigValue(Mockito.anyLong(), Mockito.eq(VirtualMachineManager.VmMetadataProductName)))
|
Mockito.when(configDepot.getConfigStringValue(Mockito.eq(VirtualMachineManager.VmMetadataProductName.key()),
|
||||||
.thenReturn(product);
|
Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn(product);
|
||||||
Mockito.when(configDepot.findScopedConfigStorage(configKey)).thenReturn(storage);
|
|
||||||
Mockito.when(configDepot.findScopedConfigStorage(VirtualMachineManager.VmMetadataProductName)).thenReturn(storage);
|
|
||||||
ReflectionTestUtils.setField(configKey, "s_depot", configDepot);
|
ReflectionTestUtils.setField(configKey, "s_depot", configDepot);
|
||||||
updatedConfigKeyDepot = true;
|
updatedConfigKeyDepot = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,6 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
||||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||||
@ -136,8 +135,8 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigValue(long id, ConfigKey<?> key) {
|
public String getConfigValue(long id, String key) {
|
||||||
ClusterDetailsVO vo = findDetail(id, key.key());
|
ClusterDetailsVO vo = findDetail(id, key);
|
||||||
return vo == null ? null : vo.getValue();
|
return vo == null ? null : vo.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,8 +44,8 @@ public class DataCenterDetailsDaoImpl extends ResourceDetailsDaoBase<DataCenterD
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigValue(long id, ConfigKey<?> key) {
|
public String getConfigValue(long id, String key) {
|
||||||
ResourceDetail vo = findDetail(id, key.key());
|
ResourceDetail vo = findDetail(id, key);
|
||||||
return vo == null ? null : vo.getValue();
|
return vo == null ? null : vo.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,11 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
||||||
|
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
||||||
|
|
||||||
import com.cloud.domain.DomainDetailVO;
|
import com.cloud.domain.DomainDetailVO;
|
||||||
import com.cloud.domain.DomainVO;
|
import com.cloud.domain.DomainVO;
|
||||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||||
@ -31,11 +36,6 @@ import com.cloud.utils.db.SearchBuilder;
|
|||||||
import com.cloud.utils.db.SearchCriteria;
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
import com.cloud.utils.db.SearchCriteria.Op;
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
import com.cloud.utils.db.TransactionLegacy;
|
import com.cloud.utils.db.TransactionLegacy;
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
|
||||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
|
||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|
||||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
|
||||||
|
|
||||||
public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> implements DomainDetailsDao, ScopedConfigStorage {
|
public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> implements DomainDetailsDao, ScopedConfigStorage {
|
||||||
protected final SearchBuilder<DomainDetailVO> domainSearch;
|
protected final SearchBuilder<DomainDetailVO> domainSearch;
|
||||||
@ -108,17 +108,17 @@ public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigValue(long id, ConfigKey<?> key) {
|
public String getConfigValue(long id, String key) {
|
||||||
DomainDetailVO vo = null;
|
DomainDetailVO vo = null;
|
||||||
String enableDomainSettingsForChildDomain = _configDao.getValue("enable.domain.settings.for.child.domain");
|
String enableDomainSettingsForChildDomain = _configDao.getValue("enable.domain.settings.for.child.domain");
|
||||||
if (!Boolean.parseBoolean(enableDomainSettingsForChildDomain)) {
|
if (!Boolean.parseBoolean(enableDomainSettingsForChildDomain)) {
|
||||||
vo = findDetail(id, key.key());
|
vo = findDetail(id, key);
|
||||||
return vo == null ? null : getActualValue(vo);
|
return vo == null ? null : getActualValue(vo);
|
||||||
}
|
}
|
||||||
DomainVO domain = _domainDao.findById(id);
|
DomainVO domain = _domainDao.findById(id);
|
||||||
// if value is not configured in domain then check its parent domain till ROOT
|
// if value is not configured in domain then check its parent domain till ROOT
|
||||||
while (domain != null) {
|
while (domain != null) {
|
||||||
vo = findDetail(domain.getId(), key.key());
|
vo = findDetail(domain.getId(), key);
|
||||||
if (vo != null) {
|
if (vo != null) {
|
||||||
break;
|
break;
|
||||||
} else if (domain.getParent() != null) {
|
} else if (domain.getParent() != null) {
|
||||||
|
|||||||
@ -17,6 +17,10 @@
|
|||||||
package com.cloud.storage.dao;
|
package com.cloud.storage.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
||||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||||
@ -26,9 +30,6 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
|
|||||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
|
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class StoragePoolDetailsDaoImpl extends ResourceDetailsDaoBase<StoragePoolDetailVO> implements StoragePoolDetailsDao, ScopedConfigStorage {
|
public class StoragePoolDetailsDaoImpl extends ResourceDetailsDaoBase<StoragePoolDetailVO> implements StoragePoolDetailsDao, ScopedConfigStorage {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -43,8 +44,8 @@ public class StoragePoolDetailsDaoImpl extends ResourceDetailsDaoBase<StoragePoo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigValue(long id, ConfigKey<?> key) {
|
public String getConfigValue(long id, String key) {
|
||||||
StoragePoolDetailVO vo = findDetail(id, key.key());
|
StoragePoolDetailVO vo = findDetail(id, key);
|
||||||
return vo == null ? null : vo.getValue();
|
return vo == null ? null : vo.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,25 +23,24 @@ import java.util.Optional;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
||||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
||||||
|
|
||||||
import com.cloud.domain.DomainDetailVO;
|
import com.cloud.domain.DomainDetailVO;
|
||||||
import com.cloud.domain.DomainVO;
|
import com.cloud.domain.DomainVO;
|
||||||
import com.cloud.domain.dao.DomainDetailsDao;
|
|
||||||
import com.cloud.domain.dao.DomainDao;
|
import com.cloud.domain.dao.DomainDao;
|
||||||
|
import com.cloud.domain.dao.DomainDetailsDao;
|
||||||
import com.cloud.user.dao.AccountDao;
|
import com.cloud.user.dao.AccountDao;
|
||||||
|
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||||
import com.cloud.utils.db.GenericDaoBase;
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
import com.cloud.utils.db.QueryBuilder;
|
import com.cloud.utils.db.QueryBuilder;
|
||||||
import com.cloud.utils.db.SearchBuilder;
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
import com.cloud.utils.db.SearchCriteria;
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
import com.cloud.utils.db.SearchCriteria.Op;
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
import com.cloud.utils.db.TransactionLegacy;
|
import com.cloud.utils.db.TransactionLegacy;
|
||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|
||||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
|
||||||
|
|
||||||
public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long> implements AccountDetailsDao, ScopedConfigStorage {
|
public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long> implements AccountDetailsDao, ScopedConfigStorage {
|
||||||
protected final SearchBuilder<AccountDetailVO> accountSearch;
|
protected final SearchBuilder<AccountDetailVO> accountSearch;
|
||||||
@ -118,9 +117,9 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigValue(long id, ConfigKey<?> key) {
|
public String getConfigValue(long id, String key) {
|
||||||
// check if account level setting is configured
|
// check if account level setting is configured
|
||||||
AccountDetailVO vo = findDetail(id, key.key());
|
AccountDetailVO vo = findDetail(id, key);
|
||||||
String value = vo == null ? null : getActualValue(vo);
|
String value = vo == null ? null : getActualValue(vo);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return value;
|
return value;
|
||||||
@ -140,7 +139,7 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
|
|||||||
if (account.isPresent()) {
|
if (account.isPresent()) {
|
||||||
DomainVO domain = _domainDao.findById(account.get().getDomainId());
|
DomainVO domain = _domainDao.findById(account.get().getDomainId());
|
||||||
while (domain != null) {
|
while (domain != null) {
|
||||||
DomainDetailVO domainVO = _domainDetailsDao.findDetail(domain.getId(), key.key());
|
DomainDetailVO domainVO = _domainDetailsDao.findDetail(domain.getId(), key);
|
||||||
if (domainVO != null) {
|
if (domainVO != null) {
|
||||||
value = _domainDetailsDao.getActualValue(domainVO);
|
value = _domainDetailsDao.getActualValue(domainVO);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -20,6 +20,11 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
|
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
||||||
|
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||||
|
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||||
@ -29,12 +34,6 @@ import com.cloud.utils.db.SearchCriteria;
|
|||||||
import com.cloud.utils.db.SearchCriteria.Op;
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
import com.cloud.utils.db.TransactionLegacy;
|
import com.cloud.utils.db.TransactionLegacy;
|
||||||
|
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
|
||||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
|
||||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreDetailVO> implements ImageStoreDetailsDao, ScopedConfigStorage {
|
public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreDetailVO> implements ImageStoreDetailsDao, ScopedConfigStorage {
|
||||||
|
|
||||||
@ -106,8 +105,8 @@ public class ImageStoreDetailsDaoImpl extends ResourceDetailsDaoBase<ImageStoreD
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigValue(long id, ConfigKey<?> key) {
|
public String getConfigValue(long id, String key) {
|
||||||
ImageStoreDetailVO vo = findDetail(id, key.key());
|
ImageStoreDetailVO vo = findDetail(id, key);
|
||||||
return vo == null ? null : vo.getValue();
|
return vo == null ? null : vo.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,4 +32,6 @@ public interface ConfigDepot {
|
|||||||
|
|
||||||
<T> void createOrUpdateConfigObject(String componentName, ConfigKey<T> key, String value);
|
<T> void createOrUpdateConfigObject(String componentName, ConfigKey<T> key, String value);
|
||||||
boolean isNewConfig(ConfigKey<?> configKey);
|
boolean isNewConfig(ConfigKey<?> configKey);
|
||||||
|
String getConfigStringValue(String key, ConfigKey.Scope scope, Long scopeId);
|
||||||
|
void invalidateConfigCache(String key, ConfigKey.Scope scope, Long scopeId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,6 @@ package org.apache.cloudstack.framework.config;
|
|||||||
import java.sql.Date;
|
import java.sql.Date;
|
||||||
|
|
||||||
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
||||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
|
||||||
|
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.Ternary;
|
import com.cloud.utils.Ternary;
|
||||||
@ -215,42 +214,38 @@ public class ConfigKey<T> {
|
|||||||
|
|
||||||
public T value() {
|
public T value() {
|
||||||
if (_value == null || isDynamic()) {
|
if (_value == null || isDynamic()) {
|
||||||
ConfigurationVO vo = (s_depot != null && s_depot.global() != null) ? s_depot.global().findById(key()) : null;
|
String value = s_depot != null ? s_depot.getConfigStringValue(_name, Scope.Global, null) : null;
|
||||||
final String value = (vo != null && vo.getValue() != null) ? vo.getValue() : defaultValue();
|
_value = valueOf((value == null) ? defaultValue() : value);
|
||||||
_value = ((value == null) ? (T)defaultValue() : valueOf(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T valueIn(Long id) {
|
protected T valueInScope(Scope scope, Long id) {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
return value();
|
return value();
|
||||||
}
|
}
|
||||||
|
|
||||||
String value = s_depot != null ? s_depot.findScopedConfigStorage(this).getConfigValue(id, this) : null;
|
String value = s_depot != null ? s_depot.getConfigStringValue(_name, scope, id) : null;
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return value();
|
return value();
|
||||||
} else {
|
|
||||||
return valueOf(value);
|
|
||||||
}
|
}
|
||||||
|
return valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T valueIn(Long id) {
|
||||||
|
return valueInScope(_scope, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T valueInDomain(Long domainId) {
|
public T valueInDomain(Long domainId) {
|
||||||
if (domainId == null) {
|
return valueInScope(Scope.Domain, domainId);
|
||||||
return value();
|
|
||||||
}
|
|
||||||
|
|
||||||
String value = s_depot != null ? s_depot.getDomainScope(this).getConfigValue(domainId, this) : null;
|
|
||||||
if (value == null) {
|
|
||||||
return value();
|
|
||||||
} else {
|
|
||||||
return valueOf(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected T valueOf(String value) {
|
protected T valueOf(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Number multiplier = 1;
|
Number multiplier = 1;
|
||||||
if (multiplier() != null) {
|
if (multiplier() != null) {
|
||||||
multiplier = (Number)multiplier();
|
multiplier = (Number)multiplier();
|
||||||
|
|||||||
@ -26,5 +26,9 @@ import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
|||||||
public interface ScopedConfigStorage {
|
public interface ScopedConfigStorage {
|
||||||
Scope getScope();
|
Scope getScope();
|
||||||
|
|
||||||
String getConfigValue(long id, ConfigKey<?> key);
|
String getConfigValue(long id, String key);
|
||||||
|
|
||||||
|
default String getConfigValue(long id, ConfigKey<?> key) {
|
||||||
|
return getConfigValue(id, key.key());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -37,12 +38,14 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
|||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||||
import org.apache.commons.lang.ObjectUtils;
|
import org.apache.commons.lang.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.Ternary;
|
import com.cloud.utils.Ternary;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConfigDepotImpl implements the ConfigDepot and ConfigDepotAdmin interface.
|
* ConfigDepotImpl implements the ConfigDepot and ConfigDepotAdmin interface.
|
||||||
@ -73,6 +76,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
|||||||
*/
|
*/
|
||||||
public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
||||||
protected Logger logger = LogManager.getLogger(getClass());
|
protected Logger logger = LogManager.getLogger(getClass());
|
||||||
|
protected final static long CONFIG_CACHE_EXPIRE_SECONDS = 30;
|
||||||
@Inject
|
@Inject
|
||||||
ConfigurationDao _configDao;
|
ConfigurationDao _configDao;
|
||||||
@Inject
|
@Inject
|
||||||
@ -83,12 +87,17 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
|||||||
List<ScopedConfigStorage> _scopedStorages;
|
List<ScopedConfigStorage> _scopedStorages;
|
||||||
Set<Configurable> _configured = Collections.synchronizedSet(new HashSet<Configurable>());
|
Set<Configurable> _configured = Collections.synchronizedSet(new HashSet<Configurable>());
|
||||||
Set<String> newConfigs = Collections.synchronizedSet(new HashSet<>());
|
Set<String> newConfigs = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
Cache<String, String> configCache;
|
||||||
|
|
||||||
private HashMap<String, Pair<String, ConfigKey<?>>> _allKeys = new HashMap<String, Pair<String, ConfigKey<?>>>(1007);
|
private HashMap<String, Pair<String, ConfigKey<?>>> _allKeys = new HashMap<String, Pair<String, ConfigKey<?>>>(1007);
|
||||||
|
|
||||||
HashMap<ConfigKey.Scope, Set<ConfigKey<?>>> _scopeLevelConfigsMap = new HashMap<ConfigKey.Scope, Set<ConfigKey<?>>>();
|
HashMap<ConfigKey.Scope, Set<ConfigKey<?>>> _scopeLevelConfigsMap = new HashMap<ConfigKey.Scope, Set<ConfigKey<?>>>();
|
||||||
|
|
||||||
public ConfigDepotImpl() {
|
public ConfigDepotImpl() {
|
||||||
|
configCache = Caffeine.newBuilder()
|
||||||
|
.maximumSize(512)
|
||||||
|
.expireAfterWrite(CONFIG_CACHE_EXPIRE_SECONDS, TimeUnit.SECONDS)
|
||||||
|
.build();
|
||||||
ConfigKey.init(this);
|
ConfigKey.init(this);
|
||||||
createEmptyScopeLevelMappings();
|
createEmptyScopeLevelMappings();
|
||||||
}
|
}
|
||||||
@ -268,6 +277,48 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
|||||||
return _configDao;
|
return _configDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getConfigStringValueInternal(String cacheKey) {
|
||||||
|
String[] parts = cacheKey.split("-");
|
||||||
|
String key = parts[0];
|
||||||
|
ConfigKey.Scope scope = ConfigKey.Scope.Global;
|
||||||
|
Long scopeId = null;
|
||||||
|
try {
|
||||||
|
scope = ConfigKey.Scope.valueOf(parts[1]);
|
||||||
|
scopeId = Long.valueOf(parts[2]);
|
||||||
|
} catch (IllegalArgumentException ignored) {}
|
||||||
|
if (!ConfigKey.Scope.Global.equals(scope) && scopeId != null) {
|
||||||
|
ScopedConfigStorage scopedConfigStorage = null;
|
||||||
|
for (ScopedConfigStorage storage : _scopedStorages) {
|
||||||
|
if (storage.getScope() == scope) {
|
||||||
|
scopedConfigStorage = storage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scopedConfigStorage == null) {
|
||||||
|
throw new CloudRuntimeException("Unable to find config storage for this scope: " + scope + " for " + key);
|
||||||
|
}
|
||||||
|
return scopedConfigStorage.getConfigValue(scopeId, key);
|
||||||
|
}
|
||||||
|
ConfigurationVO configurationVO = _configDao.findById(key);
|
||||||
|
if (configurationVO != null) {
|
||||||
|
return configurationVO.getValue();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getConfigCacheKey(String key, ConfigKey.Scope scope, Long scopeId) {
|
||||||
|
return String.format("%s-%s-%d", key, scope, (scopeId == null ? 0 : scopeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getConfigStringValue(String key, ConfigKey.Scope scope, Long scopeId) {
|
||||||
|
return configCache.get(getConfigCacheKey(key, scope, scopeId), this::getConfigStringValueInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateConfigCache(String key, ConfigKey.Scope scope, Long scopeId) {
|
||||||
|
configCache.invalidate(getConfigCacheKey(key, scope, scopeId));
|
||||||
|
}
|
||||||
|
|
||||||
public ScopedConfigStorage findScopedConfigStorage(ConfigKey<?> config) {
|
public ScopedConfigStorage findScopedConfigStorage(ConfigKey<?> config) {
|
||||||
for (ScopedConfigStorage storage : _scopedStorages) {
|
for (ScopedConfigStorage storage : _scopedStorages) {
|
||||||
if (storage.getScope() == config.scope()) {
|
if (storage.getScope() == config.scope()) {
|
||||||
|
|||||||
@ -23,12 +23,23 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class ConfigDepotImplTest {
|
public class ConfigDepotImplTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
ConfigurationDao _configDao;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
private ConfigDepotImpl configDepotImpl = new ConfigDepotImpl();
|
private ConfigDepotImpl configDepotImpl = new ConfigDepotImpl();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -57,4 +68,43 @@ public class ConfigDepotImplTest {
|
|||||||
Assert.assertFalse(configDepotImpl.isNewConfig(invalidNewConfig));
|
Assert.assertFalse(configDepotImpl.isNewConfig(invalidNewConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void runTestGetConfigStringValue(String key, String value) {
|
||||||
|
ConfigurationVO configurationVO = Mockito.mock(ConfigurationVO.class);
|
||||||
|
Mockito.when(configurationVO.getValue()).thenReturn(value);
|
||||||
|
Mockito.when(_configDao.findById(key)).thenReturn(configurationVO);
|
||||||
|
String result = configDepotImpl.getConfigStringValue(key, ConfigKey.Scope.Global, null);
|
||||||
|
Assert.assertEquals(value, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetConfigStringValue() {
|
||||||
|
runTestGetConfigStringValue("test", "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runTestGetConfigStringValueExpiry(long wait, int configDBRetrieval) {
|
||||||
|
String key = "test1";
|
||||||
|
String value = "expiry";
|
||||||
|
runTestGetConfigStringValue(key, value);
|
||||||
|
try {
|
||||||
|
Thread.sleep(wait);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Assert.fail(ie.getMessage());
|
||||||
|
}
|
||||||
|
String result = configDepotImpl.getConfigStringValue(key, ConfigKey.Scope.Global, null);
|
||||||
|
Assert.assertEquals(value, result);
|
||||||
|
Mockito.verify(_configDao, Mockito.times(configDBRetrieval)).findById(key);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetConfigStringValueWithinExpiry() {
|
||||||
|
runTestGetConfigStringValueExpiry((ConfigDepotImpl.CONFIG_CACHE_EXPIRE_SECONDS * 1000 ) / 4,
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetConfigStringValueAfterExpiry() {
|
||||||
|
runTestGetConfigStringValueExpiry(((ConfigDepotImpl.CONFIG_CACHE_EXPIRE_SECONDS) + 5) * 1000,
|
||||||
|
2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
pom.xml
6
pom.xml
@ -187,6 +187,7 @@
|
|||||||
<cs.xstream.version>1.4.20</cs.xstream.version>
|
<cs.xstream.version>1.4.20</cs.xstream.version>
|
||||||
<org.springframework.version>5.3.26</org.springframework.version>
|
<org.springframework.version>5.3.26</org.springframework.version>
|
||||||
<cs.ini.version>0.5.4</cs.ini.version>
|
<cs.ini.version>0.5.4</cs.ini.version>
|
||||||
|
<cs.caffeine.version>3.1.7</cs.caffeine.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
@ -769,6 +770,11 @@
|
|||||||
<artifactId>javax.inject</artifactId>
|
<artifactId>javax.inject</artifactId>
|
||||||
<version>1</version>
|
<version>1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
<artifactId>caffeine</artifactId>
|
||||||
|
<version>${cs.caffeine.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
|
|||||||
@ -45,17 +45,6 @@ import java.util.stream.Collectors;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
|
||||||
import com.cloud.dc.VlanDetailsVO;
|
|
||||||
import com.cloud.dc.dao.VlanDetailsDao;
|
|
||||||
import com.cloud.hypervisor.HypervisorGuru;
|
|
||||||
import com.cloud.network.dao.NsxProviderDao;
|
|
||||||
import com.cloud.network.element.NsxProviderVO;
|
|
||||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
|
||||||
import com.cloud.host.HostTagVO;
|
|
||||||
import com.cloud.storage.StoragePoolTagVO;
|
|
||||||
import com.cloud.storage.VolumeApiServiceImpl;
|
|
||||||
import com.googlecode.ipv6.IPv6Address;
|
|
||||||
import org.apache.cloudstack.acl.SecurityChecker;
|
import org.apache.cloudstack.acl.SecurityChecker;
|
||||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||||
import org.apache.cloudstack.affinity.AffinityGroupService;
|
import org.apache.cloudstack.affinity.AffinityGroupService;
|
||||||
@ -172,6 +161,7 @@ import com.cloud.dc.Pod;
|
|||||||
import com.cloud.dc.PodVlanMapVO;
|
import com.cloud.dc.PodVlanMapVO;
|
||||||
import com.cloud.dc.Vlan;
|
import com.cloud.dc.Vlan;
|
||||||
import com.cloud.dc.Vlan.VlanType;
|
import com.cloud.dc.Vlan.VlanType;
|
||||||
|
import com.cloud.dc.VlanDetailsVO;
|
||||||
import com.cloud.dc.VlanVO;
|
import com.cloud.dc.VlanVO;
|
||||||
import com.cloud.dc.dao.AccountVlanMapDao;
|
import com.cloud.dc.dao.AccountVlanMapDao;
|
||||||
import com.cloud.dc.dao.ClusterDao;
|
import com.cloud.dc.dao.ClusterDao;
|
||||||
@ -185,6 +175,7 @@ import com.cloud.dc.dao.DomainVlanMapDao;
|
|||||||
import com.cloud.dc.dao.HostPodDao;
|
import com.cloud.dc.dao.HostPodDao;
|
||||||
import com.cloud.dc.dao.PodVlanMapDao;
|
import com.cloud.dc.dao.PodVlanMapDao;
|
||||||
import com.cloud.dc.dao.VlanDao;
|
import com.cloud.dc.dao.VlanDao;
|
||||||
|
import com.cloud.dc.dao.VlanDetailsDao;
|
||||||
import com.cloud.dc.dao.VsphereStoragePolicyDao;
|
import com.cloud.dc.dao.VsphereStoragePolicyDao;
|
||||||
import com.cloud.deploy.DataCenterDeployment;
|
import com.cloud.deploy.DataCenterDeployment;
|
||||||
import com.cloud.deploy.DeploymentClusterPlanner;
|
import com.cloud.deploy.DeploymentClusterPlanner;
|
||||||
@ -203,10 +194,12 @@ import com.cloud.exception.PermissionDeniedException;
|
|||||||
import com.cloud.exception.ResourceAllocationException;
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
import com.cloud.exception.ResourceUnavailableException;
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.gpu.GPU;
|
import com.cloud.gpu.GPU;
|
||||||
|
import com.cloud.host.HostTagVO;
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
import com.cloud.host.dao.HostTagsDao;
|
import com.cloud.host.dao.HostTagsDao;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.hypervisor.HypervisorGuru;
|
||||||
import com.cloud.hypervisor.kvm.dpdk.DpdkHelper;
|
import com.cloud.hypervisor.kvm.dpdk.DpdkHelper;
|
||||||
import com.cloud.network.IpAddress;
|
import com.cloud.network.IpAddress;
|
||||||
import com.cloud.network.IpAddressManager;
|
import com.cloud.network.IpAddressManager;
|
||||||
@ -229,11 +222,13 @@ import com.cloud.network.dao.IPAddressVO;
|
|||||||
import com.cloud.network.dao.Ipv6GuestPrefixSubnetNetworkMapDao;
|
import com.cloud.network.dao.Ipv6GuestPrefixSubnetNetworkMapDao;
|
||||||
import com.cloud.network.dao.NetworkDao;
|
import com.cloud.network.dao.NetworkDao;
|
||||||
import com.cloud.network.dao.NetworkVO;
|
import com.cloud.network.dao.NetworkVO;
|
||||||
|
import com.cloud.network.dao.NsxProviderDao;
|
||||||
import com.cloud.network.dao.PhysicalNetworkDao;
|
import com.cloud.network.dao.PhysicalNetworkDao;
|
||||||
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
|
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
|
||||||
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
|
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
|
||||||
import com.cloud.network.dao.PhysicalNetworkVO;
|
import com.cloud.network.dao.PhysicalNetworkVO;
|
||||||
import com.cloud.network.dao.UserIpv6AddressDao;
|
import com.cloud.network.dao.UserIpv6AddressDao;
|
||||||
|
import com.cloud.network.element.NsxProviderVO;
|
||||||
import com.cloud.network.rules.LoadBalancerContainer.Scheme;
|
import com.cloud.network.rules.LoadBalancerContainer.Scheme;
|
||||||
import com.cloud.network.vpc.VpcManager;
|
import com.cloud.network.vpc.VpcManager;
|
||||||
import com.cloud.offering.DiskOffering;
|
import com.cloud.offering.DiskOffering;
|
||||||
@ -261,7 +256,9 @@ import com.cloud.storage.DiskOfferingVO;
|
|||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.Storage.ProvisioningType;
|
import com.cloud.storage.Storage.ProvisioningType;
|
||||||
import com.cloud.storage.StorageManager;
|
import com.cloud.storage.StorageManager;
|
||||||
|
import com.cloud.storage.StoragePoolTagVO;
|
||||||
import com.cloud.storage.Volume;
|
import com.cloud.storage.Volume;
|
||||||
|
import com.cloud.storage.VolumeApiServiceImpl;
|
||||||
import com.cloud.storage.VolumeVO;
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.dao.DiskOfferingDao;
|
import com.cloud.storage.dao.DiskOfferingDao;
|
||||||
import com.cloud.storage.dao.StoragePoolTagsDao;
|
import com.cloud.storage.dao.StoragePoolTagsDao;
|
||||||
@ -281,6 +278,7 @@ import com.cloud.utils.NumbersUtil;
|
|||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.UriUtils;
|
import com.cloud.utils.UriUtils;
|
||||||
import com.cloud.utils.component.ManagerBase;
|
import com.cloud.utils.component.ManagerBase;
|
||||||
|
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||||
import com.cloud.utils.db.DB;
|
import com.cloud.utils.db.DB;
|
||||||
import com.cloud.utils.db.EntityManager;
|
import com.cloud.utils.db.EntityManager;
|
||||||
import com.cloud.utils.db.Filter;
|
import com.cloud.utils.db.Filter;
|
||||||
@ -305,6 +303,7 @@ import com.google.common.base.Enums;
|
|||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.googlecode.ipv6.IPv6Address;
|
||||||
import com.googlecode.ipv6.IPv6Network;
|
import com.googlecode.ipv6.IPv6Network;
|
||||||
|
|
||||||
import static com.cloud.configuration.Config.SecStorageAllowedInternalDownloadSites;
|
import static com.cloud.configuration.Config.SecStorageAllowedInternalDownloadSites;
|
||||||
@ -705,7 +704,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||||||
value = DBEncryptionUtil.encrypt(value);
|
value = DBEncryptionUtil.encrypt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ConfigKey.Scope.valueOf(scope)) {
|
ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope);
|
||||||
|
switch (scopeVal) {
|
||||||
case Zone:
|
case Zone:
|
||||||
final DataCenterVO zone = _zoneDao.findById(resourceId);
|
final DataCenterVO zone = _zoneDao.findById(resourceId);
|
||||||
if (zone == null) {
|
if (zone == null) {
|
||||||
@ -796,6 +796,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||||||
throw new InvalidParameterValueException("Scope provided is invalid");
|
throw new InvalidParameterValueException("Scope provided is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_configDepot.invalidateConfigCache(name, scopeVal, resourceId);
|
||||||
return valueEncrypted ? DBEncryptionUtil.decrypt(value) : value;
|
return valueEncrypted ? DBEncryptionUtil.decrypt(value) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -808,6 +809,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||||||
logger.error("Failed to update configuration option, name: " + name + ", value:" + value);
|
logger.error("Failed to update configuration option, name: " + name + ", value:" + value);
|
||||||
throw new CloudRuntimeException("Failed to update configuration value. Please contact Cloud Support.");
|
throw new CloudRuntimeException("Failed to update configuration value. Please contact Cloud Support.");
|
||||||
}
|
}
|
||||||
|
_configDepot.invalidateConfigCache(name, ConfigKey.Scope.Global, null);
|
||||||
|
|
||||||
PreparedStatement pstmt = null;
|
PreparedStatement pstmt = null;
|
||||||
if (Config.XenServerGuestNetwork.key().equalsIgnoreCase(name)) {
|
if (Config.XenServerGuestNetwork.key().equalsIgnoreCase(name)) {
|
||||||
@ -1095,7 +1097,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||||||
}
|
}
|
||||||
|
|
||||||
String newValue = null;
|
String newValue = null;
|
||||||
switch (ConfigKey.Scope.valueOf(scope)) {
|
ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope);
|
||||||
|
switch (scopeVal) {
|
||||||
case Zone:
|
case Zone:
|
||||||
final DataCenterVO zone = _zoneDao.findById(id);
|
final DataCenterVO zone = _zoneDao.findById(id);
|
||||||
if (zone == null) {
|
if (zone == null) {
|
||||||
@ -1180,6 +1183,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||||||
newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue;
|
newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_configDepot.invalidateConfigCache(name, scopeVal, id);
|
||||||
|
|
||||||
CallContext.current().setEventDetails(" Name: " + name + " New Value: " + (name.toLowerCase().contains("password") ? "*****" : defaultValue == null ? "" : defaultValue));
|
CallContext.current().setEventDetails(" Name: " + name + " New Value: " + (name.toLowerCase().contains("password") ? "*****" : defaultValue == null ? "" : defaultValue));
|
||||||
return new Pair<Configuration, String>(_configDao.findByName(name), newValue);
|
return new Pair<Configuration, String>(_configDao.findByName(name), newValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,49 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.vm;
|
package com.cloud.vm;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.context.CallContext;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||||
|
import org.apache.cloudstack.framework.config.ConfigDepot;
|
||||||
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
|
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||||
|
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
|
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentMatchers;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.FilterType;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
|
|
||||||
import com.cloud.capacity.Capacity;
|
import com.cloud.capacity.Capacity;
|
||||||
import com.cloud.capacity.CapacityManager;
|
import com.cloud.capacity.CapacityManager;
|
||||||
import com.cloud.capacity.dao.CapacityDao;
|
import com.cloud.capacity.dao.CapacityDao;
|
||||||
@ -54,48 +97,6 @@ import com.cloud.utils.component.ComponentContext;
|
|||||||
import com.cloud.vm.dao.UserVmDao;
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||||
import com.cloud.vm.dao.VMInstanceDao;
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigDepot;
|
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
|
||||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
|
||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|
||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
|
||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
|
||||||
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
|
||||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
|
||||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
|
||||||
import org.apache.cloudstack.test.utils.SpringUtils;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.ArgumentMatchers;
|
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.FilterType;
|
|
||||||
import org.springframework.core.type.classreading.MetadataReader;
|
|
||||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
|
||||||
import org.springframework.core.type.filter.TypeFilter;
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||||
@ -243,9 +244,8 @@ public class FirstFitPlannerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<Long> initializeForClusterThresholdDisabled() {
|
private List<Long> initializeForClusterThresholdDisabled() {
|
||||||
ConfigurationVO config = mock(ConfigurationVO.class);
|
when(configDepot.getConfigStringValue(DeploymentClusterPlanner.ClusterThresholdEnabled.key(),
|
||||||
when(config.getValue()).thenReturn(String.valueOf(false));
|
ConfigKey.Scope.Global, null)).thenReturn(Boolean.FALSE.toString());
|
||||||
when(configDao.findById(DeploymentClusterPlanner.ClusterThresholdEnabled.key())).thenReturn(config);
|
|
||||||
|
|
||||||
List<Long> clustersCrossingThreshold = new ArrayList<Long>();
|
List<Long> clustersCrossingThreshold = new ArrayList<Long>();
|
||||||
clustersCrossingThreshold.add(3L);
|
clustersCrossingThreshold.add(3L);
|
||||||
|
|||||||
@ -3290,6 +3290,7 @@
|
|||||||
"message.set.default.nic": "Please confirm that you would like to make this NIC the default for this Instance.",
|
"message.set.default.nic": "Please confirm that you would like to make this NIC the default for this Instance.",
|
||||||
"message.set.default.nic.manual": "Please manually update the default NIC on the Instance now.",
|
"message.set.default.nic.manual": "Please manually update the default NIC on the Instance now.",
|
||||||
"message.setting.updated": "Setting Updated:",
|
"message.setting.updated": "Setting Updated:",
|
||||||
|
"message.setting.update.delay": "The new value will take effect within 30 seconds.",
|
||||||
"message.setup.physical.network.during.zone.creation": "When adding a zone, you need to set up one or more physical networks. Each physical network can carry one or more types of traffic, with certain restrictions on how they may be combined. Add or remove one or more traffic types onto each physical network.",
|
"message.setup.physical.network.during.zone.creation": "When adding a zone, you need to set up one or more physical networks. Each physical network can carry one or more types of traffic, with certain restrictions on how they may be combined. Add or remove one or more traffic types onto each physical network.",
|
||||||
"message.setup.physical.network.during.zone.creation.basic": "When adding a basic zone, you can set up one physical Network, which corresponds to a NIC on the hypervisor. The Network carries several types of traffic.<br/><br/>You may also <strong>add</strong> other traffic types onto the physical Network.",
|
"message.setup.physical.network.during.zone.creation.basic": "When adding a basic zone, you can set up one physical Network, which corresponds to a NIC on the hypervisor. The Network carries several types of traffic.<br/><br/>You may also <strong>add</strong> other traffic types onto the physical Network.",
|
||||||
"message.shared.network.offering.warning": "Domain admins and regular Users can only create shared Networks from Network offering with the setting specifyvlan=false. Please contact an administrator to create a Network offering if this list is empty.",
|
"message.shared.network.offering.warning": "Domain admins and regular Users can only create shared Networks from Network offering with the setting specifyvlan=false. Please contact an administrator to create a Network offering if this list is empty.",
|
||||||
|
|||||||
@ -746,7 +746,11 @@ export default {
|
|||||||
}).then(json => {
|
}).then(json => {
|
||||||
this.editableValueKey = null
|
this.editableValueKey = null
|
||||||
this.$store.dispatch('RefreshFeatures')
|
this.$store.dispatch('RefreshFeatures')
|
||||||
this.$message.success(`${this.$t('message.setting.updated')} ${record.name}`)
|
var message = `${this.$t('message.setting.updated')} ${record.name}`
|
||||||
|
if (record.isdynamic) {
|
||||||
|
message += `. ${this.$t('message.setting.update.delay')}`
|
||||||
|
}
|
||||||
|
this.$message.success(message)
|
||||||
if (json.updateconfigurationresponse &&
|
if (json.updateconfigurationresponse &&
|
||||||
json.updateconfigurationresponse.configuration &&
|
json.updateconfigurationresponse.configuration &&
|
||||||
!json.updateconfigurationresponse.configuration.isdynamic &&
|
!json.updateconfigurationresponse.configuration.isdynamic &&
|
||||||
@ -767,7 +771,10 @@ export default {
|
|||||||
api('resetConfiguration', {
|
api('resetConfiguration', {
|
||||||
name: item.name
|
name: item.name
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
const message = `${this.$t('label.setting')} ${item.name} ${this.$t('label.reset.config.value')}`
|
var message = `${this.$t('label.setting')} ${item.name} ${this.$t('label.reset.config.value')}`
|
||||||
|
if (item.isdynamic) {
|
||||||
|
message += `. ${this.$t('message.setting.update.delay')}`
|
||||||
|
}
|
||||||
this.$message.success(message)
|
this.$message.success(message)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|||||||
@ -174,7 +174,10 @@ export default {
|
|||||||
name: item.name,
|
name: item.name,
|
||||||
value: this.editableValue
|
value: this.editableValue
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
const message = `${this.$t('label.setting')} ${item.name} ${this.$t('label.update.to')} ${this.editableValue}`
|
var message = `${this.$t('label.setting')} ${item.name} ${this.$t('label.update.to')} ${this.editableValue}`
|
||||||
|
if (item.isdynamic) {
|
||||||
|
message += `. ${this.$t('message.setting.update.delay')}`
|
||||||
|
}
|
||||||
this.handleSuccessMessage(item.name, this.$route.meta.name, message)
|
this.handleSuccessMessage(item.name, this.$route.meta.name, message)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
@ -204,7 +207,10 @@ export default {
|
|||||||
[this.scopeKey]: this.resource.id,
|
[this.scopeKey]: this.resource.id,
|
||||||
name: item.name
|
name: item.name
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
const message = `${this.$t('label.setting')} ${item.name} ${this.$t('label.reset.config.value')}`
|
var message = `${this.$t('label.setting')} ${item.name} ${this.$t('label.reset.config.value')}`
|
||||||
|
if (item.isdynamic) {
|
||||||
|
message += `. ${this.$t('message.setting.update.delay')}`
|
||||||
|
}
|
||||||
this.handleSuccessMessage(item.name, this.$route.meta.name, message)
|
this.handleSuccessMessage(item.name, this.$route.meta.name, message)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|||||||
@ -258,7 +258,11 @@ export default {
|
|||||||
this.actualValue = this.editableValue
|
this.actualValue = this.editableValue
|
||||||
this.$emit('change-config', { value: newValue })
|
this.$emit('change-config', { value: newValue })
|
||||||
this.$store.dispatch('RefreshFeatures')
|
this.$store.dispatch('RefreshFeatures')
|
||||||
this.$message.success(`${this.$t('message.setting.updated')} ${configrecord.name}`)
|
var message = `${this.$t('message.setting.updated')} ${configrecord.name}`
|
||||||
|
if (configrecord.isdynamic) {
|
||||||
|
message += `. ${this.$t('message.setting.update.delay')}`
|
||||||
|
}
|
||||||
|
this.$message.success(message)
|
||||||
if (json.updateconfigurationresponse &&
|
if (json.updateconfigurationresponse &&
|
||||||
json.updateconfigurationresponse.configuration &&
|
json.updateconfigurationresponse.configuration &&
|
||||||
!json.updateconfigurationresponse.configuration.isdynamic &&
|
!json.updateconfigurationresponse.configuration.isdynamic &&
|
||||||
@ -295,7 +299,11 @@ export default {
|
|||||||
}
|
}
|
||||||
this.$emit('change-config', { value: newValue })
|
this.$emit('change-config', { value: newValue })
|
||||||
this.$store.dispatch('RefreshFeatures')
|
this.$store.dispatch('RefreshFeatures')
|
||||||
this.$message.success(`${this.$t('label.setting')} ${configrecord.name} ${this.$t('label.reset.config.value')}`)
|
var message = `${this.$t('label.setting')} ${configrecord.name} ${this.$t('label.reset.config.value')}`
|
||||||
|
if (configrecord.isdynamic) {
|
||||||
|
message += `. ${this.$t('message.setting.update.delay')}`
|
||||||
|
}
|
||||||
|
this.$message.success(message)
|
||||||
if (json.resetconfigurationresponse &&
|
if (json.resetconfigurationresponse &&
|
||||||
json.resetconfigurationresponse.configuration &&
|
json.resetconfigurationresponse.configuration &&
|
||||||
!json.resetconfigurationresponse.configuration.isdynamic &&
|
!json.resetconfigurationresponse.configuration.isdynamic &&
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user