ELB VM: implement delete LB by deleting ELB vm

in the future we will manage a pool of vms more intelligently
This commit is contained in:
Chiradeep Vittal 2011-07-28 00:15:16 -07:00
parent 2162cdf283
commit fae6fa790c
8 changed files with 107 additions and 45 deletions

View File

@ -62,9 +62,10 @@ public class ElasticLbVmMapVO {
public ElasticLbVmMapVO() {
}
public ElasticLbVmMapVO(long ipId, long elbVmId) {
public ElasticLbVmMapVO(long ipId, long elbVmId, long lbId) {
this.ipAddressId = ipId;
this.elbVmId = elbVmId;
this.lbId = lbId;
}
public Long getId() {

View File

@ -26,33 +26,24 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.NetworkVO;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestIpType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkManager;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PublicIpAddress;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.lb.ElasticLoadBalancerManager;
import com.cloud.network.lb.LoadBalancerElement;
import com.cloud.network.rules.FirewallRule;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.user.Account;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.vm.NicProfile;

View File

@ -21,6 +21,9 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
@ -30,17 +33,14 @@ import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.AgentManager.OnError;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.LoadBalancerTO;
import com.cloud.agent.manager.Commands;
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.Pod;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan.VlanType;
@ -65,9 +65,9 @@ import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.Network;
import com.cloud.network.Network.GuestIpType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
@ -80,6 +80,7 @@ import com.cloud.network.router.VirtualRouter.Role;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.LoadBalancer;
import com.cloud.network.security.SecurityGroupManagerImpl.WorkerThread;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
@ -96,11 +97,12 @@ import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachine;
@ -173,6 +175,7 @@ public class ElasticLoadBalancerManagerImpl implements
Account _systemAcct;
ServiceOfferingVO _elasticLbVmOffering;
ScheduledExecutorService _gcThreadPool;
int _elasticLbVmRamSize;
int _elasticLbvmCpuMHz;
@ -247,7 +250,6 @@ public class ElasticLoadBalancerManagerImpl implements
private void createApplyLoadBalancingRulesCommands(
List<LoadBalancingRule> rules, DomainRouterVO router, Commands cmds) {
String elbIp = "";
LoadBalancerTO[] lbs = new LoadBalancerTO[rules.size()];
int i = 0;
@ -257,7 +259,7 @@ public class ElasticLoadBalancerManagerImpl implements
String protocol = rule.getProtocol();
String algorithm = rule.getAlgorithm();
elbIp = _networkMgr.getIp(rule.getSourceIpAddressId()).getAddress()
String elbIp = _networkMgr.getIp(rule.getSourceIpAddressId()).getAddress()
.addr();
int srcPort = rule.getSourcePortStart();
List<LbDestination> destinations = rule.getDestinations();
@ -366,6 +368,8 @@ public class ElasticLoadBalancerManagerImpl implements
_frontendTrafficType = TrafficType.Public;
} else
throw new ConfigurationException("Traffic type for front end of load balancer has to be guest or public; found : " + traffType);
_gcThreadPool = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ELBVM-GC"));
_gcThreadPool.scheduleAtFixedRate(new CleanupThread(), 30, 30, TimeUnit.SECONDS);
}
@ -470,6 +474,20 @@ public class ElasticLoadBalancerManagerImpl implements
}
}
private DomainRouterVO stop(DomainRouterVO elbVm, boolean forced, User user, Account caller) throws ConcurrentOperationException, ResourceUnavailableException {
s_logger.debug("Stopping elb vm " + elbVm);
try {
if (_itMgr.advanceStop( elbVm, forced, user, caller)) {
return _routerDao.findById(elbVm.getId());
} else {
return null;
}
} catch (OperationTimedoutException e) {
throw new CloudRuntimeException("Unable to stop " + elbVm, e);
}
}
protected List<LoadBalancerVO> findExistingLoadBalancers(String lbName, Long ipId, Long accountId, Long domainId, Integer publicPort) {
SearchBuilder<LoadBalancerVO> sb = _lbDao.createSearchBuilder();
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
@ -583,6 +601,7 @@ public class ElasticLoadBalancerManagerImpl implements
if (newIp) {
releaseIp(ipId, UserContext.current().getCallerUserId(), account);
}
throw e;
}
DomainRouterVO elbVm = null;
@ -614,7 +633,7 @@ public class ElasticLoadBalancerManagerImpl implements
return null;
}
ElasticLbVmMapVO mapping = new ElasticLbVmMapVO(ipId, elbVm.getId());
ElasticLbVmMapVO mapping = new ElasticLbVmMapVO(ipId, elbVm.getId(), result.getId());
_elbVmMapDao.persist(mapping);
return result;
@ -626,25 +645,42 @@ public class ElasticLoadBalancerManagerImpl implements
}
private void createAssociateIPCommand(final DomainRouterVO router, final Network network, final PublicIp ip, Commands cmds) {
IpAddressTO[] ipsToSend = new IpAddressTO[1];
IpAddressTO ipTO = new IpAddressTO(ip.getAddress().addr(), true, false, false, ip.getVlanTag(), ip.getVlanGateway(), ip.getVlanNetmask(), ip.getMacAddress(), null, 0);
ipTO.setTrafficType(network.getTrafficType());
ipTO.setNetworkTags(network.getTags());
ipsToSend[0] = ipTO;
IpAssocCommand cmd = new IpAssocCommand(ipsToSend);
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress());
cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, router.getGuestIpAddress());
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
DataCenterVO dcVo = _dcDao.findById(router.getDataCenterIdToDeployIn());
cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString());
cmds.addCommand("IPAssocCommand", cmd);
void garbageCollectUnusedElbVms() {
List<DomainRouterVO> unusedElbVms = _elbVmMapDao.listUnusedElbVms();
if (unusedElbVms != null && unusedElbVms.size() > 0)
s_logger.info("Found " + unusedElbVms.size() + " unused ELB vms");
else
return;
User user = _accountService.getSystemUser();
for (DomainRouterVO elbVm : unusedElbVms) {
try {
s_logger.info("Attempting to stop ELB VM: " + elbVm);
stop(elbVm, true, user, _systemAcct);
} catch (ConcurrentOperationException e) {
s_logger.warn("Unable to stop unused elb vm " + elbVm + " due to ", e);
continue;
} catch (ResourceUnavailableException e) {
s_logger.warn("Unable to stop unused elb vm " + elbVm + " due to ", e);
continue;
}
try {
s_logger.info("Attempting to destroy ELB VM: " + elbVm);
_itMgr.expunge(elbVm, user, _systemAcct);
} catch (ResourceUnavailableException e) {
s_logger.warn("Unable to destroy unused elb vm " + elbVm + " due to ", e);
}
}
}
public class CleanupThread implements Runnable {
@Override
public void run() {
garbageCollectUnusedElbVms();
}
CleanupThread() {
}
}
}

View File

@ -51,8 +51,6 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVMMapVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.Network;
import com.cloud.network.Network.GuestIpType;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
@ -61,7 +59,6 @@ import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
@ -335,7 +332,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
}
txn.commit();
if (apply) {
try {
if (!applyLoadBalancerConfig(loadBalancerId)) {

View File

@ -22,6 +22,7 @@ import java.util.List;
import com.cloud.network.ElasticLbVmMapVO;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.DomainRouterVO;
public interface ElasticLbVmMapDao extends GenericDao<ElasticLbVmMapVO, Long> {
ElasticLbVmMapVO findOneByLbIdAndElbVmId(long lbId, long elbVmId);
@ -31,5 +32,6 @@ public interface ElasticLbVmMapDao extends GenericDao<ElasticLbVmMapVO, Long> {
List<ElasticLbVmMapVO> listByElbVmId(long elbVmId);
List<ElasticLbVmMapVO> listByLbId(long lbId);
int deleteLB(long lbId);
List<DomainRouterVO> listUnusedElbVms();
}

View File

@ -23,13 +23,23 @@ import java.util.List;
import javax.ejb.Local;
import com.cloud.network.ElasticLbVmMapVO;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.DomainRouterDaoImpl;
@Local(value={ElasticLbVmMapDao.class})
public class ElasticLbVmMapDaoImpl extends GenericDaoBase<ElasticLbVmMapVO, Long> implements ElasticLbVmMapDao {
private SearchBuilder<ElasticLbVmMapVO> AllFieldsSearch;
protected final DomainRouterDao _routerDao = ComponentLocator.inject(DomainRouterDaoImpl.class);
protected final SearchBuilder<ElasticLbVmMapVO> AllFieldsSearch;
protected final SearchBuilder<ElasticLbVmMapVO> UnusedVmSearch;
protected final SearchBuilder<DomainRouterVO> ElbVmSearch;
protected ElasticLbVmMapDaoImpl() {
AllFieldsSearch = createSearchBuilder();
@ -37,7 +47,15 @@ public class ElasticLbVmMapDaoImpl extends GenericDaoBase<ElasticLbVmMapVO, Long
AllFieldsSearch.and("lbId", AllFieldsSearch.entity().getLbId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("elbVmId", AllFieldsSearch.entity().getElbVmId(), SearchCriteria.Op.EQ);
AllFieldsSearch.done();
ElbVmSearch = _routerDao.createSearchBuilder();
ElbVmSearch.and("role", ElbVmSearch.entity().getRole(), SearchCriteria.Op.EQ);
UnusedVmSearch = createSearchBuilder();
UnusedVmSearch.and("elbVmId", UnusedVmSearch.entity().getElbVmId(), SearchCriteria.Op.NULL);
ElbVmSearch.join("UnusedVmSearch", UnusedVmSearch, ElbVmSearch.entity().getId(), UnusedVmSearch.entity().getElbVmId(), JoinType.LEFTOUTER);
ElbVmSearch.done();
UnusedVmSearch.done();
}
@Override
@ -84,5 +102,9 @@ public class ElasticLbVmMapDaoImpl extends GenericDaoBase<ElasticLbVmMapVO, Long
return findOneBy(sc);
}
public List<DomainRouterVO> listUnusedElbVms() {
SearchCriteria<DomainRouterVO> sc = ElbVmSearch.create();
return _routerDao.search(sc, null);
}
}

View File

@ -1,13 +1,16 @@
package com.cloud.network.dao;
import java.util.List;
import junit.framework.TestCase;
import com.cloud.network.ElasticLbVmMapVO;
import com.cloud.network.lb.dao.ElasticLbVmMapDaoImpl;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.vm.DomainRouterVO;
public class ElbVmMapDaoTest extends TestCase {
public void testTags() {
public void testFindByIp() {
ElasticLbVmMapDaoImpl dao = ComponentLocator.inject(ElasticLbVmMapDaoImpl.class);
ElasticLbVmMapVO map = dao.findOneByIp(3);
@ -17,4 +20,14 @@ public class ElbVmMapDaoTest extends TestCase {
System.out.println("Found");
}
}
public void testFindUnused() {
ElasticLbVmMapDaoImpl dao = ComponentLocator.inject(ElasticLbVmMapDaoImpl.class);
List<DomainRouterVO> map = dao.listUnusedElbVms();
if (map == null) {
System.out.println("Not Found");
} else {
System.out.println("Found");
}
}
}

View File

@ -1550,7 +1550,7 @@ CREATE TABLE `cloud`.`elastic_lb_vm_map` (
PRIMARY KEY (`id`),
CONSTRAINT `fk_elastic_lb_vm_map__ip_id` FOREIGN KEY `fk_elastic_lb_vm_map__ip_id` (`ip_addr_id`) REFERENCES `user_ip_address` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_elastic_lb_vm_map__elb_vm_id` FOREIGN KEY `fk_elastic_lb_vm_map__elb_vm_id` (`elb_vm_id`) REFERENCES `domain_router` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_elastic_lb_vm_map__lb_id` FOREIGN KEY `fk_elastic_lb_vm_map__lb_id` (`lb_id`) REFERENCES `load_balancing_rules` (`id`)
CONSTRAINT `fk_elastic_lb_vm_map__lb_id` FOREIGN KEY `fk_elastic_lb_vm_map__lb_id` (`lb_id`) REFERENCES `load_balancing_rules` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET foreign_key_checks = 1;