InternalLB: modified InternalLbElement to start the Internal Lb vm for each ip address (if not already started)
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/f4c2b53c Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/f4c2b53c Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/f4c2b53c Branch: refs/heads/internallb Commit: f4c2b53c218b2d11d510b9acc6baeb0d62042e5c Parents: 76a4b1c Author: Alena Prokharchyk <[email protected]> Authored: Thu Apr 11 13:46:47 2013 -0700 Committer: Alena Prokharchyk <[email protected]> Committed: Thu Apr 11 13:59:44 2013 -0700 ---------------------------------------------------------------------- .../CreateApplicationLoadBalancerCmd.java | 4 + .../element/InternalLoadBalancerElement.java | 90 ++++++++++++--- .../network/lb/InternalLoadBalancerManager.java | 13 ++ .../lb/InternalLoadBalancerManagerImpl.java | 84 +++++++++++--- .../network/element/VirtualRouterElement.java | 2 +- .../lb/ApplicationLoadBalancerManagerImpl.java | 9 +- .../com/cloud/network/MockNetworkModelImpl.java | 6 + .../test/com/cloud/vpc/MockNetworkModelImpl.java | 6 + 8 files changed, 177 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f4c2b53c/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java index 54b3f83..84ee4f2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java @@ -31,6 +31,7 @@ import org.apache.log4j.Logger; import com.cloud.async.AsyncJob; import com.cloud.event.EventTypes; import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceAllocationException; @@ -234,6 +235,9 @@ public class CreateApplicationLoadBalancerCmd extends BaseAsyncCreateCmd { } catch (InsufficientAddressCapacityException e) { s_logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, e.getMessage()); + } catch (InsufficientVirtualNetworkCapcityException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, e.getMessage()); } } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f4c2b53c/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java index c2df4b6..f3fb00f 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java @@ -61,6 +61,7 @@ import com.cloud.network.element.VirtualRouterElement; import com.cloud.network.element.VirtualRouterProviderVO; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.LoadBalancerContainer; import com.cloud.offering.NetworkOffering; import com.cloud.user.AccountManager; @@ -68,6 +69,8 @@ import com.cloud.utils.component.AdapterBase; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.SearchCriteria2; import com.cloud.utils.db.SearchCriteriaService; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.Ip; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; @@ -235,27 +238,82 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala @Override public boolean applyLBRules(Network network, List<LoadBalancingRule> rules) throws ResourceUnavailableException { - List<DomainRouterVO> routers; - try { - DeployDestination dest = new DeployDestination(_configMgr.getZone(network.getDataCenterId()), null, null, null); - routers = _internalLbMgr.deployInternalLbVm(network, null, dest, _accountMgr.getAccount(network.getAccountId()), null); - } catch (InsufficientCapacityException e) { - s_logger.warn("Failed to apply lb rule(s) on the element " + this.getName() + " due to:", e); - return false; - } catch (ConcurrentOperationException e) { - s_logger.warn("Failed to apply lb rule(s) on the element " + this.getName() + " due to:", e); - return false; - } - if ((routers == null) || (routers.size() == 0)) { - throw new ResourceUnavailableException("Can't find/deploy internal lb vm to handle LB rules", - DataCenter.class, network.getDataCenterId()); - } + Map<Ip, List<LoadBalancingRule>> rulesToApply = getLbRulesToApply(rules); - //TODO - apply the rules + for (Ip sourceIp : rulesToApply.keySet()) { + //2.1 Start Internal LB vm per IP address + List<DomainRouterVO> internalLbVms; + try { + DeployDestination dest = new DeployDestination(_configMgr.getZone(network.getDataCenterId()), null, null, null); + internalLbVms = _internalLbMgr.deployInternalLbVm(network, sourceIp, dest, _accountMgr.getAccount(network.getAccountId()), null); + } catch (InsufficientCapacityException e) { + s_logger.warn("Failed to apply lb rule(s) on the element " + this.getName() + " due to:", e); + return false; + } catch (ConcurrentOperationException e) { + s_logger.warn("Failed to apply lb rule(s) on the element " + this.getName() + " due to:", e); + return false; + } + + if ((internalLbVms == null) || (internalLbVms.size() == 0)) { + throw new ResourceUnavailableException("Can't find/deploy internal lb vm to handle LB rules", + DataCenter.class, network.getDataCenterId()); + } + + //2.2 Apply Internal LB rules on the VM + if (!_internalLbMgr.applyLoadBalancingRules(network, rules, internalLbVms)) { + throw new CloudRuntimeException("Failed to apply load balancing rules in network " + network.getId() + " on element " + this.getName()); + } else { + return true; + } + } + return true; } + protected Map<Ip, List<LoadBalancingRule>> getLbRulesToApply(List<LoadBalancingRule> rules) { + //1) Group rules by the source ip address as NetworkManager always passes the entire network lb config to the element + Map<Ip, List<LoadBalancingRule>> groupedRules = groupBySourceIp(rules); + + //2) Apply only set containing LB rules in transition state (Add/Revoke) + Map<Ip, List<LoadBalancingRule>> rulesToApply = new HashMap<Ip, List<LoadBalancingRule>>(); + + for (Ip sourceIp : groupedRules.keySet()) { + boolean apply = false; + List<LoadBalancingRule> rulesToCheck = groupedRules.get(sourceIp); + for (LoadBalancingRule ruleToCheck : rulesToCheck) { + if (ruleToCheck.getState() == FirewallRule.State.Revoke || ruleToCheck.getState() == FirewallRule.State.Add){ + apply = true; + break; + } + } + if (apply) { + rulesToApply.put(sourceIp, rulesToCheck); + } else { + s_logger.debug("Not applying the lb rules for soure ip " + sourceIp + " on element " + this.getName() + " as there are no rules in transition state"); + } + } + return rulesToApply; + } + + protected Map<Ip, List<LoadBalancingRule>> groupBySourceIp(List<LoadBalancingRule> rules) { + Map<Ip, List<LoadBalancingRule>> groupedRules = new HashMap<Ip, List<LoadBalancingRule>>(); + for (LoadBalancingRule rule : rules) { + Ip sourceIp = rule.getSourceIp(); + if (!groupedRules.containsKey(sourceIp)) { + groupedRules.put(sourceIp, null); + } + + List<LoadBalancingRule> rulesToApply = groupedRules.get(sourceIp); + if (rulesToApply == null) { + rulesToApply = new ArrayList<LoadBalancingRule>(); + } + rulesToApply.add(rule); + groupedRules.put(sourceIp, rulesToApply); + } + return groupedRules; + } + @Override public boolean validateLBRule(Network network, LoadBalancingRule rule) { List<LoadBalancingRule> rules = new ArrayList<LoadBalancingRule>(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f4c2b53c/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManager.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManager.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManager.java index 84a5908..fd22285 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManager.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerManager.java @@ -25,6 +25,7 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; import com.cloud.network.Network; +import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.router.VirtualRouter; import com.cloud.user.Account; import com.cloud.user.User; @@ -94,4 +95,16 @@ public interface InternalLoadBalancerManager extends Manager{ throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException; + + /** + * + * @param network + * @param rules + * @param internalLbVms + * @return + * @throws ResourceUnavailableException + */ + boolean applyLoadBalancingRules(Network network, List<LoadBalancingRule> rules, List<? extends VirtualRouter> internalLbVms) + throws ResourceUnavailableException; + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f4c2b53c/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 5ca5474..0d0e5fc 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 @@ -30,6 +30,7 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; +import com.cloud.agent.AgentManager.OnError; import com.cloud.agent.api.Answer; import com.cloud.agent.api.GetDomRVersionAnswer; import com.cloud.agent.api.GetDomRVersionCmd; @@ -50,6 +51,7 @@ import com.cloud.dc.dao.DataCenterDao; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; +import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; @@ -567,26 +569,26 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> { List<DomainRouterVO> internalLbVms = findOrDeployInternalLbVm(guestNetwork, requestedGuestIp, dest, owner, params); - return startRouters(params, internalLbVms); + return startInternalLbVms(params, internalLbVms); } - protected List<DomainRouterVO> startRouters(Map<Param, Object> params, List<DomainRouterVO> routers) + protected List<DomainRouterVO> startInternalLbVms(Map<Param, Object> params, List<DomainRouterVO> internalLbVms) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - List<DomainRouterVO> runningRouters = null; + List<DomainRouterVO> runningInternalLbVms = null; - if (routers != null) { - runningRouters = new ArrayList<DomainRouterVO>(); + if (internalLbVms != null) { + runningInternalLbVms = new ArrayList<DomainRouterVO>(); } - for (DomainRouterVO router : routers) { - router = startInternalLbVm(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), params); + for (DomainRouterVO internalLbVm : internalLbVms) { + internalLbVm = startInternalLbVm(internalLbVm, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), params); - if (router != null) { - runningRouters.add(router); + if (internalLbVm != null) { + runningInternalLbVms.add(internalLbVm); } } - return runningRouters; + return runningInternalLbVms; } @@ -630,22 +632,22 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> { } // 3) deploy internal lb vm - Pair<DeploymentPlan, List<DomainRouterVO>> planAndRouters = getDeploymentPlanAndInternalLbVms(dest, guestNetwork.getId(), requestedGuestIp); - internalLbs = planAndRouters.second(); - DeploymentPlan plan = planAndRouters.first(); + Pair<DeploymentPlan, List<DomainRouterVO>> planAndInternalLbVms = getDeploymentPlanAndInternalLbVms(dest, guestNetwork.getId(), requestedGuestIp); + internalLbs = planAndInternalLbVms.second(); + DeploymentPlan plan = planAndInternalLbVms.first(); List<Pair<NetworkVO, NicProfile>> networks = createInternalLbVmNetworks(guestNetwork, plan, null); //don't start the internal lb as we are holding the network lock that needs to be released at the end of router allocation - DomainRouterVO internalLb = deployInternalLbVm(owner, dest, plan, params, internalLbProvider, offeringId, guestNetwork.getVpcId(), + DomainRouterVO internalLbVm = deployInternalLbVm(owner, dest, plan, params, internalLbProvider, offeringId, guestNetwork.getVpcId(), networks, false); - if (internalLb != null) { - internalLbs.add(internalLb); + if (internalLbVm != null) { + internalLbs.add(internalLbVm); } } finally { if (lock != null) { _networkDao.releaseFromLockTable(lock.getId()); if (s_logger.isDebugEnabled()) { - s_logger.debug("Lock is released for network id " + lock.getId() + " as a part of router startup in " + dest); + s_logger.debug("Lock is released for network id " + lock.getId() + " as a part of internal lb vm startup in " + dest); } } } @@ -827,4 +829,52 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> { } return hypervisors; } + + @Override + public boolean applyLoadBalancingRules(Network network, final List<LoadBalancingRule> rules, List<? extends VirtualRouter> internalLbVms) throws ResourceUnavailableException { + if (rules == null || rules.isEmpty()) { + s_logger.debug("No lb rules to be applied for network " + network); + return true; + } + + //FIXME - add validation for the internal lb vm state here + return sendLBRules(internalLbVms.get(0), rules, network.getId()); + } + + protected boolean sendLBRules(VirtualRouter internalLbVm, List<LoadBalancingRule> rules, long guestNetworkId) throws ResourceUnavailableException { + Commands cmds = new Commands(OnError.Continue); + createApplyLoadBalancingRulesCommands(rules, internalLbVm, cmds, guestNetworkId); + return sendCommandsToInternalLbVm(internalLbVm, cmds); + } + + + protected boolean sendCommandsToInternalLbVm(final VirtualRouter internalLbVm, Commands cmds) throws AgentUnavailableException { + Answer[] answers = null; + try { + answers = _agentMgr.send(internalLbVm.getHostId(), cmds); + } catch (OperationTimedoutException e) { + s_logger.warn("Timed Out", e); + throw new AgentUnavailableException("Unable to send commands to virtual router ", internalLbVm.getHostId(), e); + } + + if (answers == null) { + return false; + } + + if (answers.length != cmds.size()) { + return false; + } + + // FIXME: Have to return state for individual command in the future + boolean result = true; + if (answers.length > 0) { + for (Answer answer : answers) { + if (!answer.getResult()) { + result = false; + break; + } + } + } + return result; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f4c2b53c/server/src/com/cloud/network/element/VirtualRouterElement.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index ba5f7fa..2ec4a19 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -368,7 +368,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl throw new CloudRuntimeException("Failed to apply load balancing rules in network " + network.getId()); } else { return true; - } + } } else { return false; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f4c2b53c/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 f904ef0..cb617b5 100644 --- a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java @@ -124,7 +124,7 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A } //1) Validate LB rule's parameters - validateLbRuleParameters(sourcePort, instancePort, algorithm, guestNtwk); + validateLbRule(sourcePort, instancePort, algorithm, guestNtwk, scheme); //2) Get source ip address sourceIp = getSourceIp(scheme, sourceIpNtwk, sourceIp); @@ -188,10 +188,11 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A * @param sourcePort * @param instancePort * @param algorithm - * @param networkId * @param network + * @param scheme TODO + * @param networkId */ - protected void validateLbRuleParameters(int sourcePort, int instancePort, String algorithm, Network network) { + protected void validateLbRule(int sourcePort, int instancePort, String algorithm, Network network, Scheme scheme) { // verify that lb service is supported by the network if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { InvalidParameterValueException ex = new InvalidParameterValueException( @@ -200,6 +201,8 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A throw ex; } + //FIXME - check if the schema is supported by the network + 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())) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f4c2b53c/server/test/com/cloud/network/MockNetworkModelImpl.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/network/MockNetworkModelImpl.java b/server/test/com/cloud/network/MockNetworkModelImpl.java index f4a730d..72e2f26 100644 --- a/server/test/com/cloud/network/MockNetworkModelImpl.java +++ b/server/test/com/cloud/network/MockNetworkModelImpl.java @@ -856,4 +856,10 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel { // TODO Auto-generated method stub return null; } + + @Override + public List<String> getUsedIpsInNetwork(Network network) { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f4c2b53c/server/test/com/cloud/vpc/MockNetworkModelImpl.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/vpc/MockNetworkModelImpl.java b/server/test/com/cloud/vpc/MockNetworkModelImpl.java index ce1ab9e..22a1c6f 100644 --- a/server/test/com/cloud/vpc/MockNetworkModelImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkModelImpl.java @@ -869,4 +869,10 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel { return null; } + @Override + public List<String> getUsedIpsInNetwork(Network network) { + // TODO Auto-generated method stub + return null; + } + }
