From b6fbdc37ef3c4bed6403d7644ae685e4ce9abe4c Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 9 Mar 2026 12:42:43 -0300 Subject: [PATCH] Fix LB rule creation on different tier in not on VPC with conserve mode enabled --- .../com/cloud/network/vpc/VpcManager.java | 5 ++++ .../network/firewall/FirewallManagerImpl.java | 18 ++------------- .../lb/LoadBalancingRulesManagerImpl.java | 15 +++++++++++- .../com/cloud/network/vpc/VpcManagerImpl.java | 14 +++++++++++ .../cloud/network/vpc/VpcManagerImplTest.java | 23 +++++++++++++++++++ 5 files changed, 58 insertions(+), 17 deletions(-) diff --git a/engine/components-api/src/main/java/com/cloud/network/vpc/VpcManager.java b/engine/components-api/src/main/java/com/cloud/network/vpc/VpcManager.java index e7f41d079a7..792a3a6b397 100644 --- a/engine/components-api/src/main/java/com/cloud/network/vpc/VpcManager.java +++ b/engine/components-api/src/main/java/com/cloud/network/vpc/VpcManager.java @@ -211,4 +211,9 @@ public interface VpcManager { void reconfigStaticNatForVpcVr(Long vpcId); boolean applyStaticRouteForVpcVpnIfNeeded(Long vpcId, boolean updateAllVpn) throws ResourceUnavailableException; + + /** + * Returns true if the network is part of a VPC, and the VPC is created from conserve mode enabled VPC offering + */ + boolean isNetworkOnVpcEnabledConserveMode(Network network); } diff --git a/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java index 5bfe8ba5de9..b388b193df5 100644 --- a/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java @@ -31,7 +31,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcOfferingVO; import com.cloud.network.vpc.dao.VpcOfferingDao; import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Component; @@ -401,8 +400,8 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService, } NetworkVO newRuleNetwork = getNewRuleNetwork(newRule); - boolean newRuleIsOnVpcNetwork = isNewRuleOnVpcNetwork(newRuleNetwork); - boolean vpcConserveModeEnabled = isVpcConserveModeEnabled(newRuleNetwork); + boolean newRuleIsOnVpcNetwork = newRuleNetwork.getVpcId() != null; + boolean vpcConserveModeEnabled = _vpcMgr.isNetworkOnVpcEnabledConserveMode(newRuleNetwork); for (FirewallRuleVO rule : rules) { if (rule.getId() == newRule.getId()) { @@ -509,19 +508,6 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService, } } - protected boolean isVpcConserveModeEnabled(NetworkVO newRuleNetwork) { - if (isNewRuleOnVpcNetwork(newRuleNetwork)) { - Vpc vpc = _vpcMgr.getActiveVpc(newRuleNetwork.getVpcId()); - VpcOfferingVO vpcOffering = vpc != null ? vpcOfferingDao.findById(vpc.getVpcOfferingId()) : null; - return vpcOffering != null && vpcOffering.isConserveMode(); - } - return false; - } - - protected boolean isNewRuleOnVpcNetwork(NetworkVO newRuleNetwork) { - return newRuleNetwork.getVpcId() != null; - } - protected NetworkVO getNewRuleNetwork(FirewallRule newRule) { NetworkVO newRuleNetwork = _networkDao.findById(newRule.getNetworkId()); if (newRuleNetwork == null) { diff --git a/server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 4b7e79ddebd..fa82e8106b2 100644 --- a/server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -1738,6 +1738,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements throw new NetworkRuleConflictException("Can't do load balance on IP address: " + ipVO.getAddress()); } + verifyLoadBalancerRuleNetwork(name, network, ipVO); + String cidrString = generateCidrString(cidrList); boolean performedIpAssoc = false; @@ -1790,7 +1792,18 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements return result; } - /** + + protected void verifyLoadBalancerRuleNetwork(String lbName, Network network, IPAddressVO ipVO) { + boolean isVpcConserveModeEnabled = _vpcMgr.isNetworkOnVpcEnabledConserveMode(network); + if (!isVpcConserveModeEnabled && ipVO.getAssociatedWithNetworkId() != null && network.getId() != ipVO.getAssociatedWithNetworkId()) { + String msg = String.format("Cannot create Load Balancer rule %s as the IP address %s is not associated " + + "with the network %s (ID=%s)", lbName, ipVO.getAddress(), network.getName(), network.getUuid()); + logger.error(msg); + throw new InvalidParameterValueException(msg); + } + } + + /** * Transforms the cidrList from a List of Strings to a String which contains all the CIDRs from cidrList separated by whitespaces. This is used to facilitate both the persistence * in the DB and also later when building the configuration String in the getRulesForPool method of the HAProxyConfigurator class. */ diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java index 3f9a29556e2..87b7dfe34cb 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -2956,6 +2956,20 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis return true; } + protected boolean isNetworkOnVpc(Network network) { + return network.getVpcId() != null; + } + + @Override + public boolean isNetworkOnVpcEnabledConserveMode(Network newRuleNetwork) { + if (isNetworkOnVpc(newRuleNetwork)) { + Vpc vpc = getActiveVpc(newRuleNetwork.getVpcId()); + VpcOfferingVO vpcOffering = vpc != null ? _vpcOffDao.findById(vpc.getVpcOfferingId()) : null; + return vpcOffering != null && vpcOffering.isConserveMode(); + } + return false; + } + protected boolean applyStaticRoutes(final List routes, final Account caller, final boolean updateRoutesInDB) throws ResourceUnavailableException { final boolean success = true; final List staticRouteProfiles = getVpcStaticRoutes(routes); diff --git a/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java b/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java index 4f92c60e25a..ff34d72c218 100644 --- a/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java +++ b/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java @@ -581,4 +581,27 @@ public class VpcManagerImplTest { Assert.assertThrows(InvalidParameterValueException.class, () -> manager.validateVpcPrivateGatewayAclId(vpcId, differentVpcAclId)); } + @Test + public void testIsNetworkOnVpcEnabledConserveModeIsolatedNetwork() { + Network network = mock(Network.class); + Mockito.when(network.getVpcId()).thenReturn(null); + Assert.assertFalse(manager.isNetworkOnVpcEnabledConserveMode(network)); + } + + @Test + public void testIsNetworkOnVpcEnabledConserveModeVpcNetworkConserveMode() { + Network network = mock(Network.class); + Vpc vpc = mock(Vpc.class); + VpcOfferingVO vpcOffering = mock(VpcOfferingVO.class); + long vpcId = 10L; + long vpcOfferingId = 11L; + + Mockito.when(network.getVpcId()).thenReturn(vpcId); + Mockito.when(vpcDao.getActiveVpcById(Mockito.eq(vpcId))).thenReturn(vpc); + Mockito.when(vpc.getVpcOfferingId()).thenReturn(vpcOfferingId); + Mockito.when(vpcOfferingDao.findById(Mockito.eq(vpcOfferingId))).thenReturn(vpcOffering); + Mockito.when(vpcOffering.isConserveMode()).thenReturn(true); + Assert.assertTrue(manager.isNetworkOnVpcEnabledConserveMode(network)); + } + }