mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge pull request #2109 from Accelerite/CLOUDSTACK-9922
CLOUDSTACK-9922 Unable to use 8081 port for Load balancing
This commit is contained in:
commit
6e832b55dc
@ -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