InternalLbVm: destroy the internal lb vm when the last rule for the ip is being revoked

This commit is contained in:
Alena Prokharchyk 2013-04-12 10:05:28 -07:00
parent af6201257b
commit 78c9db79da
4 changed files with 97 additions and 43 deletions

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.network.element;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -64,7 +65,9 @@ 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.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
@ -162,13 +165,13 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala
boolean result = true;
for (DomainRouterVO internalLbVm : internalLbVms) {
result = result && _internalLbMgr.destroyInternalLbVm(internalLbVm.getId(),
context.getAccount(), context.getCaller().getId()) != null;
context.getAccount(), context.getCaller().getId());
if (cleanup) {
if (!result) {
s_logger.warn("Failed to stop internal lb element " + internalLbVm + ", but would try to process clean up anyway.");
}
result = (_internalLbMgr.destroyInternalLbVm(internalLbVm.getId(),
context.getAccount(), context.getCaller().getId()) != null);
context.getAccount(), context.getCaller().getId()));
if (!result) {
s_logger.warn("Failed to clean up internal lb element " + internalLbVm);
}
@ -186,7 +189,7 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala
boolean result = true;
for (DomainRouterVO internalLbVm : internalLbVms) {
result = result && (_internalLbMgr.destroyInternalLbVm(internalLbVm.getId(),
context.getAccount(), context.getCaller().getId()) != null);
context.getAccount(), context.getCaller().getId()));
}
return result;
}
@ -214,7 +217,7 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala
boolean result = true;
for (DomainRouterVO internalLbVm : internalLbVms) {
result = result && (_internalLbMgr.destroyInternalLbVm(internalLbVm.getId(),
context.getAccount(), context.getCaller().getId()) != null);
context.getAccount(), context.getCaller().getId()));
}
_vrProviderDao.remove(elementId);
@ -240,31 +243,47 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala
public boolean applyLBRules(Network network, List<LoadBalancingRule> rules) throws ResourceUnavailableException {
Map<Ip, List<LoadBalancingRule>> rulesToApply = getLbRulesToApply(rules);
Set<Ip> vmsToDestroy = getVmsToDestroy(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());
if (vmsToDestroy.contains(sourceIp)) {
//2.1 Destroy internal lb vm
List<DomainRouterVO> vms = _internalLbMgr.findInternalLbVms(network.getId(), sourceIp);
//only one internal lb per IP exists
try {
s_logger.debug("Destroying internal lb vm for ip " + sourceIp.addr() + " as all the rules for this vm are in Revoke state");
return _internalLbMgr.destroyInternalLbVm(vms.get(0).getId(), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM),
_accountMgr.getUserIncludingRemoved(User.UID_SYSTEM).getId());
} catch (ConcurrentOperationException e) {
s_logger.warn("Failed to apply lb rule(s) for ip " + sourceIp.addr() + " on the element " + this.getName() + " due to:", e);
return false;
}
} else {
return true;
//2.2 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) for ip " + sourceIp.addr() + "on the element " + this.getName() + " due to:", e);
return false;
} catch (ConcurrentOperationException e) {
s_logger.warn("Failed to apply lb rule(s) for ip " + sourceIp.addr() + "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.3 Apply Internal LB rules on the VM
if (!_internalLbMgr.applyLoadBalancingRules(network, rulesToApply.get(sourceIp), internalLbVms)) {
throw new CloudRuntimeException("Failed to apply load balancing rules for ip " + sourceIp.addr() +
" in network " + network.getId() + " on element " + this.getName());
} else {
return true;
}
}
}
@ -275,7 +294,7 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala
//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)
//2) Apply only sets containing LB rules in transition state (Add/Revoke).
Map<Ip, List<LoadBalancingRule>> rulesToApply = new HashMap<Ip, List<LoadBalancingRule>>();
for (Ip sourceIp : groupedRules.keySet()) {
@ -287,14 +306,42 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala
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");
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 Set<Ip> getVmsToDestroy(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) Count rules in revoke state
Set<Ip> vmsToDestroy = new HashSet<Ip>();
for (Ip sourceIp : groupedRules.keySet()) {
List<LoadBalancingRule> rulesToCheck = groupedRules.get(sourceIp);
int revoke = 0;
for (LoadBalancingRule ruleToCheck : rulesToCheck) {
if (ruleToCheck.getState() == FirewallRule.State.Revoke){
revoke++;
}
}
if (revoke == rulesToCheck.size()) {
s_logger.debug("Have to destroy internal lb vm for source ip " + sourceIp);
vmsToDestroy.add(sourceIp);
}
}
return vmsToDestroy;
}
protected Map<Ip, List<LoadBalancingRule>> groupBySourceIp(List<LoadBalancingRule> rules) {
Map<Ip, List<LoadBalancingRule>> groupedRules = new HashMap<Ip, List<LoadBalancingRule>>();

View File

@ -44,7 +44,7 @@ public interface InternalLoadBalancerManager extends Manager{
* @throws ResourceUnavailableException
* @throws ConcurrentOperationException
*/
VirtualRouter destroyInternalLbVm(long vmId, Account caller, Long callerUserId)
boolean destroyInternalLbVm(long vmId, Account caller, Long callerUserId)
throws ResourceUnavailableException, ConcurrentOperationException;
@ -107,4 +107,7 @@ public interface InternalLoadBalancerManager extends Manager{
boolean applyLoadBalancingRules(Network network, List<LoadBalancingRule> rules, List<? extends VirtualRouter> internalLbVms)
throws ResourceUnavailableException;
List<DomainRouterVO> findInternalLbVms(long guestNetworkId, Ip requestedGuestIp);
}

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.network.lb;
import java.lang.Thread.State;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -522,7 +523,7 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> {
}
@Override
public VirtualRouter destroyInternalLbVm(long vmId, Account caller, Long callerUserId)
public boolean destroyInternalLbVm(long vmId, Account caller, Long callerUserId)
throws ResourceUnavailableException, ConcurrentOperationException {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Attempting to destroy Internal LB vm " + vmId);
@ -530,17 +531,12 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> {
DomainRouterVO internalLbVm = _routerDao.findById(vmId);
if (internalLbVm == null) {
return null;
return true;
}
_accountMgr.checkAccess(caller, null, true, internalLbVm);
boolean result = _itMgr.expunge(internalLbVm, _accountMgr.getActiveUser(callerUserId), caller);
if (result) {
return internalLbVm;
}
return null;
return _itMgr.expunge(internalLbVm, _accountMgr.getActiveUser(callerUserId), caller);
}
@Override
@ -582,12 +578,13 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> {
}
for (DomainRouterVO internalLbVm : internalLbVms) {
internalLbVm = startInternalLbVm(internalLbVm, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), params);
if (internalLbVm.getState() != VirtualMachine.State.Running) {
internalLbVm = startInternalLbVm(internalLbVm, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), params);
}
if (internalLbVm != null) {
runningInternalLbVms.add(internalLbVm);
}
}
return runningInternalLbVms;
}
@ -699,6 +696,14 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> {
protected Pair<DeploymentPlan, List<DomainRouterVO>> getDeploymentPlanAndInternalLbVms(DeployDestination dest, long guestNetworkId, Ip requestedGuestIp) {
long dcId = dest.getDataCenter().getId();
DeploymentPlan plan = new DataCenterDeployment(dcId);
List<DomainRouterVO> internalLbVms = findInternalLbVms(guestNetworkId, requestedGuestIp);
return new Pair<DeploymentPlan, List<DomainRouterVO>>(plan, internalLbVms);
}
@Override
public List<DomainRouterVO> findInternalLbVms(long guestNetworkId, Ip requestedGuestIp) {
List<DomainRouterVO> internalLbVms = _routerDao.listByNetworkAndRole(guestNetworkId, Role.INTERNAL_LB_VM);
if (requestedGuestIp != null) {
Iterator<DomainRouterVO> it = internalLbVms.iterator();
@ -710,8 +715,7 @@ InternalLoadBalancerManager, VirtualMachineGuru<DomainRouterVO> {
}
}
}
return new Pair<DeploymentPlan, List<DomainRouterVO>>(plan, internalLbVms);
return internalLbVms;
}

View File

@ -1602,7 +1602,7 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
}
txn.commit();
if (checkForReleaseElasticIp) {
if (checkForReleaseElasticIp && lb.getSourceIpAddressId() != null) {
boolean success = true;
long count = _firewallDao.countRulesByIpId(lb.getSourceIpAddressId());
if (count == 0) {