From 4df32ae79fb21e9f11df5c1235bc504a8e284ae7 Mon Sep 17 00:00:00 2001 From: Daniil Zhyliaiev Date: Mon, 6 Apr 2026 21:50:17 +0300 Subject: [PATCH 1/4] fix: NsxResource.executeRequest DeleteNsxNatRuleCommand comparison bug (#12833) Fixes an issue in NsxResource.executeRequest where Network.Service comparison failed when DeleteNsxNatRuleCommand was executed in a different process. Due to serialization/deserialization, the deserialized Network.Service instance was not equal to the static instances Network.Service.StaticNat and Network.Service.PortForwarding, causing the comparison to always return false. Co-authored-by: Andrey Volchkov (cherry picked from commit 30dd234b000845706c7f79f44ed498fd4eab01f2) --- .../cloudstack/agent/api/DeleteNsxNatRuleCommand.java | 7 +++++++ .../java/org/apache/cloudstack/resource/NsxResource.java | 6 +++--- .../org/apache/cloudstack/resource/NsxResourceTest.java | 6 ++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxNatRuleCommand.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxNatRuleCommand.java index c5231b19ac4..b642df85618 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxNatRuleCommand.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxNatRuleCommand.java @@ -54,6 +54,13 @@ public class DeleteNsxNatRuleCommand extends NsxNetworkCommand { return protocol; } + public String getNetworkServiceName() { + if (service != null) { + return service.getName(); + } + return null; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java index 76815b0deeb..78a9363a5e4 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java @@ -415,10 +415,10 @@ public class NsxResource implements ServerResource { private NsxAnswer executeRequest(DeleteNsxNatRuleCommand cmd) { String ruleName = null; - if (cmd.getService() == Network.Service.StaticNat) { + if (Network.Service.StaticNat.getName().equals(cmd.getNetworkServiceName())) { ruleName = NsxControllerUtils.getStaticNatRuleName(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(), cmd.getNetworkResourceId(), cmd.isResourceVpc()); - } else if (cmd.getService() == Network.Service.PortForwarding) { + } else if (Network.Service.PortForwarding.getName().equals(cmd.getNetworkServiceName())) { ruleName = NsxControllerUtils.getPortForwardRuleName(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(), cmd.getNetworkResourceId(), cmd.getRuleId(), cmd.isResourceVpc()); } @@ -456,7 +456,7 @@ public class NsxResource implements ServerResource { try { nsxApiClient.deleteNsxLbResources(tier1GatewayName, cmd.getLbId()); } catch (Exception e) { - logger.error(String.format("Failed to add NSX load balancer rule %s for network: %s", ruleName, cmd.getNetworkResourceName())); + logger.error(String.format("Failed to delete NSX load balancer rule %s for network: %s", ruleName, cmd.getNetworkResourceName())); return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage())); } return new NsxAnswer(cmd, true, null); diff --git a/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/resource/NsxResourceTest.java b/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/resource/NsxResourceTest.java index ee4f4fb64c2..0d74bb8a3b3 100644 --- a/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/resource/NsxResourceTest.java +++ b/plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/resource/NsxResourceTest.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.resource; +import com.cloud.network.Network; import com.cloud.network.dao.NetworkVO; import com.cloud.utils.exception.CloudRuntimeException; import com.vmware.nsx.model.TransportZone; @@ -61,6 +62,7 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -247,8 +249,12 @@ public class NsxResourceTest { @Test public void testDeleteNsxNatRule() { DeleteNsxNatRuleCommand cmd = new DeleteNsxNatRuleCommand(domainId, accountId, zoneId, 3L, "VPC01", true, 2L, 5L, "22", "tcp"); + Network.Service service = mock(Network.Service.class); + when(service.getName()).thenReturn("PortForwarding"); + cmd.setService(service); NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(cmd); assertTrue(answer.getResult()); + verify(nsxApi).deleteNatRule(service, "22", "tcp", "VPC01", "D1-A2-Z1-V3", "D1-A2-Z1-V3-PF5"); } @Test From 6c1437b7ddd8fc590c96d1aac6f8df7709ac4625 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 17 Apr 2026 13:56:17 +0200 Subject: [PATCH 2/4] fix end of file schema-42200to42210.sql --- .../src/main/resources/META-INF/db/schema-42200to42210.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42200to42210.sql b/engine/schema/src/main/resources/META-INF/db/schema-42200to42210.sql index 0300e555463..baa20e9f0ad 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42200to42210.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42200to42210.sql @@ -59,4 +59,3 @@ UPDATE `cloud`.`configuration` SET value = CONCAT_WS('\n', 'Hello {{username}}!', 'You have requested to reset your password. Please click the following link to reset your password:', '{{{resetLink}}}', 'If you did not request a password reset, please ignore this email.', '', 'Regards,', 'The CloudStack Team') WHERE name = 'user.password.reset.mail.template' AND value IN (CONCAT_WS('\n', 'Hello {{username}}!', 'You have requested to reset your password. Please click the following link to reset your password:', 'http://{{{resetLink}}}', 'If you did not request a password reset, please ignore this email.', '', 'Regards,', 'The CloudStack Team'), CONCAT_WS('\n', 'Hello {{username}}!', 'You have requested to reset your password. Please click the following link to reset your password:', '{{{domainUrl}}}{{{resetLink}}}', 'If you did not request a password reset, please ignore this email.', '', 'Regards,', 'The CloudStack Team')); - From be89e6f7c3784672cd0a9f8d0a0101c670162dd2 Mon Sep 17 00:00:00 2001 From: Nicolas Vazquez Date: Fri, 17 Apr 2026 23:39:19 -0300 Subject: [PATCH 3/4] [KVM] Reorder migration logs to prevent populating agent logs on migrations (#12883) * Move logs for values of the migration settings out of the loop * Apply suggestions from code review Co-authored-by: Suresh Kumar Anaparti --------- Co-authored-by: Suresh Kumar Anaparti --- .../resource/wrapper/LibvirtMigrateCommandWrapper.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java index 43607edc53a..f54918bbc22 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java @@ -259,6 +259,12 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper 0 && sleeptime > migrateWait * 1000) { DomainState state = null; try { @@ -306,8 +310,6 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper 0 && sleeptime > migratePauseAfter) { DomainState state = null; try { From 64ac0822b439d71796108f0f41485b61e3b8b395 Mon Sep 17 00:00:00 2001 From: dahn Date: Thu, 23 Apr 2026 19:16:54 +0100 Subject: [PATCH 4/4] merge conflict fixes (#13046) * merge conflict fixes * fix pre-commit issue Co-authored-by: Daan Hoogland Co-authored-by: Suresh Kumar Anaparti --- agent/conf/agent.properties | 1 - .../wrapper/LibvirtConvertInstanceCommandWrapper.java | 2 +- .../apache/cloudstack/vm/UnmanagedVMsManagerImpl.java | 10 ++-------- .../cloudstack/vm/UnmanagedVMsManagerImplTest.java | 1 - 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index 013c2e5bf2a..ba4a3874664 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -472,4 +472,3 @@ iscsi.session.cleanup.enabled=false # Optional vCenter SHA1 thumbprint for VMware to KVM conversion via VDDK, passed as # -io vddk-thumbprint=. If unset, CloudStack computes it on the KVM host via openssl. #vddk.thumbprint= - diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java index eaa8b790439..f28b5eda4a6 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java @@ -107,7 +107,7 @@ public class LibvirtConvertInstanceCommandWrapper extends CommandWrapper managedVms = new ArrayList<>(additionalNameFilters); managedVms.addAll(getHostsManagedVms(hosts)); - List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); - try (CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); - CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, Long.valueOf(serviceOffering.getCpu()), reservationDao, resourceLimitService); - CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, Long.valueOf(serviceOffering.getRamSize()), reservationDao, resourceLimitService)) { + try { ActionEventUtils.onStartedActionEvent(userId, owner.getId(), EventTypes.EVENT_VM_IMPORT, cmd.getEventDescription(), null, null, true, 0); @@ -2673,10 +2670,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { UserVm userVm = null; - List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); - try (CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); - CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, Long.valueOf(serviceOffering.getCpu()), reservationDao, resourceLimitService); - CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, Long.valueOf(serviceOffering.getRamSize()), reservationDao, resourceLimitService)) { + try { if (ImportSource.EXTERNAL == importSource) { String username = cmd.getUsername(); diff --git a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java index 9655b797ae9..874bce0f95e 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java @@ -260,7 +260,6 @@ public class UnmanagedVMsManagerImplTest { ImportVMTaskVO importVMTaskVO; @Mock private VMInstanceDetailsDao vmInstanceDetailsDao; - @Mock private ConfigKey configKeyMockParamsAllowed; @Mock