From 6bd4f625012ed98e3f85419642634f6d46d34387 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 4 Nov 2025 16:52:38 +0530 Subject: [PATCH 1/4] api,server: allow cleaning up vm extraconfig Fixes #9878 Signed-off-by: Abhishek Kumar --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../api/command/user/vm/UpdateVMCmd.java | 18 +++- .../cloud/vm/dao/VMInstanceDetailsDao.java | 1 + .../vm/dao/VMInstanceDetailsDaoImpl.java | 17 ++++ .../vm/dao/VMInstanceDetailsDaoImplTest.java | 86 +++++++++++++++++++ .../java/com/cloud/vm/UserVmManagerImpl.java | 28 ++++-- .../com/cloud/vm/UserVmManagerImplTest.java | 60 +++++++++++++ 7 files changed, 198 insertions(+), 13 deletions(-) create mode 100644 engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDetailsDaoImplTest.java diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 8fca652518f2..955193f6262f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -1165,6 +1165,7 @@ public class ApiConstants { public static final String OVM3_VIP = "ovm3vip"; public static final String CLEAN_UP_DETAILS = "cleanupdetails"; public static final String CLEAN_UP_EXTERNAL_DETAILS = "cleanupexternaldetails"; + public static final String CLEAN_UP_EXTRA_CONFIG = "cleanupextraconfig"; public static final String CLEAN_UP_PARAMETERS = "cleanupparameters"; public static final String VIRTUAL_SIZE = "virtualsize"; public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java index 7906ec632a49..b2032550f456 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java @@ -163,6 +163,12 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction, description = "Lease expiry action, valid values are STOP and DESTROY") private String leaseExpiryAction; + @Parameter(name = ApiConstants.CLEAN_UP_EXTRA_CONFIG, type = CommandType.BOOLEAN, since = "4.23.0", + description = "Optional boolean field, which indicates if extraconfig for the instance should be " + + "cleaned up or not (If set to true, extraconfig removed for this instance, extraconfig field " + + "ignored; if false or not set, no action)") + private Boolean cleanupExtraConfig; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -271,14 +277,18 @@ public String getExtraConfig() { return extraConfig; } - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - public Long getOsTypeId() { return osTypeId; } + public boolean isCleanupExtraConfig() { + return Boolean.TRUE.equals(cleanupExtraConfig); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override public String getCommandName() { return s_name; diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDetailsDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDetailsDao.java index ea9ac5afba67..4cbdc516ba0b 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDetailsDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDetailsDao.java @@ -22,4 +22,5 @@ import com.cloud.vm.VMInstanceDetailVO; public interface VMInstanceDetailsDao extends GenericDao, ResourceDetailsDao { + int removeDetailsWithPrefix(long vmId, String prefix); } diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDetailsDaoImpl.java index ca11b005fb2b..4c2fdd6f8d45 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDetailsDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDetailsDaoImpl.java @@ -17,10 +17,13 @@ package com.cloud.vm.dao; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; import com.cloud.vm.VMInstanceDetailVO; @Component @@ -31,4 +34,18 @@ public void addDetail(long resourceId, String key, String value, boolean display super.addDetail(new VMInstanceDetailVO(resourceId, key, value, display)); } + @Override + public int removeDetailsWithPrefix(long vmId, String prefix) { + if (StringUtils.isBlank(prefix)) { + return 0; + } + SearchBuilder sb = createSearchBuilder(); + sb.and("vmId", sb.entity().getResourceId(), SearchCriteria.Op.EQ); + sb.and("prefix", sb.entity().getName(), SearchCriteria.Op.LIKE); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("vmId", vmId); + sc.setParameters("prefix", prefix + "%"); + return super.remove(sc); + } } diff --git a/engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDetailsDaoImplTest.java b/engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDetailsDaoImplTest.java new file mode 100644 index 000000000000..06238e386d5e --- /dev/null +++ b/engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDetailsDaoImplTest.java @@ -0,0 +1,86 @@ +// 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 com.cloud.vm.dao; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.vm.VMInstanceDetailVO; + +@RunWith(MockitoJUnitRunner.class) +public class VMInstanceDetailsDaoImplTest { + @Spy + @InjectMocks + private VMInstanceDetailsDaoImpl vmInstanceDetailsDaoImpl; + + @Test + public void removeDetailsWithPrefixReturnsZeroWhenPrefixIsBlank() { + Assert.assertEquals(0, vmInstanceDetailsDaoImpl.removeDetailsWithPrefix(1L, "")); + Assert.assertEquals(0, vmInstanceDetailsDaoImpl.removeDetailsWithPrefix(1L, " ")); + Assert.assertEquals(0, vmInstanceDetailsDaoImpl.removeDetailsWithPrefix(1L, null)); + } + + @Test + public void removeDetailsWithPrefixRemovesMatchingDetails() { + SearchBuilder sb = mock(SearchBuilder.class); + VMInstanceDetailVO entity = mock(VMInstanceDetailVO.class); + when(sb.entity()).thenReturn(entity); + when(sb.and(anyString(), any(), any(SearchCriteria.Op.class))).thenReturn(sb); + SearchCriteria sc = mock(SearchCriteria.class); + when(sb.create()).thenReturn(sc); + when(vmInstanceDetailsDaoImpl.createSearchBuilder()).thenReturn(sb); + doReturn(3).when(vmInstanceDetailsDaoImpl).remove(sc); + int removedCount = vmInstanceDetailsDaoImpl.removeDetailsWithPrefix(1L, "testPrefix"); + Assert.assertEquals(3, removedCount); + Mockito.verify(sc).setParameters("vmId", 1L); + Mockito.verify(sc).setParameters("prefix", "testPrefix%"); + Mockito.verify(vmInstanceDetailsDaoImpl, Mockito.times(1)).remove(sc); + } + + @Test + public void removeDetailsWithPrefixDoesNotRemoveWhenNoMatch() { + SearchBuilder sb = mock(SearchBuilder.class); + VMInstanceDetailVO entity = mock(VMInstanceDetailVO.class); + when(sb.entity()).thenReturn(entity); + when(sb.and(anyString(), any(), any(SearchCriteria.Op.class))).thenReturn(sb); + SearchCriteria sc = mock(SearchCriteria.class); + when(sb.create()).thenReturn(sc); + when(vmInstanceDetailsDaoImpl.createSearchBuilder()).thenReturn(sb); + doReturn(0).when(vmInstanceDetailsDaoImpl).remove(sc); + + int removedCount = vmInstanceDetailsDaoImpl.removeDetailsWithPrefix(1L, "nonExistentPrefix"); + + Assert.assertEquals(0, removedCount); + Mockito.verify(sc).setParameters("vmId", 1L); + Mockito.verify(sc).setParameters("prefix", "nonExistentPrefix%"); + Mockito.verify(vmInstanceDetailsDaoImpl, Mockito.times(1)).remove(sc); + } +} diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 96c87c5376d8..71f33255072d 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -2864,6 +2864,22 @@ private void adjustVmLimits(Account owner, UserVmVO vmInstance, ServiceOfferingV } } + protected void updateVmExtraConfig(UserVmVO userVm, String extraConfig, boolean cleanupExtraConfig) { + if (cleanupExtraConfig) { + logger.info("Cleaning up extraconfig from user vm: {}", userVm.getUuid()); + vmInstanceDetailsDao.removeDetailsWithPrefix(userVm.getId(), ApiConstants.EXTRA_CONFIG); + return; + } + if (StringUtils.isNotBlank(extraConfig)) { + if (EnableAdditionalVmConfig.valueIn(userVm.getAccountId())) { + logger.info("Adding extra configuration to user vm: {}", userVm.getUuid()); + addExtraConfig(userVm, extraConfig); + } else { + throw new InvalidParameterValueException("attempted setting extraconfig but enable.additional.vm.configuration is disabled"); + } + } + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VM_UPDATE, eventDescription = "updating Vm") public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException { @@ -2881,6 +2897,7 @@ public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableEx List securityGroupIdList = getSecurityGroupIdList(cmd); boolean cleanupDetails = cmd.isCleanupDetails(); String extraConfig = cmd.getExtraConfig(); + boolean cleanupExtraConfig = cmd.isCleanupExtraConfig(); UserVmVO vmInstance = _vmDao.findById(cmd.getId()); VMTemplateVO template = _templateDao.findById(vmInstance.getTemplateId()); @@ -2917,7 +2934,7 @@ public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableEx .map(item -> (item).trim()) .collect(Collectors.toList()); List existingDetails = vmInstanceDetailsDao.listDetails(id); - if (cleanupDetails){ + if (cleanupDetails) { if (caller != null && caller.getType() == Account.Type.ADMIN) { for (final VMInstanceDetailVO detail : existingDetails) { if (detail != null && detail.isDisplay() && !isExtraConfig(detail.getName())) { @@ -2980,14 +2997,7 @@ public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableEx vmInstance.setDetails(details); _vmDao.saveDetails(vmInstance); } - if (StringUtils.isNotBlank(extraConfig)) { - if (EnableAdditionalVmConfig.valueIn(accountId)) { - logger.info("Adding extra configuration to user vm: " + vmInstance.getUuid()); - addExtraConfig(vmInstance, extraConfig); - } else { - throw new InvalidParameterValueException("attempted setting extraconfig but enable.additional.vm.configuration is disabled"); - } - } + updateVmExtraConfig(userVm, extraConfig, cleanupExtraConfig); } if (VMLeaseManager.InstanceLeaseEnabled.value() && cmd.getLeaseDuration() != null) { diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java index a21477aeb80e..a4092ec68aee 100644 --- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java +++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java @@ -40,8 +40,10 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import java.lang.reflect.Field; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.ZoneOffset; @@ -87,6 +89,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.Scope; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.template.VnfTemplateManager; @@ -466,6 +469,18 @@ public class UserVmManagerImplTest { Class expectedInvalidParameterValueException = InvalidParameterValueException.class; Class expectedCloudRuntimeException = CloudRuntimeException.class; + + private void overrideDefaultConfigValue(final ConfigKey configKey, final Object o) { + try { + final String name = "_defaultValue"; + Field f = ConfigKey.class.getDeclaredField(name); + f.setAccessible(true); + f.set(configKey, String.valueOf(o)); + } catch (IllegalAccessException | NoSuchFieldException e) { + Assert.fail("Failed to mock config " + configKey.key() + " value due to " + e.getMessage()); + } + } + @Before public void beforeTest() { userVmManagerImpl.resourceLimitService = resourceLimitMgr; @@ -4175,4 +4190,49 @@ public void testUnmanageUserVMSuccess() { verify(userVmDao, times(1)).releaseFromLockTable(vmId); } + @Test + public void updateVmExtraConfigCleansUpWhenCleanupFlagIsTrue() { + UserVmVO userVm = mock(UserVmVO.class); + when(userVm.getUuid()).thenReturn("test-uuid"); + when(userVm.getId()).thenReturn(1L); + + userVmManagerImpl.updateVmExtraConfig(userVm, "someConfig", true); + + verify(vmInstanceDetailsDao, times(1)).removeDetailsWithPrefix(1L, ApiConstants.EXTRA_CONFIG); + verifyNoMoreInteractions(vmInstanceDetailsDao); + } + + @Test + public void updateVmExtraConfigAddsConfigWhenValidAndEnabled() { + UserVmVO userVm = mock(UserVmVO.class); + when(userVm.getUuid()).thenReturn("test-uuid"); + when(userVm.getAccountId()).thenReturn(1L); + when(userVm.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + doNothing().when(userVmManagerImpl).persistExtraConfigKvm(anyString(), eq(userVm)); + overrideDefaultConfigValue(UserVmManagerImpl.EnableAdditionalVmConfig, true); + + userVmManagerImpl.updateVmExtraConfig(userVm, "validConfig", false); + + verify(vmInstanceDetailsDao, never()).removeDetailsWithPrefix(anyLong(), anyString()); + verify(userVmManagerImpl, times(1)).addExtraConfig(userVm, "validConfig"); + } + + @Test(expected = InvalidParameterValueException.class) + public void updateVmExtraConfigThrowsExceptionWhenConfigDisabled() { + UserVmVO userVm = mock(UserVmVO.class); + when(userVm.getAccountId()).thenReturn(1L); + overrideDefaultConfigValue(UserVmManagerImpl.EnableAdditionalVmConfig, false); + + userVmManagerImpl.updateVmExtraConfig(userVm, "validConfig", false); + } + + @Test + public void updateVmExtraConfigDoesNothingWhenExtraConfigIsBlank() { + UserVmVO userVm = mock(UserVmVO.class); + + userVmManagerImpl.updateVmExtraConfig(userVm, "", false); + + verify(vmInstanceDetailsDao, never()).removeDetailsWithPrefix(anyLong(), anyString()); + verify(userVmManagerImpl, never()).addExtraConfig(any(UserVmVO.class), anyString()); + } } From 37936883fd396b6e8f8241fdafda50e63968e786 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 1 Dec 2025 12:15:36 +0530 Subject: [PATCH 2/4] ui change Signed-off-by: Abhishek Kumar --- ui/src/views/compute/EditVM.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/src/views/compute/EditVM.vue b/ui/src/views/compute/EditVM.vue index 0763303b24a4..e5a48da42a1f 100644 --- a/ui/src/views/compute/EditVM.vue +++ b/ui/src/views/compute/EditVM.vue @@ -425,6 +425,8 @@ export default { } if (values.extraconfig && values.extraconfig.length > 0) { params.extraconfig = encodeURIComponent(values.extraconfig) + } else if (this.combinedExtraConfig) { + params.cleanupextraconfig = true } this.loading = true From b24f8cc994e7e848c1b56d675a1fc816250e7b2e Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 9 Dec 2025 15:12:02 +0530 Subject: [PATCH 3/4] update Signed-off-by: Abhishek Kumar --- .../com/cloud/vm/UserVmManagerImplTest.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java index 2e0c194b121e..cdb56d59c6a3 100644 --- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java +++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java @@ -61,7 +61,6 @@ import java.util.TimeZone; import java.util.UUID; -import com.cloud.storage.dao.SnapshotPolicyDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -144,9 +143,9 @@ import com.cloud.network.dao.LoadBalancerVMMapVO; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; -import com.cloud.network.element.UserDataServiceProvider; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.element.UserDataServiceProvider; import com.cloud.network.guru.NetworkGuru; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.PortForwardingRule; @@ -174,6 +173,7 @@ import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.SnapshotDao; +import com.cloud.storage.dao.SnapshotPolicyDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.template.VirtualMachineTemplate; @@ -469,13 +469,20 @@ public class UserVmManagerImplTest { Class expectedInvalidParameterValueException = InvalidParameterValueException.class; Class expectedCloudRuntimeException = CloudRuntimeException.class; + private Map originalConfigValues = new HashMap<>(); - private void overrideDefaultConfigValue(final ConfigKey configKey, final Object o) { + + private void updateDefaultConfigValue(final ConfigKey configKey, final Object o, boolean revert) { try { final String name = "_defaultValue"; Field f = ConfigKey.class.getDeclaredField(name); f.setAccessible(true); - f.set(configKey, String.valueOf(o)); + String stringVal = String.valueOf(o); + f.set(configKey, stringVal); + if (revert) { + return; + } + originalConfigValues.put(configKey, f.get(configKey)); } catch (IllegalAccessException | NoSuchFieldException e) { Assert.fail("Failed to mock config " + configKey.key() + " value due to " + e.getMessage()); } @@ -510,6 +517,9 @@ public void beforeTest() { public void afterTest() { CallContext.unregister(); unmanagedVMsManagerMockedStatic.close(); + for (Map.Entry entry : originalConfigValues.entrySet()) { + updateDefaultConfigValue(entry.getKey(), entry.getValue(), true); + } } @Test @@ -4211,7 +4221,7 @@ public void updateVmExtraConfigAddsConfigWhenValidAndEnabled() { when(userVm.getAccountId()).thenReturn(1L); when(userVm.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); doNothing().when(userVmManagerImpl).persistExtraConfigKvm(anyString(), eq(userVm)); - overrideDefaultConfigValue(UserVmManagerImpl.EnableAdditionalVmConfig, true); + updateDefaultConfigValue(UserVmManagerImpl.EnableAdditionalVmConfig, true, false); userVmManagerImpl.updateVmExtraConfig(userVm, "validConfig", false); @@ -4223,7 +4233,7 @@ public void updateVmExtraConfigAddsConfigWhenValidAndEnabled() { public void updateVmExtraConfigThrowsExceptionWhenConfigDisabled() { UserVmVO userVm = mock(UserVmVO.class); when(userVm.getAccountId()).thenReturn(1L); - overrideDefaultConfigValue(UserVmManagerImpl.EnableAdditionalVmConfig, false); + updateDefaultConfigValue(UserVmManagerImpl.EnableAdditionalVmConfig, false, false); userVmManagerImpl.updateVmExtraConfig(userVm, "validConfig", false); } From 189f291bb47d7348fda53ff4c39174a469793acd Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 9 Dec 2025 15:13:29 +0530 Subject: [PATCH 4/4] change --- .../src/test/java/com/cloud/vm/UserVmManagerImplTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java index cdb56d59c6a3..07ef02f6136c 100644 --- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java +++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java @@ -478,11 +478,10 @@ private void updateDefaultConfigValue(final ConfigKey configKey, final Object o, Field f = ConfigKey.class.getDeclaredField(name); f.setAccessible(true); String stringVal = String.valueOf(o); - f.set(configKey, stringVal); - if (revert) { - return; + if (!revert) { + originalConfigValues.put(configKey, f.get(configKey)); } - originalConfigValues.put(configKey, f.get(configKey)); + f.set(configKey, stringVal); } catch (IllegalAccessException | NoSuchFieldException e) { Assert.fail("Failed to mock config " + configKey.key() + " value due to " + e.getMessage()); }