Acquire an ip and launch an ELB vm

This commit is contained in:
Chiradeep Vittal 2011-07-21 18:04:48 -07:00
parent 4c8f5e0591
commit cd8e069f80
16 changed files with 781 additions and 19 deletions

View File

@ -189,5 +189,13 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.IpAddress;
}
public AssociateIPAddrCmd(String accountName, Long domainId, Long zoneId, Long networkId) {
super();
this.accountName = accountName;
this.domainId = domainId;
this.zoneId = zoneId;
this.networkId = networkId;
}
}

View File

@ -18,6 +18,8 @@
package com.cloud.api.commands;
import java.util.List;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
@ -26,10 +28,16 @@ import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.LoadBalancerResponse;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.rules.LoadBalancer;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.utils.net.NetUtils;
@Implementation(description="Creates a load balancer rule", responseObject=LoadBalancerResponse.class)
@ -54,13 +62,21 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
@Parameter(name=ApiConstants.PRIVATE_PORT, type=CommandType.INTEGER, required=true, description="the private port of the private ip address/virtual machine where the network traffic will be load balanced to")
private Integer privatePort;
@Parameter(name=ApiConstants.PUBLIC_IP_ID, type=CommandType.LONG, required=true, description="public ip address id from where the network traffic will be load balanced from")
@Parameter(name=ApiConstants.PUBLIC_IP_ID, type=CommandType.LONG, required=false, description="public ip address id from where the network traffic will be load balanced from")
private Long publicIpId;
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required=false, description="public ip address id from where the network traffic will be load balanced from")
private Long zoneId;
@Parameter(name=ApiConstants.PUBLIC_PORT, type=CommandType.INTEGER, required=true, description="the public port from where the network traffic will be load balanced from")
private Integer publicPort;
@Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account associated with the load balancer. Must be used with the domainId parameter.")
private String accountName;
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, description="the domain ID associated with the load balancer")
private Long domainId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -86,7 +102,7 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
public Long getPublicIpId() {
IpAddress ipAddr = _networkService.getIp(publicIpId);
if (ipAddr == null || !ipAddr.readyToUse()) {
throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id" + ipAddr.getId());
throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id " + ipAddr.getId());
}
return publicIpId;
@ -109,10 +125,51 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
return s_name;
}
protected LoadBalancer findExistingLB() {
List<? extends LoadBalancer> 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() {
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);
@ -171,12 +228,33 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
@Override
public long getAccountId() {
return _networkService.getIp(getPublicIpId()).getAccountId();
if (publicIpId != null)
return _networkService.getIp(getPublicIpId()).getAccountId();
Account account = UserContext.current().getCaller();
if ((account == null) ) {
if ((domainId != null) && (accountName != null)) {
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
if (userAccount != null) {
return userAccount.getId();
}
}
}
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public long getDomainId() {
return _networkService.getIp(getPublicIpId()).getDomainId();
if (publicIpId != null)
return _networkService.getIp(getPublicIpId()).getDomainId();
if (domainId != null) {
return domainId;
}
return UserContext.current().getCaller().getDomainId();
}
@Override
@ -192,5 +270,18 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
@Override
public long getEntityOwnerId() {
return getAccountId();
}
}
public String getAccountName() {
return accountName;
}
public Long getZoneId() {
return zoneId;
}
public void setPublicIpId(Long publicIpId) {
this.publicIpId = publicIpId;
}
}

View File

@ -119,4 +119,15 @@ public class ListLoadBalancerRulesCmd extends BaseListCmd {
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
public ListLoadBalancerRulesCmd(String accountName, Long domainId, Long id, String loadBalancerRuleName, Long publicIpId, Long virtualMachineId, Long zoneId) {
super();
this.accountName = accountName;
this.domainId = domainId;
this.id = id;
this.loadBalancerRuleName = loadBalancerRuleName;
this.publicIpId = publicIpId;
this.virtualMachineId = virtualMachineId;
this.zoneId = zoneId;
}
}

View File

@ -93,6 +93,8 @@ public interface Network extends ControlledEntity {
public static final Provider F5BigIp = new Provider("F5BigIp");
public static final Provider ExternalDhcpServer = new Provider("ExternalDhcpServer");
public static final Provider ExternalGateWay = new Provider("ExternalGateWay");
public static final Provider ElasticLoadBalancerVm = new Provider("ElasticLoadBalancerVm");
public static final Provider None = new Provider("None");
private String name;

View File

@ -26,7 +26,7 @@ import com.cloud.vm.VirtualMachine;
public interface VirtualRouter extends VirtualMachine {
public enum Role {
DHCP_FIREWALL_LB_PASSWD_USERDATA,
DHCP_USERDATA
DHCP_USERDATA, LB
}
Role getRole();
}
}

View File

@ -32,5 +32,5 @@ public interface LoadBalancer extends FirewallRule {
int getDefaultPortEnd();
String getAlgorithm();
}

View File

@ -151,6 +151,8 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject
DomainRouter,
ConsoleProxy,
SecondaryStorageVm,
ElasticIpVm,
ElasticLoadBalancerVm,
/*
* UserBareMetal is only used for selecting VirtualMachineGuru, there is no

View File

@ -89,6 +89,8 @@
<adapter name="DomainRouter" class="com.cloud.network.element.VirtualRouterElement"/>
<adapter name="Dhcp" class="com.cloud.network.element.DhcpElement"/>
<adapter name="Ovs" class="com.cloud.network.element.OvsElement"/>
<adapter name="ElasticLoadBalancer" class="com.cloud.network.element.ElasticLoadBalancerElement"/>
</adapters>
<adapters key="com.cloud.acl.SecurityChecker">
<adapter name="DomainChecker" class="com.cloud.acl.DomainChecker"/>

View File

@ -79,6 +79,7 @@ import com.cloud.network.dao.LoadBalancerVMMapDaoImpl;
import com.cloud.network.dao.NetworkDaoImpl;
import com.cloud.network.dao.NetworkDomainDaoImpl;
import com.cloud.network.dao.NetworkRuleConfigDaoImpl;
import com.cloud.network.lb.ElasticLoadBalancerManagerImpl;
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
import com.cloud.network.ovs.OvsNetworkManagerImpl;
import com.cloud.network.ovs.OvsTunnelManagerImpl;
@ -315,6 +316,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
ComponentInfo<? extends Manager> info = addManager("ConsoleProxyManager", ConsoleProxyManagerImpl.class);
info.addParameter("consoleproxy.sslEnabled", "true");
addManager("ClusteredAgentManager", ClusteredAgentManagerImpl.class);
addManager("ElasticLoadBalancerManager", ElasticLoadBalancerManagerImpl.class);
}
@Override

View File

@ -205,6 +205,7 @@ public class DataCenterVO implements DataCenter {
dhcpProvider = Provider.DhcpServer.getName();
dnsProvider = Provider.DhcpServer.getName();
userDataProvider = Provider.DhcpServer.getName();
loadBalancerProvider = Provider.ElasticLoadBalancerVm.getName();
}
this.zoneToken = zoneToken;

View File

@ -559,6 +559,16 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (zone.getNetworkType() != NetworkType.Basic && network.getAccountId() != ipOwner.getId()) {
throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP");
}
VlanType vlanType = VlanType.VirtualNetwork;
boolean assign = false;
//For basic zone, if there isn't a public network outside of the guest network, specify the vlan type to be direct attached
if (zone.getNetworkType() == NetworkType.Basic) {
if (network.getTrafficType() == TrafficType.Guest){
vlanType = VlanType.DirectAttached;
assign = true;
}
}
PublicIp ip = null;
@ -601,7 +611,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
}
ip = fetchNewPublicIp(zoneId, null, null, ipOwner, VlanType.VirtualNetwork, network.getId(), isSourceNat, false, null);
ip = fetchNewPublicIp(zoneId, null, null, ipOwner, vlanType, network.getId(), isSourceNat, assign, null);
if (ip == null) {
throw new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zoneId);
@ -754,8 +764,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestNetworkOffering);
NetworkOfferingVO defaultGuestDirectNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectNetworkOffering, "Direct", TrafficType.Guest, false, true, null, null, null, true,
Availability.Optional,
// services - all true except for firewall/lb/vpn and gateway services
true, true, true, false, false, false, false, GuestIpType.Direct);
// services - all true except for firewall/vpn and gateway services
true, true, true, false, false, true, false, GuestIpType.Direct);
defaultGuestDirectNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering);
AccountsUsingNetworkSearch = _accountDao.createSearchBuilder();

View File

@ -0,0 +1,144 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.element;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.DataCenter;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PublicIpAddress;
import com.cloud.network.lb.ElasticLoadBalancerManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value=NetworkElement.class)
public class ElasticLoadBalancerElement extends AdapterBase implements NetworkElement{
private static final Logger s_logger = Logger.getLogger(ElasticLoadBalancerElement.class);
private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
@Inject ConfigurationManager _configMgr;
@Inject NetworkManager _networkManager;
@Inject ElasticLoadBalancerManager _lbMgr;
private boolean canHandle(Network config) {
DataCenter zone = _configMgr.getZone(config.getDataCenterId());
if (config.getGuestType() != Network.GuestIpType.Virtual || config.getTrafficType() != TrafficType.Guest) {
s_logger.trace("Not handling network with guest Type " + config.getGuestType() + " and traffic type " + config.getTrafficType());
return false;
}
return (_networkManager.zoneIsConfiguredForExternalNetworking(zone.getId()) &&
zone.getLoadBalancerProvider() != null && zone.getLoadBalancerProvider().equals(Network.Provider.F5BigIp.getName()));
}
@Override
public Provider getProvider() {
return Provider.ElasticLoadBalancerVm;
}
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return capabilities;
}
private static Map<Service, Map<Capability, String>> setCapabilities() {
Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
Map<Capability, String> lbCapabilities = new HashMap<Capability, String>();
lbCapabilities.put(Capability.SupportedLBAlgorithms, "roundrobin,leastconn,source");
lbCapabilities.put(Capability.SupportedProtocols, "tcp, udp");
capabilities.put(Service.Lb, lbCapabilities);
return capabilities;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException {
return true;
}
@Override
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
return true;
}
@Override
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO kill all loadbalancer vms by calling the ElasticLoadBalancerManager
return false;
}
@Override
public boolean restart(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
// TODO restart all loadbalancer vms by calling the ElasticLoadBalancerManager
return false;
}
@Override
public boolean destroy(Network network) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO kill all loadbalancer vms by calling the ElasticLoadBalancerManager
return false;
}
@Override
public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress) throws ResourceUnavailableException {
return true;
}
@Override
public boolean applyRules(Network network, List<? extends FirewallRule> rules) throws ResourceUnavailableException {
if (!canHandle(network)) {
return false;
}
return _lbMgr.applyLoadBalancerRules(network, rules);
}
}

View File

@ -0,0 +1,39 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.lb;
import java.util.List;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.rules.FirewallRule;
import com.cloud.user.Account;
public interface ElasticLoadBalancerManager {
public static final int DEFAULT_ELB_VM_RAMSIZE = 512; // 512 MB
public static final int DEFAULT_ELB_VM_CPU_MHZ = 500; // 500 MHz
public long deployLoadBalancerVM(Long networkId, Long accountId);
public boolean applyLoadBalancerRules(Network network,
List<? extends FirewallRule> rules)
throws ResourceUnavailableException;;
}

View File

@ -0,0 +1,428 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.lb;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
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.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.to.LoadBalancerTO;
import com.cloud.agent.manager.Commands;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.router.VirtualNetworkApplianceManager;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.router.VirtualRouter.Role;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.org.Cluster;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.User;
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.vm.DomainRouterVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineName;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfile.Param;
import com.cloud.vm.dao.DomainRouterDao;
@Local(value = { ElasticLoadBalancerManager.class })
public class ElasticLoadBalancerManagerImpl implements
ElasticLoadBalancerManager, Manager {
private static final Logger s_logger = Logger
.getLogger(ElasticLoadBalancerManagerImpl.class);
@Inject
IPAddressDao _ipAddressDao;
@Inject
AgentManager _agentMgr;
@Inject
NetworkManager _networkMgr;
@Inject
LoadBalancerDao _loadBalancerDao = null;
@Inject
LoadBalancingRulesManager _lbMgr;
@Inject
VirtualNetworkApplianceManager _routerMgr;
@Inject
DomainRouterDao _routerDao = null;
@Inject
protected HostPodDao _podDao = null;
@Inject
protected ClusterDao _clusterDao;
@Inject
DataCenterDao _dcDao = null;
@Inject
protected NetworkDao _networkDao;
@Inject
protected NetworkOfferingDao _networkOfferingDao;
@Inject
VMTemplateDao _templateDao = null;
@Inject
VirtualMachineManager _itMgr;
@Inject
ConfigurationDao _configDao;
@Inject
ServiceOfferingDao _serviceOfferingDao = null;
@Inject
AccountService _accountService;
String _name;
String _instance;
Account _systemAcct;
ServiceOfferingVO _elasticLbVmOffering;
int _elasticLbVmRamSize;
int _elasticLbvmCpuMHz;
public long deployLoadBalancerVM(Long networkId, Long accountId) { /* ELB_TODO :need to remove hardcoded network id,account id,pod id , cluster id */
NetworkVO network = _networkDao.findById(networkId);
DataCenter dc = _dcDao.findById(network.getDataCenterId());
Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>(
1);
params.put(VirtualMachineProfile.Param.RestartNetwork, true);
Account owner = _accountService.getActiveAccount("system", new Long(1));
DeployDestination dest = new DeployDestination(dc, null, null, null);
s_logger.debug("About to deploy elastic LB vm if necessary");
try {
VirtualRouter elbVm = deployELBVm(network, dest, owner, params);
s_logger.debug("ELB vm = " + elbVm);
if (elbVm == null) {
throw new InvalidParameterValueException("No VM with id '"
+ elbVm + "' found.");
}
DomainRouterVO elbRouterVm = _routerDao.findById(elbVm.getId());
String publicIp = elbRouterVm.getGuestIpAddress();
IPAddressVO ipvo = _ipAddressDao.findByIpAndSourceNetworkId(networkId, publicIp);
ipvo.setAssociatedWithNetworkId(networkId);
_ipAddressDao.update(ipvo.getId(), ipvo);
return ipvo.getId();
} catch (Throwable t) {
String errorMsg = "Error while deploying Loadbalancer VM: " + t;
s_logger.warn(errorMsg);
return 0;
}
}
private boolean sendCommandsToRouter(final DomainRouterVO router,
Commands cmds) throws AgentUnavailableException {
Answer[] answers = null;
try {
answers = _agentMgr.send(router.getHostId(), cmds);
} catch (OperationTimedoutException e) {
s_logger.warn("Timed Out", e);
throw new AgentUnavailableException(
"Unable to send commands to virtual router ",
router.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
if (answers.length > 0) {
Answer ans = answers[0];
return ans.getResult();
}
return true;
}
private void createApplyLoadBalancingRulesCommands(
List<LoadBalancingRule> rules, DomainRouterVO router, Commands cmds) {
String elbIp = "";
LoadBalancerTO[] lbs = new LoadBalancerTO[rules.size()];
int i = 0;
for (LoadBalancingRule rule : rules) {
boolean revoked = (rule.getState()
.equals(FirewallRule.State.Revoke));
String protocol = rule.getProtocol();
String algorithm = rule.getAlgorithm();
elbIp = _networkMgr.getIp(rule.getSourceIpAddressId()).getAddress()
.addr();
int srcPort = rule.getSourcePortStart();
List<LbDestination> destinations = rule.getDestinations();
LoadBalancerTO lb = new LoadBalancerTO(elbIp, srcPort, protocol,
algorithm, revoked, false, destinations);
lbs[i++] = lb;
}
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs);
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP,
router.getPrivateIpAddress());
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME,
router.getInstanceName());
cmds.addCommand(cmd);
}
protected boolean applyLBRules(DomainRouterVO router,
List<LoadBalancingRule> rules) throws ResourceUnavailableException {
Commands cmds = new Commands(OnError.Continue);
createApplyLoadBalancingRulesCommands(rules, router, cmds);
// Send commands to router
return sendCommandsToRouter(router, cmds);
}
public boolean applyLoadBalancerRules(Network network,
List<? extends FirewallRule> rules)
throws ResourceUnavailableException {
DomainRouterVO router = _routerDao.findByNetwork(network.getId());/* ELB_TODO :may have multiple LB's , need to get the correct LB based on network id and account id */
if (router == null) {
s_logger.warn("Unable to apply lb rules, virtual router doesn't exist in the network "
+ network.getId());
throw new ResourceUnavailableException("Unable to apply lb rules",
DataCenter.class, network.getDataCenterId());
}
if (router.getState() == State.Running) {
if (rules != null && !rules.isEmpty()) {
if (rules.get(0).getPurpose() == Purpose.LoadBalancing) {
// for elastic load balancer we have to resend all lb rules
// belonging to same sourceIpAddressId for the network
List<LoadBalancerVO> lbs = _loadBalancerDao
.listByNetworkId(network.getId());
List<LoadBalancingRule> lbRules = new ArrayList<LoadBalancingRule>();
for (LoadBalancerVO lb : lbs) {
if (lb.getSourceIpAddressId() == rules.get(0)
.getSourceIpAddressId()) {
List<LbDestination> dstList = _lbMgr
.getExistingDestinations(lb.getId());
LoadBalancingRule loadBalancing = new LoadBalancingRule(
lb, dstList);
lbRules.add(loadBalancing);
}
}
return applyLBRules(router, lbRules);
} else {
s_logger.warn("Unable to apply rules of purpose: "
+ rules.get(0).getPurpose());
return false;
}
} else {
return true;
}
} else if (router.getState() == State.Stopped
|| router.getState() == State.Stopping) {
s_logger.debug("Router is in "
+ router.getState()
+ ", so not sending apply firewall rules commands to the backend");
return true;
} else {
s_logger.warn("Unable to apply firewall rules, virtual router is not in the right state "
+ router.getState());
throw new ResourceUnavailableException(
"Unable to apply firewall rules, virtual router is not in the right state",
VirtualRouter.class, router.getId());
}
}
@Override
public boolean configure(String name, Map<String, Object> params)
throws ConfigurationException {
_name = name;
final Map<String, String> configs = _configDao.getConfiguration("AgentManager", params);
_systemAcct = _accountService.getSystemAccount();
_instance = configs.get("instance.name");
if (_instance == null) {
_instance = "VM";
}
boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key()));
_elasticLbVmRamSize = NumbersUtil.parseInt(configs.get("elastic.lb.vm.ram.size"), DEFAULT_ELB_VM_RAMSIZE);
_elasticLbvmCpuMHz = NumbersUtil.parseInt(configs.get("elastic.lb.vm.cpu.mhz"), DEFAULT_ELB_VM_CPU_MHZ);
_elasticLbVmOffering = new ServiceOfferingVO("System Offering For Elastic LB VM", 1, _elasticLbVmRamSize, _elasticLbvmCpuMHz, 0, 0, true, null, useLocalStorage, true, null, true, VirtualMachine.Type.ElasticLoadBalancerVm, true);
_elasticLbVmOffering.setUniqueName("Cloud.Com-ElasticLBVm");
_elasticLbVmOffering = _serviceOfferingDao.persistSystemServiceOffering(_elasticLbVmOffering);
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return _name;
}
@DB
public DomainRouterVO deployELBVm(Network guestNetwork, DeployDestination dest, Account owner, Map<Param, Object> params) throws
ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
long dcId = dest.getDataCenter().getId();
// lock guest network
Long guestNetworkId = guestNetwork.getId();
guestNetwork = _networkDao.acquireInLockTable(guestNetworkId);
if (guestNetwork == null) {
throw new ConcurrentOperationException("Unable to acquire network configuration: " + guestNetworkId);
}
try {
NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(guestNetwork.getNetworkOfferingId());
if (offering.isSystemOnly() || guestNetwork.getIsShared()) {
owner = _accountService.getSystemAccount();
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Starting a elastic ip vm for network configurations: " + guestNetwork + " in " + dest);
}
assert guestNetwork.getState() == Network.State.Implemented
|| guestNetwork.getState() == Network.State.Setup
|| guestNetwork.getState() == Network.State.Implementing
: "Network is not yet fully implemented: "+ guestNetwork;
DataCenterDeployment plan = null;
DomainRouterVO router = null;
//router = _routerDao.findByNetworkAndPodAndRole(guestNetwork.getId(), podId, Role.LB);
plan = new DataCenterDeployment(dcId, null, null, null, null);
// } else {
// s_logger.debug("Not deploying elastic ip vm");
// return null;
// }
if (router == null) {
long id = _routerDao.getNextInSequence(Long.class, "id");
if (s_logger.isDebugEnabled()) {
s_logger.debug("Creating the elastic LB vm " + id);
}
List<NetworkOfferingVO> offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork);
NetworkOfferingVO controlOffering = offerings.get(0);
NetworkVO controlConfig = _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false, false).get(0);
List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>(2);
NicProfile guestNic = new NicProfile();
networks.add(new Pair<NetworkVO, NicProfile>((NetworkVO) guestNetwork, guestNic));
networks.add(new Pair<NetworkVO, NicProfile>(controlConfig, null));
VMTemplateVO template = _templateDao.findSystemVMTemplate(dcId);
router = new DomainRouterVO(id, _elasticLbVmOffering.getId(), VirtualMachineName.getRouterName(id, _instance), template.getId(), template.getHypervisorType(), template.getGuestOSId(),
owner.getDomainId(), owner.getId(), guestNetwork.getId(), _elasticLbVmOffering.getOfferHA());
router.setRole(Role.LB);
router = _itMgr.allocate(router, template, _elasticLbVmOffering, networks, plan, null, owner);
}
State state = router.getState();
if (state != State.Running) {
router = this.start(router, _accountService.getSystemUser(), _accountService.getSystemAccount(), params);
}
return router;
} finally {
_networkDao.releaseFromLockTable(guestNetworkId);
}
}
private DomainRouterVO start(DomainRouterVO router, User user, Account caller, Map<Param, Object> params) throws StorageUnavailableException, InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException {
s_logger.debug("Starting router " + router);
if (_itMgr.start(router, params, user, caller) != null) {
return _routerDao.findById(router.getId());
} else {
return null;
}
}
}

View File

@ -50,12 +50,15 @@ 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;
import com.cloud.network.dao.FirewallRulesDao;
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.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
@ -118,6 +121,10 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
NicDao _nicDao;
@Inject
UsageEventDao _usageEventDao;
@Inject
ElasticLoadBalancerManager _elbMgr;
@Inject
NetworkDao _networkDao;
@Override
@DB
@ -346,9 +353,25 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
UserContext caller = UserContext.current();
long ipId = lb.getSourceIpAddressId();
// make sure ip address exists
IPAddressVO ipAddr = _ipAddressDao.findById(ipId);
Long networkId= ipAddr.getSourceNetworkId();
NetworkVO network=_networkDao.findById(networkId);
if (network.getGuestType() == GuestIpType.Direct) {
LoadBalancerVO lbvo;
Account account = caller.getCaller();
lbvo = _lbDao.findByAccountAndName(account.getId(), lb.getName());
if (lbvo == null) {
_elbMgr.deployLoadBalancerVM(networkId, account.getId());
IPAddressVO ipvo = _ipAddressDao.findById(ipId);
ipvo.setAssociatedWithNetworkId(networkId);
_ipAddressDao.update(ipvo.getId(), ipvo);
ipAddr.setAssociatedWithNetworkId(networkId);
} else {
}
}
// make sure ip address exists
if (ipAddr == null || !ipAddr.readyToUse()) {
throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id" + ipId);
}
@ -380,7 +403,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
throw new InvalidParameterValueException("Invalid algorithm: " + lb.getAlgorithm());
}
Long networkId = ipAddr.getAssociatedWithNetworkId();
networkId = ipAddr.getAssociatedWithNetworkId();
if (networkId == null) {
throw new InvalidParameterValueException("Unable to create load balancer rule ; ip id=" + ipId + " is not associated with any network");
@ -389,9 +412,8 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
_accountMgr.checkAccess(caller.getCaller(), ipAddr);
// verify that lb service is supported by the network
Network network = _networkMgr.getNetwork(networkId);
if (!_networkMgr.isServiceSupported(network.getNetworkOfferingId(), Service.Lb)) {
throw new InvalidParameterValueException("LB service is not supported in network id=" + networkId);
throw new InvalidParameterValueException("LB service is not supported in network id= " + networkId);
}
LoadBalancerVO newRule = new LoadBalancerVO(lb.getXid(), lb.getName(), lb.getDescription(), lb.getSourceIpAddressId(), lb.getSourcePortEnd(), lb.getDefaultPortStart(), lb.getAlgorithm(),

View File

@ -809,7 +809,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
true, false, null, null, null, true,
Availability.Required,
true, true, true, //services - all true except for lb/vpn and gateway
false, true, false, false, GuestIpType.Direct);
false, true, true, false, GuestIpType.Direct);
guestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(guestNetworkOffering);
@ -829,7 +829,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
false, true, null, null, null, true,
Availability.Optional,
true, true, true, //services - all true except for firewall/lb/vpn and gateway
false, false, false, false, GuestIpType.Direct);
false, false, true, false, GuestIpType.Direct);
defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering);
}