mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	CLOUDSTACK-9922 Unable to use 8081 port for Load balancing
This commit is contained in:
		
						commit
						f66bbb9521
					
				| @ -57,7 +57,7 @@ import com.cloud.offering.NetworkOffering; | ||||
| import com.cloud.projects.Project; | ||||
| import com.cloud.user.Account; | ||||
| 
 | ||||
| @APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted, | ||||
| @APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account. Either of the parameters are required, i.e. either zoneId, or networkId, or vpcId  ", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted, | ||||
|         requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) | ||||
| public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { | ||||
|     public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmd.class.getName()); | ||||
|  | ||||
| @ -26,6 +26,8 @@ import java.util.Set; | ||||
| 
 | ||||
| import javax.inject.Inject; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.beans.factory.annotation.Qualifier; | ||||
| import org.apache.log4j.Logger; | ||||
| 
 | ||||
| import org.apache.cloudstack.api.command.admin.internallb.ConfigureInternalLoadBalancerElementCmd; | ||||
| @ -81,6 +83,7 @@ import com.cloud.vm.ReservationContext; | ||||
| import com.cloud.vm.VirtualMachine; | ||||
| import com.cloud.vm.VirtualMachineProfile; | ||||
| import com.cloud.vm.dao.DomainRouterDao; | ||||
| import com.cloud.network.router.NetworkHelper; | ||||
| 
 | ||||
| public class InternalLoadBalancerElement extends AdapterBase implements LoadBalancingServiceProvider, InternalLoadBalancerElementService, IpDeployer { | ||||
|     private static final Logger s_logger = Logger.getLogger(InternalLoadBalancerElement.class); | ||||
| @ -107,6 +110,9 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala | ||||
|     ApplicationLoadBalancerRuleDao _appLbDao; | ||||
|     @Inject | ||||
|     EntityManager _entityMgr; | ||||
|     @Autowired | ||||
|     @Qualifier("networkHelper") | ||||
|     protected NetworkHelper _networkHelper; | ||||
| 
 | ||||
|     protected InternalLoadBalancerElement() { | ||||
|     } | ||||
| @ -413,7 +419,7 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala | ||||
|             if (routers == null || routers.isEmpty()) { | ||||
|                 return true; | ||||
|             } | ||||
|             return VirtualRouterElement.validateHAProxyLBRule(rule); | ||||
|             return _networkHelper.validateHAProxyLBRule(rule); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @ -44,6 +44,7 @@ import com.cloud.user.AccountManager; | ||||
| import com.cloud.utils.db.EntityManager; | ||||
| import com.cloud.utils.net.NetUtils; | ||||
| import com.cloud.vm.dao.DomainRouterDao; | ||||
| import com.cloud.network.router.NetworkHelper; | ||||
| 
 | ||||
| @Configuration | ||||
| @ComponentScan(basePackageClasses = {NetUtils.class}, | ||||
| @ -61,6 +62,11 @@ public class ElementChildTestConfiguration { | ||||
|             return Mockito.mock(DomainRouterDao.class); | ||||
|         } | ||||
| 
 | ||||
|         @Bean | ||||
|         public NetworkHelper networkHelper() { | ||||
|             return Mockito.mock(NetworkHelper.class); | ||||
|         } | ||||
| 
 | ||||
|         @Bean | ||||
|         public VirtualRouterProviderDao virtualRouterProviderDao() { | ||||
|             return Mockito.mock(VirtualRouterProviderDao.class); | ||||
|  | ||||
| @ -23,7 +23,9 @@ import java.util.Map; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| import javax.inject.Inject; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.beans.factory.annotation.Qualifier; | ||||
| import com.cloud.network.router.NetworkHelper; | ||||
| import org.apache.commons.collections.CollectionUtils; | ||||
| import org.apache.log4j.Logger; | ||||
| import org.cloud.network.router.deployment.RouterDeploymentDefinition; | ||||
| @ -78,7 +80,6 @@ import com.cloud.network.dao.NetworkDetailsDao; | ||||
| import com.cloud.network.dao.OvsProviderDao; | ||||
| import com.cloud.network.dao.VirtualRouterProviderDao; | ||||
| import com.cloud.network.lb.LoadBalancingRule; | ||||
| import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; | ||||
| import com.cloud.network.lb.LoadBalancingRulesManager; | ||||
| import com.cloud.network.router.VirtualRouter; | ||||
| import com.cloud.network.router.VirtualRouter.Role; | ||||
| @ -95,13 +96,11 @@ import com.cloud.offerings.NetworkOfferingVO; | ||||
| import com.cloud.offerings.dao.NetworkOfferingDao; | ||||
| import com.cloud.user.Account; | ||||
| import com.cloud.user.AccountManager; | ||||
| import com.cloud.utils.Pair; | ||||
| import com.cloud.utils.component.AdapterBase; | ||||
| import com.cloud.utils.crypt.DBEncryptionUtil; | ||||
| import com.cloud.utils.db.QueryBuilder; | ||||
| import com.cloud.utils.db.SearchCriteria.Op; | ||||
| import com.cloud.utils.exception.CloudRuntimeException; | ||||
| import com.cloud.utils.net.NetUtils; | ||||
| import com.cloud.vm.DomainRouterVO; | ||||
| import com.cloud.vm.NicProfile; | ||||
| import com.cloud.vm.ReservationContext; | ||||
| @ -171,6 +170,10 @@ NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource, DnsServ | ||||
|     @Inject | ||||
|     protected RouterDeploymentDefinitionBuilder routerDeploymentDefinitionBuilder; | ||||
| 
 | ||||
|     @Autowired | ||||
|     @Qualifier("networkHelper") | ||||
|     protected NetworkHelper _networkHelper; | ||||
| 
 | ||||
|     protected boolean canHandle(final Network network, final Service service) { | ||||
|         final Long physicalNetworkId = _networkMdl.getPhysicalNetworkId(network); | ||||
|         if (physicalNetworkId == null) { | ||||
| @ -302,104 +305,6 @@ NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource, DnsServ | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|      * This function detects numbers like 12 ,32h ,42m .. etc,. 1) plain number | ||||
|      * like 12 2) time or tablesize like 12h, 34m, 45k, 54m , here last | ||||
|      * character is non-digit but from known characters . | ||||
|      */ | ||||
|     private static boolean containsOnlyNumbers(final String str, final String endChar) { | ||||
|         if (str == null) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         String number = str; | ||||
|         if (endChar != null) { | ||||
|             boolean matchedEndChar = false; | ||||
|             if (str.length() < 2) { | ||||
|                 return false; // at least one numeric and one char. example: | ||||
|             } | ||||
|             // 3h | ||||
|             final char strEnd = str.toCharArray()[str.length() - 1]; | ||||
|             for (final char c : endChar.toCharArray()) { | ||||
|                 if (strEnd == c) { | ||||
|                     number = str.substring(0, str.length() - 1); | ||||
|                     matchedEndChar = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             if (!matchedEndChar) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         try { | ||||
|             Integer.parseInt(number); | ||||
|         } catch (final NumberFormatException e) { | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     public static boolean validateHAProxyLBRule(final LoadBalancingRule rule) { | ||||
|         final String timeEndChar = "dhms"; | ||||
| 
 | ||||
|         if (rule.getSourcePortStart() == NetUtils.HAPROXY_STATS_PORT) { | ||||
|             s_logger.debug("Can't create LB on port 8081, haproxy is listening for  LB stats on this port"); | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         for (final LbStickinessPolicy stickinessPolicy : rule.getStickinessPolicies()) { | ||||
|             final List<Pair<String, String>> paramsList = stickinessPolicy.getParams(); | ||||
| 
 | ||||
|             if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) { | ||||
| 
 | ||||
|             } else if (StickinessMethodType.SourceBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) { | ||||
|                 String tablesize = "200k"; // optional | ||||
|                 String expire = "30m"; // optional | ||||
| 
 | ||||
|                 /* overwrite default values with the stick parameters */ | ||||
|                 for (final Pair<String, String> paramKV : paramsList) { | ||||
|                     final String key = paramKV.first(); | ||||
|                     final String value = paramKV.second(); | ||||
|                     if ("tablesize".equalsIgnoreCase(key)) { | ||||
|                         tablesize = value; | ||||
|                     } | ||||
|                     if ("expire".equalsIgnoreCase(key)) { | ||||
|                         expire = value; | ||||
|                     } | ||||
|                 } | ||||
|                 if (expire != null && !containsOnlyNumbers(expire, timeEndChar)) { | ||||
|                     throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: expire is not in timeformat: " + expire); | ||||
|                 } | ||||
|                 if (tablesize != null && !containsOnlyNumbers(tablesize, "kmg")) { | ||||
|                     throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: tablesize is not in size format: " + tablesize); | ||||
| 
 | ||||
|                 } | ||||
|             } else if (StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) { | ||||
|                 String length = null; // optional | ||||
|                 String holdTime = null; // optional | ||||
| 
 | ||||
|                 for (final Pair<String, String> paramKV : paramsList) { | ||||
|                     final String key = paramKV.first(); | ||||
|                     final String value = paramKV.second(); | ||||
|                     if ("length".equalsIgnoreCase(key)) { | ||||
|                         length = value; | ||||
|                     } | ||||
|                     if ("holdtime".equalsIgnoreCase(key)) { | ||||
|                         holdTime = value; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (length != null && !containsOnlyNumbers(length, null)) { | ||||
|                     throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: length is not a number: " + length); | ||||
|                 } | ||||
|                 if (holdTime != null && !containsOnlyNumbers(holdTime, timeEndChar) && !containsOnlyNumbers(holdTime, null)) { | ||||
|                     throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: holdtime is not in timeformat: " + holdTime); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean validateLBRule(final Network network, final LoadBalancingRule rule) { | ||||
|         final List<LoadBalancingRule> rules = new ArrayList<LoadBalancingRule>(); | ||||
| @ -409,7 +314,7 @@ NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource, DnsServ | ||||
|             if (routers == null || routers.isEmpty()) { | ||||
|                 return true; | ||||
|             } | ||||
|             return validateHAProxyLBRule(rule); | ||||
|             return _networkHelper.validateHAProxyLBRule(rule); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @ -21,6 +21,7 @@ import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.cloud.network.router.deployment.RouterDeploymentDefinition; | ||||
| import com.cloud.network.lb.LoadBalancingRule; | ||||
| 
 | ||||
| import com.cloud.agent.api.to.NicTO; | ||||
| import com.cloud.agent.manager.Commands; | ||||
| @ -89,4 +90,6 @@ public interface NetworkHelper { | ||||
| 
 | ||||
|     public abstract LinkedHashMap<Network, List<? extends NicProfile>> configureGuestNic(RouterDeploymentDefinition routerDeploymentDefinition) | ||||
|             throws ConcurrentOperationException, InsufficientAddressCapacityException; | ||||
| } | ||||
| 
 | ||||
|     public boolean validateHAProxyLBRule(final LoadBalancingRule rule); | ||||
| } | ||||
|  | ||||
| @ -27,6 +27,12 @@ import java.util.Map; | ||||
| import javax.annotation.PostConstruct; | ||||
| import javax.ejb.Local; | ||||
| import javax.inject.Inject; | ||||
| import com.cloud.configuration.Config; | ||||
| import org.apache.cloudstack.framework.config.dao.ConfigurationDao; | ||||
| import com.cloud.exception.InvalidParameterValueException; | ||||
| import com.cloud.network.lb.LoadBalancingRule; | ||||
| import com.cloud.network.rules.LbStickinessMethod; | ||||
| import com.cloud.utils.Pair; | ||||
| 
 | ||||
| import org.apache.cloudstack.context.CallContext; | ||||
| import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; | ||||
| @ -147,6 +153,8 @@ public class NetworkHelperImpl implements NetworkHelper { | ||||
|     protected VirtualMachineManager _itMgr; | ||||
|     @Inject | ||||
|     protected IpAddressManager _ipAddrMgr; | ||||
|     @Inject | ||||
|     ConfigurationDao _configDao; | ||||
| 
 | ||||
|     protected final Map<HypervisorType, ConfigKey<String>> hypervisorsMap = new HashMap<>(); | ||||
| 
 | ||||
| @ -771,4 +779,103 @@ public class NetworkHelperImpl implements NetworkHelper { | ||||
|     public static void setVMInstanceName(final String vmInstanceName) { | ||||
|         s_vmInstanceName = vmInstanceName; | ||||
|     } | ||||
|     public boolean validateHAProxyLBRule(final LoadBalancingRule rule) { | ||||
|         final String timeEndChar = "dhms"; | ||||
|         int haproxy_stats_port = Integer.parseInt(_configDao.getValue(Config.NetworkLBHaproxyStatsPort.key())); | ||||
|         if (rule.getSourcePortStart() == haproxy_stats_port) { | ||||
|             if (s_logger.isDebugEnabled()) { | ||||
|                 s_logger.debug("Can't create LB on port "+ haproxy_stats_port +", haproxy is listening for  LB stats on this port"); | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         for (final LoadBalancingRule.LbStickinessPolicy stickinessPolicy : rule.getStickinessPolicies()) { | ||||
|             final List<Pair<String, String>> paramsList = stickinessPolicy.getParams(); | ||||
| 
 | ||||
|             if (LbStickinessMethod.StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) { | ||||
| 
 | ||||
|             } else if (LbStickinessMethod.StickinessMethodType.SourceBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) { | ||||
|                 String tablesize = "200k"; // optional | ||||
|                 String expire = "30m"; // optional | ||||
| 
 | ||||
|                 /* overwrite default values with the stick parameters */ | ||||
|                 for (final Pair<String, String> paramKV : paramsList) { | ||||
|                     final String key = paramKV.first(); | ||||
|                     final String value = paramKV.second(); | ||||
|                     if ("tablesize".equalsIgnoreCase(key)) { | ||||
|                         tablesize = value; | ||||
|                     } | ||||
|                     if ("expire".equalsIgnoreCase(key)) { | ||||
|                         expire = value; | ||||
|                     } | ||||
|                 } | ||||
|                 if (expire != null && !containsOnlyNumbers(expire, timeEndChar)) { | ||||
|                     throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: expire is not in timeformat: " + expire); | ||||
|                 } | ||||
|                 if (tablesize != null && !containsOnlyNumbers(tablesize, "kmg")) { | ||||
|                     throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: tablesize is not in size format: " + tablesize); | ||||
| 
 | ||||
|                 } | ||||
|             } else if (LbStickinessMethod.StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName())) { | ||||
|                 String length = null; // optional | ||||
|                 String holdTime = null; // optional | ||||
| 
 | ||||
|                 for (final Pair<String, String> paramKV : paramsList) { | ||||
|                     final String key = paramKV.first(); | ||||
|                     final String value = paramKV.second(); | ||||
|                     if ("length".equalsIgnoreCase(key)) { | ||||
|                         length = value; | ||||
|                     } | ||||
|                     if ("holdtime".equalsIgnoreCase(key)) { | ||||
|                         holdTime = value; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (length != null && !containsOnlyNumbers(length, null)) { | ||||
|                     throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: length is not a number: " + length); | ||||
|                 } | ||||
|                 if (holdTime != null && !containsOnlyNumbers(holdTime, timeEndChar) && !containsOnlyNumbers(holdTime, null)) { | ||||
|                     throw new InvalidParameterValueException("Failed LB in validation rule id: " + rule.getId() + " Cause: holdtime is not in timeformat: " + holdTime); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|      * This function detects numbers like 12 ,32h ,42m .. etc,. 1) plain number | ||||
|      * like 12 2) time or tablesize like 12h, 34m, 45k, 54m , here last | ||||
|      * character is non-digit but from known characters . | ||||
|      */ | ||||
|     private static boolean containsOnlyNumbers(final String str, final String endChar) { | ||||
|         if (str == null) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         String number = str; | ||||
|         if (endChar != null) { | ||||
|             boolean matchedEndChar = false; | ||||
|             if (str.length() < 2) { | ||||
|                 return false; // at least one numeric and one char. example: | ||||
|             } | ||||
|             // 3h | ||||
|             final char strEnd = str.toCharArray()[str.length() - 1]; | ||||
|             for (final char c : endChar.toCharArray()) { | ||||
|                 if (strEnd == c) { | ||||
|                     number = str.substring(0, str.length() - 1); | ||||
|                     matchedEndChar = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             if (!matchedEndChar) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         try { | ||||
|             Integer.parseInt(number); | ||||
|         } catch (final NumberFormatException e) { | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user