InternalLB: modified InternalLbElement to start the Internal Lb vm for each ip address (if not already started)

This commit is contained in:
Alena Prokharchyk 2013-04-11 13:46:47 -07:00
parent 76a4b1cf81
commit f4c2b53c21
8 changed files with 177 additions and 37 deletions

View File

@ -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());
}
}
}

View File

@ -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>();

View File

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

View File

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

View File

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

View File

@ -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())) {

View File

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

View File

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