mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	Enable resetting config values to default value (#4230)
* Enable resetting config values to default value Provide reset button to zone,cluster,domain,account, primary and secondary storage so that config values can be reset to default value * fix ui issue * Update test/integration/smoke/test_reset_configuration_settings.py * Update test/integration/smoke/test_reset_configuration_settings.py Co-authored-by: Rakesh Venkatesh <rakeshv@apache.org> Co-authored-by: dahn <daan.hoogland@gmail.com>
This commit is contained in:
		
							parent
							
								
									e06a66ba14
								
							
						
					
					
						commit
						2bd1dc1e14
					
				| @ -18,6 +18,7 @@ package com.cloud.configuration; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; | ||||
| import org.apache.cloudstack.api.command.admin.network.CreateManagementNetworkIpRangeCmd; | ||||
| import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; | ||||
| @ -76,6 +77,15 @@ public interface ConfigurationService { | ||||
|      */ | ||||
|     Configuration updateConfiguration(UpdateCfgCmd cmd) throws InvalidParameterValueException; | ||||
| 
 | ||||
|     /** | ||||
|      * Resets a configuration entry with default value | ||||
|      * | ||||
|      * @param cmd | ||||
|      *            - the command wrapping name parameter | ||||
|      * @return updated configuration object if successful | ||||
|      */ | ||||
|     Pair<Configuration, String> resetConfiguration(ResetCfgCmd cmd) throws InvalidParameterValueException; | ||||
| 
 | ||||
|     /** | ||||
|      * Create a service offering through the API | ||||
|      * | ||||
|  | ||||
| @ -714,6 +714,7 @@ public class ApiConstants { | ||||
|     public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory"; | ||||
|     public static final String VM_SNAPSHOT_QUIESCEVM = "quiescevm"; | ||||
|     public static final String IMAGE_STORE_UUID = "imagestoreuuid"; | ||||
|     public static final String IMAGE_STORE_ID = "imagestoreid"; | ||||
|     public static final String GUEST_VM_CIDR = "guestvmcidr"; | ||||
|     public static final String NETWORK_CIDR = "networkcidr"; | ||||
|     public static final String RESERVED_IP_RANGE = "reservediprange"; | ||||
|  | ||||
| @ -0,0 +1,166 @@ | ||||
| // Licensed to the Apache Software Foundation (ASF) under one | ||||
| // or more contributor license agreements.  See the NOTICE file | ||||
| // distributed with this work for additional information | ||||
| // regarding copyright ownership.  The ASF licenses this file | ||||
| // to you under the Apache License, Version 2.0 (the | ||||
| // "License"); you may not use this file except in compliance | ||||
| // with the License.  You may obtain a copy of the License at | ||||
| // | ||||
| //   http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, | ||||
| // software distributed under the License is distributed on an | ||||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
| // KIND, either express or implied.  See the License for the | ||||
| // specific language governing permissions and limitations | ||||
| // under the License. | ||||
| package org.apache.cloudstack.api.command.admin.config; | ||||
| 
 | ||||
| import org.apache.cloudstack.api.APICommand; | ||||
| import org.apache.cloudstack.api.ApiArgValidator; | ||||
| import org.apache.cloudstack.api.ApiConstants; | ||||
| import org.apache.cloudstack.api.ApiErrorCode; | ||||
| import org.apache.cloudstack.api.BaseCmd; | ||||
| import org.apache.cloudstack.api.Parameter; | ||||
| import org.apache.cloudstack.api.ServerApiException; | ||||
| import org.apache.cloudstack.api.response.ImageStoreResponse; | ||||
| import org.apache.cloudstack.framework.config.ConfigKey; | ||||
| import org.apache.log4j.Logger; | ||||
| 
 | ||||
| import org.apache.cloudstack.api.response.AccountResponse; | ||||
| import org.apache.cloudstack.api.response.ClusterResponse; | ||||
| import org.apache.cloudstack.api.response.ConfigurationResponse; | ||||
| import org.apache.cloudstack.api.response.DomainResponse; | ||||
| import org.apache.cloudstack.api.response.StoragePoolResponse; | ||||
| import org.apache.cloudstack.api.response.ZoneResponse; | ||||
| import org.apache.cloudstack.config.Configuration; | ||||
| 
 | ||||
| import com.cloud.user.Account; | ||||
| import com.cloud.utils.Pair; | ||||
| 
 | ||||
| @APICommand(name = "resetConfiguration", description = "Resets a configuration. The configuration will be set to default value for global setting, and removed from account_details or domain_details for Account/Domain settings", responseObject = ConfigurationResponse.class, | ||||
|         requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.16.0") | ||||
| public class ResetCfgCmd extends BaseCmd { | ||||
|     public static final Logger s_logger = Logger.getLogger(ResetCfgCmd.class.getName()); | ||||
|     private static final String s_name = "resetconfigurationresponse"; | ||||
| 
 | ||||
|     ///////////////////////////////////////////////////// | ||||
|     //////////////// API parameters ///////////////////// | ||||
|     ///////////////////////////////////////////////////// | ||||
| 
 | ||||
|     @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the configuration", validations = {ApiArgValidator.NotNullOrEmpty}) | ||||
|     private String cfgName; | ||||
| 
 | ||||
|     @Parameter(name = ApiConstants.ZONE_ID, | ||||
|                type = CommandType.UUID, | ||||
|                entityType = ZoneResponse.class, | ||||
|                description = "the ID of the Zone to reset the parameter value for corresponding zone") | ||||
|     private Long zoneId; | ||||
| 
 | ||||
|     @Parameter(name = ApiConstants.CLUSTER_ID, | ||||
|                type = CommandType.UUID, | ||||
|                entityType = ClusterResponse.class, | ||||
|                description = "the ID of the Cluster to reset the parameter value for corresponding cluster") | ||||
|     private Long clusterId; | ||||
| 
 | ||||
|     @Parameter(name = ApiConstants.STORAGE_ID, | ||||
|                type = CommandType.UUID, | ||||
|                entityType = StoragePoolResponse.class, | ||||
|                description = "the ID of the Storage pool to reset the parameter value for corresponding storage pool") | ||||
|     private Long storagePoolId; | ||||
| 
 | ||||
|     @Parameter(name = ApiConstants.DOMAIN_ID, | ||||
|             type = CommandType.UUID, | ||||
|             entityType = DomainResponse.class, | ||||
|             description = "the ID of the Domain to reset the parameter value for corresponding domain") | ||||
|     private Long domainId; | ||||
| 
 | ||||
|     @Parameter(name = ApiConstants.ACCOUNT_ID, | ||||
|                type = CommandType.UUID, | ||||
|                entityType = AccountResponse.class, | ||||
|                description = "the ID of the Account to reset the parameter value for corresponding account") | ||||
|     private Long accountId; | ||||
| 
 | ||||
|     @Parameter(name = ApiConstants.IMAGE_STORE_ID, | ||||
|             type = CommandType.UUID, | ||||
|             entityType = ImageStoreResponse.class, | ||||
|             description = "the ID of the Image Store to reset the parameter value for corresponding image store") | ||||
|     private Long imageStoreId; | ||||
| 
 | ||||
|     ///////////////////////////////////////////////////// | ||||
|     /////////////////// Accessors /////////////////////// | ||||
|     ///////////////////////////////////////////////////// | ||||
| 
 | ||||
|     public String getCfgName() { | ||||
|         return cfgName; | ||||
|     } | ||||
| 
 | ||||
|     public Long getZoneId() { | ||||
|         return zoneId; | ||||
|     } | ||||
| 
 | ||||
|     public Long getClusterId() { | ||||
|         return clusterId; | ||||
|     } | ||||
| 
 | ||||
|     public Long getStoragepoolId() { | ||||
|         return storagePoolId; | ||||
|     } | ||||
| 
 | ||||
|     public Long getDomainId() { | ||||
|         return domainId; | ||||
|     } | ||||
| 
 | ||||
|     public Long getAccountId() { | ||||
|         return accountId; | ||||
|     } | ||||
| 
 | ||||
|     public Long getImageStoreId() { | ||||
|         return imageStoreId; | ||||
|     } | ||||
| 
 | ||||
|     ///////////////////////////////////////////////////// | ||||
|     /////////////// API Implementation/////////////////// | ||||
|     ///////////////////////////////////////////////////// | ||||
| 
 | ||||
|     @Override | ||||
|     public String getCommandName() { | ||||
|         return s_name; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public long getEntityOwnerId() { | ||||
|         return Account.ACCOUNT_ID_SYSTEM; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void execute() { | ||||
|         Pair<Configuration, String> cfg = _configService.resetConfiguration(this); | ||||
|         if (cfg != null) { | ||||
|             ConfigurationResponse response = _responseGenerator.createConfigurationResponse(cfg.first()); | ||||
|             response.setResponseName(getCommandName()); | ||||
|             if (getZoneId() != null) { | ||||
|                 response.setScope(ConfigKey.Scope.Zone.name()); | ||||
|             } | ||||
|             if (getClusterId() != null) { | ||||
|                 response.setScope(ConfigKey.Scope.Cluster.name()); | ||||
|             } | ||||
|             if (getStoragepoolId() != null) { | ||||
|                 response.setScope(ConfigKey.Scope.StoragePool.name()); | ||||
|             } | ||||
|             if (getDomainId() != null) { | ||||
|                 response.setScope(ConfigKey.Scope.Domain.name()); | ||||
|             } | ||||
|             if (getAccountId() != null) { | ||||
|                 response.setScope(ConfigKey.Scope.Account.name()); | ||||
|             } | ||||
|             if (getImageStoreId() != null) { | ||||
|                 response.setScope(ConfigKey.Scope.ImageStore.name()); | ||||
|             } | ||||
|             response.setValue(cfg.second()); | ||||
|             this.setResponseObject(response); | ||||
|         } else { | ||||
|             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to reset config"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -35,6 +35,11 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long | ||||
|     protected final SearchBuilder<ClusterDetailsVO> ClusterSearch; | ||||
|     protected final SearchBuilder<ClusterDetailsVO> DetailSearch; | ||||
| 
 | ||||
|     private final String CpuOverprovisioningFactor = "cpu.overprovisioning.factor"; | ||||
|     private final String MemoryOverprovisioningFactor = "mem.overprovisioning.factor"; | ||||
|     private final String CpuOverCommitRatio = "cpuOvercommitRatio"; | ||||
|     private final String MemoryOverCommitRatio = "memoryOvercommitRatio"; | ||||
| 
 | ||||
|     protected ClusterDetailsDaoImpl() { | ||||
|         ClusterSearch = createSearchBuilder(); | ||||
|         ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ); | ||||
| @ -50,12 +55,7 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long | ||||
|     public ClusterDetailsVO findDetail(long clusterId, String name) { | ||||
|         SearchCriteria<ClusterDetailsVO> sc = DetailSearch.create(); | ||||
|         // This is temporary fix to support list/update configuration api for cpu and memory overprovisioning ratios | ||||
|         if (name.equalsIgnoreCase("cpu.overprovisioning.factor")) { | ||||
|             name = "cpuOvercommitRatio"; | ||||
|         } | ||||
|         if (name.equalsIgnoreCase("mem.overprovisioning.factor")) { | ||||
|             name = "memoryOvercommitRatio"; | ||||
|         } | ||||
|         name = getCpuMemoryOvercommitRatio(name); | ||||
|         sc.setParameters("clusterId", clusterId); | ||||
|         sc.setParameters("name", name); | ||||
| 
 | ||||
| @ -103,11 +103,13 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long | ||||
|         expunge(sc); | ||||
| 
 | ||||
|         for (Map.Entry<String, String> detail : details.entrySet()) { | ||||
|             String name = detail.getKey(); | ||||
|             name = getCpuMemoryOvercommitRatio(name); | ||||
|             String value = detail.getValue(); | ||||
|             if ("password".equals(detail.getKey())) { | ||||
|                 value = DBEncryptionUtil.encrypt(value); | ||||
|             } | ||||
|             ClusterDetailsVO vo = new ClusterDetailsVO(clusterId, detail.getKey(), value); | ||||
|             ClusterDetailsVO vo = new ClusterDetailsVO(clusterId, name, value); | ||||
|             persist(vo); | ||||
|         } | ||||
|         txn.commit(); | ||||
| @ -115,6 +117,7 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long | ||||
| 
 | ||||
|     @Override | ||||
|     public void persist(long clusterId, String name, String value) { | ||||
|         name = getCpuMemoryOvercommitRatio(name); | ||||
|         TransactionLegacy txn = TransactionLegacy.currentTxn(); | ||||
|         txn.start(); | ||||
|         SearchCriteria<ClusterDetailsVO> sc = DetailSearch.create(); | ||||
| @ -147,4 +150,15 @@ public class ClusterDetailsDaoImpl extends GenericDaoBase<ClusterDetailsVO, Long | ||||
|             dcName = tokens[3]; | ||||
|         return dcName; | ||||
|     } | ||||
| 
 | ||||
|     private String getCpuMemoryOvercommitRatio(String name) { | ||||
|         if (name.equalsIgnoreCase(CpuOverprovisioningFactor)) { | ||||
|             name = CpuOverCommitRatio; | ||||
|         } | ||||
|         if (name.equalsIgnoreCase(MemoryOverprovisioningFactor)) { | ||||
|             name = MemoryOverCommitRatio; | ||||
|         } | ||||
| 
 | ||||
|         return name; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -30,10 +30,12 @@ import java.util.Comparator; | ||||
| import java.util.HashMap; | ||||
| import java.util.HashSet; | ||||
| import java.util.Iterator; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
| import java.util.ListIterator; | ||||
| import java.util.Map; | ||||
| import java.util.Map.Entry; | ||||
| import java.util.Optional; | ||||
| import java.util.Set; | ||||
| import java.util.UUID; | ||||
| import java.util.Vector; | ||||
| @ -51,6 +53,7 @@ import org.apache.cloudstack.agent.lb.IndirectAgentLBServiceImpl; | ||||
| import org.apache.cloudstack.annotation.AnnotationService; | ||||
| import org.apache.cloudstack.annotation.dao.AnnotationDao; | ||||
| import org.apache.cloudstack.api.ApiConstants; | ||||
| import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; | ||||
| import org.apache.cloudstack.api.command.admin.network.CreateManagementNetworkIpRangeCmd; | ||||
| import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; | ||||
| @ -105,6 +108,7 @@ import org.apache.cloudstack.region.dao.RegionDao; | ||||
| import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO; | ||||
| import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao; | ||||
| import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; | ||||
| import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO; | ||||
| import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; | ||||
| import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; | ||||
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; | ||||
| @ -630,9 +634,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati | ||||
|                 if (cluster == null) { | ||||
|                     throw new InvalidParameterValueException("unable to find cluster by id " + resourceId); | ||||
|                 } | ||||
|                 ClusterDetailsVO clusterDetailsVO = _clusterDetailsDao.findDetail(resourceId, name); | ||||
|                 String newName = name; | ||||
|                 if (name.equalsIgnoreCase("cpu.overprovisioning.factor")) { | ||||
|                     newName = "cpuOvercommitRatio"; | ||||
|                 } | ||||
|                 if (name.equalsIgnoreCase("mem.overprovisioning.factor")) { | ||||
|                     newName = "memoryOvercommitRatio"; | ||||
|                 } | ||||
|                 ClusterDetailsVO clusterDetailsVO = _clusterDetailsDao.findDetail(resourceId, newName); | ||||
|                 if (clusterDetailsVO == null) { | ||||
|                     clusterDetailsVO = new ClusterDetailsVO(resourceId, name, value); | ||||
|                     clusterDetailsVO = new ClusterDetailsVO(resourceId, newName, value); | ||||
|                     _clusterDetailsDao.persist(clusterDetailsVO); | ||||
|                 } else { | ||||
|                     clusterDetailsVO.setValue(value); | ||||
| @ -879,6 +890,159 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private ParamCountPair getParamCount(Map<String, Long> scopeMap) { | ||||
|         Long id = null; | ||||
|         int paramCount = 0; | ||||
|         String scope = ConfigKey.Scope.Global.toString(); | ||||
| 
 | ||||
|         for (var entry : scopeMap.entrySet()) { | ||||
|             if (entry.getValue() != null) { | ||||
|                 id = entry.getValue(); | ||||
|                 scope = entry.getKey(); | ||||
|                 paramCount++; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return new ParamCountPair(id, paramCount, scope); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     @ActionEvent(eventType = EventTypes.EVENT_CONFIGURATION_VALUE_EDIT, eventDescription = "resetting configuration") | ||||
|     public Pair<Configuration, String> resetConfiguration(final ResetCfgCmd cmd) throws InvalidParameterValueException { | ||||
|         final Long userId = CallContext.current().getCallingUserId(); | ||||
|         final String name = cmd.getCfgName(); | ||||
|         final Long zoneId = cmd.getZoneId(); | ||||
|         final Long clusterId = cmd.getClusterId(); | ||||
|         final Long storagepoolId = cmd.getStoragepoolId(); | ||||
|         final Long accountId = cmd.getAccountId(); | ||||
|         final Long domainId = cmd.getDomainId(); | ||||
|         final Long imageStoreId = cmd.getImageStoreId(); | ||||
|         Optional optionalValue; | ||||
|         final ConfigKey<?> configKey = _configDepot.get(name); | ||||
|         if (configKey == null) { | ||||
|             s_logger.warn("Probably the component manager where configuration variable " + name + " is defined needs to implement Configurable interface"); | ||||
|             throw new InvalidParameterValueException("Config parameter with name " + name + " doesn't exist"); | ||||
|         } | ||||
|         String defaultValue = configKey.defaultValue(); | ||||
|         String category = configKey.category(); | ||||
|         String configScope = configKey.scope().toString(); | ||||
| 
 | ||||
|         String scope = ""; | ||||
|         Map<String, Long> scopeMap = new LinkedHashMap<>(); | ||||
| 
 | ||||
|         Long id = null; | ||||
|         int paramCountCheck = 0; | ||||
| 
 | ||||
|         scopeMap.put(ConfigKey.Scope.Zone.toString(), zoneId); | ||||
|         scopeMap.put(ConfigKey.Scope.Cluster.toString(), clusterId); | ||||
|         scopeMap.put(ConfigKey.Scope.Domain.toString(), domainId); | ||||
|         scopeMap.put(ConfigKey.Scope.Account.toString(), accountId); | ||||
|         scopeMap.put(ConfigKey.Scope.StoragePool.toString(), storagepoolId); | ||||
|         scopeMap.put(ConfigKey.Scope.ImageStore.toString(), imageStoreId); | ||||
| 
 | ||||
|         ParamCountPair paramCountPair = getParamCount(scopeMap); | ||||
|         id = paramCountPair.getId(); | ||||
|         paramCountCheck = paramCountPair.getParamCount(); | ||||
|         scope = paramCountPair.getScope(); | ||||
| 
 | ||||
|         if (paramCountCheck > 1) { | ||||
|             throw new InvalidParameterValueException("cannot handle multiple IDs, provide only one ID corresponding to the scope"); | ||||
|         } | ||||
| 
 | ||||
|         if (scope != null && !scope.equals(ConfigKey.Scope.Global.toString()) && !configScope.contains(scope)) { | ||||
|             throw new InvalidParameterValueException("Invalid scope id provided for the parameter " + name); | ||||
|         } | ||||
| 
 | ||||
|         String newValue = null; | ||||
|         switch (ConfigKey.Scope.valueOf(scope)) { | ||||
|             case Zone: | ||||
|                 final DataCenterVO zone = _zoneDao.findById(id); | ||||
|                 if (zone == null) { | ||||
|                     throw new InvalidParameterValueException("unable to find zone by id " + id); | ||||
|                 } | ||||
|                 _dcDetailsDao.removeDetail(id, name); | ||||
|                 optionalValue = Optional.ofNullable(configKey.valueIn(id)); | ||||
|                 newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; | ||||
|                 break; | ||||
| 
 | ||||
|             case Cluster: | ||||
|                 final ClusterVO cluster = _clusterDao.findById(id); | ||||
|                 if (cluster == null) { | ||||
|                     throw new InvalidParameterValueException("unable to find cluster by id " + id); | ||||
|                 } | ||||
|                 ClusterDetailsVO clusterDetailsVO = _clusterDetailsDao.findDetail(id, name); | ||||
|                 newValue = configKey.value().toString(); | ||||
|                 if (name.equalsIgnoreCase("cpu.overprovisioning.factor") || name.equalsIgnoreCase("mem.overprovisioning.factor")) { | ||||
|                     _clusterDetailsDao.persist(id, name, newValue); | ||||
|                 } else if (clusterDetailsVO != null) { | ||||
|                     _clusterDetailsDao.remove(clusterDetailsVO.getId()); | ||||
|                 } | ||||
|                 optionalValue = Optional.ofNullable(configKey.valueIn(id)); | ||||
|                 newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; | ||||
|                 break; | ||||
| 
 | ||||
|             case StoragePool: | ||||
|                 final StoragePoolVO pool = _storagePoolDao.findById(id); | ||||
|                 if (pool == null) { | ||||
|                     throw new InvalidParameterValueException("unable to find storage pool by id " + id); | ||||
|                 } | ||||
|                 _storagePoolDetailsDao.removeDetail(id, name); | ||||
|                 optionalValue = Optional.ofNullable(configKey.valueIn(id)); | ||||
|                 newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; | ||||
|                 break; | ||||
| 
 | ||||
|             case Domain: | ||||
|                 final DomainVO domain = _domainDao.findById(id); | ||||
|                 if (domain == null) { | ||||
|                     throw new InvalidParameterValueException("unable to find domain by id " + id); | ||||
|                 } | ||||
|                 DomainDetailVO domainDetailVO = _domainDetailsDao.findDetail(id, name); | ||||
|                 if (domainDetailVO != null) { | ||||
|                     _domainDetailsDao.remove(domainDetailVO.getId()); | ||||
|                 } | ||||
|                 optionalValue = Optional.ofNullable(configKey.valueIn(id)); | ||||
|                 newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; | ||||
|                 break; | ||||
| 
 | ||||
|             case Account: | ||||
|                 final AccountVO account = _accountDao.findById(id); | ||||
|                 if (account == null) { | ||||
|                     throw new InvalidParameterValueException("unable to find account by id " + id); | ||||
|                 } | ||||
|                 AccountDetailVO accountDetailVO = _accountDetailsDao.findDetail(id, name); | ||||
|                 if (accountDetailVO != null) { | ||||
|                     _accountDetailsDao.remove(accountDetailVO.getId()); | ||||
|                 } | ||||
|                 optionalValue = Optional.ofNullable(configKey.valueIn(id)); | ||||
|                 newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; | ||||
|                 break; | ||||
| 
 | ||||
|             case ImageStore: | ||||
|                 final ImageStoreVO imageStoreVO = _imageStoreDao.findById(id); | ||||
|                 if (imageStoreVO == null) { | ||||
|                     throw new InvalidParameterValueException("unable to find the image store by id " + id); | ||||
|                 } | ||||
|                 ImageStoreDetailVO imageStoreDetailVO = _imageStoreDetailsDao.findDetail(id, name); | ||||
|                 if (imageStoreDetailVO != null) { | ||||
|                     _imageStoreDetailsDao.remove(imageStoreDetailVO.getId()); | ||||
|                 } | ||||
|                 optionalValue = Optional.ofNullable(configKey.valueIn(id)); | ||||
|                 newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; | ||||
|                 break; | ||||
| 
 | ||||
|             default: | ||||
|                 if (!_configDao.update(name, category, defaultValue)) { | ||||
|                     s_logger.error("Failed to reset configuration option, name: " + name + ", defaultValue:" + defaultValue); | ||||
|                     throw new CloudRuntimeException("Failed to reset configuration value. Please contact Cloud Support."); | ||||
|                 } | ||||
|                 optionalValue = Optional.ofNullable(configKey.value()); | ||||
|                 newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; | ||||
|         } | ||||
| 
 | ||||
|         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 validateConfigurationValue(final String name, String value, final String scope) { | ||||
| 
 | ||||
|         final ConfigurationVO cfg = _configDao.findByName(name); | ||||
| @ -7056,4 +7220,40 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati | ||||
|                 ENABLE_ACCOUNT_SETTINGS_FOR_DOMAIN, ENABLE_DOMAIN_SETTINGS_FOR_CHILD_DOMAIN | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     static class ParamCountPair { | ||||
|         private Long id; | ||||
|         private int paramCount; | ||||
|         private String scope; | ||||
| 
 | ||||
|         public ParamCountPair(Long id, int paramCount, String scope) { | ||||
|             this.id = id; | ||||
|             this.paramCount = paramCount; | ||||
|             this.scope = scope; | ||||
|         } | ||||
| 
 | ||||
|         public Long getId() { | ||||
|             return id; | ||||
|         } | ||||
| 
 | ||||
|         public void setId(Long id) { | ||||
|             this.id = id; | ||||
|         } | ||||
| 
 | ||||
|         public int getParamCount() { | ||||
|             return paramCount; | ||||
|         } | ||||
| 
 | ||||
|         public void setParamCount(int paramCount) { | ||||
|             this.paramCount = paramCount; | ||||
|         } | ||||
| 
 | ||||
|         public String getScope() { | ||||
|             return scope; | ||||
|         } | ||||
| 
 | ||||
|         public void setScope(String scope) { | ||||
|             this.scope = scope; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -74,6 +74,7 @@ import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.ListDeploymentPlannersCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; | ||||
| import org.apache.cloudstack.api.command.admin.direct.download.RevokeTemplateDirectDownloadCertificateCmd; | ||||
| @ -3009,6 +3010,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe | ||||
|         cmdList.add(ListHypervisorCapabilitiesCmd.class); | ||||
|         cmdList.add(UpdateCfgCmd.class); | ||||
|         cmdList.add(UpdateHypervisorCapabilitiesCmd.class); | ||||
|         cmdList.add(ResetCfgCmd.class); | ||||
|         cmdList.add(CreateDomainCmd.class); | ||||
|         cmdList.add(DeleteDomainCmd.class); | ||||
|         cmdList.add(ListDomainChildrenCmd.class); | ||||
|  | ||||
| @ -23,6 +23,7 @@ import java.util.Set; | ||||
| import javax.inject.Inject; | ||||
| import javax.naming.ConfigurationException; | ||||
| 
 | ||||
| import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd; | ||||
| import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; | ||||
| import org.apache.cloudstack.api.command.admin.network.CreateManagementNetworkIpRangeCmd; | ||||
| import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; | ||||
| @ -615,4 +616,10 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Pair<Configuration, String> resetConfiguration(ResetCfgCmd cmd) throws InvalidParameterValueException { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
							
								
								
									
										367
									
								
								test/integration/smoke/test_reset_configuration_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										367
									
								
								test/integration/smoke/test_reset_configuration_settings.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,367 @@ | ||||
| # Licensed to the Apache Software Foundation (ASF) under one | ||||
| # or more contributor license agreements.  See the NOTICE file | ||||
| # distributed with this work for additional information | ||||
| # regarding copyright ownership.  The ASF licenses this file | ||||
| # to you under the Apache License, Version 2.0 (the | ||||
| # "License"); you may not use this file except in compliance | ||||
| # with the License.  You may obtain a copy of the License at | ||||
| # | ||||
| #   http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, | ||||
| # software distributed under the License is distributed on an | ||||
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||
| # KIND, either express or implied.  See the License for the | ||||
| # specific language governing permissions and limitations | ||||
| # under the License. | ||||
| 
 | ||||
| # Import Local Modules | ||||
| from nose.plugins.attrib import attr | ||||
| from marvin.cloudstackTestCase import cloudstackTestCase, unittest | ||||
| from marvin.lib.utils import (validateList, | ||||
|                               cleanup_resources) | ||||
| from marvin.lib.base import (Account, | ||||
|                              Configurations, | ||||
|                              Domain, | ||||
|                              Cluster, | ||||
|                              StoragePool) | ||||
| from marvin.lib.common import (get_domain, | ||||
|                                get_zone) | ||||
| 
 | ||||
| class TestRestConfigurationSettings(cloudstackTestCase): | ||||
|     @classmethod | ||||
|     def setUpClass(self): | ||||
|         self.testClient = super( | ||||
|             TestRestConfigurationSettings, | ||||
|             self).getClsTestClient() | ||||
|         self.apiclient = self.testClient.getApiClient() | ||||
|         self.testdata = self.testClient.getParsedTestDataConfig() | ||||
| 
 | ||||
|         # Get Zone, Domain | ||||
|         self.domain = get_domain(self.apiclient) | ||||
|         self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) | ||||
|         self._cleanup = [] | ||||
|         return | ||||
| 
 | ||||
|     @classmethod | ||||
|     def tearDownClass(cls): | ||||
|         super(TestRestConfigurationSettings, cls).tearDownClass() | ||||
|         return | ||||
| 
 | ||||
|     def setUp(self): | ||||
|         self.apiclient = self.testClient.getApiClient() | ||||
|         self.dbclient = self.testClient.getDbConnection() | ||||
|         self.cleanup = [] | ||||
| 
 | ||||
|         return | ||||
| 
 | ||||
|     def tearDown(self): | ||||
|         super(TestRestConfigurationSettings, self).tearDown() | ||||
|         return | ||||
| 
 | ||||
|     @attr(tags=["advanced", "advancedsg"], required_hardware="false") | ||||
|     def test_01_test_settings_for_domain(self): | ||||
|         """ | ||||
|         1. Get the default value for the setting in domain scope | ||||
|         2. Change the default value to new value | ||||
|         3. Make sure updated value is same as new value | ||||
|         4. Reset the config value | ||||
|         5. Make sure that current value is same as default value | ||||
|         :return: | ||||
|         """ | ||||
|         config_name="ldap.basedn" | ||||
|         #1. Get default value | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name) | ||||
| 
 | ||||
|         orig_value = str(configs[0].value) | ||||
|         new_value = "testing" | ||||
| 
 | ||||
|         #2. Update to new value | ||||
|         Configurations.update( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             value=new_value, | ||||
|             domainid=self.domain.id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             domainid=self.domain.id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name) | ||||
| 
 | ||||
|         #3. validate they are same | ||||
|         self.assertEqual(new_value, | ||||
|                          str(configs[0].value), | ||||
|                          "Failed to set new config value") | ||||
| 
 | ||||
|         #4. Reset the value | ||||
|         Configurations.reset( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             domainid=self.domain.id | ||||
|         ) | ||||
| 
 | ||||
|         #5. Make sure its same as original value | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             domainid=self.domain.id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(orig_value, | ||||
|                          str(configs[0].value), | ||||
|                          "Failed to reset the value") | ||||
| 
 | ||||
|     @attr(tags=["advanced", "advancedsg"], required_hardware="false") | ||||
|     def test_02_test_settings_for_account(self): | ||||
|         """ | ||||
|         1. Get the default value for the setting in account scope | ||||
|         2. Change the default value to new value | ||||
|         3. Make sure updated value is same as new value | ||||
|         4. Reset the config value | ||||
|         5. Make sure that current value is same as default value | ||||
|         :return: | ||||
|         """ | ||||
|         accounts = Account.list( | ||||
|             self.apiclient, | ||||
|             domainid=self.domain.id, | ||||
|             listall=True | ||||
|         ) | ||||
| 
 | ||||
|         self.assertIsNotNone(accounts[0], | ||||
|                              "There should be atleast 1 account in the zone") | ||||
| 
 | ||||
|         config_name = "enable.additional.vm.configuration" | ||||
|         #1. Get the default value | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name) | ||||
| 
 | ||||
|         orig_value = str(configs[0].value) | ||||
|         new_value = "true" | ||||
| 
 | ||||
|         Configurations.update( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             value=new_value, | ||||
|             accountid=accounts[0].id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             accountid=accounts[0].id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(new_value, | ||||
|                          str(configs[0].value), | ||||
|                          "Failed to set new config value") | ||||
| 
 | ||||
|         Configurations.reset( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             accountid=accounts[0].id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             accountid=accounts[0].id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(orig_value, | ||||
|                          str(configs[0].value), | ||||
|                          "Failed to reset the value") | ||||
| 
 | ||||
|     @attr(tags=["advanced", "advancedsg"], required_hardware="false") | ||||
|     def test_03_test_settings_for_cluster(self): | ||||
|         """ | ||||
|         1. Get the default value for the setting in cluster scope | ||||
|         2. Change the default value to new value | ||||
|         3. Make sure updated value is same as new value | ||||
|         4. Reset the config value | ||||
|         5. Make sure that current value is same as default value | ||||
|         :return: | ||||
|         """ | ||||
|         cluster = Cluster.list( | ||||
|             self.apiclient | ||||
|         ) | ||||
| 
 | ||||
|         self.assertIsNotNone(cluster[0], | ||||
|                              "There should be atleast 1 cluster in the zone") | ||||
| 
 | ||||
|         config_name = "cluster.storage.operations.exclude" | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             clusterid=cluster[0].id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get cluster setting %s " % config_name) | ||||
| 
 | ||||
|         orig_value = str(configs[0].value) | ||||
|         new_value = "true" | ||||
| 
 | ||||
|         Configurations.update( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             value=new_value, | ||||
|             clusterid=cluster[0].id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             clusterid=cluster[0].id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get cluster setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(new_value, | ||||
|                          str(configs[0].value), | ||||
|                          "Failed to set new config value") | ||||
| 
 | ||||
|         Configurations.reset( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             clusterid=cluster[0].id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             clusterid=cluster[0].id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get cluster setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(orig_value, | ||||
|                          str(configs[0].value), | ||||
|                          "Failed to reset the value") | ||||
| 
 | ||||
|     @attr(tags=["advanced", "advancedsg"], required_hardware="false") | ||||
|     def test_04_test_settings_for_storage(self): | ||||
|         """ | ||||
|         1. Get the default value for the setting in storage scope | ||||
|         2. Change the default value to new value | ||||
|         3. Make sure updated value is same as new value | ||||
|         4. Reset the config value | ||||
|         5. Make sure that current value is same as default value | ||||
|         :return: | ||||
|         """ | ||||
|         storage = StoragePool.list( | ||||
|             self.apiclient | ||||
|         ) | ||||
| 
 | ||||
|         self.assertIsNotNone(storage[0], | ||||
|                              "There should be atleast 1 primary storage pool in the zone") | ||||
| 
 | ||||
|         config_name = "vmware.create.full.clone" | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             storageid=storage[0].id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get storage pool setting %s " % config_name) | ||||
| 
 | ||||
|         orig_value = str(configs[0].value) | ||||
|         new_value = 'false' | ||||
| 
 | ||||
|         Configurations.update( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             value=new_value, | ||||
|             storageid=storage[0].id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             storageid=storage[0].id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get storage pool setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(new_value, | ||||
|                          (configs[0].value), | ||||
|                          "Failed to set new config value") | ||||
| 
 | ||||
|         Configurations.reset( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             storageid=storage[0].id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             storage=storage[0].id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get storage pool setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(orig_value, | ||||
|                          (configs[0].value), | ||||
|                          "Failed to reset the value for storage pool") | ||||
| 
 | ||||
|     @attr(tags=["advanced", "advancedsg"], required_hardware="false") | ||||
|     def test_05_test_settings_for_zone(self): | ||||
|         """ | ||||
|         1. Get the default value for the setting in zone scope | ||||
|         2. Change the default value to new value | ||||
|         3. Make sure updated value is same as new value | ||||
|         4. Reset the config value | ||||
|         5. Make sure that current value is same as default value | ||||
|         :return: | ||||
|         """ | ||||
|         config_name = "enable.dynamic.scale.vm" | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             zoneid=self.zone.id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get zone setting %s " % config_name) | ||||
| 
 | ||||
|         orig_value = str(configs[0].value) | ||||
|         new_value = 'true' | ||||
| 
 | ||||
|         Configurations.update( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             value=new_value, | ||||
|             zoneid=self.zone.id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             zoneid=self.zone.id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get ol setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(new_value, | ||||
|                          (configs[0].value), | ||||
|                          "Failed to set new config value") | ||||
| 
 | ||||
|         Configurations.reset( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             zoneid=self.zone.id | ||||
|         ) | ||||
| 
 | ||||
|         configs = Configurations.list( | ||||
|             self.apiclient, | ||||
|             name=config_name, | ||||
|             zoneid=self.zone.id | ||||
|         ) | ||||
|         self.assertIsNotNone(configs, "Fail to get zone setting %s " % config_name) | ||||
| 
 | ||||
|         self.assertEqual(orig_value, | ||||
|                          (configs[0].value), | ||||
|                          "Failed to reset the value for zone") | ||||
| @ -4273,6 +4273,26 @@ class Configurations: | ||||
|         return (apiclient.listCapabilities(cmd)) | ||||
| 
 | ||||
| 
 | ||||
|     @classmethod | ||||
|     def reset(cls, apiclient, name, zoneid=None, clusterid=None, storageid=None, domainid=None, accountid=None): | ||||
|         """Resets the specified configuration to original value""" | ||||
| 
 | ||||
|         cmd = resetConfiguration.resetConfigurationCmd() | ||||
|         cmd.name = name | ||||
| 
 | ||||
|         if zoneid: | ||||
|             cmd.zoneid = zoneid | ||||
|         if clusterid: | ||||
|             cmd.clusterid = clusterid | ||||
|         if storageid: | ||||
|             cmd.storageid = storageid | ||||
|         if domainid: | ||||
|             cmd.domainid = domainid | ||||
|         if accountid: | ||||
|             cmd.accountid = accountid | ||||
| 
 | ||||
|         apiclient.resetConfiguration(cmd) | ||||
| 
 | ||||
| class NetScaler: | ||||
|     """Manage external netscaler device""" | ||||
| 
 | ||||
|  | ||||
| @ -1863,6 +1863,7 @@ | ||||
| "label.reservedsystemnetmask": "Reserved system netmask", | ||||
| "label.reservedsystemstartip": "Start Reserved system IP", | ||||
| "label.reset": "Reset", | ||||
| "label.reset.config.value": "Reset to default value", | ||||
| "label.reset.ssh.key.pair": "Reset SSH Key Pair", | ||||
| "label.reset.ssh.key.pair.on.vm": "Reset SSH Key Pair on VM", | ||||
| "label.reset.to.default": "Reset to default", | ||||
| @ -2943,6 +2944,7 @@ | ||||
| "message.error.rados.user": "Please enter RADOS User", | ||||
| "message.error.remove.nic": "There was an error", | ||||
| "message.error.remove.secondary.ipaddress": "There was an error removing the secondary IP Address", | ||||
| "message.error.reset.config": "Unable to reset config to default value", | ||||
| "message.error.required.input": "Please enter input", | ||||
| "message.error.retrieve.kubeconfig": "Unable to retrieve Kubernetes cluster config", | ||||
| "message.error.s3nfs.path": "Please enter S3 NFS Path", | ||||
|  | ||||
| @ -348,6 +348,12 @@ | ||||
|         v-if="editableValueKey === record.key" | ||||
|         iconType="check-circle" | ||||
|         iconTwoToneColor="#52c41a" /> | ||||
|       <tooltip-button | ||||
|         :tooltip="$t('label.reset.config.value')" | ||||
|         @click="resetConfig(record)" | ||||
|         v-if="editableValueKey !== record.key" | ||||
|         icon="reload" | ||||
|         :disabled="!('updateConfiguration' in $store.getters.apis)" /> | ||||
|     </template> | ||||
|     <template slot="tariffActions" slot-scope="text, record"> | ||||
|       <tooltip-button | ||||
| @ -526,6 +532,23 @@ export default { | ||||
|         this.$emit('refresh') | ||||
|       }) | ||||
|     }, | ||||
|     resetConfig (item) { | ||||
|       api('resetConfiguration', { | ||||
|         name: item.name | ||||
|       }).then(() => { | ||||
|         const message = `${this.$t('label.setting')} ${item.name} ${this.$t('label.reset.config.value')}` | ||||
|         this.$message.success(message) | ||||
|       }).catch(error => { | ||||
|         console.error(error) | ||||
|         this.$message.error(this.$t('message.error.reset.config')) | ||||
|         this.$notification.error({ | ||||
|           message: this.$t('label.error'), | ||||
|           description: this.$t('message.error.reset.config') | ||||
|         }) | ||||
|       }).finally(() => { | ||||
|         this.$emit('refresh') | ||||
|       }) | ||||
|     }, | ||||
|     editValue (record) { | ||||
|       this.editableValueKey = record.key | ||||
|       this.editableValue = record.value | ||||
|  | ||||
| @ -64,6 +64,12 @@ | ||||
|             v-if="editableValueKey === index" | ||||
|             iconType="check-circle" | ||||
|             iconTwoToneColor="#52c41a" /> | ||||
|           <tooltip-button | ||||
|             :tooltip="$t('label.reset.config.value')" | ||||
|             @click="resetConfig(item)" | ||||
|             v-if="editableValueKey !== index" | ||||
|             icon="reload" | ||||
|             :disabled="!('updateConfiguration' in $store.getters.apis)" /> | ||||
|         </div> | ||||
|       </a-list-item> | ||||
|     </a-list> | ||||
| @ -182,6 +188,28 @@ export default { | ||||
|     handleSearch (value) { | ||||
|       this.filter = value | ||||
|       this.fetchData() | ||||
|     }, | ||||
|     resetConfig (item) { | ||||
|       this.tabLoading = true | ||||
|       api('resetConfiguration', { | ||||
|         [this.scopeKey]: this.resource.id, | ||||
|         name: item.name | ||||
|       }).then(() => { | ||||
|         const message = `${this.$t('label.setting')} ${item.name} ${this.$t('label.reset.config.value')}` | ||||
|         this.$message.success(message) | ||||
|       }).catch(error => { | ||||
|         console.error(error) | ||||
|         this.$message.error(this.$t('message.error.reset.config')) | ||||
|         this.$notification.error({ | ||||
|           message: this.$t('label.error'), | ||||
|           description: this.$t('message.error.reset.config') | ||||
|         }) | ||||
|       }).finally(() => { | ||||
|         this.tabLoading = false | ||||
|         this.fetchData(() => { | ||||
|           this.editableValueKey = null | ||||
|         }) | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user