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;
+    }
+
 }

Reply via email to