InternalLB: added logic for acquiring guest ip address for the Internal LB rule
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/76a4b1cf Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/76a4b1cf Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/76a4b1cf Branch: refs/heads/internallb Commit: 76a4b1cf81610d931d6098ca94fa509c9ba2e274 Parents: 915e39f Author: Alena Prokharchyk <[email protected]> Authored: Thu Apr 11 11:41:47 2013 -0700 Committer: Alena Prokharchyk <[email protected]> Committed: Thu Apr 11 12:09:56 2013 -0700 ---------------------------------------------------------------------- api/src/com/cloud/network/NetworkModel.java | 2 + .../network/lb/ApplicationLoadBalancerService.java | 3 +- .../lb/InternalLoadBalancerManagerImpl.java | 3 +- server/src/com/cloud/network/NetworkModelImpl.java | 25 +- .../lb/ApplicationLoadBalancerManagerImpl.java | 303 +++++++++++++-- .../lb/dao/ApplicationLoadBalancerRuleDao.java | 6 +- .../lb/dao/ApplicationLoadBalancerRuleDaoImpl.java | 55 +++- 7 files changed, 353 insertions(+), 44 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/76a4b1cf/api/src/com/cloud/network/NetworkModel.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/NetworkModel.java b/api/src/com/cloud/network/NetworkModel.java index 6842ebb..6260d37 100644 --- a/api/src/com/cloud/network/NetworkModel.java +++ b/api/src/com/cloud/network/NetworkModel.java @@ -266,4 +266,6 @@ public interface NetworkModel { IpAddress getPublicIpAddress(String ipAddress, long zoneId); + List<String> getUsedIpsInNetwork(Network network); + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/76a4b1cf/api/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerService.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerService.java b/api/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerService.java index 0d9620b..88196a3 100644 --- a/api/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerService.java +++ b/api/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerService.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.cloudstack.api.command.user.loadbalancer.ListApplicationLoadBalancersCmd; import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.utils.Pair; @@ -30,7 +31,7 @@ public interface ApplicationLoadBalancerService { ApplicationLoadBalancerRule createApplicationLoadBalancer(String name, String description, Scheme scheme, long sourceIpNetworkId, String sourceIp, int sourcePort, int instancePort, String algorithm, long networkId, long lbOwnerId) throws InsufficientAddressCapacityException, - NetworkRuleConflictException; + NetworkRuleConflictException, InsufficientVirtualNetworkCapcityException; boolean deleteApplicationLoadBalancer(long id); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/76a4b1cf/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManagerImpl.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManagerImpl.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManagerImpl.java index d6d3adb..5ca5474 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManagerImpl.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManagerImpl.java @@ -81,7 +81,6 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.RedundantState; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; import com.cloud.offerings.dao.NetworkOfferingDao; @@ -437,7 +436,7 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> { protected void finalizeLbRulesForIp(Commands cmds, DomainRouterVO internalLbVm, Provider provider, Ip sourceIp, long guestNtwkId) { s_logger.debug("Resending load balancing rules as a part of start for " + internalLbVm); - List<ApplicationLoadBalancerRuleVO> lbs = _lbDao.listBySrcIpSrcNtwkIdAndScheme(sourceIp, guestNtwkId, Scheme.Internal); + List<ApplicationLoadBalancerRuleVO> lbs = _lbDao.listBySrcIpSrcNtwkId(sourceIp, guestNtwkId); List<LoadBalancingRule> lbRules = new ArrayList<LoadBalancingRule>(); if (_ntwkModel.isProviderSupportServiceInNetwork(guestNtwkId, Service.Lb, provider)) { // Re-apply load balancing rules http://git-wip-us.apache.org/repos/asf/cloudstack/blob/76a4b1cf/server/src/com/cloud/network/NetworkModelImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 0a82e09..75d8bc1 100644 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -32,6 +32,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.network.lb.dao.ApplicationLoadBalancerRuleDao; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -177,7 +178,9 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { @Inject UserIpv6AddressDao _ipv6Dao; @Inject - NicSecondaryIpDao _nicSecondaryIpDao;; + NicSecondaryIpDao _nicSecondaryIpDao; + @Inject + ApplicationLoadBalancerRuleDao _appLbRuleDao; private final HashMap<String, NetworkOfferingVO> _systemNetworks = new HashMap<String, NetworkOfferingVO>(5); @@ -1644,10 +1647,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { @Override public Set<Long> getAvailableIps(Network network, String requestedIp) { String[] cidr = network.getCidr().split("/"); - List<String> ips = _nicDao.listIpAddressInNetwork(network.getId()); - List<String> secondaryIps = _nicSecondaryIpDao.listSecondaryIpAddressInNetwork(network.getId()); - ips.addAll(secondaryIps); - Set<Long> allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1])); + List<String> ips = getUsedIpsInNetwork(network); Set<Long> usedIps = new TreeSet<Long>(); for (String ip : ips) { @@ -1658,6 +1658,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { usedIps.add(NetUtils.ip2Long(ip)); } + + Set<Long> allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1])); if (usedIps.size() != 0) { allPossibleIps.removeAll(usedIps); } @@ -1668,6 +1670,19 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { return allPossibleIps; } + + @Override + public List<String> getUsedIpsInNetwork(Network network) { + //Get all ips used by vms nics + List<String> ips = _nicDao.listIpAddressInNetwork(network.getId()); + //Get all secondary ips for nics + List<String> secondaryIps = _nicSecondaryIpDao.listSecondaryIpAddressInNetwork(network.getId()); + ips.addAll(secondaryIps); + //Get ips used by load balancers + List<String> lbIps = _appLbRuleDao.listLbIpsBySourceIpNetworkId(network.getId()); + ips.addAll(lbIps); + return ips; + } @Override public String getDomainNetworkDomain(long domainId, long zoneId) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/76a4b1cf/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java index d48ce77..f904ef0 100644 --- a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java @@ -24,6 +24,7 @@ import java.util.Map; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.loadbalancer.ListApplicationLoadBalancersCmd; import org.apache.cloudstack.network.lb.dao.ApplicationLoadBalancerRuleDao; import org.apache.log4j.Logger; @@ -33,17 +34,23 @@ import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.UnsupportedServiceException; import com.cloud.network.Network; +import com.cloud.network.Network.Capability; import com.cloud.network.Network.Service; +import com.cloud.network.NetworkManager; import com.cloud.network.NetworkModel; +import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; import com.cloud.network.lb.LoadBalancingRulesManager; +import com.cloud.network.rules.FirewallRule.State; import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.server.ResourceTag.TaggedResourceType; @@ -55,6 +62,7 @@ import com.cloud.user.UserContext; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; @@ -75,71 +83,89 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A @Inject LoadBalancingRulesManager _lbMgr; @Inject FirewallRulesDao _firewallDao; @Inject ResourceTagDao _resourceTagDao; + @Inject NetworkManager _ntwkMgr; @Override @ActionEvent(eventType = EventTypes.EVENT_LOAD_BALANCER_CREATE, eventDescription = "creating load balancer") public ApplicationLoadBalancerRule createApplicationLoadBalancer(String name, String description, Scheme scheme, long sourceIpNetworkId, String sourceIp, int sourcePort, int instancePort, String algorithm, long networkId, long lbOwnerId) throws InsufficientAddressCapacityException, - NetworkRuleConflictException { + NetworkRuleConflictException, InsufficientVirtualNetworkCapcityException { - if (!NetUtils.isValidPort(instancePort)) { - throw new InvalidParameterValueException("Invalid value for instance port: " + instancePort); + //Validate LB rule guest network + Network guestNtwk = _networkModel.getNetwork(networkId); + if (guestNtwk == null) { + throw new InvalidParameterValueException("Can't find network by id"); } + Account caller = UserContext.current().getCaller(); + _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, guestNtwk); - if (!NetUtils.isValidPort(instancePort)) { - throw new InvalidParameterValueException("Invalid value for source port: " + sourcePort); - } - - if ((algorithm == null) || !NetUtils.isValidAlgorithm(algorithm)) { - throw new InvalidParameterValueException("Invalid algorithm: " + algorithm); - } - - Network network = _networkModel.getNetwork(networkId); - // verify that lb service is supported by the network - if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { - InvalidParameterValueException ex = new InvalidParameterValueException( - "LB service is not supported in specified network id"); - ex.addProxyObject(network, networkId, "networkId"); - throw ex; + Network sourceIpNtwk = _networkModel.getNetwork(sourceIpNetworkId); + if (sourceIpNtwk == null) { + throw new InvalidParameterValueException("Can't find source ip network by id"); } Account lbOwner = _accountMgr.getAccount(lbOwnerId); if (lbOwner == null) { throw new InvalidParameterValueException("Can't find the lb owner account"); } - - //TODO - assign guest ip address here//add validation for the source ip address/network id - ApplicationLoadBalancerRuleVO newRule = new ApplicationLoadBalancerRuleVO(name, description, sourcePort, instancePort, algorithm, networkId, - lbOwner.getId(), lbOwner.getDomainId(), new Ip(sourceIp), sourceIpNetworkId, scheme); + return createApplicationLoadBalancer(name, description, scheme, sourceIpNtwk, sourceIp, sourcePort, instancePort, algorithm, lbOwner, guestNtwk); + } - // verify rule is supported by Lb provider of the network + + protected ApplicationLoadBalancerRule createApplicationLoadBalancer(String name, String description, Scheme scheme, Network sourceIpNtwk, String sourceIp, int sourcePort, int instancePort, String algorithm, + Account lbOwner, Network guestNtwk) throws NetworkRuleConflictException, InsufficientVirtualNetworkCapcityException { + + //Only Internal scheme is supported in this release + if (scheme != Scheme.Internal) { + throw new UnsupportedServiceException("Only scheme of type " + Scheme.Internal + " is supported"); + } + + //1) Validate LB rule's parameters + validateLbRuleParameters(sourcePort, instancePort, algorithm, guestNtwk); + + //2) Get source ip address + sourceIp = getSourceIp(scheme, sourceIpNtwk, sourceIp); + + ApplicationLoadBalancerRuleVO newRule = new ApplicationLoadBalancerRuleVO(name, description, sourcePort, instancePort, algorithm, guestNtwk.getId(), + lbOwner.getId(), lbOwner.getDomainId(), new Ip(sourceIp), sourceIpNtwk.getId(), scheme); + + //3) Validate Load Balancing rule on the providers LoadBalancingRule loadBalancing = new LoadBalancingRule(newRule, new ArrayList<LbDestination>(), new ArrayList<LbStickinessPolicy>(), new ArrayList<LbHealthCheckPolicy>(), new Ip(sourceIp)); - if (!_lbMgr.validateLbRule(loadBalancing)) { throw new InvalidParameterValueException("LB service provider cannot support this rule"); } + + //4) Persist Load Balancer rule + return persistLbRule(newRule, sourceIp, guestNtwk); + } + + + @DB + protected ApplicationLoadBalancerRule persistLbRule(ApplicationLoadBalancerRuleVO newRule, String sourceIp, Network guestNtwk) throws NetworkRuleConflictException { + Transaction txn = Transaction.currentTxn(); txn.start(); + //1) Persist the rule newRule = _lbDao.persist(newRule); boolean success = true; try { - //TODO - add validation for the LB rule against other lb rules - + //2) Detect conflicts + detectLbRulesConflicts(newRule); if (!_firewallDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } - s_logger.debug("Load balancer " + newRule.getId() + " for Ip address " + sourceIp + ", source port " - + sourcePort + ", instance port " + instancePort + " is added successfully."); + s_logger.debug("Load balancer " + newRule.getId() + " for Ip address " + newRule + ", source port " + + newRule.getSourcePortStart() + ", instance port " + newRule.getDefaultPortStart() + " is added successfully."); UserContext.current().setEventDetails("Load balancer Id: " + newRule.getId()); - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_LOAD_BALANCER_CREATE, lbOwnerId, - network.getDataCenterId(), newRule.getId(), null, LoadBalancingRule.class.getName(), + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_LOAD_BALANCER_CREATE, newRule.getAccountId(), + guestNtwk.getDataCenterId(), newRule.getId(), null, LoadBalancingRule.class.getName(), newRule.getUuid()); txn.commit(); @@ -153,11 +179,173 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A } finally { if (!success && newRule != null) { _lbMgr.removeLBRule(newRule); - //TODO - unassign the guest ip address here } } } + /** + * Validates Lb rule parameters + * @param sourcePort + * @param instancePort + * @param algorithm + * @param networkId + * @param network + */ + protected void validateLbRuleParameters(int sourcePort, int instancePort, String algorithm, Network network) { + // verify that lb service is supported by the network + if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { + InvalidParameterValueException ex = new InvalidParameterValueException( + "LB service is not supported in specified network id"); + ex.addProxyObject(network, network.getId(), "networkId"); + throw ex; + } + + Map<Network.Capability, String> caps = _networkModel.getNetworkServiceCapabilities(network.getId(), Service.Lb); + String supportedProtocols = caps.get(Capability.SupportedProtocols).toLowerCase(); + if (!supportedProtocols.contains(NetUtils.TCP_PROTO.toLowerCase())) { + throw new InvalidParameterValueException("Protocol " + NetUtils.TCP_PROTO.toLowerCase() + " is not supported in zone " + network.getDataCenterId()); + } + + //Validate rule parameters + if (!NetUtils.isValidPort(instancePort)) { + throw new InvalidParameterValueException("Invalid value for instance port: " + instancePort); + } + + if (!NetUtils.isValidPort(instancePort)) { + throw new InvalidParameterValueException("Invalid value for source port: " + sourcePort); + } + + if ((algorithm == null) || !NetUtils.isValidAlgorithm(algorithm)) { + throw new InvalidParameterValueException("Invalid algorithm: " + algorithm); + } + } + + + /** + * Gets source ip address based on the LB rule scheme/source IP network/requested IP address + * @param scheme + * @param sourceIpNtwk + * @param requestedIp + * @return + * @throws InsufficientVirtualNetworkCapcityException + */ + protected String getSourceIp(Scheme scheme, Network sourceIpNtwk, String requestedIp) throws InsufficientVirtualNetworkCapcityException { + //Get source IP address + if (requestedIp != null) { + validateRequestedSourceIpForLbRule(sourceIpNtwk, new Ip(requestedIp), scheme); + } else { + requestedIp = allocateSourceIpForLbRule(scheme, sourceIpNtwk); + } + + if (requestedIp == null) { + throw new InsufficientVirtualNetworkCapcityException("Unable to acquire IP address for network " + sourceIpNtwk, Network.class, sourceIpNtwk.getId()); + } + return requestedIp; + } + + + /** + * Allocates new Source IP address for the Load Balancer rule based on LB rule scheme/sourceNetwork + * @param scheme + * @param sourceIp + * @param sourceIpNtwk + * @return + */ + protected String allocateSourceIpForLbRule(Scheme scheme, Network sourceIpNtwk) { + String sourceIp = null; + if (scheme != Scheme.Internal) { + throw new InvalidParameterValueException("Only scheme " + Scheme.Internal + " is supported"); + } else { + sourceIp = allocateSourceIpForInternalLbRule(sourceIpNtwk); + } + return sourceIp; + } + + + /** + * Allocates sourceIp for the Internal LB rule + * @param sourceIpNtwk + * @return + */ + protected String allocateSourceIpForInternalLbRule(Network sourceIpNtwk) { + return _ntwkMgr.acquireGuestIpAddress(sourceIpNtwk, null); + } + + + /** + * Validates requested source ip address of the LB rule based on Lb rule scheme/sourceNetwork + * @param sourceIpNtwk + * @param requestedSourceIp + * @param scheme + */ + private void validateRequestedSourceIpForLbRule(Network sourceIpNtwk, Ip requestedSourceIp, Scheme scheme) { + //only Internal scheme is supported in this release + if (scheme != Scheme.Internal) { + throw new UnsupportedServiceException("Only scheme of type " + Scheme.Internal + " is supported"); + } else { + //validate guest source ip + validateRequestedSourceIpForInternalLbRule(sourceIpNtwk, requestedSourceIp); + } + } + + + /** + * Validates requested source IP address of Internal Lb rule against sourceNetworkId + * @param sourceIpNtwk + * @param requestedSourceIp + */ + private void validateRequestedSourceIpForInternalLbRule(Network sourceIpNtwk, Ip requestedSourceIp) { + //Check if the IP address used by the load balancer or other nics + if (_lbDao.countBySourceIp(requestedSourceIp, sourceIpNtwk.getId()) > 0) { + s_logger.debug("IP address " + requestedSourceIp.addr() + " is already used by existing LB rule, skipping the validation"); + return; + } else { + List<String> usedIps = _networkModel.getUsedIpsInNetwork(sourceIpNtwk); + if (usedIps.size() > 0) { + throw new InvalidParameterValueException("Ip address " + requestedSourceIp.addr() + " is already in use"); + } + } + } + + + /** + * Validates source IP network for the LB rule + * @param sourceNtwk + * @param scheme + * @return + */ + protected Network validateSourceIpNtwkForLbRule(Network sourceNtwk, Scheme scheme) { + //only Internal scheme is supported in this release + if (scheme != Scheme.Internal) { + throw new UnsupportedServiceException("Only scheme of type " + Scheme.Internal + " is supported"); + } else { + //validate source ip network + return validateSourceIpNtwkForInternalLbRule(sourceNtwk); + } + + } + + /** + * Validates source IP network for the Internal LB rule + * @param sourceIpNtwk + * @return + */ + protected Network validateSourceIpNtwkForInternalLbRule(Network sourceIpNtwk) { + if (sourceIpNtwk.getTrafficType() != TrafficType.Guest) { + throw new InvalidParameterValueException("Only traffic type " + TrafficType.Guest + " is supported"); + } + + //Can't create the LB rule if the network's cidr is NULL + String ntwkCidr = sourceIpNtwk.getCidr(); + if (ntwkCidr == null) { + throw new InvalidParameterValueException("Can't create the application load balancer rule for the network having NULL cidr"); + } + + //check if the requested ip address is within the cidr + return sourceIpNtwk; + } + + @Override public boolean deleteApplicationLoadBalancer(long id) { return _lbMgr.deleteLoadBalancerRule(id, true); @@ -266,5 +454,58 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A public ApplicationLoadBalancerRule findById(long ruleId) { return _lbDao.findById(ruleId); } + + + /** + * Detects lb rule conflicts against other rules + * @param newLbRule + * @throws NetworkRuleConflictException + */ + protected void detectLbRulesConflicts(ApplicationLoadBalancerRule newLbRule) throws NetworkRuleConflictException { + if (newLbRule.getScheme() != Scheme.Internal) { + throw new UnsupportedServiceException("Only scheme of type " + Scheme.Internal + " is supported"); + } else { + detectInternalLbRulesConflict(newLbRule); + } + } + + + /** + * Detects Internal Lb Rules conflicts + * @param newLbRule + * @throws NetworkRuleConflictException + */ + protected void detectInternalLbRulesConflict(ApplicationLoadBalancerRule newLbRule) throws NetworkRuleConflictException { + List<ApplicationLoadBalancerRuleVO> lbRules = _lbDao.listBySourceIpAndNotRevoked(newLbRule.getSourceIp(), newLbRule.getSourceIpNetworkId()); + + for (ApplicationLoadBalancerRuleVO lbRule : lbRules) { + if (lbRule.getId() == newLbRule.getId()) { + continue; // Skips my own rule. + } + + if (lbRule.getNetworkId() != newLbRule.getNetworkId() && lbRule.getState() != State.Revoke) { + throw new NetworkRuleConflictException("New rule is for a different network than what's specified in rule " + + lbRule.getXid()); + } + + if ((lbRule.getSourcePortStart().intValue() <= newLbRule.getSourcePortStart().intValue() + && lbRule.getSourcePortEnd().intValue() >= newLbRule.getSourcePortStart().intValue()) + || (lbRule.getSourcePortStart().intValue() <= newLbRule.getSourcePortEnd().intValue() + && lbRule.getSourcePortEnd().intValue() >= newLbRule.getSourcePortEnd().intValue()) + || (newLbRule.getSourcePortStart().intValue() <= lbRule.getSourcePortStart().intValue() + && newLbRule.getSourcePortEnd().intValue() >= lbRule.getSourcePortStart().intValue()) + || (newLbRule.getSourcePortStart().intValue() <= lbRule.getSourcePortEnd().intValue() + && newLbRule.getSourcePortEnd().intValue() >= lbRule.getSourcePortEnd().intValue())) { + + + throw new NetworkRuleConflictException("The range specified, " + newLbRule.getSourcePortStart() + "-" + newLbRule.getSourcePortEnd() + ", conflicts with rule " + lbRule.getId() + + " which has " + lbRule.getSourcePortStart() + "-" + lbRule.getSourcePortEnd()); + } + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("No network rule conflicts detected for " + newLbRule + " against " + (lbRules.size() - 1) + " existing rules"); + } + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/76a4b1cf/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDao.java ---------------------------------------------------------------------- diff --git a/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDao.java b/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDao.java index 6209949..c702987 100644 --- a/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDao.java +++ b/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDao.java @@ -21,10 +21,12 @@ import java.util.List; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRuleVO; -import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.Ip; public interface ApplicationLoadBalancerRuleDao extends GenericDao<ApplicationLoadBalancerRuleVO, Long>{ - List<ApplicationLoadBalancerRuleVO> listBySrcIpSrcNtwkIdAndScheme(Ip sourceIp, long sourceNetworkId, Scheme scheme); + List<ApplicationLoadBalancerRuleVO> listBySrcIpSrcNtwkId(Ip sourceIp, long sourceNetworkId); + List<String> listLbIpsBySourceIpNetworkId(long sourceIpNetworkId); + long countBySourceIp(Ip sourceIp, long sourceIpNetworkId); + List<ApplicationLoadBalancerRuleVO> listBySourceIpAndNotRevoked(Ip sourceIp, long sourceNetworkId); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/76a4b1cf/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java ---------------------------------------------------------------------- diff --git a/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java b/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java index ff6d38b..a3d2ca9 100644 --- a/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java @@ -24,16 +24,24 @@ import javax.ejb.Local; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRuleVO; import org.springframework.stereotype.Component; -import com.cloud.network.rules.LoadBalancerContainer.Scheme; +import com.cloud.network.rules.FirewallRule; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Func; +import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.net.Ip; @Component @Local(value = { ApplicationLoadBalancerRuleDao.class }) public class ApplicationLoadBalancerRuleDaoImpl extends GenericDaoBase<ApplicationLoadBalancerRuleVO, Long> implements ApplicationLoadBalancerRuleDao{ protected final SearchBuilder<ApplicationLoadBalancerRuleVO> AllFieldsSearch; + final GenericSearchBuilder<ApplicationLoadBalancerRuleVO, String> listIps; + final GenericSearchBuilder<ApplicationLoadBalancerRuleVO, Long> CountBy; + protected final SearchBuilder<ApplicationLoadBalancerRuleVO> NotRevokedSearch; + + protected ApplicationLoadBalancerRuleDaoImpl() { AllFieldsSearch = createSearchBuilder(); @@ -42,14 +50,55 @@ public class ApplicationLoadBalancerRuleDaoImpl extends GenericDaoBase<Applicati AllFieldsSearch.and("networkId", AllFieldsSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); AllFieldsSearch.and("scheme", AllFieldsSearch.entity().getScheme(), SearchCriteria.Op.EQ); AllFieldsSearch.done(); + + listIps = createSearchBuilder(String.class); + listIps.select(null, Func.DISTINCT, listIps.entity().getSourceIp()); + listIps.and("sourceIpNetworkId", listIps.entity().getSourceIpNetworkId(), Op.EQ); + listIps.done(); + + CountBy = createSearchBuilder(Long.class); + CountBy.select(null, Func.COUNT, CountBy.entity().getId()); + CountBy.and("sourceIp", CountBy.entity().getSourceIp(), Op.EQ); + CountBy.and("sourceIpNetworkId", CountBy.entity().getSourceIpNetworkId(), Op.EQ); + CountBy.done(); + + NotRevokedSearch = createSearchBuilder(); + NotRevokedSearch.and("sourceIp", AllFieldsSearch.entity().getSourceIp(), SearchCriteria.Op.EQ); + NotRevokedSearch.and("sourceIpNetworkId", AllFieldsSearch.entity().getSourceIpNetworkId(), SearchCriteria.Op.EQ); + NotRevokedSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.NEQ); + NotRevokedSearch.done(); } @Override - public List<ApplicationLoadBalancerRuleVO> listBySrcIpSrcNtwkIdAndScheme(Ip sourceIp, long sourceNetworkId, Scheme scheme) { + public List<ApplicationLoadBalancerRuleVO> listBySrcIpSrcNtwkId(Ip sourceIp, long sourceNetworkId) { SearchCriteria<ApplicationLoadBalancerRuleVO> sc = AllFieldsSearch.create(); sc.setParameters("sourceIp", sourceIp); sc.setParameters("sourceIpNetworkId", sourceNetworkId); - sc.setParameters("scheme", scheme); + return listBy(sc); + } + + @Override + public List<String> listLbIpsBySourceIpNetworkId(long sourceIpNetworkId) { + SearchCriteria<String> sc = listIps.create(); + sc.setParameters("sourceIpNetworkId", sourceIpNetworkId); + return customSearch(sc, null); + } + + @Override + public long countBySourceIp(Ip sourceIp, long sourceIpNetworkId) { + SearchCriteria<Long> sc = CountBy.create(); + sc.setParameters("sourceIp", sourceIp); + sc.setParameters("sourceIpNetworkId", sourceIpNetworkId); + List<Long> results = customSearch(sc, null); + return results.get(0); + } + + @Override + public List<ApplicationLoadBalancerRuleVO> listBySourceIpAndNotRevoked(Ip sourceIp, long sourceNetworkId) { + SearchCriteria<ApplicationLoadBalancerRuleVO> sc = NotRevokedSearch.create(); + sc.setParameters("sourceIp", sourceIp); + sc.setParameters("sourceIpNetworkId", sourceNetworkId); + sc.setParameters("state", FirewallRule.State.Revoke); return listBy(sc); }
