mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
merge ELB / nectarine branch
This commit is contained in:
commit
8277584b8a
@ -249,5 +249,6 @@ public class ApiConstants {
|
|||||||
public static final String SNAPSHOT_RESERVATION = "snapshotreservation";
|
public static final String SNAPSHOT_RESERVATION = "snapshotreservation";
|
||||||
public static final String IP_NETWORK_LIST = "iptonetworklist";
|
public static final String IP_NETWORK_LIST = "iptonetworklist";
|
||||||
public static final String REDUNDANT_ROUTER = "redundantrouter";
|
public static final String REDUNDANT_ROUTER = "redundantrouter";
|
||||||
|
public static final String FOR_LOAD_BALANCING = "forloadbalancing";
|
||||||
public static final String KEYBOARD="keyboard";
|
public static final String KEYBOARD="keyboard";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -190,4 +190,12 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
|
|||||||
public AsyncJob.Type getInstanceType() {
|
public AsyncJob.Type getInstanceType() {
|
||||||
return AsyncJob.Type.IpAddress;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,20 +23,27 @@ import java.util.List;
|
|||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.cloud.api.ApiConstants;
|
import com.cloud.api.ApiConstants;
|
||||||
|
import com.cloud.api.BaseAsyncCmd;
|
||||||
import com.cloud.api.BaseCmd;
|
import com.cloud.api.BaseCmd;
|
||||||
import com.cloud.api.Implementation;
|
import com.cloud.api.Implementation;
|
||||||
import com.cloud.api.Parameter;
|
import com.cloud.api.Parameter;
|
||||||
import com.cloud.api.ServerApiException;
|
import com.cloud.api.ServerApiException;
|
||||||
import com.cloud.api.BaseCmd.CommandType;
|
import com.cloud.api.BaseCmd.CommandType;
|
||||||
import com.cloud.api.response.LoadBalancerResponse;
|
import com.cloud.api.response.LoadBalancerResponse;
|
||||||
|
import com.cloud.event.EventTypes;
|
||||||
|
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||||
import com.cloud.exception.InvalidParameterValueException;
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
import com.cloud.exception.NetworkRuleConflictException;
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.network.IpAddress;
|
import com.cloud.network.IpAddress;
|
||||||
import com.cloud.network.rules.LoadBalancer;
|
import com.cloud.network.rules.LoadBalancer;
|
||||||
|
import com.cloud.user.Account;
|
||||||
|
import com.cloud.user.UserContext;
|
||||||
import com.cloud.utils.net.NetUtils;
|
import com.cloud.utils.net.NetUtils;
|
||||||
|
|
||||||
@Implementation(description="Creates a load balancer rule", responseObject=LoadBalancerResponse.class)
|
@Implementation(description="Creates a load balancer rule", responseObject=LoadBalancerResponse.class)
|
||||||
public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer {
|
public class CreateLoadBalancerRuleCmd extends BaseAsyncCmd /*implements LoadBalancer */{
|
||||||
public static final Logger s_logger = Logger.getLogger(CreateLoadBalancerRuleCmd.class.getName());
|
public static final Logger s_logger = Logger.getLogger(CreateLoadBalancerRuleCmd.class.getName());
|
||||||
|
|
||||||
private static final String s_name = "createloadbalancerruleresponse";
|
private static final String s_name = "createloadbalancerruleresponse";
|
||||||
@ -57,26 +64,31 @@ 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")
|
@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;
|
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;
|
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")
|
@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;
|
private Integer publicPort;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
|
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
|
||||||
private List<String> cidrlist;
|
private List<String> cidrlist;
|
||||||
|
@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 ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAlgorithm() {
|
public String getAlgorithm() {
|
||||||
return algorithm;
|
return algorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
@ -120,7 +132,7 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() throws ResourceAllocationException, ResourceUnavailableException {
|
||||||
if (cidrlist != null){
|
if (cidrlist != null){
|
||||||
for (String cidr: cidrlist){
|
for (String cidr: cidrlist){
|
||||||
if (!NetUtils.isValidCIDR(cidr)){
|
if (!NetUtils.isValidCIDR(cidr)){
|
||||||
@ -135,74 +147,68 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
|
|||||||
} catch (NetworkRuleConflictException e) {
|
} catch (NetworkRuleConflictException e) {
|
||||||
s_logger.warn("Exception: ", e);
|
s_logger.warn("Exception: ", e);
|
||||||
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage());
|
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);
|
LoadBalancerResponse response = _responseGenerator.createLoadBalancerResponse(result);
|
||||||
response.setResponseName(getCommandName());
|
response.setResponseName(getCommandName());
|
||||||
this.setResponseObject(response);
|
this.setResponseObject(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getId() {
|
|
||||||
throw new UnsupportedOperationException("not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getXid() {
|
|
||||||
// FIXME: Should fix this.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public Long getSourceIpAddressId() {
|
||||||
public long getSourceIpAddressId() {
|
|
||||||
return publicIpId;
|
return publicIpId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourcePortStart() {
|
public int getSourcePortStart() {
|
||||||
return publicPort.intValue();
|
return publicPort.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourcePortEnd() {
|
public int getSourcePortEnd() {
|
||||||
return publicPort.intValue();
|
return publicPort.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProtocol() {
|
public String getProtocol() {
|
||||||
return NetUtils.TCP_PROTO;
|
return NetUtils.TCP_PROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Purpose getPurpose() {
|
|
||||||
return Purpose.LoadBalancing;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public State getState() {
|
|
||||||
throw new UnsupportedOperationException("not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getNetworkId() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getAccountId() {
|
public long getAccountId() {
|
||||||
|
if (publicIpId != null)
|
||||||
return _networkService.getIp(getPublicIpId()).getAccountId();
|
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() {
|
public long getDomainId() {
|
||||||
|
if (publicIpId != null)
|
||||||
return _networkService.getIp(getPublicIpId()).getDomainId();
|
return _networkService.getIp(getPublicIpId()).getDomainId();
|
||||||
|
if (domainId != null) {
|
||||||
|
return domainId;
|
||||||
|
}
|
||||||
|
return UserContext.current().getCaller().getDomainId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDefaultPortStart() {
|
public int getDefaultPortStart() {
|
||||||
return privatePort.intValue();
|
return privatePort.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDefaultPortEnd() {
|
public int getDefaultPortEnd() {
|
||||||
return privatePort.intValue();
|
return privatePort.intValue();
|
||||||
}
|
}
|
||||||
@ -211,4 +217,37 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
|
|||||||
public long getEntityOwnerId() {
|
public long getEntityOwnerId() {
|
||||||
return getAccountId();
|
return getAccountId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAccountName() {
|
||||||
|
return accountName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getZoneId() {
|
||||||
|
return zoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicIpId(Long publicIpId) {
|
||||||
|
this.publicIpId = publicIpId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEventType() {
|
||||||
|
return EventTypes.EVENT_LOAD_BALANCER_CREATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEventDescription() {
|
||||||
|
return "creating load balancer: " + getName() + " account: " + getAccountName();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getXid() {
|
||||||
|
/*FIXME*/
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceIpAddressId(Long ipId) {
|
||||||
|
this.publicIpId = ipId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,6 +99,10 @@ public class DeleteLoadBalancerRuleCmd extends BaseAsyncCmd {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getSyncObjId() {
|
public Long getSyncObjId() {
|
||||||
return _lbService.findById(id).getNetworkId();
|
LoadBalancer lb = _lbService.findById(id);
|
||||||
|
if (lb == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return lb.getNetworkId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,6 +49,7 @@ public class ListCapabilitiesCmd extends BaseCmd {
|
|||||||
response.setSecurityGroupsEnabled((Boolean)capabilities.get("securityGroupsEnabled"));
|
response.setSecurityGroupsEnabled((Boolean)capabilities.get("securityGroupsEnabled"));
|
||||||
response.setCloudStackVersion((String)capabilities.get("cloudStackVersion"));
|
response.setCloudStackVersion((String)capabilities.get("cloudStackVersion"));
|
||||||
response.setUserPublicTemplateEnabled((Boolean)capabilities.get("userPublicTemplateEnabled"));
|
response.setUserPublicTemplateEnabled((Boolean)capabilities.get("userPublicTemplateEnabled"));
|
||||||
|
response.setSupportELB((String)capabilities.get("supportELB"));
|
||||||
response.setObjectName("capability");
|
response.setObjectName("capability");
|
||||||
response.setResponseName(getCommandName());
|
response.setResponseName(getCommandName());
|
||||||
this.setResponseObject(response);
|
this.setResponseObject(response);
|
||||||
|
|||||||
@ -119,4 +119,17 @@ public class ListLoadBalancerRulesCmd extends BaseListCmd {
|
|||||||
response.setResponseName(getCommandName());
|
response.setResponseName(getCommandName());
|
||||||
this.setResponseObject(response);
|
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;
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,6 +66,9 @@ public class ListPublicIpAddressesCmd extends BaseListCmd {
|
|||||||
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, description="lists all public IP addresses by Zone ID")
|
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, description="lists all public IP addresses by Zone ID")
|
||||||
private Long zoneId;
|
private Long zoneId;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.FOR_LOAD_BALANCING, type=CommandType.BOOLEAN, description="list only ips used for load balancing")
|
||||||
|
private Boolean forLoadBalancing;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -129,4 +132,33 @@ public class ListPublicIpAddressesCmd extends BaseListCmd {
|
|||||||
public AsyncJob.Type getInstanceType() {
|
public AsyncJob.Type getInstanceType() {
|
||||||
return AsyncJob.Type.IpAddress;
|
return AsyncJob.Type.IpAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Boolean isForLoadBalancing() {
|
||||||
|
return forLoadBalancing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getAllocatedOnly() {
|
||||||
|
return allocatedOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllocatedOnly(Boolean allocatedOnly) {
|
||||||
|
this.allocatedOnly = allocatedOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getForVirtualNetwork() {
|
||||||
|
return forVirtualNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForVirtualNetwork(Boolean forVirtualNetwork) {
|
||||||
|
this.forVirtualNetwork = forVirtualNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getForLoadBalancing() {
|
||||||
|
return forLoadBalancing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForLoadBalancing(Boolean forLoadBalancing) {
|
||||||
|
this.forLoadBalancing = forLoadBalancing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,10 @@ public class CapabilitiesResponse extends BaseResponse {
|
|||||||
@SerializedName("userpublictemplateenabled") @Param(description="true if user and domain admins can set templates to be shared, false otherwise")
|
@SerializedName("userpublictemplateenabled") @Param(description="true if user and domain admins can set templates to be shared, false otherwise")
|
||||||
private boolean userPublicTemplateEnabled;
|
private boolean userPublicTemplateEnabled;
|
||||||
|
|
||||||
|
|
||||||
|
@SerializedName("supportELB") @Param(description="true if region supports elastic load balancer on basic zones")
|
||||||
|
private String supportELB;
|
||||||
|
|
||||||
public boolean getSecurityGroupsEnabled() {
|
public boolean getSecurityGroupsEnabled() {
|
||||||
return securityGroupsEnabled;
|
return securityGroupsEnabled;
|
||||||
}
|
}
|
||||||
@ -54,4 +58,12 @@ public class CapabilitiesResponse extends BaseResponse {
|
|||||||
public void setUserPublicTemplateEnabled(boolean userPublicTemplateEnabled) {
|
public void setUserPublicTemplateEnabled(boolean userPublicTemplateEnabled) {
|
||||||
this.userPublicTemplateEnabled = userPublicTemplateEnabled;
|
this.userPublicTemplateEnabled = userPublicTemplateEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSupportELB(String supportELB) {
|
||||||
|
this.supportELB = supportELB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSupportELB() {
|
||||||
|
return supportELB;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,6 +93,8 @@ public interface Network extends ControlledEntity {
|
|||||||
public static final Provider F5BigIp = new Provider("F5BigIp");
|
public static final Provider F5BigIp = new Provider("F5BigIp");
|
||||||
public static final Provider ExternalDhcpServer = new Provider("ExternalDhcpServer");
|
public static final Provider ExternalDhcpServer = new Provider("ExternalDhcpServer");
|
||||||
public static final Provider ExternalGateWay = new Provider("ExternalGateWay");
|
public static final Provider ExternalGateWay = new Provider("ExternalGateWay");
|
||||||
|
public static final Provider ElasticLoadBalancerVm = new Provider("ElasticLoadBalancerVm");
|
||||||
|
|
||||||
public static final Provider None = new Provider("None");
|
public static final Provider None = new Provider("None");
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|||||||
@ -19,9 +19,11 @@ package com.cloud.network.lb;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
|
||||||
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
|
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
|
||||||
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
|
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
|
||||||
import com.cloud.api.commands.UpdateLoadBalancerRuleCmd;
|
import com.cloud.api.commands.UpdateLoadBalancerRuleCmd;
|
||||||
|
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||||
import com.cloud.exception.NetworkRuleConflictException;
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
import com.cloud.exception.ResourceUnavailableException;
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.network.rules.LoadBalancer;
|
import com.cloud.network.rules.LoadBalancer;
|
||||||
@ -32,8 +34,9 @@ public interface LoadBalancingRulesService {
|
|||||||
* Create a load balancer rule from the given ipAddress/port to the given private port
|
* 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
|
* @param cmd the command specifying the ip address, public port, protocol, private port, and algorithm
|
||||||
* @return the newly created LoadBalancerVO if successful, null otherwise
|
* @return the newly created LoadBalancerVO if successful, null otherwise
|
||||||
|
* @throws InsufficientAddressCapacityException
|
||||||
*/
|
*/
|
||||||
LoadBalancer createLoadBalancerRule(LoadBalancer lb) throws NetworkRuleConflictException;
|
LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException, InsufficientAddressCapacityException;
|
||||||
|
|
||||||
LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd);
|
LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd);
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import com.cloud.vm.VirtualMachine;
|
|||||||
public interface VirtualRouter extends VirtualMachine {
|
public interface VirtualRouter extends VirtualMachine {
|
||||||
public enum Role {
|
public enum Role {
|
||||||
DHCP_FIREWALL_LB_PASSWD_USERDATA,
|
DHCP_FIREWALL_LB_PASSWD_USERDATA,
|
||||||
DHCP_USERDATA
|
DHCP_USERDATA, LB
|
||||||
}
|
}
|
||||||
Role getRole();
|
Role getRole();
|
||||||
boolean getIsRedundantRouter();
|
boolean getIsRedundantRouter();
|
||||||
|
|||||||
@ -176,6 +176,8 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject
|
|||||||
DomainRouter,
|
DomainRouter,
|
||||||
ConsoleProxy,
|
ConsoleProxy,
|
||||||
SecondaryStorageVm,
|
SecondaryStorageVm,
|
||||||
|
ElasticIpVm,
|
||||||
|
ElasticLoadBalancerVm,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UserBareMetal is only used for selecting VirtualMachineGuru, there is no
|
* UserBareMetal is only used for selecting VirtualMachineGuru, there is no
|
||||||
|
|||||||
@ -95,6 +95,8 @@
|
|||||||
<adapter name="DomainRouter" class="com.cloud.network.element.VirtualRouterElement"/>
|
<adapter name="DomainRouter" class="com.cloud.network.element.VirtualRouterElement"/>
|
||||||
<adapter name="Dhcp" class="com.cloud.network.element.DhcpElement"/>
|
<adapter name="Dhcp" class="com.cloud.network.element.DhcpElement"/>
|
||||||
<adapter name="Ovs" class="com.cloud.network.element.OvsElement"/>
|
<adapter name="Ovs" class="com.cloud.network.element.OvsElement"/>
|
||||||
|
<adapter name="ElasticLoadBalancer" class="com.cloud.network.element.ElasticLoadBalancerElement"/>
|
||||||
|
|
||||||
</adapters>
|
</adapters>
|
||||||
<adapters key="com.cloud.acl.SecurityChecker">
|
<adapters key="com.cloud.acl.SecurityChecker">
|
||||||
<adapter name="DomainChecker" class="com.cloud.acl.DomainChecker"/>
|
<adapter name="DomainChecker" class="com.cloud.acl.DomainChecker"/>
|
||||||
|
|||||||
@ -85,6 +85,21 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter {
|
|||||||
this.redundantState = redundantState;
|
this.redundantState = redundantState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DomainRouterVO(long id,
|
||||||
|
long serviceOfferingId,
|
||||||
|
String name,
|
||||||
|
long templateId,
|
||||||
|
HypervisorType hypervisorType,
|
||||||
|
long guestOSId,
|
||||||
|
long domainId,
|
||||||
|
long accountId,
|
||||||
|
long networkId,
|
||||||
|
boolean haEnabled,
|
||||||
|
VirtualMachine.Type vmType) {
|
||||||
|
super(id, serviceOfferingId, name, name, vmType, templateId, hypervisorType, guestOSId, domainId, accountId, haEnabled);
|
||||||
|
this.networkId = networkId;
|
||||||
|
}
|
||||||
|
|
||||||
public void setPublicIpAddress(String publicIpAddress) {
|
public void setPublicIpAddress(String publicIpAddress) {
|
||||||
this.publicIpAddress = publicIpAddress;
|
this.publicIpAddress = publicIpAddress;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -457,6 +457,33 @@ setup_console_proxy() {
|
|||||||
chkconfig nfs-common off
|
chkconfig nfs-common off
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setup_elbvm() {
|
||||||
|
log_it "Setting up Elastic Load Balancer system vm"
|
||||||
|
local hyp=$1
|
||||||
|
setup_common eth0 eth1
|
||||||
|
sed -i /gateway/d /etc/hosts
|
||||||
|
public_ip=$ETH2_IP
|
||||||
|
[ "$ETH2_IP" == "0.0.0.0" ] || [ "$ETH2_IP" == "" ] && public_ip=$ETH0_IP
|
||||||
|
echo "$public_ip $NAME" >> /etc/hosts
|
||||||
|
|
||||||
|
if [ "$SSHONGUEST" == "true" ]
|
||||||
|
then
|
||||||
|
sed '/3922/s/eth1/eth0/'
|
||||||
|
setup_sshd $ETH0_IP
|
||||||
|
else
|
||||||
|
cp /etc/iptables/iptables-elbvm /etc/iptables/rules
|
||||||
|
setup_sshd $ETH1_IP
|
||||||
|
fi
|
||||||
|
|
||||||
|
enable_fwding 0
|
||||||
|
enable_svc haproxy 0
|
||||||
|
enable_svc dnsmasq 0
|
||||||
|
enable_svc cloud-passwd-srvr 0
|
||||||
|
enable_svc cloud 0
|
||||||
|
chkconfig nfs-common off
|
||||||
|
chkconfig portmap off
|
||||||
|
}
|
||||||
|
|
||||||
setup_default() {
|
setup_default() {
|
||||||
cat > /etc/network/interfaces << EOF
|
cat > /etc/network/interfaces << EOF
|
||||||
auto lo eth0
|
auto lo eth0
|
||||||
@ -491,6 +518,10 @@ start() {
|
|||||||
[ "$NAME" == "" ] && NAME=consoleproxy
|
[ "$NAME" == "" ] && NAME=consoleproxy
|
||||||
setup_console_proxy $hyp;
|
setup_console_proxy $hyp;
|
||||||
;;
|
;;
|
||||||
|
elbvm)
|
||||||
|
[ "$NAME" == "" ] && NAME=elb
|
||||||
|
setup_elbvm
|
||||||
|
;;
|
||||||
unknown)
|
unknown)
|
||||||
[ "$NAME" == "" ] && NAME=systemvm
|
[ "$NAME" == "" ] && NAME=systemvm
|
||||||
setup_default;
|
setup_default;
|
||||||
|
|||||||
17
patches/systemvm/debian/config/etc/iptables/iptables-elbvm
Executable file
17
patches/systemvm/debian/config/etc/iptables/iptables-elbvm
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
*nat
|
||||||
|
:PREROUTING ACCEPT [0:0]
|
||||||
|
:POSTROUTING ACCEPT [0:0]
|
||||||
|
:OUTPUT ACCEPT [0:0]
|
||||||
|
COMMIT
|
||||||
|
*filter
|
||||||
|
:INPUT DROP [0:0]
|
||||||
|
:FORWARD DROP [0:0]
|
||||||
|
:OUTPUT ACCEPT [0:0]
|
||||||
|
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
|
-A INPUT -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
|
-A INPUT -i eth2 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
|
-A INPUT -p icmp -j ACCEPT
|
||||||
|
-A INPUT -i lo -j ACCEPT
|
||||||
|
-A INPUT -i eth1 -p tcp -m state --state NEW --dport 3922 -j ACCEPT
|
||||||
|
COMMIT
|
||||||
|
|
||||||
@ -100,6 +100,16 @@ dhcpsrvr_svcs() {
|
|||||||
echo "cloud nfs-common haproxy portmap" > /var/cache/cloud/disabled_svcs
|
echo "cloud nfs-common haproxy portmap" > /var/cache/cloud/disabled_svcs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elbvm_svcs() {
|
||||||
|
chkconfig cloud off
|
||||||
|
chkconfig haproxy on ;
|
||||||
|
chkconfig ssh on
|
||||||
|
chkconfig nfs-common off
|
||||||
|
chkconfig portmap off
|
||||||
|
echo "ssh haproxy" > /var/cache/cloud/enabled_svcs
|
||||||
|
echo "cloud cloud-passwd-srvr dnsmasq apache2 nfs-common portmap" > /var/cache/cloud/disabled_svcs
|
||||||
|
}
|
||||||
|
|
||||||
enable_pcihotplug() {
|
enable_pcihotplug() {
|
||||||
sed -i -e "/acpiphp/d" /etc/modules
|
sed -i -e "/acpiphp/d" /etc/modules
|
||||||
sed -i -e "/pci_hotplug/d" /etc/modules
|
sed -i -e "/pci_hotplug/d" /etc/modules
|
||||||
@ -198,4 +208,14 @@ then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$TYPE" == "elbvm" ]
|
||||||
|
then
|
||||||
|
elbvm_svcs
|
||||||
|
if [ $? -gt 0 ]
|
||||||
|
then
|
||||||
|
printf "Failed to execute elbvm svcs\n" >$logfile
|
||||||
|
exit 9
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
exit $?
|
exit $?
|
||||||
|
|||||||
@ -27,48 +27,15 @@
|
|||||||
# @VERSION@
|
# @VERSION@
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
printf "Usage: %s: -i <domR eth1 ip> -a <added public ip address> -d <removed> -f <load balancer config> -s <stats guest ip address> \n" $(basename $0) >&2
|
printf "Usage: %s: -i <domR eth1 ip> -a <added public ip address> -d <removed> -f <load balancer config> \n" $(basename $0) >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
# set -x
|
# set -x
|
||||||
|
|
||||||
# check if gateway domain is up and running
|
# ensure that the nic has the public ip we are load balancing on
|
||||||
check_gw() {
|
ip_entry() {
|
||||||
ping -c 1 -n -q $1 > /dev/null
|
|
||||||
if [ $? -gt 0 ]
|
|
||||||
then
|
|
||||||
sleep 1
|
|
||||||
ping -c 1 -n -q $1 > /dev/null
|
|
||||||
fi
|
|
||||||
return $?;
|
|
||||||
}
|
|
||||||
fw_remove_backup() {
|
|
||||||
for vif in $VIF_LIST; do
|
|
||||||
iptables -F back_load_balancer_$vif 2> /dev/null
|
|
||||||
iptables -D INPUT -i $vif -p tcp -j back_load_balancer_$vif 2> /dev/null
|
|
||||||
iptables -X back_load_balancer_$vif 2> /dev/null
|
|
||||||
done
|
|
||||||
iptables -F back_lb_stats 2> /dev/null
|
|
||||||
iptables -D INPUT -i $STAT_IF -p tcp -j back_lb_stats 2> /dev/null
|
|
||||||
iptables -X back_lb_stats 2> /dev/null
|
|
||||||
}
|
|
||||||
fw_restore() {
|
|
||||||
for vif in $VIF_LIST; do
|
|
||||||
iptables -F load_balancer_$vif 2> /dev/null
|
|
||||||
iptables -D INPUT -i $vif -p tcp -j load_balancer_$vif 2> /dev/null
|
|
||||||
iptables -X load_balancer_$vif 2> /dev/null
|
|
||||||
iptables -E back_load_balancer_$vif load_balancer_$vif 2> /dev/null
|
|
||||||
done
|
|
||||||
iptables -F lb_stats 2> /dev/null
|
|
||||||
iptables -D INPUT -i $STAT_IF -p tcp -j lb_stats 2> /dev/null
|
|
||||||
iptables -X lb_stats 2> /dev/null
|
|
||||||
iptables -E back_lb_stats lb_stats 2> /dev/null
|
|
||||||
}
|
|
||||||
# firewall entry to ensure that haproxy can receive on specified port
|
|
||||||
fw_entry() {
|
|
||||||
local added=$1
|
local added=$1
|
||||||
local removed=$2
|
local removed=$2
|
||||||
local stats=$3
|
|
||||||
|
|
||||||
if [ "$added" == "none" ]
|
if [ "$added" == "none" ]
|
||||||
then
|
then
|
||||||
@ -83,24 +50,56 @@ fw_entry() {
|
|||||||
local a=$(echo $added | cut -d, -f1- --output-delimiter=" ")
|
local a=$(echo $added | cut -d, -f1- --output-delimiter=" ")
|
||||||
local r=$(echo $removed | cut -d, -f1- --output-delimiter=" ")
|
local r=$(echo $removed | cut -d, -f1- --output-delimiter=" ")
|
||||||
|
|
||||||
# back up the iptable rules by renaming before creating new.
|
for i in $a
|
||||||
|
do
|
||||||
|
local pubIp=$(echo $i | cut -d: -f1)
|
||||||
|
logger -t cloud "Adding public ip $pubIp for load balancing"
|
||||||
for vif in $VIF_LIST; do
|
for vif in $VIF_LIST; do
|
||||||
iptables -E load_balancer_$vif back_load_balancer_$vif 2> /dev/null
|
sudo ip addr add dev $vif $pubIp/32
|
||||||
iptables -N load_balancer_$vif 2> /dev/null
|
#ignore error since it is because the ip is already there
|
||||||
iptables -A INPUT -i $vif -p tcp -j load_balancer_$vif
|
|
||||||
done
|
done
|
||||||
iptables -E lb_stats back_lb_stats 2> /dev/null
|
done
|
||||||
iptables -N lb_stats 2> /dev/null
|
|
||||||
iptables -A INPUT -i $STAT_IF -p tcp -j lb_stats
|
for i in $r
|
||||||
|
do
|
||||||
|
logger -t cloud "Removing public ips for deleted loadbalancers"
|
||||||
|
local pubIp=$(echo $i | cut -d: -f1)
|
||||||
|
logger -t cloud "Removing public ip $pubIp for deleted loadbalancers"
|
||||||
|
for vif in $VIF_LIST; do
|
||||||
|
sudo ip addr del $pubIp/32 dev $vif
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# firewall entry to ensure that haproxy can receive on specified port
|
||||||
|
fw_entry() {
|
||||||
|
local added=$1
|
||||||
|
local removed=$2
|
||||||
|
|
||||||
|
if [ "$added" == "none" ]
|
||||||
|
then
|
||||||
|
added=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$removed" == "none" ]
|
||||||
|
then
|
||||||
|
removed=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
local a=$(echo $added | cut -d, -f1- --output-delimiter=" ")
|
||||||
|
local r=$(echo $removed | cut -d, -f1- --output-delimiter=" ")
|
||||||
|
|
||||||
for i in $a
|
for i in $a
|
||||||
do
|
do
|
||||||
local pubIp=$(echo $i | cut -d: -f1)
|
local pubIp=$(echo $i | cut -d: -f1)
|
||||||
local dport=$(echo $i | cut -d: -f2)
|
local dport=$(echo $i | cut -d: -f2)
|
||||||
local cidrs=$(echo $i | cut -d: -f3 | sed 's/-/,/')
|
logger -t cloud "Opening up firewall $pubIp:$dport (INPUT chain) for load balancing"
|
||||||
|
|
||||||
for vif in $VIF_LIST; do
|
for vif in $VIF_LIST; do
|
||||||
iptables -A load_balancer_$vif -s $cidrs -p tcp -d $pubIp --dport $dport -j ACCEPT
|
sudo iptables -D INPUT -i $vif -p tcp -d $pubIp --dport $dport -j ACCEPT 2> /dev/null
|
||||||
|
sudo iptables -A INPUT -i $vif -p tcp -d $pubIp --dport $dport -j ACCEPT
|
||||||
|
|
||||||
if [ $? -gt 0 ]
|
if [ $? -gt 0 ]
|
||||||
then
|
then
|
||||||
@ -108,10 +107,17 @@ fw_entry() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
local pubIp=$(echo $stats | cut -d: -f1)
|
|
||||||
local dport=$(echo $stats | cut -d: -f2)
|
for i in $r
|
||||||
local cidrs=$(echo $stats | cut -d: -f3 | sed 's/-/,/')
|
do
|
||||||
iptables -A lb_stats -s $cidrs -p tcp -m state --state NEW -d $pubIp --dport $dport -j ACCEPT
|
local pubIp=$(echo $i | cut -d: -f1)
|
||||||
|
local dport=$(echo $i | cut -d: -f2)
|
||||||
|
logger -t cloud "Closing up firewall (INPUT chain) $pubIp:$dport for deleted load balancers"
|
||||||
|
|
||||||
|
for vif in $VIF_LIST; do
|
||||||
|
sudo iptables -D INPUT -i $vif -p tcp -d $pubIp --dport $dport -j ACCEPT
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -124,6 +130,7 @@ reconfig_lb() {
|
|||||||
|
|
||||||
# Restore the HA Proxy to its previous state, and revert iptables rules on DomR
|
# Restore the HA Proxy to its previous state, and revert iptables rules on DomR
|
||||||
restore_lb() {
|
restore_lb() {
|
||||||
|
logger -t cloud "Restoring HA Proxy to previous state"
|
||||||
# Copy the old version of haproxy.cfg into the file that reconfigLB.sh uses
|
# Copy the old version of haproxy.cfg into the file that reconfigLB.sh uses
|
||||||
cp /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg.new
|
cp /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg.new
|
||||||
|
|
||||||
@ -143,7 +150,12 @@ get_vif_list() {
|
|||||||
vif_list="$vif_list $vif";
|
vif_list="$vif_list $vif";
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
if [ "$vif_list" == "" ]
|
||||||
|
then
|
||||||
|
vif_list="eth0"
|
||||||
|
fi
|
||||||
|
|
||||||
|
logger -t cloud "Loadbalancer public interfaces = $vif_list"
|
||||||
echo $vif_list
|
echo $vif_list
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,9 +164,8 @@ iflag=
|
|||||||
aflag=
|
aflag=
|
||||||
dflag=
|
dflag=
|
||||||
fflag=
|
fflag=
|
||||||
sflag=
|
|
||||||
|
|
||||||
while getopts 'i:a:d:f:s:' OPTION
|
while getopts 'i:a:d:f:' OPTION
|
||||||
do
|
do
|
||||||
case $OPTION in
|
case $OPTION in
|
||||||
i) iflag=1
|
i) iflag=1
|
||||||
@ -169,28 +180,12 @@ do
|
|||||||
f) fflag=1
|
f) fflag=1
|
||||||
cfgfile="$OPTARG"
|
cfgfile="$OPTARG"
|
||||||
;;
|
;;
|
||||||
s) sflag=1
|
|
||||||
statsIp="$OPTARG"
|
|
||||||
;;
|
|
||||||
?) usage
|
?) usage
|
||||||
exit 2
|
exit 2
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
VIF_LIST=$(get_vif_list)
|
|
||||||
# TODO make the stat interface generic
|
|
||||||
STAT_IF="eth0"
|
|
||||||
|
|
||||||
# hot reconfigure haproxy
|
|
||||||
reconfig_lb $cfgfile
|
|
||||||
|
|
||||||
if [ $? -gt 0 ]
|
|
||||||
then
|
|
||||||
printf "Reconfiguring loadbalancer failed\n"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$addedIps" == "" ]
|
if [ "$addedIps" == "" ]
|
||||||
then
|
then
|
||||||
addedIps="none"
|
addedIps="none"
|
||||||
@ -201,21 +196,61 @@ then
|
|||||||
removedIps="none"
|
removedIps="none"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# iptables entry to ensure that haproxy receives traffic
|
VIF_LIST=$(get_vif_list)
|
||||||
fw_entry $addedIps $removedIps $statsIp
|
|
||||||
|
|
||||||
|
if [ "$addedIps" == "" ]
|
||||||
|
then
|
||||||
|
addedIps="none"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$removedIps" == "" ]
|
||||||
|
then
|
||||||
|
removedIps="none"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#FIXME: make this explicit via check on vm type or passed in flag
|
||||||
|
if [ "$VIF_LIST" == "eth0" ]
|
||||||
|
then
|
||||||
|
ip_entry $addedIps $removedIps
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# hot reconfigure haproxy
|
||||||
|
reconfig_lb $cfgfile
|
||||||
|
|
||||||
if [ $? -gt 0 ]
|
if [ $? -gt 0 ]
|
||||||
then
|
then
|
||||||
|
logger -t cloud "Reconfiguring loadbalancer failed"
|
||||||
|
#FIXME: make this explicit via check on vm type or passed in flag
|
||||||
|
if [ "$VIF_LIST" == "eth0" ]
|
||||||
|
then
|
||||||
|
ip_entry $removedIps $addedIps
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# iptables entry to ensure that haproxy receives traffic
|
||||||
|
fw_entry $addedIps $removedIps
|
||||||
|
|
||||||
|
if [ $? -gt 0 ]
|
||||||
|
then
|
||||||
|
logger -t cloud "Failed to apply firewall rules for load balancing, reverting HA Proxy config"
|
||||||
# Restore the LB
|
# Restore the LB
|
||||||
restore_lb
|
restore_lb
|
||||||
|
|
||||||
# Revert iptables rules on DomR
|
logger -t cloud "Reverting firewall config"
|
||||||
fw_restore
|
# Revert iptables rules on DomR, with addedIps and removedIps swapped
|
||||||
|
fw_entry $removedIps $addedIps
|
||||||
|
|
||||||
|
#FIXME: make this explicit via check on vm type or passed in flag
|
||||||
|
if [ "$VIF_LIST" == "eth0" ]
|
||||||
|
then
|
||||||
|
logger -t cloud "Reverting ip address changes to eth0"
|
||||||
|
ip_entry $removedIps $addedIps
|
||||||
|
fi
|
||||||
|
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
# Remove backedup iptable rules
|
|
||||||
fw_remove_backup
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@ -362,11 +362,10 @@ def chain_name(vm_name):
|
|||||||
if vm_name.startswith('i-') or vm_name.startswith('r-'):
|
if vm_name.startswith('i-') or vm_name.startswith('r-'):
|
||||||
if vm_name.endswith('untagged'):
|
if vm_name.endswith('untagged'):
|
||||||
return '-'.join(vm_name.split('-')[:-1])
|
return '-'.join(vm_name.split('-')[:-1])
|
||||||
return '-'.join(vm_name.split('-'))
|
|
||||||
return vm_name
|
return vm_name
|
||||||
|
|
||||||
def chain_name_def(vm_name):
|
def chain_name_def(vm_name):
|
||||||
if vm_name.startswith('i-') or vm_name.startswith('r-'):
|
if vm_name.startswith('i-'):
|
||||||
if vm_name.endswith('untagged'):
|
if vm_name.endswith('untagged'):
|
||||||
return '-'.join(vm_name.split('-')[:-2]) + "-def"
|
return '-'.join(vm_name.split('-')[:-2]) + "-def"
|
||||||
return '-'.join(vm_name.split('-')[:-1]) + "-def"
|
return '-'.join(vm_name.split('-')[:-1]) + "-def"
|
||||||
@ -392,7 +391,7 @@ def can_bridge_firewall(session, args):
|
|||||||
util.pread2(['iptables', '-A', 'FORWARD', '-j', 'DROP'])
|
util.pread2(['iptables', '-A', 'FORWARD', '-j', 'DROP'])
|
||||||
except:
|
except:
|
||||||
result = 'false'
|
result = 'false'
|
||||||
|
allow_egress_traffic(session)
|
||||||
if not os.path.exists('/var/run/cloud'):
|
if not os.path.exists('/var/run/cloud'):
|
||||||
os.makedirs('/var/run/cloud')
|
os.makedirs('/var/run/cloud')
|
||||||
|
|
||||||
@ -401,6 +400,28 @@ def can_bridge_firewall(session, args):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@echo
|
||||||
|
def allow_egress_traffic(session):
|
||||||
|
devs = []
|
||||||
|
for pif in session.xenapi.PIF.get_all():
|
||||||
|
pif_rec = session.xenapi.PIF.get_record(pif)
|
||||||
|
vlan = pif_rec.get('VLAN')
|
||||||
|
dev = pif_rec.get('device')
|
||||||
|
if vlan == '-1':
|
||||||
|
devs.append(dev)
|
||||||
|
else:
|
||||||
|
devs.append(dev + "." + vlan)
|
||||||
|
for d in devs:
|
||||||
|
try:
|
||||||
|
util.pread2(['/bin/bash', '-c', "iptables -n -L FORWARD | grep '%s '" % d])
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
util.pread2(['iptables', '-I', 'FORWARD', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', d, '-j', 'ACCEPT'])
|
||||||
|
except:
|
||||||
|
util.SMlog("Failed to add FORWARD rule through to %s" % d)
|
||||||
|
return 'false'
|
||||||
|
return 'true'
|
||||||
|
|
||||||
|
|
||||||
def ipset(ipsetname, proto, start, end, ips):
|
def ipset(ipsetname, proto, start, end, ips):
|
||||||
try:
|
try:
|
||||||
@ -434,7 +455,7 @@ def destroy_network_rules_for_vm(session, args):
|
|||||||
vmchain_default = chain_name_def(vm_name)
|
vmchain_default = chain_name_def(vm_name)
|
||||||
|
|
||||||
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
|
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
|
||||||
if vm_name.startswith('i-') or vm_name.startswith('r-'):
|
if vm_name.startswith('i-') or vm_name.startswith('r-') or vm_name.startswith('l-'):
|
||||||
try:
|
try:
|
||||||
util.pread2(['iptables', '-F', vmchain_default])
|
util.pread2(['iptables', '-F', vmchain_default])
|
||||||
util.pread2(['iptables', '-X', vmchain_default])
|
util.pread2(['iptables', '-X', vmchain_default])
|
||||||
@ -453,7 +474,7 @@ def destroy_network_rules_for_vm(session, args):
|
|||||||
|
|
||||||
remove_rule_log_for_vm(vm_name)
|
remove_rule_log_for_vm(vm_name)
|
||||||
|
|
||||||
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]:
|
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]:
|
||||||
return 'true'
|
return 'true'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -573,15 +594,18 @@ def default_network_rules_systemvm(session, args):
|
|||||||
except:
|
except:
|
||||||
util.pread2(['iptables', '-F', vmchain])
|
util.pread2(['iptables', '-F', vmchain])
|
||||||
|
|
||||||
|
allow_egress_traffic(session)
|
||||||
|
|
||||||
for vif in vifs:
|
for vif in vifs:
|
||||||
try:
|
try:
|
||||||
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', vif, '-j', vmchain])
|
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', vif, '-j', vmchain])
|
||||||
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', vmchain])
|
util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', vmchain])
|
||||||
|
util.pread2(['iptables', '-I', vmchain, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', 'RETURN'])
|
||||||
except:
|
except:
|
||||||
util.SMlog("Failed to program default rules")
|
util.SMlog("Failed to program default rules")
|
||||||
return 'false'
|
return 'false'
|
||||||
|
|
||||||
|
|
||||||
util.pread2(['iptables', '-A', vmchain, '-j', 'ACCEPT'])
|
util.pread2(['iptables', '-A', vmchain, '-j', 'ACCEPT'])
|
||||||
|
|
||||||
if write_rule_log_for_vm(vm_name, '-1', '_ignore_', domid, '_initial_', '-1') == False:
|
if write_rule_log_for_vm(vm_name, '-1', '_ignore_', domid, '_initial_', '-1') == False:
|
||||||
@ -641,7 +665,7 @@ def default_network_rules(session, args):
|
|||||||
try:
|
try:
|
||||||
for v in vifs:
|
for v in vifs:
|
||||||
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default])
|
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default])
|
||||||
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default])
|
util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default])
|
||||||
util.pread2(['iptables', '-A', vmchain_default, '-m', 'state', '--state', 'RELATED,ESTABLISHED', '-j', 'ACCEPT'])
|
util.pread2(['iptables', '-A', vmchain_default, '-m', 'state', '--state', 'RELATED,ESTABLISHED', '-j', 'ACCEPT'])
|
||||||
#allow dhcp
|
#allow dhcp
|
||||||
for v in vifs:
|
for v in vifs:
|
||||||
@ -724,7 +748,7 @@ def network_rules_for_rebooted_vm(session, vmName):
|
|||||||
util.SMlog("Found a rebooted VM -- reprogramming rules for " + vm_name)
|
util.SMlog("Found a rebooted VM -- reprogramming rules for " + vm_name)
|
||||||
|
|
||||||
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
|
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
|
||||||
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]:
|
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]:
|
||||||
default_network_rules_systemvm(session, {"vmName":vm_name})
|
default_network_rules_systemvm(session, {"vmName":vm_name})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -741,7 +765,7 @@ def network_rules_for_rebooted_vm(session, vmName):
|
|||||||
|
|
||||||
for v in vifs:
|
for v in vifs:
|
||||||
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default])
|
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default])
|
||||||
util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default])
|
util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default])
|
||||||
|
|
||||||
#change antispoof rule in vmchain
|
#change antispoof rule in vmchain
|
||||||
try:
|
try:
|
||||||
@ -812,7 +836,7 @@ def get_rule_logs_for_vms(session, args):
|
|||||||
result = []
|
result = []
|
||||||
try:
|
try:
|
||||||
for name in [session.xenapi.VM.get_name_label(x) for x in vms]:
|
for name in [session.xenapi.VM.get_name_label(x) for x in vms]:
|
||||||
if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-'] ]:
|
if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-', 'l-'] ]:
|
||||||
continue
|
continue
|
||||||
network_rules_for_rebooted_vm(session, name)
|
network_rules_for_rebooted_vm(session, name)
|
||||||
if name.startswith('i-'):
|
if name.startswith('i-'):
|
||||||
@ -829,7 +853,7 @@ def cleanup_rules_for_dead_vms(session):
|
|||||||
vms = session.xenapi.VM.get_all()
|
vms = session.xenapi.VM.get_all()
|
||||||
cleaned = 0
|
cleaned = 0
|
||||||
for vm_name in [session.xenapi.VM.get_name_label(x) for x in vms]:
|
for vm_name in [session.xenapi.VM.get_name_label(x) for x in vms]:
|
||||||
if 1 in [ vm_name.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
|
if 1 in [ vm_name.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]:
|
||||||
vm = session.xenapi.VM.get_by_name_label(vm_name)
|
vm = session.xenapi.VM.get_by_name_label(vm_name)
|
||||||
if len(vm) != 1:
|
if len(vm) != 1:
|
||||||
continue
|
continue
|
||||||
@ -857,11 +881,11 @@ def cleanup_rules(session, args):
|
|||||||
cleaned = 0
|
cleaned = 0
|
||||||
cleanup = []
|
cleanup = []
|
||||||
for chain in chains:
|
for chain in chains:
|
||||||
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
|
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]:
|
||||||
vm = session.xenapi.VM.get_by_name_label(vm_name)
|
vm = session.xenapi.VM.get_by_name_label(chain)
|
||||||
if len(vm) != 1:
|
if len(vm) != 1:
|
||||||
util.SMlog("chain " + chain + " does not correspond to a vm, cleaning up")
|
util.SMlog("chain " + chain + " does not correspond to a vm, cleaning up")
|
||||||
cleanup.append(vm_name)
|
cleanup.append(chain)
|
||||||
continue
|
continue
|
||||||
vm_rec = session.xenapi.VM.get_record(vm[0])
|
vm_rec = session.xenapi.VM.get_record(vm[0])
|
||||||
state = vm_rec.get('power_state')
|
state = vm_rec.get('power_state')
|
||||||
@ -1058,6 +1082,16 @@ def checkRouter(session, args):
|
|||||||
return txt
|
return txt
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats,
|
||||||
XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "preparemigration": preparemigration, "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "networkUsage": networkUsage, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn, "cleanup_rules":cleanup_rules, "checkRouter": checkRouter})
|
"getvncport": getvncport, "getgateway": getgateway, "preparemigration": preparemigration,
|
||||||
|
"setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver,
|
||||||
|
"ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword,
|
||||||
|
"saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule,
|
||||||
|
"setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile,
|
||||||
|
"networkUsage": networkUsage, "network_rules":network_rules,
|
||||||
|
"can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules,
|
||||||
|
"destroy_network_rules_for_vm":destroy_network_rules_for_vm,
|
||||||
|
"default_network_rules_systemvm":default_network_rules_systemvm,
|
||||||
|
"get_rule_logs_for_vms":get_rule_logs_for_vms,
|
||||||
|
"setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn,
|
||||||
|
"cleanup_rules":cleanup_rules, "checkRouter": checkRouter})
|
||||||
|
|||||||
@ -186,6 +186,14 @@ public enum Config {
|
|||||||
UseUserConcentratedPodAllocation("Advanced", ManagementServer.class, Boolean.class, "use.user.concentrated.pod.allocation", "true", "If true, deployment planner applies the user concentration heuristic during VM resource allocation", "true,false"),
|
UseUserConcentratedPodAllocation("Advanced", ManagementServer.class, Boolean.class, "use.user.concentrated.pod.allocation", "true", "If true, deployment planner applies the user concentration heuristic during VM resource allocation", "true,false"),
|
||||||
HostCapacityTypeToOrderClusters("Advanced", ManagementServer.class, String.class, "host.capacityType.to.order.clusters", "CPU", "The host capacity type (CPU or RAM) is used by deployment planner to order clusters during VM resource allocation", "CPU,RAM"),
|
HostCapacityTypeToOrderClusters("Advanced", ManagementServer.class, String.class, "host.capacityType.to.order.clusters", "CPU", "The host capacity type (CPU or RAM) is used by deployment planner to order clusters during VM resource allocation", "CPU,RAM"),
|
||||||
EndpointeUrl("Advanced", ManagementServer.class, String.class, "endpointe.url", "http://localhost:8080/client/api", "Endpointe Url", "The endpoint callback URL"),
|
EndpointeUrl("Advanced", ManagementServer.class, String.class, "endpointe.url", "http://localhost:8080/client/api", "Endpointe Url", "The endpoint callback URL"),
|
||||||
|
ElasticLoadBalancerEnabled("Advanced", ManagementServer.class, String.class, "network.loadbalancer.basiczone.elb.enabled", "false", "Whether the load balancing service is enabled for basic zones", "true,false"),
|
||||||
|
ElasticLoadBalancerNetwork("Advanced", ManagementServer.class, String.class, "network.loadbalancer.basiczone.elb.network", "guest", "Whether the elastic load balancing service public ips are taken from the public or guest network", "guest,public"),
|
||||||
|
ElasticLoadBalancerVmMemory("Advanced", ManagementServer.class, Integer.class, "network.loadbalancer.basiczone.elb.vm.ram.size", "128", "Memory in MB for the elastic load balancer vm", null),
|
||||||
|
ElasticLoadBalancerVmCpuMhz("Advanced", ManagementServer.class, Integer.class, "network.loadbalancer.basiczone.elb.vm.cpu.mhz", "128", "CPU speed for the elastic load balancer vm", null),
|
||||||
|
ElasticLoadBalancerVmNumVcpu("Advanced", ManagementServer.class, Integer.class, "network.loadbalancer.basiczone.elb.vm.vcpu.num", "1", "Number of VCPU for the elastic load balancer vm", null),
|
||||||
|
ElasticLoadBalancerVmGcInterval("Advanced", ManagementServer.class, Integer.class, "network.loadbalancer.basiczone.elb.gc.interval.minutes", "30", "Garbage collection interval to destroy unused ELB vms in minutes. Minimum of 5", null),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// XenServer
|
// XenServer
|
||||||
VmAllocationAlgorithm("Advanced", ManagementServer.class, String.class, "vm.allocation.algorithm", "random", "If 'random', hosts within a pod will be randomly considered for VM/volume allocation. If 'firstfit', they will be considered on a first-fit basis.", null),
|
VmAllocationAlgorithm("Advanced", ManagementServer.class, String.class, "vm.allocation.algorithm", "random", "If 'random', hosts within a pod will be randomly considered for VM/volume allocation. If 'firstfit', they will be considered on a first-fit basis.", null),
|
||||||
@ -252,7 +260,7 @@ public enum Config {
|
|||||||
|
|
||||||
AgentLbEnable("Advanced", ClusterManager.class, Boolean.class, "agent.lb.enabled", "true", "If agent load balancing enabled in cluster setup", null),
|
AgentLbEnable("Advanced", ClusterManager.class, Boolean.class, "agent.lb.enabled", "true", "If agent load balancing enabled in cluster setup", null),
|
||||||
SubDomainNetworkAccess("Advanced", NetworkManager.class, Boolean.class, "allow.subdomain.network.access", "true", "Allow subdomains to use networks dedicated to their parent domain(s)", null),
|
SubDomainNetworkAccess("Advanced", NetworkManager.class, Boolean.class, "allow.subdomain.network.access", "true", "Allow subdomains to use networks dedicated to their parent domain(s)", null),
|
||||||
UseExternalDnsServers("Advanced", NetworkManager.class, Boolean.class, "use.external.dns", "false", "Bypass internal dns, use exetrnal dns1 and dns2", null),
|
UseExternalDnsServers("Advanced", NetworkManager.class, Boolean.class, "use.external.dns", "false", "Bypass the cloudstack dhcp/DNS server vm name service, use zone external dns1 and dns2", null),
|
||||||
EncodeApiResponse("Advanced", ManagementServer.class, Boolean.class, "encode.api.response", "false", "Do UTF-8 encoding for the api response, false by default", null),
|
EncodeApiResponse("Advanced", ManagementServer.class, Boolean.class, "encode.api.response", "false", "Do UTF-8 encoding for the api response, false by default", null),
|
||||||
|
|
||||||
DnsBasicZoneUpdates("Advanced", NetworkManager.class, String.class, "network.dns.basiczone.updates", "all", "This parameter can take 2 values: all (default) and pod. It defines if DHCP/DNS requests have to be send to all dhcp servers in cloudstack, or only to the one in the same pod", "all,pod"),
|
DnsBasicZoneUpdates("Advanced", NetworkManager.class, String.class, "network.dns.basiczone.updates", "all", "This parameter can take 2 values: all (default) and pod. It defines if DHCP/DNS requests have to be send to all dhcp servers in cloudstack, or only to the one in the same pod", "all,pod"),
|
||||||
|
|||||||
@ -81,7 +81,9 @@ import com.cloud.network.dao.NetworkDomainDaoImpl;
|
|||||||
import com.cloud.network.dao.NetworkRuleConfigDaoImpl;
|
import com.cloud.network.dao.NetworkRuleConfigDaoImpl;
|
||||||
import com.cloud.network.dao.RemoteAccessVpnDaoImpl;
|
import com.cloud.network.dao.RemoteAccessVpnDaoImpl;
|
||||||
import com.cloud.network.dao.VpnUserDaoImpl;
|
import com.cloud.network.dao.VpnUserDaoImpl;
|
||||||
|
import com.cloud.network.lb.ElasticLoadBalancerManagerImpl;
|
||||||
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
|
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
|
||||||
|
import com.cloud.network.lb.dao.ElasticLbVmMapDaoImpl;
|
||||||
import com.cloud.network.ovs.OvsNetworkManagerImpl;
|
import com.cloud.network.ovs.OvsNetworkManagerImpl;
|
||||||
import com.cloud.network.ovs.OvsTunnelManagerImpl;
|
import com.cloud.network.ovs.OvsTunnelManagerImpl;
|
||||||
import com.cloud.network.ovs.dao.GreTunnelDaoImpl;
|
import com.cloud.network.ovs.dao.GreTunnelDaoImpl;
|
||||||
@ -265,6 +267,8 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
|||||||
addDao("DcDetailsDao", DcDetailsDaoImpl.class);
|
addDao("DcDetailsDao", DcDetailsDaoImpl.class);
|
||||||
addDao("SwiftDao", SwiftDaoImpl.class);
|
addDao("SwiftDao", SwiftDaoImpl.class);
|
||||||
addDao("AgentTransferMapDao", HostTransferMapDaoImpl.class);
|
addDao("AgentTransferMapDao", HostTransferMapDaoImpl.class);
|
||||||
|
addDao("ElasticLbVmMap", ElasticLbVmMapDaoImpl.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -312,6 +316,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
|||||||
ComponentInfo<? extends Manager> info = addManager("ConsoleProxyManager", ConsoleProxyManagerImpl.class);
|
ComponentInfo<? extends Manager> info = addManager("ConsoleProxyManager", ConsoleProxyManagerImpl.class);
|
||||||
info.addParameter("consoleproxy.sslEnabled", "true");
|
info.addParameter("consoleproxy.sslEnabled", "true");
|
||||||
addManager("ClusteredAgentManager", ClusteredAgentManagerImpl.class);
|
addManager("ClusteredAgentManager", ClusteredAgentManagerImpl.class);
|
||||||
|
addManager("ElasticLoadBalancerManager", ElasticLoadBalancerManagerImpl.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -205,6 +205,7 @@ public class DataCenterVO implements DataCenter {
|
|||||||
dhcpProvider = Provider.DhcpServer.getName();
|
dhcpProvider = Provider.DhcpServer.getName();
|
||||||
dnsProvider = Provider.DhcpServer.getName();
|
dnsProvider = Provider.DhcpServer.getName();
|
||||||
userDataProvider = Provider.DhcpServer.getName();
|
userDataProvider = Provider.DhcpServer.getName();
|
||||||
|
loadBalancerProvider = Provider.ElasticLoadBalancerVm.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.zoneToken = zoneToken;
|
this.zoneToken = zoneToken;
|
||||||
|
|||||||
103
server/src/com/cloud/network/ElasticLbVmMapVO.java
Normal file
103
server/src/com/cloud/network/ElasticLbVmMapVO.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2011 Citrix Systems, 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;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.PrimaryKeyJoinColumn;
|
||||||
|
import javax.persistence.SecondaryTable;
|
||||||
|
import javax.persistence.SecondaryTables;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import com.cloud.utils.net.Ip;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = ("elastic_lb_vm_map"))
|
||||||
|
@SecondaryTables({
|
||||||
|
@SecondaryTable(name = "user_ip_address", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "ip_addr_id", referencedColumnName = "id") })
|
||||||
|
})
|
||||||
|
public class ElasticLbVmMapVO {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "lb_id")
|
||||||
|
private Long lbId;
|
||||||
|
|
||||||
|
@Column(name = "ip_addr_id")
|
||||||
|
private long ipAddressId;
|
||||||
|
|
||||||
|
@Column(name = "elb_vm_id")
|
||||||
|
private long elbVmId;
|
||||||
|
|
||||||
|
/*@Column(name = "name", table = "load_balancing_rules", insertable = false, updatable = false)
|
||||||
|
private String lbName;*/
|
||||||
|
|
||||||
|
@Column(name = "public_ip_address", table = "user_ip_address", insertable = false, updatable = false)
|
||||||
|
@Enumerated(value=EnumType.STRING)
|
||||||
|
private Ip address = null;
|
||||||
|
|
||||||
|
public ElasticLbVmMapVO() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElasticLbVmMapVO(long ipId, long elbVmId, long lbId) {
|
||||||
|
this.ipAddressId = ipId;
|
||||||
|
this.elbVmId = elbVmId;
|
||||||
|
this.lbId = lbId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLbId() {
|
||||||
|
return lbId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getElbVmId() {
|
||||||
|
return elbVmId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public String getLbName() {
|
||||||
|
// return lbName;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
public long getIpAddressId() {
|
||||||
|
return ipAddressId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLbId(Long lbId) {
|
||||||
|
this.lbId = lbId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ip getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -562,6 +562,16 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
|
|||||||
if (zone.getNetworkType() != NetworkType.Basic && network.getAccountId() != ipOwner.getId()) {
|
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");
|
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;
|
PublicIp ip = null;
|
||||||
|
|
||||||
@ -604,7 +614,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) {
|
if (ip == null) {
|
||||||
throw new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zoneId);
|
throw new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zoneId);
|
||||||
@ -745,7 +755,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
|
|||||||
NetworkOfferingVO guestNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemGuestNetwork, "System Offering for System-Guest-Network", TrafficType.Guest, true, false, null, null,
|
NetworkOfferingVO guestNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemGuestNetwork, "System Offering for System-Guest-Network", TrafficType.Guest, true, false, null, null,
|
||||||
null, true, Availability.Required,
|
null, true, Availability.Required,
|
||||||
// services - all true except for firewall/lb/vpn and gateway services
|
// services - all true except for firewall/lb/vpn and gateway services
|
||||||
true, true, true, false, false, false, false, GuestIpType.Direct);
|
true, true, true, false, false, true, false, GuestIpType.Direct);
|
||||||
guestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(guestNetworkOffering);
|
guestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(guestNetworkOffering);
|
||||||
_systemNetworks.put(NetworkOfferingVO.SystemGuestNetwork, guestNetworkOffering);
|
_systemNetworks.put(NetworkOfferingVO.SystemGuestNetwork, guestNetworkOffering);
|
||||||
|
|
||||||
@ -757,8 +767,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
|
|||||||
defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestNetworkOffering);
|
defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestNetworkOffering);
|
||||||
NetworkOfferingVO defaultGuestDirectNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectNetworkOffering, "Direct", TrafficType.Guest, false, true, null, null, null, true,
|
NetworkOfferingVO defaultGuestDirectNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectNetworkOffering, "Direct", TrafficType.Guest, false, true, null, null, null, true,
|
||||||
Availability.Optional,
|
Availability.Optional,
|
||||||
// services - all true except for firewall/lb/vpn and gateway services
|
// services - all true except for firewall/vpn and gateway services
|
||||||
true, true, true, false, false, false, false, GuestIpType.Direct);
|
true, true, true, false, false, true, false, GuestIpType.Direct);
|
||||||
defaultGuestDirectNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering);
|
defaultGuestDirectNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering);
|
||||||
|
|
||||||
AccountsUsingNetworkSearch = _accountDao.createSearchBuilder();
|
AccountsUsingNetworkSearch = _accountDao.createSearchBuilder();
|
||||||
|
|||||||
@ -0,0 +1,169 @@
|
|||||||
|
/**
|
||||||
|
* 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 javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.configuration.Config;
|
||||||
|
import com.cloud.configuration.dao.ConfigurationDao;
|
||||||
|
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.Network.Capability;
|
||||||
|
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.dao.NetworkDao;
|
||||||
|
import com.cloud.network.lb.ElasticLoadBalancerManager;
|
||||||
|
import com.cloud.network.rules.FirewallRule;
|
||||||
|
import com.cloud.offering.NetworkOffering;
|
||||||
|
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||||
|
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 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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* 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.api.commands.CreateLoadBalancerRuleCmd;
|
||||||
|
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||||
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.rules.FirewallRule;
|
||||||
|
import com.cloud.network.rules.LoadBalancer;
|
||||||
|
import com.cloud.user.Account;
|
||||||
|
|
||||||
|
public interface ElasticLoadBalancerManager {
|
||||||
|
public static final int DEFAULT_ELB_VM_RAMSIZE = 128; // 512 MB
|
||||||
|
public static final int DEFAULT_ELB_VM_CPU_MHZ = 256; // 500 MHz
|
||||||
|
|
||||||
|
public boolean applyLoadBalancerRules(Network network,
|
||||||
|
List<? extends FirewallRule> rules)
|
||||||
|
throws ResourceUnavailableException;
|
||||||
|
|
||||||
|
public LoadBalancer handleCreateLoadBalancerRule(CreateLoadBalancerRuleCmd lb, Account caller) throws InsufficientAddressCapacityException, NetworkRuleConflictException;
|
||||||
|
|
||||||
|
public void handleDeleteLoadBalancerRule(LoadBalancer lb, long callerUserId, Account caller);
|
||||||
|
}
|
||||||
@ -0,0 +1,982 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2011 Citrix Systems, 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.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
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.StopAnswer;
|
||||||
|
import com.cloud.agent.api.check.CheckSshAnswer;
|
||||||
|
import com.cloud.agent.api.check.CheckSshCommand;
|
||||||
|
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.api.commands.CreateLoadBalancerRuleCmd;
|
||||||
|
import com.cloud.configuration.Config;
|
||||||
|
import com.cloud.configuration.dao.ConfigurationDao;
|
||||||
|
import com.cloud.dc.DataCenter;
|
||||||
|
import com.cloud.dc.DataCenter.NetworkType;
|
||||||
|
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;
|
||||||
|
import com.cloud.dc.dao.PodVlanMapDao;
|
||||||
|
import com.cloud.dc.dao.VlanDao;
|
||||||
|
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;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.network.ElasticLbVmMapVO;
|
||||||
|
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.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;
|
||||||
|
import com.cloud.network.dao.NetworkDao;
|
||||||
|
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
||||||
|
import com.cloud.network.lb.dao.ElasticLbVmMapDao;
|
||||||
|
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.network.rules.LoadBalancer;
|
||||||
|
import com.cloud.offering.NetworkOffering;
|
||||||
|
import com.cloud.offerings.NetworkOfferingVO;
|
||||||
|
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||||
|
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.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.concurrency.NamedThreadFactory;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
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.ReservationContext;
|
||||||
|
import com.cloud.vm.VMInstanceVO;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.VirtualMachineGuru;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
import com.cloud.vm.VirtualMachineGuru;
|
||||||
|
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, VirtualMachineGuru<DomainRouterVO> {
|
||||||
|
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;
|
||||||
|
@Inject
|
||||||
|
LoadBalancerDao _lbDao;
|
||||||
|
@Inject
|
||||||
|
VlanDao _vlanDao;
|
||||||
|
@Inject
|
||||||
|
PodVlanMapDao _podVlanMapDao;
|
||||||
|
@Inject
|
||||||
|
ElasticLbVmMapDao _elbVmMapDao;
|
||||||
|
@Inject
|
||||||
|
NetworkDao _networksDao;
|
||||||
|
@Inject
|
||||||
|
AccountDao _accountDao;
|
||||||
|
|
||||||
|
|
||||||
|
String _name;
|
||||||
|
String _instance;
|
||||||
|
static final private String _elbVmNamePrefix = "l";
|
||||||
|
static final private String _systemVmType = "elbvm";
|
||||||
|
|
||||||
|
boolean _enabled;
|
||||||
|
TrafficType _frontendTrafficType = TrafficType.Guest;
|
||||||
|
|
||||||
|
Account _systemAcct;
|
||||||
|
ServiceOfferingVO _elasticLbVmOffering;
|
||||||
|
ScheduledExecutorService _gcThreadPool;
|
||||||
|
String _mgmtCidr;
|
||||||
|
String _mgmtHost;
|
||||||
|
|
||||||
|
Set<Long> _gcCandidateElbVmIds = Collections.newSetFromMap(new ConcurrentHashMap<Long,Boolean>());
|
||||||
|
|
||||||
|
int _elasticLbVmRamSize;
|
||||||
|
int _elasticLbvmCpuMHz;
|
||||||
|
int _elasticLbvmNumCpu;
|
||||||
|
|
||||||
|
private Long getPodIdForDirectIp(IPAddressVO ipAddr) {
|
||||||
|
List<PodVlanMapVO> podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(ipAddr.getVlanId());
|
||||||
|
if (podVlanMaps.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return podVlanMaps.get(0).getPodId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DomainRouterVO deployLoadBalancerVM(Long networkId, IPAddressVO ipAddr, Long accountId) {
|
||||||
|
NetworkVO network = _networkDao.findById(networkId);
|
||||||
|
DataCenter dc = _dcDao.findById(network.getDataCenterId());
|
||||||
|
Long podId = getPodIdForDirectIp(ipAddr);
|
||||||
|
Pod pod = podId == null?null:_podDao.findById(podId);
|
||||||
|
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, pod, null, null);
|
||||||
|
s_logger.debug("About to deploy ELB vm ");
|
||||||
|
|
||||||
|
try {
|
||||||
|
DomainRouterVO elbVm = deployELBVm(network, dest, owner, params);
|
||||||
|
if (elbVm == null) {
|
||||||
|
throw new InvalidParameterValueException("Could not deploy or find existing ELB VM");
|
||||||
|
}
|
||||||
|
s_logger.debug("Deployed ELB vm = " + elbVm);
|
||||||
|
|
||||||
|
return elbVm;
|
||||||
|
|
||||||
|
} catch (Throwable t) {
|
||||||
|
s_logger.warn("Error while deploying ELB VM: " + t);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendCommandsToRouter(final DomainRouterVO elbVm,
|
||||||
|
Commands cmds) throws AgentUnavailableException {
|
||||||
|
Answer[] answers = null;
|
||||||
|
try {
|
||||||
|
answers = _agentMgr.send(elbVm.getHostId(), cmds);
|
||||||
|
} catch (OperationTimedoutException e) {
|
||||||
|
s_logger.warn("ELB: Timed Out", e);
|
||||||
|
throw new AgentUnavailableException(
|
||||||
|
"Unable to send commands to virtual elbVm ",
|
||||||
|
elbVm.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 elbVm, Commands cmds) {
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
String elbIp = _networkMgr.getIp(rule.getSourceIpAddressId()).getAddress()
|
||||||
|
.addr();
|
||||||
|
int srcPort = rule.getSourcePortStart();
|
||||||
|
List<LbDestination> destinations = rule.getDestinations();
|
||||||
|
LoadBalancerTO lb = new LoadBalancerTO(elbIp, srcPort, protocol, null,
|
||||||
|
algorithm, revoked, false, destinations);
|
||||||
|
lbs[i++] = lb;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs);
|
||||||
|
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP,
|
||||||
|
elbVm.getPrivateIpAddress());
|
||||||
|
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME,
|
||||||
|
elbVm.getInstanceName());
|
||||||
|
cmds.addCommand(cmd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean applyLBRules(DomainRouterVO elbVm,
|
||||||
|
List<LoadBalancingRule> rules) throws ResourceUnavailableException {
|
||||||
|
Commands cmds = new Commands(OnError.Continue);
|
||||||
|
createApplyLoadBalancingRulesCommands(rules, elbVm, cmds);
|
||||||
|
// Send commands to elbVm
|
||||||
|
return sendCommandsToRouter(elbVm, cmds);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DomainRouterVO findElbVmForLb(FirewallRule lb) {//TODO: use a table to lookup
|
||||||
|
ElasticLbVmMapVO map = _elbVmMapDao.findOneByIp(lb.getSourceIpAddressId());
|
||||||
|
if (map == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DomainRouterVO elbVm = _routerDao.findById(map.getElbVmId());
|
||||||
|
return elbVm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean applyLoadBalancerRules(Network network,
|
||||||
|
List<? extends FirewallRule> rules)
|
||||||
|
throws ResourceUnavailableException {
|
||||||
|
if (rules == null || rules.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (rules.get(0).getPurpose() != Purpose.LoadBalancing) {
|
||||||
|
s_logger.warn("ELB: Not handling non-LB firewall rules");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainRouterVO elbVm = findElbVmForLb(rules.get(0));
|
||||||
|
|
||||||
|
if (elbVm == null) {
|
||||||
|
s_logger.warn("Unable to apply lb rules, ELB vm doesn't exist in the network "
|
||||||
|
+ network.getId());
|
||||||
|
throw new ResourceUnavailableException("Unable to apply lb rules",
|
||||||
|
DataCenter.class, network.getDataCenterId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elbVm.getState() == State.Running) {
|
||||||
|
//resend all rules for the public ip
|
||||||
|
List<LoadBalancerVO> lbs = _lbDao.listByIpAddress(rules.get(0).getSourceIpAddressId());
|
||||||
|
List<LoadBalancingRule> lbRules = new ArrayList<LoadBalancingRule>();
|
||||||
|
for (LoadBalancerVO lb : lbs) {
|
||||||
|
List<LbDestination> dstList = _lbMgr.getExistingDestinations(lb.getId());
|
||||||
|
LoadBalancingRule loadBalancing = new LoadBalancingRule(
|
||||||
|
lb, dstList);
|
||||||
|
lbRules.add(loadBalancing);
|
||||||
|
}
|
||||||
|
return applyLBRules(elbVm, lbRules);
|
||||||
|
} else if (elbVm.getState() == State.Stopped
|
||||||
|
|| elbVm.getState() == State.Stopping) {
|
||||||
|
s_logger.debug("ELB VM is in "
|
||||||
|
+ elbVm.getState()
|
||||||
|
+ ", so not sending apply LoadBalancing rules commands to the backend");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
s_logger.warn("Unable to apply loadbalancing rules, ELB VM is not in the right state "
|
||||||
|
+ elbVm.getState());
|
||||||
|
throw new ResourceUnavailableException(
|
||||||
|
"Unable to apply loadbalancing rules, ELB VM is not in the right state",
|
||||||
|
VirtualRouter.class, elbVm.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";
|
||||||
|
}
|
||||||
|
_mgmtCidr = _configDao.getValue(Config.ManagementNetwork.key());
|
||||||
|
_mgmtHost = _configDao.getValue(Config.ManagementHostIPAdr.key());
|
||||||
|
|
||||||
|
boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key()));
|
||||||
|
|
||||||
|
_elasticLbVmRamSize = NumbersUtil.parseInt(configs.get(Config.ElasticLoadBalancerVmMemory.key()), DEFAULT_ELB_VM_RAMSIZE);
|
||||||
|
_elasticLbvmCpuMHz = NumbersUtil.parseInt(configs.get(Config.ElasticLoadBalancerVmCpuMhz.key()), DEFAULT_ELB_VM_CPU_MHZ);
|
||||||
|
_elasticLbvmNumCpu = NumbersUtil.parseInt(configs.get(Config.ElasticLoadBalancerVmNumVcpu.key()), 1);
|
||||||
|
_elasticLbVmOffering = new ServiceOfferingVO("System Offering For Elastic LB VM", _elasticLbvmNumCpu,
|
||||||
|
_elasticLbVmRamSize, _elasticLbvmCpuMHz, 0, 0, true, null, useLocalStorage,
|
||||||
|
true, null, true, VirtualMachine.Type.ElasticLoadBalancerVm, true);
|
||||||
|
_elasticLbVmOffering.setUniqueName("Cloud.Com-ElasticLBVm");
|
||||||
|
_elasticLbVmOffering = _serviceOfferingDao.persistSystemServiceOffering(_elasticLbVmOffering);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String enabled = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key());
|
||||||
|
_enabled = (enabled == null) ? false: Boolean.parseBoolean(enabled);
|
||||||
|
s_logger.info("Elastic Load balancer enabled: " + _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("ELB: Traffic type for front end of load balancer has to be guest or public; found : " + traffType);
|
||||||
|
s_logger.info("ELB: Elastic Load Balancer: will balance on " + traffType );
|
||||||
|
int gcIntervalMinutes = NumbersUtil.parseInt(configs.get(Config.ElasticLoadBalancerVmGcInterval.key()), 5);
|
||||||
|
if (gcIntervalMinutes < 5)
|
||||||
|
gcIntervalMinutes = 5;
|
||||||
|
s_logger.info("ELB: Elastic Load Balancer: scheduling GC to run every " + gcIntervalMinutes + " minutes" );
|
||||||
|
_gcThreadPool = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ELBVM-GC"));
|
||||||
|
_gcThreadPool.scheduleAtFixedRate(new CleanupThread(), gcIntervalMinutes, gcIntervalMinutes, TimeUnit.MINUTES);
|
||||||
|
_itMgr.registerGuru(VirtualMachine.Type.ElasticLoadBalancerVm, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DomainRouterVO findELBVmWithCapacity(Network guestNetwork, IPAddressVO ipAddr) {
|
||||||
|
List<DomainRouterVO> unusedElbVms = _elbVmMapDao.listUnusedElbVms();
|
||||||
|
if (unusedElbVms.size() > 0) {
|
||||||
|
List<DomainRouterVO> candidateVms = new ArrayList<DomainRouterVO>();
|
||||||
|
for (DomainRouterVO candidateVm: unusedElbVms) {
|
||||||
|
if (candidateVm.getPodIdToDeployIn() == getPodIdForDirectIp(ipAddr))
|
||||||
|
candidateVms.add(candidateVm);
|
||||||
|
}
|
||||||
|
return candidateVms.size()==0?null:candidateVms.get(new Random().nextInt(candidateVms.size()));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 lock: " + 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 ELB 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 elbVm = null;
|
||||||
|
|
||||||
|
plan = new DataCenterDeployment(dcId, dest.getPod().getId(), null, null, null);
|
||||||
|
|
||||||
|
if (elbVm == null) {
|
||||||
|
long id = _routerDao.getNextInSequence(Long.class, "id");
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug("Creating the ELB 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();
|
||||||
|
guestNic.setDefaultNic(true);
|
||||||
|
networks.add(new Pair<NetworkVO, NicProfile>((NetworkVO) guestNetwork, guestNic));
|
||||||
|
networks.add(new Pair<NetworkVO, NicProfile>(controlConfig, null));
|
||||||
|
|
||||||
|
VMTemplateVO template = _templateDao.findSystemVMTemplate(dcId);
|
||||||
|
|
||||||
|
|
||||||
|
elbVm = new DomainRouterVO(id, _elasticLbVmOffering.getId(), VirtualMachineName.getSystemVmName(id, _instance, _elbVmNamePrefix), template.getId(), template.getHypervisorType(), template.getGuestOSId(),
|
||||||
|
owner.getDomainId(), owner.getId(), guestNetwork.getId(), _elasticLbVmOffering.getOfferHA(), VirtualMachine.Type.ElasticLoadBalancerVm);
|
||||||
|
elbVm.setRole(Role.LB);
|
||||||
|
elbVm = _itMgr.allocate(elbVm, template, _elasticLbVmOffering, networks, plan, null, owner);
|
||||||
|
//TODO: create usage stats
|
||||||
|
}
|
||||||
|
|
||||||
|
State state = elbVm.getState();
|
||||||
|
if (state != State.Running) {
|
||||||
|
elbVm = this.start(elbVm, _accountService.getSystemUser(), _accountService.getSystemAccount(), params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return elbVm;
|
||||||
|
} finally {
|
||||||
|
_networkDao.releaseFromLockTable(guestNetworkId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DomainRouterVO start(DomainRouterVO elbVm, User user, Account caller, Map<Param, Object> params) throws StorageUnavailableException, InsufficientCapacityException,
|
||||||
|
ConcurrentOperationException, ResourceUnavailableException {
|
||||||
|
s_logger.debug("Starting ELB VM " + elbVm);
|
||||||
|
if (_itMgr.start(elbVm, params, user, caller) != null) {
|
||||||
|
return _routerDao.findById(elbVm.getId());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
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<LoadBalancerVO> 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<LoadBalancerVO> 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<NetworkOfferingVO> offerings = _networkOfferingDao.listByTrafficTypeAndGuestType(true, _frontendTrafficType, GuestIpType.Direct);
|
||||||
|
if (offerings == null || offerings.size() == 0) {
|
||||||
|
s_logger.warn("ELB: Could not find system offering for direct networks of type " + _frontendTrafficType);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
NetworkOffering frontEndOffering = offerings.get(0);
|
||||||
|
List<NetworkVO> networks = _networksDao.listBy(Account.ACCOUNT_ID_SYSTEM, frontEndOffering.getId(), lb.getZoneId());
|
||||||
|
if (networks == null || networks.size() == 0) {
|
||||||
|
s_logger.warn("ELB: Could not find network of offering type " + frontEndOffering + " in zone " + lb.getZoneId());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Network frontEndNetwork = networks.get(0);
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
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 frontend IP for ELB " + ip);
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseIp(long ipId, long userId, Account caller) {
|
||||||
|
s_logger.info("ELB: Release public IP for loadbalancing " + ipId);
|
||||||
|
IPAddressVO ipvo = _ipAddressDao.findById(ipId);
|
||||||
|
ipvo.setAssociatedWithNetworkId(null);
|
||||||
|
_ipAddressDao.update(ipvo.getId(), ipvo);
|
||||||
|
_networkMgr.releasePublicIpAddress(ipId, userId, caller);
|
||||||
|
_ipAddressDao.unassignIpAddress(ipId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NetworkVO getNetworkToDeployLb(Long ipId) {
|
||||||
|
IPAddressVO ipAddr = _ipAddressDao.findById(ipId);
|
||||||
|
Long networkId= ipAddr.getSourceNetworkId();
|
||||||
|
NetworkVO network=_networkDao.findById(networkId);
|
||||||
|
|
||||||
|
|
||||||
|
if (network.getGuestType() != GuestIpType.Direct) {
|
||||||
|
s_logger.info("ELB: not handling guest traffic of type " + network.getGuestType());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return network;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@DB
|
||||||
|
public LoadBalancer handleCreateLoadBalancerRule( CreateLoadBalancerRuleCmd lb, Account account) throws InsufficientAddressCapacityException, NetworkRuleConflictException {
|
||||||
|
Long ipId = lb.getSourceIpAddressId();
|
||||||
|
if (ipId != null && getNetworkToDeployLb(ipId) == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
boolean newIp = false;
|
||||||
|
account = _accountDao.acquireInLockTable(account.getId());
|
||||||
|
if (account == null) {
|
||||||
|
s_logger.warn("ELB: CreateLoadBalancer: Failed to acquire lock on account");
|
||||||
|
throw new CloudRuntimeException("Failed to acquire lock on account");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
List<LoadBalancerVO> 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 {
|
||||||
|
s_logger.debug("Could not find any existing frontend ips for this account for this LB rule, acquiring a new frontent IP for ELB");
|
||||||
|
PublicIp ip = allocIp(lb, account);
|
||||||
|
ipId = ip.getId();
|
||||||
|
newIp = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ipId = existingLbs.get(0).getSourceIpAddressId();
|
||||||
|
s_logger.debug("ELB: Found existing frontend ip for this account for this LB rule " + ipId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s_logger.warn("ELB: Found existing load balancers matching requested new LB");
|
||||||
|
throw new NetworkRuleConflictException("ELB: Found existing load balancers matching requested new LB");
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkVO network = getNetworkToDeployLb(ipId);
|
||||||
|
IPAddressVO ipAddr = _ipAddressDao.findById(ipId);
|
||||||
|
long networkId = network.getId();
|
||||||
|
|
||||||
|
|
||||||
|
LoadBalancer result = null;
|
||||||
|
try {
|
||||||
|
lb.setSourceIpAddressId(ipId);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainRouterVO elbVm = null;
|
||||||
|
|
||||||
|
|
||||||
|
if (existingLbs == null) {
|
||||||
|
elbVm = findELBVmWithCapacity(network, ipAddr);
|
||||||
|
if (elbVm == null) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(), result.getId());
|
||||||
|
_elbVmMapDao.persist(mapping);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (account != null) {
|
||||||
|
_accountDao.releaseFromLockTable(account.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void garbageCollectUnusedElbVms() {
|
||||||
|
List<DomainRouterVO> unusedElbVms = _elbVmMapDao.listUnusedElbVms();
|
||||||
|
if (unusedElbVms != null && unusedElbVms.size() > 0)
|
||||||
|
s_logger.info("Found " + unusedElbVms.size() + " unused ELB vms");
|
||||||
|
Set<Long> currentGcCandidates = new HashSet<Long>();
|
||||||
|
for (DomainRouterVO elbVm: unusedElbVms) {
|
||||||
|
currentGcCandidates.add(elbVm.getId());
|
||||||
|
}
|
||||||
|
_gcCandidateElbVmIds.retainAll(currentGcCandidates);
|
||||||
|
currentGcCandidates.removeAll(_gcCandidateElbVmIds);
|
||||||
|
User user = _accountService.getSystemUser();
|
||||||
|
for (Long elbVmId : _gcCandidateElbVmIds) {
|
||||||
|
DomainRouterVO elbVm = _routerDao.findById(elbVmId);
|
||||||
|
boolean gceed = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
s_logger.info("Attempting to stop ELB VM: " + elbVm);
|
||||||
|
stop(elbVm, true, user, _systemAcct);
|
||||||
|
gceed = true;
|
||||||
|
} catch (ConcurrentOperationException e) {
|
||||||
|
s_logger.warn("Unable to stop unused ELB vm " + elbVm + " due to ", e);
|
||||||
|
} catch (ResourceUnavailableException e) {
|
||||||
|
s_logger.warn("Unable to stop unused ELB vm " + elbVm + " due to ", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (gceed) {
|
||||||
|
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);
|
||||||
|
gceed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!gceed) {
|
||||||
|
currentGcCandidates.add(elbVm.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
_gcCandidateElbVmIds = currentGcCandidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CleanupThread implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
garbageCollectUnusedElbVms();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CleanupThread() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleDeleteLoadBalancerRule(LoadBalancer lb, long userId, Account caller) {
|
||||||
|
List<LoadBalancerVO> remainingLbs = _loadBalancerDao.listByIpAddress(lb.getSourceIpAddressId());
|
||||||
|
if (remainingLbs.size() == 0) {
|
||||||
|
s_logger.debug("ELB mgr: releasing ip " + lb.getSourceIpAddressId() + " since no LB rules remain for this ip address");
|
||||||
|
releaseIp(lb.getSourceIpAddressId(), userId, caller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainRouterVO findByName(String name) {
|
||||||
|
if (!VirtualMachineName.isValidSystemVmName(name, _instance, _elbVmNamePrefix)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _routerDao.findById(VirtualMachineName.getSystemVmId(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainRouterVO findById(long id) {
|
||||||
|
return _routerDao.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainRouterVO persist(DomainRouterVO elbVm) {
|
||||||
|
return _routerDao.persist(elbVm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean finalizeVirtualMachineProfile(VirtualMachineProfile<DomainRouterVO> profile, DeployDestination dest, ReservationContext context) {
|
||||||
|
DomainRouterVO elbVm = profile.getVirtualMachine();
|
||||||
|
NetworkVO network = _networkDao.findById(elbVm.getNetworkId());
|
||||||
|
|
||||||
|
DataCenter dc = dest.getDataCenter();
|
||||||
|
|
||||||
|
StringBuilder buf = profile.getBootArgsBuilder();
|
||||||
|
buf.append(" template=domP type=" + _systemVmType);
|
||||||
|
buf.append(" name=").append(profile.getHostName());
|
||||||
|
NicProfile controlNic = null;
|
||||||
|
String defaultDns1 = null;
|
||||||
|
String defaultDns2 = null;
|
||||||
|
|
||||||
|
for (NicProfile nic : profile.getNics()) {
|
||||||
|
int deviceId = nic.getDeviceId();
|
||||||
|
buf.append(" eth").append(deviceId).append("ip=").append(nic.getIp4Address());
|
||||||
|
buf.append(" eth").append(deviceId).append("mask=").append(nic.getNetmask());
|
||||||
|
if (nic.isDefaultNic()) {
|
||||||
|
buf.append(" gateway=").append(nic.getGateway());
|
||||||
|
defaultDns1 = nic.getDns1();
|
||||||
|
defaultDns2 = nic.getDns2();
|
||||||
|
}
|
||||||
|
if (nic.getTrafficType() == TrafficType.Management) {
|
||||||
|
buf.append(" localgw=").append(dest.getPod().getGateway());
|
||||||
|
} else if (nic.getTrafficType() == TrafficType.Control) {
|
||||||
|
// control command is sent over management network in VMware
|
||||||
|
if (dest.getHost().getHypervisorType() == HypervisorType.VMware) {
|
||||||
|
if (s_logger.isInfoEnabled()) {
|
||||||
|
s_logger.info("Check if we need to add management server explicit route to ELB vm. pod cidr: " + dest.getPod().getCidrAddress() + "/" + dest.getPod().getCidrSize()
|
||||||
|
+ ", pod gateway: " + dest.getPod().getGateway() + ", management host: " + _mgmtHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug("Added management server explicit route to ELB vm.");
|
||||||
|
}
|
||||||
|
// always add management explicit route, for basic networking setup
|
||||||
|
buf.append(" mgmtcidr=").append(_mgmtCidr);
|
||||||
|
buf.append(" localgw=").append(dest.getPod().getGateway());
|
||||||
|
|
||||||
|
if (dc.getNetworkType() == NetworkType.Basic) {
|
||||||
|
// ask elb vm to setup SSH on guest network
|
||||||
|
buf.append(" sshonguest=true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
controlNic = nic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String domain = network.getNetworkDomain();
|
||||||
|
if (domain != null) {
|
||||||
|
buf.append(" domain=" + domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.append(" dns1=").append(defaultDns1);
|
||||||
|
if (defaultDns2 != null) {
|
||||||
|
buf.append(" dns2=").append(defaultDns2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug("Boot Args for " + profile + ": " + buf.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controlNic == null) {
|
||||||
|
throw new CloudRuntimeException("Didn't start a control port");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<DomainRouterVO> profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException {
|
||||||
|
DomainRouterVO elbVm = profile.getVirtualMachine();
|
||||||
|
|
||||||
|
List<NicProfile> nics = profile.getNics();
|
||||||
|
for (NicProfile nic : nics) {
|
||||||
|
if (nic.getTrafficType() == TrafficType.Public) {
|
||||||
|
elbVm.setPublicIpAddress(nic.getIp4Address());
|
||||||
|
elbVm.setPublicNetmask(nic.getNetmask());
|
||||||
|
elbVm.setPublicMacAddress(nic.getMacAddress());
|
||||||
|
} else if (nic.getTrafficType() == TrafficType.Guest) {
|
||||||
|
elbVm.setGuestIpAddress(nic.getIp4Address());
|
||||||
|
} else if (nic.getTrafficType() == TrafficType.Control) {
|
||||||
|
elbVm.setPrivateIpAddress(nic.getIp4Address());
|
||||||
|
elbVm.setPrivateMacAddress(nic.getMacAddress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_routerDao.update(elbVm.getId(), elbVm);
|
||||||
|
|
||||||
|
finalizeCommandsOnStart(cmds, profile);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean finalizeStart(VirtualMachineProfile<DomainRouterVO> profile, long hostId, Commands cmds, ReservationContext context) {
|
||||||
|
CheckSshAnswer answer = (CheckSshAnswer) cmds.getAnswer("checkSsh");
|
||||||
|
if (answer == null || !answer.getResult()) {
|
||||||
|
s_logger.warn("Unable to ssh to the ELB VM: " + answer.getDetails());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile<DomainRouterVO> profile) {
|
||||||
|
DomainRouterVO elbVm = profile.getVirtualMachine();
|
||||||
|
DataCenterVO dcVo = _dcDao.findById(elbVm.getDataCenterIdToDeployIn());
|
||||||
|
|
||||||
|
NicProfile controlNic = null;
|
||||||
|
|
||||||
|
if(profile.getHypervisorType() == HypervisorType.VMware && dcVo.getNetworkType() == NetworkType.Basic) {
|
||||||
|
// TODO this is a ugly to test hypervisor type here
|
||||||
|
// for basic network mode, we will use the guest NIC for control NIC
|
||||||
|
for (NicProfile nic : profile.getNics()) {
|
||||||
|
if (nic.getTrafficType() == TrafficType.Guest && nic.getIp4Address() != null) {
|
||||||
|
controlNic = nic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (NicProfile nic : profile.getNics()) {
|
||||||
|
if (nic.getTrafficType() == TrafficType.Control && nic.getIp4Address() != null) {
|
||||||
|
controlNic = nic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controlNic == null) {
|
||||||
|
s_logger.error("Control network doesn't exist for the ELB vm " + elbVm);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds.addCommand("checkSsh", new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922, 5, 20));
|
||||||
|
|
||||||
|
// Re-apply load balancing rules
|
||||||
|
List<LoadBalancerVO> lbs = _elbVmMapDao.listLbsForElbVm(elbVm.getId());
|
||||||
|
List<LoadBalancingRule> lbRules = new ArrayList<LoadBalancingRule>();
|
||||||
|
for (LoadBalancerVO lb : lbs) {
|
||||||
|
List<LbDestination> dstList = _lbMgr.getExistingDestinations(lb.getId());
|
||||||
|
LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList);
|
||||||
|
lbRules.add(loadBalancing);
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("Found " + lbRules.size() + " load balancing rule(s) to apply as a part of ELB vm " + elbVm + " start.");
|
||||||
|
if (!lbRules.isEmpty()) {
|
||||||
|
createApplyLoadBalancingRulesCommands(lbRules, elbVm, cmds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finalizeStop(VirtualMachineProfile<DomainRouterVO> profile, StopAnswer answer) {
|
||||||
|
if (answer != null) {
|
||||||
|
VMInstanceVO vm = profile.getVirtualMachine();
|
||||||
|
DomainRouterVO elbVm = _routerDao.findById(vm.getId());
|
||||||
|
processStopOrRebootAnswer(elbVm, answer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processStopOrRebootAnswer(final DomainRouterVO elbVm, Answer answer) {
|
||||||
|
//TODO: process network usage stats
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finalizeExpunge(DomainRouterVO vm) {
|
||||||
|
// no-op
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long convertToId(String vmName) {
|
||||||
|
if (!VirtualMachineName.isValidSystemVmName(vmName, _instance, _elbVmNamePrefix)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VirtualMachineName.getSystemVmId(vmName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,11 +19,17 @@ package com.cloud.network.lb;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
|
||||||
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
import com.cloud.exception.ResourceUnavailableException;
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
||||||
|
import com.cloud.network.rules.LoadBalancer;
|
||||||
import com.cloud.user.Account;
|
import com.cloud.user.Account;
|
||||||
|
|
||||||
public interface LoadBalancingRulesManager extends LoadBalancingRulesService {
|
public interface LoadBalancingRulesManager extends LoadBalancingRulesService {
|
||||||
|
|
||||||
|
LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException;
|
||||||
|
|
||||||
boolean removeAllLoadBalanacersForIp(long ipId, Account caller, long callerUserId);
|
boolean removeAllLoadBalanacersForIp(long ipId, Account caller, long callerUserId);
|
||||||
boolean removeAllLoadBalanacersForNetwork(long networkId, Account caller, long callerUserId);
|
boolean removeAllLoadBalanacersForNetwork(long networkId, Account caller, long callerUserId);
|
||||||
List<LbDestination> getExistingDestinations(long lbId);
|
List<LbDestination> getExistingDestinations(long lbId);
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import javax.naming.ConfigurationException;
|
|||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
|
||||||
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
|
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
|
||||||
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
|
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
|
||||||
import com.cloud.api.commands.UpdateLoadBalancerRuleCmd;
|
import com.cloud.api.commands.UpdateLoadBalancerRuleCmd;
|
||||||
@ -42,6 +43,7 @@ import com.cloud.event.EventTypes;
|
|||||||
import com.cloud.event.UsageEventVO;
|
import com.cloud.event.UsageEventVO;
|
||||||
import com.cloud.event.dao.EventDao;
|
import com.cloud.event.dao.EventDao;
|
||||||
import com.cloud.event.dao.UsageEventDao;
|
import com.cloud.event.dao.UsageEventDao;
|
||||||
|
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||||
import com.cloud.exception.InvalidParameterValueException;
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
import com.cloud.exception.NetworkRuleConflictException;
|
import com.cloud.exception.NetworkRuleConflictException;
|
||||||
import com.cloud.exception.PermissionDeniedException;
|
import com.cloud.exception.PermissionDeniedException;
|
||||||
@ -49,14 +51,15 @@ import com.cloud.exception.ResourceUnavailableException;
|
|||||||
import com.cloud.network.IPAddressVO;
|
import com.cloud.network.IPAddressVO;
|
||||||
import com.cloud.network.LoadBalancerVMMapVO;
|
import com.cloud.network.LoadBalancerVMMapVO;
|
||||||
import com.cloud.network.LoadBalancerVO;
|
import com.cloud.network.LoadBalancerVO;
|
||||||
import com.cloud.network.Network;
|
|
||||||
import com.cloud.network.Network.Service;
|
import com.cloud.network.Network.Service;
|
||||||
import com.cloud.network.NetworkManager;
|
import com.cloud.network.NetworkManager;
|
||||||
import com.cloud.network.dao.FirewallRulesCidrsDao;
|
import com.cloud.network.dao.FirewallRulesCidrsDao;
|
||||||
|
import com.cloud.network.NetworkVO;
|
||||||
import com.cloud.network.dao.FirewallRulesDao;
|
import com.cloud.network.dao.FirewallRulesDao;
|
||||||
import com.cloud.network.dao.IPAddressDao;
|
import com.cloud.network.dao.IPAddressDao;
|
||||||
import com.cloud.network.dao.LoadBalancerDao;
|
import com.cloud.network.dao.LoadBalancerDao;
|
||||||
import com.cloud.network.dao.LoadBalancerVMMapDao;
|
import com.cloud.network.dao.LoadBalancerVMMapDao;
|
||||||
|
import com.cloud.network.dao.NetworkDao;
|
||||||
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
||||||
import com.cloud.network.rules.FirewallRule;
|
import com.cloud.network.rules.FirewallRule;
|
||||||
import com.cloud.network.rules.FirewallRule.Purpose;
|
import com.cloud.network.rules.FirewallRule.Purpose;
|
||||||
@ -70,6 +73,7 @@ import com.cloud.user.UserContext;
|
|||||||
import com.cloud.user.dao.AccountDao;
|
import com.cloud.user.dao.AccountDao;
|
||||||
import com.cloud.uservm.UserVm;
|
import com.cloud.uservm.UserVm;
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
|
import com.cloud.utils.component.Adapters;
|
||||||
import com.cloud.utils.component.Inject;
|
import com.cloud.utils.component.Inject;
|
||||||
import com.cloud.utils.component.Manager;
|
import com.cloud.utils.component.Manager;
|
||||||
import com.cloud.utils.db.DB;
|
import com.cloud.utils.db.DB;
|
||||||
@ -122,6 +126,11 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
|
|||||||
UsageEventDao _usageEventDao;
|
UsageEventDao _usageEventDao;
|
||||||
@Inject
|
@Inject
|
||||||
FirewallRulesCidrsDao _firewallCidrsDao;
|
FirewallRulesCidrsDao _firewallCidrsDao;
|
||||||
|
@Inject
|
||||||
|
ElasticLoadBalancerManager _elbMgr;
|
||||||
|
@Inject
|
||||||
|
NetworkDao _networkDao;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@DB
|
@DB
|
||||||
@ -340,23 +349,15 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_rulesDao.remove(lb.getId());
|
_rulesDao.remove(lb.getId());
|
||||||
|
_elbMgr.handleDeleteLoadBalancerRule(lb, callerUserId, caller);
|
||||||
s_logger.debug("Load balancer with id " + lb.getId() + " is removed successfully");
|
s_logger.debug("Load balancer with id " + lb.getId() + " is removed successfully");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override @DB
|
@Override @DB
|
||||||
@ActionEvent(eventType = EventTypes.EVENT_LOAD_BALANCER_CREATE, eventDescription = "creating load balancer")
|
@ActionEvent(eventType = EventTypes.EVENT_LOAD_BALANCER_CREATE, eventDescription = "creating load balancer")
|
||||||
public LoadBalancer createLoadBalancerRule(LoadBalancer lb) throws NetworkRuleConflictException {
|
public LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException, InsufficientAddressCapacityException {
|
||||||
UserContext caller = UserContext.current();
|
UserContext caller = UserContext.current();
|
||||||
|
|
||||||
long ipId = lb.getSourceIpAddressId();
|
|
||||||
|
|
||||||
// make sure ip address exists
|
|
||||||
IPAddressVO ipAddr = _ipAddressDao.findById(ipId);
|
|
||||||
if (ipAddr == null || !ipAddr.readyToUse()) {
|
|
||||||
throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id" + ipId);
|
|
||||||
}
|
|
||||||
|
|
||||||
int srcPortStart = lb.getSourcePortStart();
|
int srcPortStart = lb.getSourcePortStart();
|
||||||
int srcPortEnd = lb.getSourcePortEnd();
|
int srcPortEnd = lb.getSourcePortEnd();
|
||||||
int defPortStart = lb.getDefaultPortStart();
|
int defPortStart = lb.getDefaultPortStart();
|
||||||
@ -384,7 +385,29 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
|
|||||||
throw new InvalidParameterValueException("Invalid algorithm: " + lb.getAlgorithm());
|
throw new InvalidParameterValueException("Invalid algorithm: " + lb.getAlgorithm());
|
||||||
}
|
}
|
||||||
|
|
||||||
Long networkId = ipAddr.getAssociatedWithNetworkId();
|
LoadBalancer result = _elbMgr.handleCreateLoadBalancerRule(lb, caller.getCaller());
|
||||||
|
if (result == null){
|
||||||
|
result = createLoadBalancer(lb);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DB
|
||||||
|
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) {
|
if (networkId == null) {
|
||||||
throw new InvalidParameterValueException("Unable to create load balancer rule ; ip id=" + ipId + " is not associated with any network");
|
throw new InvalidParameterValueException("Unable to create load balancer rule ; ip id=" + ipId + " is not associated with any network");
|
||||||
|
|
||||||
@ -393,7 +416,6 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
|
|||||||
_accountMgr.checkAccess(caller.getCaller(), ipAddr);
|
_accountMgr.checkAccess(caller.getCaller(), ipAddr);
|
||||||
|
|
||||||
// verify that lb service is supported by the network
|
// verify that lb service is supported by the network
|
||||||
Network network = _networkMgr.getNetwork(networkId);
|
|
||||||
if (!_networkMgr.isServiceSupported(network.getNetworkOfferingId(), Service.Lb)) {
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
39
server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java
Normal file
39
server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2011 Citrix Systems, 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.dao;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.network.ElasticLbVmMapVO;
|
||||||
|
import com.cloud.network.LoadBalancerVO;
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
import com.cloud.vm.DomainRouterVO;
|
||||||
|
|
||||||
|
public interface ElasticLbVmMapDao extends GenericDao<ElasticLbVmMapVO, Long> {
|
||||||
|
ElasticLbVmMapVO findOneByLbIdAndElbVmId(long lbId, long elbVmId);
|
||||||
|
ElasticLbVmMapVO findOneByIpIdAndElbVmId(long ipId, long elbVmId);
|
||||||
|
ElasticLbVmMapVO findOneByIp(long ipId);
|
||||||
|
|
||||||
|
List<ElasticLbVmMapVO> listByElbVmId(long elbVmId);
|
||||||
|
List<ElasticLbVmMapVO> listByLbId(long lbId);
|
||||||
|
int deleteLB(long lbId);
|
||||||
|
List<DomainRouterVO> listUnusedElbVms();
|
||||||
|
List<LoadBalancerVO> listLbsForElbVm(long elbVmId);
|
||||||
|
|
||||||
|
}
|
||||||
136
server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java
Normal file
136
server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2011 Citrix Systems, 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.dao;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
import com.cloud.network.ElasticLbVmMapVO;
|
||||||
|
import com.cloud.network.LoadBalancerVO;
|
||||||
|
import com.cloud.network.dao.LoadBalancerDao;
|
||||||
|
import com.cloud.network.dao.LoadBalancerDaoImpl;
|
||||||
|
import com.cloud.network.router.VirtualRouter.Role;
|
||||||
|
import com.cloud.network.router.VirtualRouter.Role;
|
||||||
|
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 {
|
||||||
|
protected final DomainRouterDao _routerDao = ComponentLocator.inject(DomainRouterDaoImpl.class);
|
||||||
|
protected final LoadBalancerDao _loadbalancerDao = ComponentLocator.inject(LoadBalancerDaoImpl.class);
|
||||||
|
|
||||||
|
|
||||||
|
protected final SearchBuilder<ElasticLbVmMapVO> AllFieldsSearch;
|
||||||
|
protected final SearchBuilder<ElasticLbVmMapVO> UnusedVmSearch;
|
||||||
|
protected final SearchBuilder<ElasticLbVmMapVO> LoadBalancersForElbVmSearch;
|
||||||
|
|
||||||
|
|
||||||
|
protected final SearchBuilder<DomainRouterVO> ElbVmSearch;
|
||||||
|
|
||||||
|
protected final SearchBuilder<LoadBalancerVO> LoadBalancerSearch;
|
||||||
|
|
||||||
|
protected ElasticLbVmMapDaoImpl() {
|
||||||
|
AllFieldsSearch = createSearchBuilder();
|
||||||
|
AllFieldsSearch.and("ipId", AllFieldsSearch.entity().getIpAddressId(), SearchCriteria.Op.EQ);
|
||||||
|
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();
|
||||||
|
|
||||||
|
LoadBalancerSearch = _loadbalancerDao.createSearchBuilder();
|
||||||
|
LoadBalancersForElbVmSearch = createSearchBuilder();
|
||||||
|
LoadBalancersForElbVmSearch.and("elbVmId", LoadBalancersForElbVmSearch.entity().getElbVmId(), SearchCriteria.Op.EQ);
|
||||||
|
LoadBalancerSearch.join("LoadBalancersForElbVm", LoadBalancersForElbVmSearch, LoadBalancerSearch.entity().getId(), LoadBalancersForElbVmSearch.entity().getLbId(), JoinType.INNER);
|
||||||
|
LoadBalancersForElbVmSearch.done();
|
||||||
|
LoadBalancerSearch.done();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElasticLbVmMapVO findOneByLbIdAndElbVmId(long lbId, long elbVmId) {
|
||||||
|
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("lbId", lbId);
|
||||||
|
sc.setParameters("elbVmId", elbVmId);
|
||||||
|
return findOneBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ElasticLbVmMapVO> listByLbId(long lbId) {
|
||||||
|
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("lbId", lbId);
|
||||||
|
return listBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ElasticLbVmMapVO> listByElbVmId(long elbVmId) {
|
||||||
|
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("elbVmId", elbVmId);
|
||||||
|
return listBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int deleteLB(long lbId) {
|
||||||
|
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("lbId", lbId);
|
||||||
|
return super.expunge(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElasticLbVmMapVO findOneByIpIdAndElbVmId(long ipId, long elbVmId) {
|
||||||
|
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("ipId", ipId);
|
||||||
|
sc.setParameters("elbVmId", elbVmId);
|
||||||
|
return findOneBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElasticLbVmMapVO findOneByIp(long ipId) {
|
||||||
|
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("ipId", ipId);
|
||||||
|
return findOneBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DomainRouterVO> listUnusedElbVms() {
|
||||||
|
SearchCriteria<DomainRouterVO> sc = ElbVmSearch.create();
|
||||||
|
sc.setParameters("role", Role.LB);
|
||||||
|
return _routerDao.search(sc, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LoadBalancerVO> listLbsForElbVm(long elbVmId) {
|
||||||
|
SearchCriteria<LoadBalancerVO> sc = LoadBalancerSearch.create();
|
||||||
|
sc.setJoinParameters("LoadBalancersForElbVm", "elbVmId", elbVmId);
|
||||||
|
return _loadbalancerDao.search(sc, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -76,6 +76,7 @@ import com.cloud.dc.DataCenterVO;
|
|||||||
import com.cloud.dc.HostPodVO;
|
import com.cloud.dc.HostPodVO;
|
||||||
import com.cloud.dc.dao.AccountVlanMapDao;
|
import com.cloud.dc.dao.AccountVlanMapDao;
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.dc.dao.DcDetailsDaoImpl;
|
||||||
import com.cloud.dc.dao.HostPodDao;
|
import com.cloud.dc.dao.HostPodDao;
|
||||||
import com.cloud.dc.dao.VlanDao;
|
import com.cloud.dc.dao.VlanDao;
|
||||||
import com.cloud.deploy.DataCenterDeployment;
|
import com.cloud.deploy.DataCenterDeployment;
|
||||||
@ -661,8 +662,14 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
|
|||||||
cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName));
|
cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName));
|
||||||
cmd.addVmData("metadata", "local-ipv4", guestIpAddress);
|
cmd.addVmData("metadata", "local-ipv4", guestIpAddress);
|
||||||
cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vmName));
|
cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vmName));
|
||||||
|
if (dcVo.getNetworkType() == NetworkType.Basic) {
|
||||||
|
cmd.addVmData("metadata", "public-ipv4", guestIpAddress);
|
||||||
|
cmd.addVmData("metadata", "public-hostname", StringUtils.unicodeEscape(vmName));
|
||||||
|
}else
|
||||||
|
{
|
||||||
cmd.addVmData("metadata", "public-ipv4", router.getPublicIpAddress());
|
cmd.addVmData("metadata", "public-ipv4", router.getPublicIpAddress());
|
||||||
cmd.addVmData("metadata", "public-hostname", router.getPublicIpAddress());
|
cmd.addVmData("metadata", "public-hostname", router.getPublicIpAddress());
|
||||||
|
}
|
||||||
cmd.addVmData("metadata", "instance-id", vmInstanceName);
|
cmd.addVmData("metadata", "instance-id", vmInstanceName);
|
||||||
cmd.addVmData("metadata", "vm-id", String.valueOf(vmId));
|
cmd.addVmData("metadata", "vm-id", String.valueOf(vmId));
|
||||||
cmd.addVmData("metadata", "public-keys", publicKey);
|
cmd.addVmData("metadata", "public-keys", publicKey);
|
||||||
@ -1044,7 +1051,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
|
|||||||
|
|
||||||
// In Basic zone and Guest network we have to start domR per pod, not per network
|
// In Basic zone and Guest network we have to start domR per pod, not per network
|
||||||
if (isPodBased) {
|
if (isPodBased) {
|
||||||
routers = _routerDao.findByNetworkAndPod(guestNetwork.getId(), podId);
|
routers = _routerDao.listByNetworkAndPodAndRole(guestNetwork.getId(), podId, Role.DHCP_USERDATA);
|
||||||
plan = new DataCenterDeployment(dcId, podId, null, null, null);
|
plan = new DataCenterDeployment(dcId, podId, null, null, null);
|
||||||
} else {
|
} else {
|
||||||
routers = _routerDao.findByNetwork(guestNetwork.getId());
|
routers = _routerDao.findByNetwork(guestNetwork.getId());
|
||||||
|
|||||||
@ -810,7 +810,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
|||||||
true, false, null, null, null, true,
|
true, false, null, null, null, true,
|
||||||
Availability.Required,
|
Availability.Required,
|
||||||
true, true, true, //services - all true except for lb/vpn and gateway
|
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);
|
guestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(guestNetworkOffering);
|
||||||
|
|
||||||
@ -830,7 +830,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
|||||||
false, true, null, null, null, true,
|
false, true, null, null, null, true,
|
||||||
Availability.Optional,
|
Availability.Optional,
|
||||||
true, true, true, //services - all true except for firewall/lb/vpn and gateway
|
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);
|
defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -174,8 +174,10 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
|||||||
import com.cloud.info.ConsoleProxyInfo;
|
import com.cloud.info.ConsoleProxyInfo;
|
||||||
import com.cloud.keystore.KeystoreManager;
|
import com.cloud.keystore.KeystoreManager;
|
||||||
import com.cloud.network.IPAddressVO;
|
import com.cloud.network.IPAddressVO;
|
||||||
|
import com.cloud.network.LoadBalancerVO;
|
||||||
import com.cloud.network.NetworkVO;
|
import com.cloud.network.NetworkVO;
|
||||||
import com.cloud.network.dao.IPAddressDao;
|
import com.cloud.network.dao.IPAddressDao;
|
||||||
|
import com.cloud.network.dao.LoadBalancerDao;
|
||||||
import com.cloud.network.dao.NetworkDao;
|
import com.cloud.network.dao.NetworkDao;
|
||||||
import com.cloud.network.security.SecurityGroupVO;
|
import com.cloud.network.security.SecurityGroupVO;
|
||||||
import com.cloud.network.security.dao.SecurityGroupDao;
|
import com.cloud.network.security.dao.SecurityGroupDao;
|
||||||
@ -325,6 +327,7 @@ public class ManagementServerImpl implements ManagementServer {
|
|||||||
private final UploadMonitor _uploadMonitor;
|
private final UploadMonitor _uploadMonitor;
|
||||||
private final UploadDao _uploadDao;
|
private final UploadDao _uploadDao;
|
||||||
private final SSHKeyPairDao _sshKeyPairDao;
|
private final SSHKeyPairDao _sshKeyPairDao;
|
||||||
|
private final LoadBalancerDao _loadbalancerDao;
|
||||||
|
|
||||||
private final KeystoreManager _ksMgr;
|
private final KeystoreManager _ksMgr;
|
||||||
|
|
||||||
@ -338,7 +341,7 @@ public class ManagementServerImpl implements ManagementServer {
|
|||||||
|
|
||||||
private String _hashKey = null;
|
private String _hashKey = null;
|
||||||
|
|
||||||
protected ManagementServerImpl() {
|
public ManagementServerImpl() {
|
||||||
ComponentLocator locator = ComponentLocator.getLocator(Name);
|
ComponentLocator locator = ComponentLocator.getLocator(Name);
|
||||||
_configDao = locator.getDao(ConfigurationDao.class);
|
_configDao = locator.getDao(ConfigurationDao.class);
|
||||||
_routerDao = locator.getDao(DomainRouterDao.class);
|
_routerDao = locator.getDao(DomainRouterDao.class);
|
||||||
@ -354,6 +357,7 @@ public class ManagementServerImpl implements ManagementServer {
|
|||||||
_clusterDao = locator.getDao(ClusterDao.class);
|
_clusterDao = locator.getDao(ClusterDao.class);
|
||||||
_nicDao = locator.getDao(NicDao.class);
|
_nicDao = locator.getDao(NicDao.class);
|
||||||
_networkDao = locator.getDao(NetworkDao.class);
|
_networkDao = locator.getDao(NetworkDao.class);
|
||||||
|
_loadbalancerDao = locator.getDao(LoadBalancerDao.class);
|
||||||
|
|
||||||
_accountMgr = locator.getManager(AccountManager.class);
|
_accountMgr = locator.getManager(AccountManager.class);
|
||||||
_agentMgr = locator.getManager(AgentManager.class);
|
_agentMgr = locator.getManager(AgentManager.class);
|
||||||
@ -2501,6 +2505,7 @@ public class ManagementServerImpl implements ManagementServer {
|
|||||||
Object address = cmd.getIpAddress();
|
Object address = cmd.getIpAddress();
|
||||||
Object vlan = cmd.getVlanId();
|
Object vlan = cmd.getVlanId();
|
||||||
Object forVirtualNetwork = cmd.isForVirtualNetwork();
|
Object forVirtualNetwork = cmd.isForVirtualNetwork();
|
||||||
|
Object forLoadBalancing = cmd.isForLoadBalancing();
|
||||||
Object ipId = cmd.getId();
|
Object ipId = cmd.getId();
|
||||||
|
|
||||||
SearchBuilder<IPAddressVO> sb = _publicIpAddressDao.createSearchBuilder();
|
SearchBuilder<IPAddressVO> sb = _publicIpAddressDao.createSearchBuilder();
|
||||||
@ -2517,6 +2522,12 @@ public class ManagementServerImpl implements ManagementServer {
|
|||||||
sb.join("domainSearch", domainSearch, sb.entity().getAllocatedInDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
|
sb.join("domainSearch", domainSearch, sb.entity().getAllocatedInDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (forLoadBalancing != null && (Boolean)forLoadBalancing) {
|
||||||
|
SearchBuilder<LoadBalancerVO> lbSearch = _loadbalancerDao.createSearchBuilder();
|
||||||
|
sb.join("lbSearch", lbSearch, sb.entity().getId(), lbSearch.entity().getSourceIpAddressId(), JoinType.INNER);
|
||||||
|
sb.groupBy(sb.entity().getId());
|
||||||
|
}
|
||||||
|
|
||||||
if (keyword != null && address == null) {
|
if (keyword != null && address == null) {
|
||||||
sb.and("addressLIKE", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
|
sb.and("addressLIKE", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
|
||||||
}
|
}
|
||||||
@ -4195,9 +4206,18 @@ public class ManagementServerImpl implements ManagementServer {
|
|||||||
Map<String, Object> capabilities = new HashMap<String, Object>();
|
Map<String, Object> capabilities = new HashMap<String, Object>();
|
||||||
|
|
||||||
boolean securityGroupsEnabled = false;
|
boolean securityGroupsEnabled = false;
|
||||||
|
boolean elasticLoadBalancerEnabled = false;
|
||||||
|
String supportELB = "false";
|
||||||
List<DataCenterVO> dc = _dcDao.listSecurityGroupEnabledZones();
|
List<DataCenterVO> dc = _dcDao.listSecurityGroupEnabledZones();
|
||||||
if (dc != null && !dc.isEmpty()) {
|
if (dc != null && !dc.isEmpty()) {
|
||||||
securityGroupsEnabled = true;
|
securityGroupsEnabled = true;
|
||||||
|
String elbEnabled = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key());
|
||||||
|
elasticLoadBalancerEnabled = elbEnabled==null?false:Boolean.parseBoolean(elbEnabled);
|
||||||
|
if (elasticLoadBalancerEnabled) {
|
||||||
|
String networkType = _configDao.getValue(Config.ElasticLoadBalancerNetwork.key());
|
||||||
|
if (networkType != null)
|
||||||
|
supportELB = networkType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String userPublicTemplateEnabled = _configs.get(Config.AllowPublicUserTemplates.key());
|
String userPublicTemplateEnabled = _configs.get(Config.AllowPublicUserTemplates.key());
|
||||||
@ -4205,6 +4225,7 @@ public class ManagementServerImpl implements ManagementServer {
|
|||||||
capabilities.put("securityGroupsEnabled", securityGroupsEnabled);
|
capabilities.put("securityGroupsEnabled", securityGroupsEnabled);
|
||||||
capabilities.put("userPublicTemplateEnabled", (userPublicTemplateEnabled == null || userPublicTemplateEnabled.equals("false") ? false : true));
|
capabilities.put("userPublicTemplateEnabled", (userPublicTemplateEnabled == null || userPublicTemplateEnabled.equals("false") ? false : true));
|
||||||
capabilities.put("cloudStackVersion", getVersion());
|
capabilities.put("cloudStackVersion", getVersion());
|
||||||
|
capabilities.put("supportELB", supportELB);
|
||||||
return capabilities;
|
return capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -94,4 +94,10 @@ public interface DomainRouterDao extends GenericDao<DomainRouterVO, Long> {
|
|||||||
|
|
||||||
List<DomainRouterVO> findByNetworkOutsideThePod(long networkId, long podId, State state);
|
List<DomainRouterVO> findByNetworkOutsideThePod(long networkId, long podId, State state);
|
||||||
List<DomainRouterVO> listByNetworkAndState(long networkId, State state);
|
List<DomainRouterVO> listByNetworkAndState(long networkId, State state);
|
||||||
|
|
||||||
|
List<DomainRouterVO> listByNetworkAndPodAndRole(long networkId, long podId, Role role);
|
||||||
|
|
||||||
|
List<DomainRouterVO> listByNetworkAndRole(long networkId, Role role);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -219,4 +219,21 @@ public class DomainRouterDaoImpl extends GenericDaoBase<DomainRouterVO, Long> im
|
|||||||
}
|
}
|
||||||
return listBy(sc);
|
return listBy(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DomainRouterVO> listByNetworkAndPodAndRole(long networkId, long podId, Role role) {
|
||||||
|
SearchCriteria<DomainRouterVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("network", networkId);
|
||||||
|
sc.setParameters("podId", podId);
|
||||||
|
sc.setParameters("role", role);
|
||||||
|
return listBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DomainRouterVO> listByNetworkAndRole(long networkId, Role role) {
|
||||||
|
SearchCriteria<DomainRouterVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("network", networkId);
|
||||||
|
sc.setParameters("role", role);
|
||||||
|
return listBy(sc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,7 +66,7 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
|
|||||||
protected final SearchBuilder<UserVmVO> AccountHostSearch;
|
protected final SearchBuilder<UserVmVO> AccountHostSearch;
|
||||||
|
|
||||||
protected final SearchBuilder<UserVmVO> DestroySearch;
|
protected final SearchBuilder<UserVmVO> DestroySearch;
|
||||||
protected SearchBuilder<UserVmVO> AccountDataCenterVirtualSearch;
|
protected SearchBuilder<UserVmVO> AccountDataCenterVirtualSearch = null;
|
||||||
protected GenericSearchBuilder<UserVmVO, Long> CountByAccountPod;
|
protected GenericSearchBuilder<UserVmVO, Long> CountByAccountPod;
|
||||||
protected GenericSearchBuilder<UserVmVO, Long> CountByAccount;
|
protected GenericSearchBuilder<UserVmVO, Long> CountByAccount;
|
||||||
protected GenericSearchBuilder<UserVmVO, Long> PodsHavingVmsForAccount;
|
protected GenericSearchBuilder<UserVmVO, Long> PodsHavingVmsForAccount;
|
||||||
|
|||||||
45
server/test/com/cloud/network/dao/ElbVmMapDaoTest.java
Normal file
45
server/test/com/cloud/network/dao/ElbVmMapDaoTest.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package com.cloud.network.dao;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import com.cloud.network.ElasticLbVmMapVO;
|
||||||
|
import com.cloud.network.LoadBalancerVO;
|
||||||
|
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 testFindByIp() {
|
||||||
|
ElasticLbVmMapDaoImpl dao = ComponentLocator.inject(ElasticLbVmMapDaoImpl.class);
|
||||||
|
|
||||||
|
ElasticLbVmMapVO map = dao.findOneByIp(3);
|
||||||
|
if (map == null) {
|
||||||
|
System.out.println("Not Found");
|
||||||
|
} else {
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFindLB() {
|
||||||
|
ElasticLbVmMapDaoImpl dao = ComponentLocator.inject(ElasticLbVmMapDaoImpl.class);
|
||||||
|
|
||||||
|
List<LoadBalancerVO> lbs = dao.listLbsForElbVm(12);
|
||||||
|
if (lbs == null) {
|
||||||
|
System.out.println("Not Found");
|
||||||
|
} else {
|
||||||
|
System.out.println("Found " + lbs.size() + " lbs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1603,4 +1603,15 @@ CREATE TABLE `cloud`.`op_host_transfer` (
|
|||||||
CONSTRAINT `fk_op_host_transfer__future_mgmt_server_id` FOREIGN KEY `fk_op_host_transfer__future_mgmt_server_id`(`future_mgmt_server_id`) REFERENCES `mshost`(`msid`)
|
CONSTRAINT `fk_op_host_transfer__future_mgmt_server_id` FOREIGN KEY `fk_op_host_transfer__future_mgmt_server_id`(`future_mgmt_server_id`) REFERENCES `mshost`(`msid`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `cloud`.`elastic_lb_vm_map` (
|
||||||
|
`id` bigint unsigned NOT NULL auto_increment,
|
||||||
|
`ip_addr_id` bigint unsigned NOT NULL,
|
||||||
|
`elb_vm_id` bigint unsigned NOT NULL,
|
||||||
|
`lb_id` bigint unsigned,
|
||||||
|
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 `vm_instance` (`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`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
SET foreign_key_checks = 1;
|
SET foreign_key_checks = 1;
|
||||||
|
|||||||
@ -53,5 +53,27 @@ INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-serve
|
|||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.uri','/admin?stats','Load Balancer(haproxy) uri.');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.uri','/admin?stats','Load Balancer(haproxy) uri.');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.auth','admin1:AdMiN123','Load Balancer(haproxy) authetication string in the format username:password');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.auth','admin1:AdMiN123','Load Balancer(haproxy) authetication string in the format username:password');
|
||||||
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.port','8081','Load Balancer(haproxy) stats port number.');
|
INSERT IGNORE INTO configuration VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.stats.port','8081','Load Balancer(haproxy) stats port number.');
|
||||||
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'NetworkManager', 'use.external.dns', 'false', 'Bypass the cloudstack DHCP/DNS server vm name service, use zone external dns1 and dns2');
|
||||||
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'network.loadbalancer.basiczone.elb.enabled', 'false', 'Whether the load balancing service is enabled for basic zones');
|
||||||
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'network.loadbalancer.basiczone.elb.gc.interval.minutes', '120', 'Garbage collection interval to destroy unused ELB vms in minutes. Minimum of 5');
|
||||||
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'network.loadbalancer.basiczone.elb.network', 'guest', 'Whether the elastic load balancing service public ips are taken from the public or guest network');
|
||||||
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'network.loadbalancer.basiczone.elb.vm.cpu.mhz', '128', 'CPU speed for the elastic load balancer vm');
|
||||||
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'network.loadbalancer.basiczone.elb.vm.ram.size', '128', 'Memory in MB for the elastic load balancer vm');
|
||||||
|
INSERT IGNORE INTO configuration VALUES ('Advanced', 'DEFAULT', 'management-server', 'network.loadbalancer.basiczone.elb.vm.vcpu.num', '1', 'Number of VCPU for the elastic load balancer vm');
|
||||||
|
|
||||||
UPDATE `cloud`.`nics` SET strategy='Start' where reserver_name='DirectPodBasedNetworkGuru';
|
UPDATE `cloud`.`nics` SET strategy='Start' where reserver_name='DirectPodBasedNetworkGuru';
|
||||||
|
UPDATE `cloud`.`network_offerings` SET lb_service=1 where unique_name='System-Guest-Network';
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `cloud`.`elastic_lb_vm_map` (
|
||||||
|
`id` bigint unsigned NOT NULL auto_increment,
|
||||||
|
`ip_addr_id` bigint unsigned NOT NULL,
|
||||||
|
`elb_vm_id` bigint unsigned NOT NULL,
|
||||||
|
`lb_id` bigint unsigned,
|
||||||
|
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 `vm_instance` (`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`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ dictionary = {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="tabbox" style="margin-top: 15px;">
|
<div class="tabbox" style="margin-top: 15px;">
|
||||||
<div class="content_tabs on" id="tab_details">
|
<div class="content_tabs on" id="tab_details" style="display: none">
|
||||||
<fmt:message key="label.details"/></div>
|
<fmt:message key="label.details"/></div>
|
||||||
<div class="content_tabs off" id="tab_port_range" style="display: none">
|
<div class="content_tabs off" id="tab_port_range" style="display: none">
|
||||||
<fmt:message key="label.port.range"/></div>
|
<fmt:message key="label.port.range"/></div>
|
||||||
@ -43,7 +43,7 @@ dictionary = {
|
|||||||
<div class="content_tabs off" id="tab_vpn" style="display: none">
|
<div class="content_tabs off" id="tab_vpn" style="display: none">
|
||||||
<fmt:message key="label.vpn"/></div>
|
<fmt:message key="label.vpn"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="tab_content_details">
|
<div id="tab_content_details" style="display: none">
|
||||||
<div id="tab_spinning_wheel" class="rightpanel_mainloader_panel" style="display: none;">
|
<div id="tab_spinning_wheel" class="rightpanel_mainloader_panel" style="display: none;">
|
||||||
<div class="rightpanel_mainloaderbox">
|
<div class="rightpanel_mainloaderbox">
|
||||||
<div class="rightpanel_mainloader_animatedicon">
|
<div class="rightpanel_mainloader_animatedicon">
|
||||||
@ -423,8 +423,11 @@ dictionary = {
|
|||||||
<input id="private_port" class="text" style="width: 70%; " type="text" />
|
<input id="private_port" class="text" style="width: 70%; " type="text" />
|
||||||
<div id="private_port_errormsg" class="errormsg" style="display: none;"></div>
|
<div id="private_port_errormsg" class="errormsg" style="display: none;"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_row_cell" style="width: 12%;">
|
<div class="grid_row_cell" style="width: 15%;">
|
||||||
<select id="algorithm_select" class="select" style="width: 70%;">
|
<select id="algorithm_select" class="select" style="width: 70%;">
|
||||||
|
<option value='roundrobin'>roundrobin</option>
|
||||||
|
<option value='leastconn'>leastconn</option>
|
||||||
|
<option value='source'>source</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_row_cell" style="width: 6%;">
|
<div class="grid_row_cell" style="width: 6%;">
|
||||||
@ -495,6 +498,15 @@ dictionary = {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="actionpanel_button_wrapper" id="add_load_balancer_and_ip_button" style="display:none;">
|
||||||
|
<div class="actionpanel_button">
|
||||||
|
<div class="actionpanel_button_icons">
|
||||||
|
<img src="images/addvm_actionicon.png" /></div>
|
||||||
|
<div class="actionpanel_button_links">
|
||||||
|
<fmt:message key="label.add.load.balancer"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- top buttons (end) -->
|
<!-- top buttons (end) -->
|
||||||
|
|
||||||
@ -548,8 +560,11 @@ dictionary = {
|
|||||||
<div class="grid_row_cell" style="width: 12%; ">
|
<div class="grid_row_cell" style="width: 12%; ">
|
||||||
<div class="row_celltitles" id="private_port"></div>
|
<div class="row_celltitles" id="private_port"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_row_cell" style="width: 12%; ">
|
<div class="grid_row_cell" style="width: 15%; ">
|
||||||
<select id="algorithm_select" class="select" style="width: 70%;">
|
<select id="algorithm_select" class="select" style="width: 70%;">
|
||||||
|
<option value='roundrobin'>roundrobin</option>
|
||||||
|
<option value='leastconn'>leastconn</option>
|
||||||
|
<option value='source'>source</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_row_cell" style="width: 6%; ">
|
<div class="grid_row_cell" style="width: 6%; ">
|
||||||
@ -782,6 +797,45 @@ dictionary = {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="dialog_add_load_balancer_and_ip" title='<fmt:message key="label.add.load.balancer"/>' style="display: none">
|
||||||
|
<div class="dialog_formcontent">
|
||||||
|
<form action="#" method="post" id="form1">
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<label>
|
||||||
|
<fmt:message key="label.zone"/>:</label>
|
||||||
|
<select class="select" name="acquire_zone" id="acquire_zone">
|
||||||
|
<option value="default"><fmt:message key="label.waiting"/>....</option>
|
||||||
|
</select>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label><fmt:message key="label.name"/>:</label>
|
||||||
|
<input class="text" type="text" id="name"/>
|
||||||
|
<div id="name_errormsg" class="dialog_formcontent_errormsg" style="display:none;"></div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label><fmt:message key="label.public.port"/>:</label>
|
||||||
|
<input class="text" type="text" id="public_port"/>
|
||||||
|
<div id="public_port_errormsg" class="dialog_formcontent_errormsg" style="display:none;"></div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label><fmt:message key="label.private.port"/>:</label>
|
||||||
|
<input class="text" type="text" id="private_port"/>
|
||||||
|
<div id="private_port_errormsg" class="dialog_formcontent_errormsg" style="display:none;"></div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label><fmt:message key="label.algorithm"/>:</label>
|
||||||
|
<select class="select" id="algorithm_select">
|
||||||
|
<option value='roundrobin'>roundrobin</option>
|
||||||
|
<option value='leastconn'>leastconn</option>
|
||||||
|
<option value='source'>source</option>
|
||||||
|
</select>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Create User for VPN (begin) -->
|
<!-- Create User for VPN (begin) -->
|
||||||
<div id="dialog_add_vpnuser" title="Add VPN User" style="display:none">
|
<div id="dialog_add_vpnuser" title="Add VPN User" style="display:none">
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@ -209,7 +209,11 @@ $(document).ready(function() {
|
|||||||
bindAndListMidMenuItems($("#leftmenu_volume"), "listVolumes", volumeGetSearchParams, "listvolumesresponse", "volume", "jsp/volume.jsp", afterLoadVolumeJSP, volumeToMidmenu, volumeToRightPanel, getMidmenuId, false);
|
bindAndListMidMenuItems($("#leftmenu_volume"), "listVolumes", volumeGetSearchParams, "listvolumesresponse", "volume", "jsp/volume.jsp", afterLoadVolumeJSP, volumeToMidmenu, volumeToRightPanel, getMidmenuId, false);
|
||||||
bindAndListMidMenuItems($("#leftmenu_snapshot"), "listSnapshots", snapshotGetSearchParams, "listsnapshotsresponse", "snapshot", "jsp/snapshot.jsp", afterLoadSnapshotJSP, snapshotToMidmenu, snapshotToRightPanel, getMidmenuId, false);
|
bindAndListMidMenuItems($("#leftmenu_snapshot"), "listSnapshots", snapshotGetSearchParams, "listsnapshotsresponse", "snapshot", "jsp/snapshot.jsp", afterLoadSnapshotJSP, snapshotToMidmenu, snapshotToRightPanel, getMidmenuId, false);
|
||||||
|
|
||||||
//bindAndListMidMenuItems($("#leftmenu_ip"), "listPublicIpAddresses&forvirtualnetwork=true", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false);
|
if(g_supportELB == "guest") //ips are allocated on guest network
|
||||||
|
bindAndListMidMenuItems($("#leftmenu_ip"), "listPublicIpAddresses&forvirtualnetwork=false&forloadbalancing=true", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false);
|
||||||
|
else if(g_supportELB == "public") //ips are allocated on public network
|
||||||
|
bindAndListMidMenuItems($("#leftmenu_ip"), "listPublicIpAddresses&forvirtualnetwork=true&forloadbalancing=true", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false);
|
||||||
|
else
|
||||||
bindAndListMidMenuItems($("#leftmenu_ip"), "listPublicIpAddresses", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false); //remove "&forvirtualnetwork=true" for advanced zone whose security group is enabled
|
bindAndListMidMenuItems($("#leftmenu_ip"), "listPublicIpAddresses", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false); //remove "&forvirtualnetwork=true" for advanced zone whose security group is enabled
|
||||||
|
|
||||||
bindAndListMidMenuItems($("#leftmenu_security_group"), "listSecurityGroups", securityGroupGetSearchParams, "listsecuritygroupsresponse", "securitygroup", "jsp/securitygroup.jsp", afterLoadSecurityGroupJSP, securityGroupToMidmenu, securityGroupToRightPanel, getMidmenuId, false);
|
bindAndListMidMenuItems($("#leftmenu_security_group"), "listSecurityGroups", securityGroupGetSearchParams, "listsecuritygroupsresponse", "securitygroup", "jsp/securitygroup.jsp", afterLoadSecurityGroupJSP, securityGroupToMidmenu, securityGroupToRightPanel, getMidmenuId, false);
|
||||||
@ -591,6 +595,7 @@ $(document).ready(function() {
|
|||||||
g_domainid = null;
|
g_domainid = null;
|
||||||
g_timezoneoffset = null;
|
g_timezoneoffset = null;
|
||||||
g_timezone = null;
|
g_timezone = null;
|
||||||
|
g_supportELB = null;
|
||||||
|
|
||||||
$.cookie('JSESSIONID', null);
|
$.cookie('JSESSIONID', null);
|
||||||
$.cookie('sessionKey', null);
|
$.cookie('sessionKey', null);
|
||||||
@ -601,6 +606,7 @@ $(document).ready(function() {
|
|||||||
$.cookie('networktype', null);
|
$.cookie('networktype', null);
|
||||||
$.cookie('timezoneoffset', null);
|
$.cookie('timezoneoffset', null);
|
||||||
$.cookie('timezone', null);
|
$.cookie('timezone', null);
|
||||||
|
$.cookie('supportELB', null);
|
||||||
|
|
||||||
$("body").stopTime();
|
$("body").stopTime();
|
||||||
|
|
||||||
@ -694,6 +700,13 @@ $(document).ready(function() {
|
|||||||
dataType: "json",
|
dataType: "json",
|
||||||
async: false,
|
async: false,
|
||||||
success: function(json) {
|
success: function(json) {
|
||||||
|
/* g_supportELB: guest — ips are allocated on guest network (so use 'forvirtualnetwork' = false)
|
||||||
|
* g_supportELB: public - ips are allocated on public network (so use 'forvirtualnetwork' = true)
|
||||||
|
* g_supportELB: false – no ELB support
|
||||||
|
*/
|
||||||
|
g_supportELB = json.listcapabilitiesresponse.capability.supportELB;
|
||||||
|
$.cookie('supportELB', g_supportELB, { expires: 1});
|
||||||
|
|
||||||
if (json.listcapabilitiesresponse.capability.userpublictemplateenabled != null) {
|
if (json.listcapabilitiesresponse.capability.userpublictemplateenabled != null) {
|
||||||
g_userPublicTemplateEnabled = ""+json.listcapabilitiesresponse.capability.userpublictemplateenabled;
|
g_userPublicTemplateEnabled = ""+json.listcapabilitiesresponse.capability.userpublictemplateenabled;
|
||||||
$.cookie('userpublictemplateenabled', g_userPublicTemplateEnabled, { expires: 1});
|
$.cookie('userpublictemplateenabled', g_userPublicTemplateEnabled, { expires: 1});
|
||||||
@ -788,6 +801,9 @@ $(document).ready(function() {
|
|||||||
g_timezoneoffset = g_loginResponse.timezoneoffset;
|
g_timezoneoffset = g_loginResponse.timezoneoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(g_supportELB == null)
|
||||||
|
g_supportELB = $.cookie("supportELB");
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
data: createURL("command=listCapabilities"),
|
data: createURL("command=listCapabilities"),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
|
|||||||
@ -73,6 +73,143 @@ function afterLoadIpJSP() {
|
|||||||
switchBetweenDifferentTabs(tabArray, tabContentArray, afterSwitchFnArray);
|
switchBetweenDifferentTabs(tabArray, tabContentArray, afterSwitchFnArray);
|
||||||
//***** switch between different tabs (end) **********************************************************************
|
//***** switch between different tabs (end) **********************************************************************
|
||||||
|
|
||||||
|
if(g_supportELB == "guest" || g_supportELB == "public") {
|
||||||
|
$("#tab_details,#tab_port_range,#tab_port_forwarding,#tab_load_balancer,#tab_vpn").hide();
|
||||||
|
|
||||||
|
$("#tab_content_details").hide();
|
||||||
|
|
||||||
|
$("#acquire_new_ip_button").hide();
|
||||||
|
$("#add_load_balancer_and_ip_button").show();
|
||||||
|
|
||||||
|
initDialog("dialog_add_load_balancer_and_ip");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
data: createURL("command=listZones&available=true"),
|
||||||
|
dataType: "json",
|
||||||
|
success: function(json) {
|
||||||
|
var zones = json.listzonesresponse.zone;
|
||||||
|
var zoneSelect = $("#dialog_add_load_balancer_and_ip #acquire_zone").empty();
|
||||||
|
if (zones != null && zones.length > 0) {
|
||||||
|
for (var i = 0; i < zones.length; i++) {
|
||||||
|
if(zones[i].networktype == "Basic")
|
||||||
|
zoneSelect.append("<option value='" + zones[i].id + "'>" + fromdb(zones[i].name) + "</option>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#add_load_balancer_and_ip_button").unbind("click").bind("click", function(event) {
|
||||||
|
$("#dialog_add_load_balancer_and_ip").dialog('option', 'buttons', {
|
||||||
|
"Acquire": function() {
|
||||||
|
var $thisDialog = $(this);
|
||||||
|
|
||||||
|
var isValid = true;
|
||||||
|
isValid &= validateString("Name", $thisDialog.find("#name"), $thisDialog.find("#name_errormsg"));
|
||||||
|
isValid &= validateInteger("Public Port", $thisDialog.find("#public_port"), $thisDialog.find("#public_port_errormsg"), 1, 65535);
|
||||||
|
isValid &= validateInteger("Private Port", $thisDialog.find("#private_port"), $thisDialog.find("#private_port_errormsg"), 1, 65535);
|
||||||
|
if (!isValid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$thisDialog.dialog("close");
|
||||||
|
|
||||||
|
var array1 = [];
|
||||||
|
|
||||||
|
var zoneId = $thisDialog.find("#acquire_zone").val();
|
||||||
|
array1.push("&zoneid="+zoneId);
|
||||||
|
|
||||||
|
var name = $thisDialog.find("#name").val();
|
||||||
|
array1.push("&name="+todb(name));
|
||||||
|
|
||||||
|
var publicPort = $thisDialog.find("#public_port").val();
|
||||||
|
array1.push("&publicport="+publicPort);
|
||||||
|
|
||||||
|
var privatePort = $thisDialog.find("#private_port").val();
|
||||||
|
array1.push("&privateport="+privatePort);
|
||||||
|
|
||||||
|
var algorithm = $thisDialog.find("#algorithm_select").val();
|
||||||
|
array1.push("&algorithm="+algorithm);
|
||||||
|
|
||||||
|
var $midmenuItem1 = beforeAddingMidMenuItem() ;
|
||||||
|
$.ajax({
|
||||||
|
data: createURL("command=createLoadBalancerRule"+array1.join("")),
|
||||||
|
dataType: "json",
|
||||||
|
success: function(json) {
|
||||||
|
var jobId = json.createloadbalancerruleresponse.jobid;
|
||||||
|
var timerKey = "addLbAndIpJob_"+jobId;
|
||||||
|
|
||||||
|
$("body").everyTime(2000, timerKey, function() {
|
||||||
|
$.ajax({
|
||||||
|
data: createURL("command=queryAsyncJobResult&jobId="+jobId),
|
||||||
|
dataType: "json",
|
||||||
|
success: function(json) {
|
||||||
|
var result = json.queryasyncjobresultresponse;
|
||||||
|
if (result.jobstatus == 0) {
|
||||||
|
return; //Job has not completed
|
||||||
|
} else {
|
||||||
|
$("body").stopTime(timerKey);
|
||||||
|
if (result.jobstatus == 1) {
|
||||||
|
// Succeeded
|
||||||
|
var publicipid = result.jobresult.loadbalancer.publicipid;
|
||||||
|
|
||||||
|
var cmd;
|
||||||
|
if(g_supportELB == "guest") {
|
||||||
|
cmd = "command=listPublicIpAddresses&forvirtualnetwork=false&id="+publicipid;
|
||||||
|
}
|
||||||
|
else if(g_supportELB == "public") {
|
||||||
|
cmd = "command=listPublicIpAddresses&forvirtualnetwork=true&id="+publicipid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(g_supportELB == null)
|
||||||
|
alert("supportELB should be either guest or public. It should not be null.");
|
||||||
|
else
|
||||||
|
alert("supportELB should be either guest or public. It should not be " + g_supportELB);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
data: createURL(cmd),
|
||||||
|
dataType: "json",
|
||||||
|
async: false,
|
||||||
|
success: function(json) {
|
||||||
|
var items = json.listpublicipaddressesresponse.publicipaddress;
|
||||||
|
if(items != null && items.length > 0) {
|
||||||
|
ipToMidmenu(items[0], $midmenuItem1);
|
||||||
|
bindClickToMidMenu($midmenuItem1, ipToRightPanel, ipGetMidmenuId);
|
||||||
|
afterAddingMidMenuItem($midmenuItem1, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (result.jobstatus == 2) {
|
||||||
|
afterAddingMidMenuItem($midmenuItem1, false, fromdb(result.jobresult.errortext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(XMLHttpResponse) {
|
||||||
|
$("body").stopTime(timerKey);
|
||||||
|
handleError(XMLHttpResponse, function() {
|
||||||
|
afterAddingMidMenuItem($midmenuItem1, false, parseXMLHttpResponse(XMLHttpResponse));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
error: function(XMLHttpResponse) {
|
||||||
|
handleError(XMLHttpResponse, function() {
|
||||||
|
afterAddingMidMenuItem($midmenuItem1, false, parseXMLHttpResponse(XMLHttpResponse));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"Cancel": function() {
|
||||||
|
$(this).dialog("close");
|
||||||
|
}
|
||||||
|
}).dialog("open");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$("#tab_details,#tab_content_details").show();
|
||||||
|
|
||||||
//dialogs
|
//dialogs
|
||||||
initDialog("dialog_acquire_public_ip", 325);
|
initDialog("dialog_acquire_public_ip", 325);
|
||||||
initDialog("dialog_enable_vpn");
|
initDialog("dialog_enable_vpn");
|
||||||
@ -97,7 +234,6 @@ function afterLoadIpJSP() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#acquire_new_ip_button").unbind("click").bind("click", function(event) {
|
$("#acquire_new_ip_button").unbind("click").bind("click", function(event) {
|
||||||
var submenuContent = $("#submenu_content_network");
|
|
||||||
$("#dialog_acquire_public_ip").dialog('option', 'buttons', {
|
$("#dialog_acquire_public_ip").dialog('option', 'buttons', {
|
||||||
"Acquire": function() {
|
"Acquire": function() {
|
||||||
var thisDialog = $(this);
|
var thisDialog = $(this);
|
||||||
@ -233,6 +369,17 @@ function afterLoadIpJSP() {
|
|||||||
$("#dialog_error").text(fromdb(errorMsg)).dialog("open");
|
$("#dialog_error").text(fromdb(errorMsg)).dialog("open");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
error: function(XMLHttpResponse) {
|
||||||
|
$("body").stopTime(timerKey);
|
||||||
|
handleError(XMLHttpResponse, function() {
|
||||||
|
$template.slideUp("slow", function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
|
||||||
|
$("#dialog_error").text(fromdb(errorMsg)).dialog("open");
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
0
|
0
|
||||||
@ -290,6 +437,14 @@ function afterLoadIpJSP() {
|
|||||||
isValid &= validateInteger("Private Port", $createPortForwardingRow.find("#private_port"), $createPortForwardingRow.find("#private_port_errormsg"), 1, 65535, false); //required
|
isValid &= validateInteger("Private Port", $createPortForwardingRow.find("#private_port"), $createPortForwardingRow.find("#private_port_errormsg"), 1, 65535, false); //required
|
||||||
isValid &= validateInteger("Private End Port", $createPortForwardingRow.find("#private_end_port"), $createPortForwardingRow.find("#private_end_port_errormsg"), 1, 65535, true); //optional
|
isValid &= validateInteger("Private End Port", $createPortForwardingRow.find("#private_end_port"), $createPortForwardingRow.find("#private_end_port_errormsg"), 1, 65535, true); //optional
|
||||||
|
|
||||||
|
isValid &= validateCIDRList("CIDR", $createPortForwardingRow.find("#cidr"), $createPortForwardingRow.find("#cidr_errormsg"), true); //optional
|
||||||
|
|
||||||
|
isValid &= validateInteger("Public Port", $createPortForwardingRow.find("#public_port"), $createPortForwardingRow.find("#public_port_errormsg"), 1, 65535, false); //required
|
||||||
|
//isValid &= validateInteger("Public End Port", $createPortForwardingRow.find("#public_end_port"), $createPortForwardingRow.find("#public_end_port_errormsg"), 1, 65535, true); //optional
|
||||||
|
|
||||||
|
isValid &= validateInteger("Private Port", $createPortForwardingRow.find("#private_port"), $createPortForwardingRow.find("#private_port_errormsg"), 1, 65535, false); //required
|
||||||
|
//isValid &= validateInteger("Private End Port", $createPortForwardingRow.find("#private_end_port"), $createPortForwardingRow.find("#private_end_port_errormsg"), 1, 65535, true); //optional
|
||||||
|
|
||||||
isValid &= validateDropDownBox("Instance", $createPortForwardingRow.find("#vm"), $createPortForwardingRow.find("#vm_errormsg"));
|
isValid &= validateDropDownBox("Instance", $createPortForwardingRow.find("#vm"), $createPortForwardingRow.find("#vm_errormsg"));
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
return;
|
return;
|
||||||
@ -393,6 +548,7 @@ function afterLoadIpJSP() {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
//*** Port Forwarding tab (end) ***
|
//*** Port Forwarding tab (end) ***
|
||||||
|
}
|
||||||
|
|
||||||
//*** Load Balancer tab (begin) ***
|
//*** Load Balancer tab (begin) ***
|
||||||
var createLoadBalancerRow = $("#tab_content_load_balancer #create_load_balancer_row");
|
var createLoadBalancerRow = $("#tab_content_load_balancer #create_load_balancer_row");
|
||||||
@ -439,10 +595,46 @@ function afterLoadIpJSP() {
|
|||||||
data: createURL("command=createLoadBalancerRule"+array1.join("")),
|
data: createURL("command=createLoadBalancerRule"+array1.join("")),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function(json) {
|
success: function(json) {
|
||||||
var item = json.createloadbalancerruleresponse.loadbalancer;
|
var jobId = json.createloadbalancerruleresponse.jobid;
|
||||||
|
var timerKey = "addLbJob_"+jobId;
|
||||||
|
|
||||||
|
$("body").everyTime(2000, timerKey, function() {
|
||||||
|
$.ajax({
|
||||||
|
data: createURL("command=queryAsyncJobResult&jobId="+jobId),
|
||||||
|
dataType: "json",
|
||||||
|
success: function(json) {
|
||||||
|
var result = json.queryasyncjobresultresponse;
|
||||||
|
if (result.jobstatus == 0) {
|
||||||
|
return; //Job has not completed
|
||||||
|
} else {
|
||||||
|
$("body").stopTime(timerKey);
|
||||||
|
if (result.jobstatus == 1) {
|
||||||
|
// Succeeded
|
||||||
|
var item = result.jobresult.loadbalancer;
|
||||||
loadBalancerJsonToTemplate(item, $template);
|
loadBalancerJsonToTemplate(item, $template);
|
||||||
$spinningWheel.hide();
|
$spinningWheel.hide();
|
||||||
refreshCreateLoadBalancerRow();
|
refreshCreateLoadBalancerRow();
|
||||||
|
} else if (result.jobstatus == 2) {
|
||||||
|
$template.slideUp("slow", function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
var errorMsg = fromdb(result.jobresult.errortext);
|
||||||
|
$("#dialog_error").text(fromdb(errorMsg)).dialog("open");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(XMLHttpResponse) {
|
||||||
|
$("body").stopTime(timerKey);
|
||||||
|
handleError(XMLHttpResponse, function() {
|
||||||
|
$template.slideUp("slow", function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
|
||||||
|
$("#dialog_error").text(fromdb(errorMsg)).dialog("open");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
},
|
},
|
||||||
error: function(XMLHttpResponse) {
|
error: function(XMLHttpResponse) {
|
||||||
handleError(XMLHttpResponse, function() {
|
handleError(XMLHttpResponse, function() {
|
||||||
@ -454,6 +646,7 @@ function afterLoadIpJSP() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
//*** Load Balancer tab (end) ***
|
//*** Load Balancer tab (end) ***
|
||||||
@ -516,6 +709,10 @@ function ipToRightPanel($midmenuItem1) {
|
|||||||
copyActionInfoFromMidMenuToRightPanel($midmenuItem1);
|
copyActionInfoFromMidMenuToRightPanel($midmenuItem1);
|
||||||
|
|
||||||
$("#right_panel_content").data("$midmenuItem1", $midmenuItem1);
|
$("#right_panel_content").data("$midmenuItem1", $midmenuItem1);
|
||||||
|
|
||||||
|
if(g_supportELB == "guest" || g_supportELB == "public")
|
||||||
|
$("#tab_load_balancer").click();
|
||||||
|
else
|
||||||
$("#tab_details").click();
|
$("#tab_details").click();
|
||||||
|
|
||||||
if(ipObj.isstaticnat == true) {
|
if(ipObj.isstaticnat == true) {
|
||||||
@ -1184,14 +1381,30 @@ function ipJsonToDetailsTab() {
|
|||||||
|
|
||||||
var networkObj = $midmenuItem1.data("networkObj");
|
var networkObj = $midmenuItem1.data("networkObj");
|
||||||
|
|
||||||
var id = ipObj.id;
|
var publicipid = ipObj.id;
|
||||||
|
|
||||||
var $thisTab = $("#right_panel_content").find("#tab_content_details");
|
var $thisTab = $("#right_panel_content").find("#tab_content_details");
|
||||||
$thisTab.find("#tab_container").hide();
|
$thisTab.find("#tab_container").hide();
|
||||||
$thisTab.find("#tab_spinning_wheel").show();
|
$thisTab.find("#tab_spinning_wheel").show();
|
||||||
|
|
||||||
|
|
||||||
|
var cmd;
|
||||||
|
if(g_supportELB == "guest") {
|
||||||
|
cmd = "command=listPublicIpAddresses&forvirtualnetwork=false&id="+publicipid;
|
||||||
|
}
|
||||||
|
else if(g_supportELB == "public") {
|
||||||
|
cmd = "command=listPublicIpAddresses&forvirtualnetwork=true&id="+publicipid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(g_supportELB == null)
|
||||||
|
alert("supportELB should be either guest or public. It should not be null.");
|
||||||
|
else
|
||||||
|
alert("supportELB should be either guest or public. It should not be " + g_supportELB);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
data: createURL("command=listPublicIpAddresses&id="+id),
|
data: createURL(cmd),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
async: false,
|
async: false,
|
||||||
success: function(json) {
|
success: function(json) {
|
||||||
@ -1744,8 +1957,21 @@ function loadBalancerJsonToTemplate(jsonObj, $template) {
|
|||||||
$("body").stopTime(timerKey);
|
$("body").stopTime(timerKey);
|
||||||
$spinningWheel.hide();
|
$spinningWheel.hide();
|
||||||
if (result.jobstatus == 1) { // Succeeded
|
if (result.jobstatus == 1) { // Succeeded
|
||||||
|
var total_lbrules = $("#tab_content_load_balancer").find("#grid_content").find(".grid_rows").length;
|
||||||
$template.slideUp("slow", function() {
|
$template.slideUp("slow", function() {
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
|
|
||||||
|
if(g_supportELB == "guest" || g_supportELB == "public") {
|
||||||
|
var count_lb = $("div[id*='loadBalancer_']").length;
|
||||||
|
if(count_lb == 0) {
|
||||||
|
var params = $("#middle_menu_pagination").data("params");
|
||||||
|
if(params == null)
|
||||||
|
return;
|
||||||
|
listMidMenuItems2(params.commandString, params.getSearchParamsFn, params.jsonResponse1, params.jsonResponse2, params.toMidmenuFn, params.toRightPanelFn, params.getMidmenuIdFn, params.isMultipleSelectionInMidMenu, 1);
|
||||||
|
if($("div[id*='midmenuItem_']").length == 0)
|
||||||
|
$("#tab_content_load_balancer").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else if (result.jobstatus == 2) { // Failed
|
} else if (result.jobstatus == 2) { // Failed
|
||||||
var errorMsg = g_dictionary["label.deleting.failed"] + " - " + fromdb(result.jobresult.errortext);
|
var errorMsg = g_dictionary["label.deleting.failed"] + " - " + fromdb(result.jobresult.errortext);
|
||||||
|
|||||||
@ -1318,7 +1318,7 @@ function listMidMenuItems(commandString, getSearchParamsFn, jsonResponse1, jsonR
|
|||||||
}
|
}
|
||||||
|
|
||||||
function bindAndListMidMenuItems($leftmenu, commandString, getSearchParamsFn, jsonResponse1, jsonResponse2, rightPanelJSP, afterLoadRightPanelJSPFn, toMidmenuFn, toRightPanelFn, getMidmenuIdFn, isMultipleSelectionInMidMenu) {
|
function bindAndListMidMenuItems($leftmenu, commandString, getSearchParamsFn, jsonResponse1, jsonResponse2, rightPanelJSP, afterLoadRightPanelJSPFn, toMidmenuFn, toRightPanelFn, getMidmenuIdFn, isMultipleSelectionInMidMenu) {
|
||||||
$leftmenu.bind("click", function(event) {
|
$leftmenu.unbind().bind("click", function(event) {
|
||||||
selectLeftSubMenu($(this));
|
selectLeftSubMenu($(this));
|
||||||
listMidMenuItems(commandString, getSearchParamsFn, jsonResponse1, jsonResponse2, rightPanelJSP, afterLoadRightPanelJSPFn, toMidmenuFn, toRightPanelFn, getMidmenuIdFn, isMultipleSelectionInMidMenu, $(this).attr("id"), null);
|
listMidMenuItems(commandString, getSearchParamsFn, jsonResponse1, jsonResponse2, rightPanelJSP, afterLoadRightPanelJSPFn, toMidmenuFn, toRightPanelFn, getMidmenuIdFn, isMultipleSelectionInMidMenu, $(this).attr("id"), null);
|
||||||
return false;
|
return false;
|
||||||
@ -1526,14 +1526,17 @@ var g_domainid = null;
|
|||||||
var g_enableLogging = false;
|
var g_enableLogging = false;
|
||||||
var g_timezoneoffset = null;
|
var g_timezoneoffset = null;
|
||||||
var g_timezone = null;
|
var g_timezone = null;
|
||||||
|
var g_supportELB = null;
|
||||||
|
|
||||||
// capabilities
|
// capabilities
|
||||||
var g_directAttachSecurityGroupsEnabled = "false";
|
var g_directAttachSecurityGroupsEnabled = "false";
|
||||||
function getDirectAttachSecurityGroupsEnabled() { return g_directAttachSecurityGroupsEnabled; }
|
function getDirectAttachSecurityGroupsEnabled() { return g_directAttachSecurityGroupsEnabled; }
|
||||||
|
|
||||||
var g_userPublicTemplateEnabled = "true"
|
var g_userPublicTemplateEnabled = "true";
|
||||||
function getUserPublicTemplateEnabled() { return g_userPublicTemplateEnabled; }
|
function getUserPublicTemplateEnabled() { return g_userPublicTemplateEnabled; }
|
||||||
|
|
||||||
|
var g_supportELB = null;
|
||||||
|
|
||||||
//keyboard keycode
|
//keyboard keycode
|
||||||
var keycode_Enter = 13;
|
var keycode_Enter = 13;
|
||||||
|
|
||||||
|
|||||||
@ -1445,6 +1445,27 @@ function addZoneWizardSubmit($thisWizard) {
|
|||||||
listZonesUpdate();
|
listZonesUpdate();
|
||||||
g_directAttachSecurityGroupsEnabled = true;
|
g_directAttachSecurityGroupsEnabled = true;
|
||||||
$("#leftmenu_security_group_container").show();
|
$("#leftmenu_security_group_container").show();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
data: createURL("command=listCapabilities"),
|
||||||
|
dataType: "json",
|
||||||
|
async: false,
|
||||||
|
success: function(json) {
|
||||||
|
/* g_supportELB: guest — ips are allocated on guest network (so use 'forvirtualnetwork' = false)
|
||||||
|
* g_supportELB: public - ips are allocated on public network (so use 'forvirtualnetwork' = true)
|
||||||
|
* g_supportELB: false – no ELB support
|
||||||
|
*/
|
||||||
|
g_supportELB = json.listcapabilitiesresponse.capability.supportELB;
|
||||||
|
$.cookie('supportELB', g_supportELB, { expires: 1});
|
||||||
|
|
||||||
|
if(g_supportELB == "guest") //ips are allocated on guest network
|
||||||
|
bindAndListMidMenuItems($("#leftmenu_ip"), "listPublicIpAddresses&forvirtualnetwork=false&forloadbalancing=true", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false);
|
||||||
|
else if(g_supportELB == "public") //ips are allocated on public network
|
||||||
|
bindAndListMidMenuItems($("#leftmenu_ip"), "listPublicIpAddresses&forvirtualnetwork=true&forloadbalancing=true", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false);
|
||||||
|
else
|
||||||
|
bindAndListMidMenuItems($("#leftmenu_ip"), "listPublicIpAddresses", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false); //remove "&forvirtualnetwork=true" for advanced zone whose security group is enabled
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
error: function(XMLHttpResponse) {
|
error: function(XMLHttpResponse) {
|
||||||
handleError(XMLHttpResponse, function() {
|
handleError(XMLHttpResponse, function() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user