From b240c4a645e5575eabe548eecc876a165268456d Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Wed, 27 Jul 2011 20:44:04 -0700 Subject: [PATCH] WIP: make creating an ELB bullet proof --- .../commands/CreateLoadBalancerRuleCmd.java | 44 +--- .../network/lb/LoadBalancingRulesService.java | 4 +- .../element/ElasticLoadBalancerElement.java | 45 +++- .../lb/ElasticLoadBalancerManager.java | 3 +- .../lb/ElasticLoadBalancerManagerImpl.java | 199 +++++++++++++++--- .../network/lb/LoadBalancingRulesManager.java | 6 + .../lb/LoadBalancingRulesManagerImpl.java | 51 +++-- 7 files changed, 251 insertions(+), 101 deletions(-) diff --git a/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java b/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java index ff7d9c5cc52..f0aeff3aaa6 100644 --- a/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java +++ b/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java @@ -126,55 +126,17 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCmd /*implements LoadBa return s_name; } - protected LoadBalancer findExistingLB() { - List lbs = _lbService.searchForLoadBalancers(new ListLoadBalancerRulesCmd(getAccountName(), getDomainId(), null, getName(), publicIpId, null, getZoneId()) ); - if (lbs != null && lbs.size() > 0) { - return lbs.get(0); - } - return null; - } - - protected void allocateIp() throws ResourceAllocationException, ResourceUnavailableException { - AssociateIPAddrCmd allocIpCmd = new AssociateIPAddrCmd(getAccountName(), getDomainId(), getZoneId(), null); - try { - IpAddress ip = _networkService.allocateIP(allocIpCmd); - if (ip != null) { - this.setPublicIpId(ip.getId()); - allocIpCmd.setEntityId(ip.getId()); - } else { - throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to allocate ip address"); - } - //UserContext.current().setEventDetails("Ip Id: "+ ip.getId()); - //IpAddress result = _networkService.associateIP(allocIpCmd); - } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); - throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage()); - } catch (InsufficientAddressCapacityException ex) { - s_logger.info(ex); - s_logger.trace(ex); - throw new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); - } - } - @Override public void execute() throws ResourceAllocationException, ResourceUnavailableException { LoadBalancer result = null; try { - if (publicIpId == null) { - if (getZoneId() == null ) { - throw new InvalidParameterValueException("Either zone id or public ip id needs to be specified"); - } - LoadBalancer existing = findExistingLB(); - if (existing == null) { - allocateIp(); - } else { - this.setPublicIpId(existing.getSourceIpAddressId()); - } - } result = _lbService.createLoadBalancerRule(this); } catch (NetworkRuleConflictException e) { s_logger.warn("Exception: ", e); throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); + } catch (InsufficientAddressCapacityException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, e.getMessage()); } LoadBalancerResponse response = _responseGenerator.createLoadBalancerResponse(result); response.setResponseName(getCommandName()); diff --git a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java index ae2eda46e6e..38bde4d6311 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java @@ -23,6 +23,7 @@ import com.cloud.api.commands.CreateLoadBalancerRuleCmd; import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd; import com.cloud.api.commands.ListLoadBalancerRulesCmd; import com.cloud.api.commands.UpdateLoadBalancerRuleCmd; +import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.rules.LoadBalancer; @@ -33,8 +34,9 @@ public interface LoadBalancingRulesService { * Create a load balancer rule from the given ipAddress/port to the given private port * @param cmd the command specifying the ip address, public port, protocol, private port, and algorithm * @return the newly created LoadBalancerVO if successful, null otherwise + * @throws InsufficientAddressCapacityException */ - LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException; + LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException, InsufficientAddressCapacityException; LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd); diff --git a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java index e25ff5d44c8..40deb28930f 100644 --- a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java @@ -22,25 +22,37 @@ import java.util.List; import java.util.Map; import javax.ejb.Local; +import javax.naming.ConfigurationException; import org.apache.log4j.Logger; -import com.cloud.configuration.ConfigurationManager; -import com.cloud.dc.DataCenter; +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.NetworkManager; +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; @@ -53,12 +65,16 @@ import com.cloud.vm.VirtualMachineProfile; public class ElasticLoadBalancerElement extends AdapterBase implements NetworkElement{ private static final Logger s_logger = Logger.getLogger(ElasticLoadBalancerElement.class); private static final Map> capabilities = setCapabilities(); - @Inject ConfigurationManager _configMgr; @Inject NetworkManager _networkManager; @Inject ElasticLoadBalancerManager _lbMgr; + @Inject ConfigurationDao _configDao; + @Inject NetworkOfferingDao _networkOfferingDao; + @Inject NetworkDao _networksDao; + + boolean _enabled; + TrafficType _frontEndTrafficType = TrafficType.Guest; private boolean canHandle(Network network) { - // DataCenter zone = _configMgr.getZone(network.getDataCenterId()); if (network.getGuestType() != Network.GuestIpType.Direct || network.getTrafficType() != TrafficType.Guest) { s_logger.debug("Not handling network with guest Type " + network.getGuestType() + " and traffic type " + network.getTrafficType()); return false; @@ -140,4 +156,23 @@ public class ElasticLoadBalancerElement extends AdapterBase implements NetworkEl return _lbMgr.applyLoadBalancerRules(network, rules); } + + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + + super.configure(name, params); + String enabled = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key()); + _enabled = (enabled == null) ? false: Boolean.parseBoolean(enabled); + if (_enabled) { + String traffType = _configDao.getValue(Config.ElasticLoadBalancerNetwork.key()); + if ("guest".equalsIgnoreCase(traffType)) { + _frontEndTrafficType = TrafficType.Guest; + } else if ("public".equalsIgnoreCase(traffType)){ + _frontEndTrafficType = TrafficType.Public; + } else + throw new ConfigurationException("Traffic type for front end of load balancer has to be guest or public; found : " + traffType); + } + return true; + } } diff --git a/server/src/com/cloud/network/lb/ElasticLoadBalancerManager.java b/server/src/com/cloud/network/lb/ElasticLoadBalancerManager.java index 7bac4d97b49..06ccd5448f2 100644 --- a/server/src/com/cloud/network/lb/ElasticLoadBalancerManager.java +++ b/server/src/com/cloud/network/lb/ElasticLoadBalancerManager.java @@ -21,6 +21,7 @@ import java.util.List; import com.cloud.api.commands.CreateLoadBalancerRuleCmd; 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; @@ -38,6 +39,6 @@ public interface ElasticLoadBalancerManager { List rules) throws ResourceUnavailableException; - public void handleCreateLoadBalancerRule(CreateLoadBalancerRuleCmd lb, Account caller); + public LoadBalancer handleCreateLoadBalancerRule(CreateLoadBalancerRuleCmd lb, Account caller) throws InsufficientAddressCapacityException; } diff --git a/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 345997978c8..4beb8345f2b 100644 --- a/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -43,6 +43,7 @@ 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; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; @@ -52,8 +53,10 @@ import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; @@ -62,6 +65,7 @@ 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.addr.PublicIp; @@ -86,11 +90,16 @@ import com.cloud.storage.dao.VMTemplateDao; import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.User; +import com.cloud.user.UserContext; +import com.cloud.user.dao.AccountDao; 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.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.vm.DomainRouterVO; import com.cloud.vm.NicProfile; @@ -150,10 +159,17 @@ public class ElasticLoadBalancerManagerImpl implements PodVlanMapDao _podVlanMapDao; @Inject ElasticLbVmMapDao _elbVmMapDao; + @Inject + NetworkDao _networksDao; + @Inject + AccountDao _accountDao; String _name; String _instance; + + boolean _enabled; + TrafficType _frontendTrafficType = TrafficType.Guest; Account _systemAcct; ServiceOfferingVO _elasticLbVmOffering; @@ -340,6 +356,18 @@ public class ElasticLoadBalancerManagerImpl implements _elasticLbVmOffering.setUniqueName("Cloud.Com-ElasticLBVm"); _elasticLbVmOffering = _serviceOfferingDao.persistSystemServiceOffering(_elasticLbVmOffering); + String enabled = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key()); + _enabled = (enabled == null) ? false: Boolean.parseBoolean(enabled); + if (_enabled) { + String traffType = _configDao.getValue(Config.ElasticLoadBalancerNetwork.key()); + if ("guest".equalsIgnoreCase(traffType)) { + _frontendTrafficType = TrafficType.Guest; + } else if ("public".equalsIgnoreCase(traffType)){ + _frontendTrafficType = TrafficType.Public; + } else + throw new ConfigurationException("Traffic type for front end of load balancer has to be guest or public; found : " + traffType); + } + return true; } @@ -441,52 +469,153 @@ public class ElasticLoadBalancerManagerImpl implements return null; } } + + protected List findExistingLoadBalancers(String lbName, Long ipId, Long accountId, Long domainId, Integer publicPort) { + SearchBuilder sb = _lbDao.createSearchBuilder(); + sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ); + sb.and("publicPort", sb.entity().getSourcePortStart(), SearchCriteria.Op.EQ); + if (ipId != null) { + sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ); + } + if (domainId != null) { + sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); + } + if (publicPort != null) { + sb.and("publicPort", sb.entity().getSourcePortStart(), SearchCriteria.Op.EQ); + } + SearchCriteria sc = sb.create(); + sc.setParameters("name", lbName); + sc.setParameters("accountId", accountId); + if (ipId != null) { + sc.setParameters("sourceIpAddress", ipId); + } + if (domainId != null) { + sc.setParameters("domainId",domainId); + } + if (publicPort != null) { + sc.setParameters("publicPort", publicPort); + } + List lbs = _lbDao.search(sc, null); + + return lbs == null || lbs.size()==0 ? null: lbs; + } + + @DB + public PublicIp allocIp(CreateLoadBalancerRuleCmd lb, Account account) throws InsufficientAddressCapacityException { + //TODO: this only works in the guest network. Handle the public network case also. + List offerings = _networkOfferingDao.listByTrafficTypeAndGuestType(true, _frontendTrafficType, GuestIpType.Direct); + if (offerings == null || offerings.size() == 0) { + s_logger.warn("Could not find system offering for direct networks of type " + _frontendTrafficType); + return null; + } + NetworkOffering frontEndOffering = offerings.get(0); + List networks = _networksDao.listBy(Account.ACCOUNT_ID_SYSTEM, frontEndOffering.getId(), lb.getZoneId()); + if (networks == null || networks.size() == 0) { + s_logger.warn("Could not find network of offering type " + frontEndOffering + " in zone " + lb.getZoneId()); + return null; + } + Network frontEndNetwork = networks.get(0); + Transaction txn = Transaction.currentTxn(); + PublicIp ip = _networkMgr.assignPublicIpAddress(lb.getZoneId(), null, account, VlanType.DirectAttached, frontEndNetwork.getId(), null); + IPAddressVO ipvo = _ipAddressDao.findById(ip.getId()); + ipvo.setAssociatedWithNetworkId(frontEndNetwork.getId()); + _ipAddressDao.update(ipvo.getId(), ipvo); + txn.commit(); + s_logger.info("Acquired public IP for loadbalancing " + ip); + + return ip; + } + + public void releaseIp(long ipId, long userId, Account caller) { + s_logger.info("Release public IP for loadbalancing " + ipId); + _networkMgr.releasePublicIpAddress(ipId, userId, caller); + } @Override @DB - public void handleCreateLoadBalancerRule( CreateLoadBalancerRuleCmd lb, Account account) { - - long ipId = lb.getSourceIpAddressId(); - IPAddressVO ipAddr = _ipAddressDao.findById(ipId); - Long networkId= ipAddr.getSourceNetworkId(); - NetworkVO network=_networkDao.findById(networkId); - - if (network.getGuestType() != GuestIpType.Direct) { - s_logger.info("Elastic LB Manager: not handling guest traffic of type " + network.getGuestType()); - return; + public LoadBalancer handleCreateLoadBalancerRule( CreateLoadBalancerRuleCmd lb, Account account) throws InsufficientAddressCapacityException { + Long ipId = lb.getSourceIpAddressId(); + boolean newIp = false; + account = _accountDao.acquireInLockTable(account.getId()); + if (account == null) { + s_logger.warn("CreateLoadBalancer: Failed to acquire lock on account"); } - DomainRouterVO elbVm = null; + try { + List existingLbs = findExistingLoadBalancers(lb.getName(), lb.getSourceIpAddressId(), lb.getAccountId(), lb.getDomainId(), lb.getSourcePortStart()); + if (existingLbs == null ){ + existingLbs = findExistingLoadBalancers(lb.getName(), lb.getSourceIpAddressId(), lb.getAccountId(), lb.getDomainId(), null); + if (existingLbs == null) { + if (lb.getSourceIpAddressId() != null) { + existingLbs = findExistingLoadBalancers(lb.getName(), null, lb.getAccountId(), lb.getDomainId(), null); + if (existingLbs != null) { + throw new InvalidParameterValueException("Supplied LB name " + lb.getName() + " is not associated with IP " + lb.getSourceIpAddressId() ); + } + } else { + PublicIp ip = allocIp(lb, account); + ipId = ip.getId(); + newIp = true; + } + } + } - LoadBalancerVO lbvo; - lbvo = _lbDao.findByAccountAndName(account.getId(), lb.getName()); - if (lbvo == null) { - elbVm = findELBVmWithCapacity(network, ipAddr); - if (elbVm == null) { - elbVm = deployLoadBalancerVM(networkId, ipAddr, account.getId()); + IPAddressVO ipAddr = _ipAddressDao.findById(ipId); + Long networkId= ipAddr.getSourceNetworkId(); + NetworkVO network=_networkDao.findById(networkId); + + + if (network.getGuestType() != GuestIpType.Direct) { + s_logger.info("Elastic LB Manager: not handling guest traffic of type " + network.getGuestType()); + return null; + } + LoadBalancer result = null; + try { + result = _lbMgr.createLoadBalancer(lb); + } catch (NetworkRuleConflictException e) { + s_logger.warn("Failed to create LB rule, not continuing with ELB deployment"); + if (newIp) { + releaseIp(ipId, UserContext.current().getCallerUserId(), account); + } + } + + DomainRouterVO elbVm = null; + + + if (existingLbs == null) { + elbVm = findELBVmWithCapacity(network, ipAddr); if (elbVm == null) { - s_logger.warn("Failed to deploy a new ELB vm for ip " + ipAddr + " in network " + network + "lb name=" + lb.getName()); - return; //TODO: throw exception + elbVm = deployLoadBalancerVM(networkId, ipAddr, account.getId()); + if (elbVm == null) { + s_logger.warn("Failed to deploy a new ELB vm for ip " + ipAddr + " in network " + network + "lb name=" + lb.getName()); + if (newIp) + releaseIp(ipId, UserContext.current().getCallerUserId(), account); + + } + } + + } else { + ElasticLbVmMapVO elbVmMap = _elbVmMapDao.findOneByIp(ipId); + if (elbVmMap != null) { + elbVm = _routerDao.findById(elbVmMap.getElbVmId()); } } - } else { - ElasticLbVmMapVO elbVmMap = _elbVmMapDao.findOneByIp(lb.getSourceIpAddressId()); - if (elbVmMap != null) { - elbVm = _routerDao.findById(elbVmMap.getElbVmId()); + if (elbVm == null) { + s_logger.warn("No ELB VM can be found or deployed"); + s_logger.warn("Deleting LB since we failed to deploy ELB VM"); + _lbDao.remove(result.getId()); + return null; + } + + ElasticLbVmMapVO mapping = new ElasticLbVmMapVO(ipId, elbVm.getId()); + _elbVmMapDao.persist(mapping); + return result; + + } finally { + if (account != null) { + _accountDao.releaseFromLockTable(account.getId()); } } - if (elbVm == null) { - s_logger.warn("No ELB VM can be found or deployed"); - return; - } - Transaction txn = Transaction.currentTxn(); - txn.start(); - IPAddressVO ipvo = _ipAddressDao.findById(ipId); - ipvo.setAssociatedWithNetworkId(networkId); - _ipAddressDao.update(ipvo.getId(), ipvo); - ElasticLbVmMapVO mapping = new ElasticLbVmMapVO(ipId, elbVm.getId()); - _elbVmMapDao.persist(mapping); - txn.commit(); } diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java index 61d61429639..8da4adb8a1a 100644 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java @@ -19,11 +19,17 @@ package com.cloud.network.lb; import java.util.List; +import com.cloud.api.commands.CreateLoadBalancerRuleCmd; +import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.rules.LoadBalancer; import com.cloud.user.Account; public interface LoadBalancingRulesManager extends LoadBalancingRulesService { + + LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException; + boolean removeAllLoadBalanacersForIp(long ipId, Account caller, long callerUserId); boolean removeAllLoadBalanacersForNetwork(long networkId, Account caller, long callerUserId); List getExistingDestinations(long lbId); diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 6cca151b226..68e1f9c2e7d 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -43,6 +43,7 @@ import com.cloud.event.EventTypes; import com.cloud.event.UsageEventVO; import com.cloud.event.dao.EventDao; import com.cloud.event.dao.UsageEventDao; +import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.PermissionDeniedException; @@ -60,6 +61,7 @@ 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; @@ -72,6 +74,7 @@ import com.cloud.user.UserContext; import com.cloud.user.dao.AccountDao; import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; +import com.cloud.utils.component.Adapters; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.db.DB; @@ -126,7 +129,9 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, ElasticLoadBalancerManager _elbMgr; @Inject NetworkDao _networkDao; - + @Inject(adapter = LoadBalancerElement.class) + Adapters _lbElements; + @Override @DB @ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true) @@ -347,26 +352,11 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, s_logger.debug("Load balancer with id " + lb.getId() + " is removed successfully"); return true; } - + @Override @ActionEvent(eventType = EventTypes.EVENT_LOAD_BALANCER_CREATE, eventDescription = "creating load balancer") - public LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException { + public LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException, InsufficientAddressCapacityException { UserContext caller = UserContext.current(); - - long ipId = lb.getSourceIpAddressId(); - - - _elbMgr.handleCreateLoadBalancerRule(lb, caller.getCaller()); - - - IPAddressVO ipAddr = _ipAddressDao.findById(ipId); - Long networkId= ipAddr.getSourceNetworkId(); - NetworkVO network=_networkDao.findById(networkId); - // make sure ip address exists - if (ipAddr == null || !ipAddr.readyToUse()) { - throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id" + ipId); - } - int srcPortStart = lb.getSourcePortStart(); int srcPortEnd = lb.getSourcePortEnd(); int defPortStart = lb.getDefaultPortStart(); @@ -394,6 +384,31 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, throw new InvalidParameterValueException("Invalid algorithm: " + lb.getAlgorithm()); } + Long ipId = lb.getSourceIpAddressId(); + + if (ipId == null) { + return _elbMgr.handleCreateLoadBalancerRule(lb, caller.getCaller()); + + } else { + return createLoadBalancer(lb); + } + + } + + public LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException { + long ipId = lb.getSourceIpAddressId(); + UserContext caller = UserContext.current(); + int srcPortStart = lb.getSourcePortStart(); + int defPortStart = lb.getDefaultPortStart(); + + IPAddressVO ipAddr = _ipAddressDao.findById(lb.getSourceIpAddressId()); + Long networkId = ipAddr.getSourceNetworkId(); + NetworkVO network = _networkDao.findById(networkId); + // make sure ip address exists + if (ipAddr == null || !ipAddr.readyToUse()) { + throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id" + ipId); + } + networkId = ipAddr.getAssociatedWithNetworkId(); if (networkId == null) { throw new InvalidParameterValueException("Unable to create load balancer rule ; ip id=" + ipId + " is not associated with any network");