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 IP_NETWORK_LIST = "iptonetworklist";
|
||||
public static final String REDUNDANT_ROUTER = "redundantrouter";
|
||||
public static final String FOR_LOAD_BALANCING = "forloadbalancing";
|
||||
public static final String KEYBOARD="keyboard";
|
||||
}
|
||||
|
||||
@ -190,4 +190,12 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
|
||||
public AsyncJob.Type getInstanceType() {
|
||||
return AsyncJob.Type.IpAddress;
|
||||
}
|
||||
|
||||
public AssociateIPAddrCmd(String accountName, Long domainId, Long zoneId, Long networkId) {
|
||||
super();
|
||||
this.accountName = accountName;
|
||||
this.domainId = domainId;
|
||||
this.zoneId = zoneId;
|
||||
this.networkId = networkId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,20 +23,27 @@ import java.util.List;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.api.ApiConstants;
|
||||
import com.cloud.api.BaseAsyncCmd;
|
||||
import com.cloud.api.BaseCmd;
|
||||
import com.cloud.api.Implementation;
|
||||
import com.cloud.api.Parameter;
|
||||
import com.cloud.api.ServerApiException;
|
||||
import com.cloud.api.BaseCmd.CommandType;
|
||||
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.NetworkRuleConflictException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.IpAddress;
|
||||
import com.cloud.network.rules.LoadBalancer;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
@Implementation(description="Creates a load balancer rule", responseObject=LoadBalancerResponse.class)
|
||||
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());
|
||||
|
||||
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")
|
||||
private Integer privatePort;
|
||||
|
||||
@Parameter(name=ApiConstants.PUBLIC_IP_ID, type=CommandType.LONG, required=true, description="public ip address id from where the network traffic will be load balanced from")
|
||||
@Parameter(name=ApiConstants.PUBLIC_IP_ID, type=CommandType.LONG, required=false, description="public ip address id from where the network traffic will be load balanced from")
|
||||
private Long publicIpId;
|
||||
|
||||
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required=false, description="public ip address id from where the network traffic will be load balanced from")
|
||||
private Long zoneId;
|
||||
|
||||
@Parameter(name=ApiConstants.PUBLIC_PORT, type=CommandType.INTEGER, required=true, description="the public port from where the network traffic will be load balanced from")
|
||||
private Integer publicPort;
|
||||
|
||||
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
|
||||
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 ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
@ -92,7 +104,7 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
|
||||
public Long getPublicIpId() {
|
||||
IpAddress ipAddr = _networkService.getIp(publicIpId);
|
||||
if (ipAddr == null || !ipAddr.readyToUse()) {
|
||||
throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id" + ipAddr.getId());
|
||||
throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id " + ipAddr.getId());
|
||||
}
|
||||
|
||||
return publicIpId;
|
||||
@ -120,7 +132,7 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public void execute() throws ResourceAllocationException, ResourceUnavailableException {
|
||||
if (cidrlist != null){
|
||||
for (String cidr: cidrlist){
|
||||
if (!NetUtils.isValidCIDR(cidr)){
|
||||
@ -135,74 +147,68 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
|
||||
} catch (NetworkRuleConflictException e) {
|
||||
s_logger.warn("Exception: ", e);
|
||||
throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, e.getMessage());
|
||||
} catch (InsufficientAddressCapacityException e) {
|
||||
s_logger.warn("Exception: ", e);
|
||||
throw new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, e.getMessage());
|
||||
}
|
||||
LoadBalancerResponse response = _responseGenerator.createLoadBalancerResponse(result);
|
||||
response.setResponseName(getCommandName());
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSourcePortStart() {
|
||||
return publicPort.intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSourcePortEnd() {
|
||||
return publicPort.intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol() {
|
||||
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() {
|
||||
return _networkService.getIp(getPublicIpId()).getAccountId();
|
||||
if (publicIpId != null)
|
||||
return _networkService.getIp(getPublicIpId()).getAccountId();
|
||||
Account account = UserContext.current().getCaller();
|
||||
if ((account == null) ) {
|
||||
if ((domainId != null) && (accountName != null)) {
|
||||
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
|
||||
if (userAccount != null) {
|
||||
return userAccount.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (account != null) {
|
||||
return account.getId();
|
||||
}
|
||||
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDomainId() {
|
||||
return _networkService.getIp(getPublicIpId()).getDomainId();
|
||||
if (publicIpId != null)
|
||||
return _networkService.getIp(getPublicIpId()).getDomainId();
|
||||
if (domainId != null) {
|
||||
return domainId;
|
||||
}
|
||||
return UserContext.current().getCaller().getDomainId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultPortStart() {
|
||||
return privatePort.intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultPortEnd() {
|
||||
return privatePort.intValue();
|
||||
}
|
||||
@ -211,4 +217,37 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
|
||||
public long getEntityOwnerId() {
|
||||
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
|
||||
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.setCloudStackVersion((String)capabilities.get("cloudStackVersion"));
|
||||
response.setUserPublicTemplateEnabled((Boolean)capabilities.get("userPublicTemplateEnabled"));
|
||||
response.setSupportELB((String)capabilities.get("supportELB"));
|
||||
response.setObjectName("capability");
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
|
||||
@ -119,4 +119,17 @@ public class ListLoadBalancerRulesCmd extends BaseListCmd {
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
}
|
||||
|
||||
/*
|
||||
public ListLoadBalancerRulesCmd(String accountName, Long domainId, Long id, String loadBalancerRuleName, Long publicIpId, Long virtualMachineId, Long zoneId) {
|
||||
super();
|
||||
this.accountName = accountName;
|
||||
this.domainId = domainId;
|
||||
this.id = id;
|
||||
this.loadBalancerRuleName = loadBalancerRuleName;
|
||||
this.publicIpId = publicIpId;
|
||||
this.virtualMachineId = virtualMachineId;
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@ -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")
|
||||
private Long zoneId;
|
||||
|
||||
@Parameter(name=ApiConstants.FOR_LOAD_BALANCING, type=CommandType.BOOLEAN, description="list only ips used for load balancing")
|
||||
private Boolean forLoadBalancing;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@ -129,4 +132,33 @@ public class ListPublicIpAddressesCmd extends BaseListCmd {
|
||||
public AsyncJob.Type getInstanceType() {
|
||||
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")
|
||||
private boolean userPublicTemplateEnabled;
|
||||
|
||||
|
||||
@SerializedName("supportELB") @Param(description="true if region supports elastic load balancer on basic zones")
|
||||
private String supportELB;
|
||||
|
||||
public boolean getSecurityGroupsEnabled() {
|
||||
return securityGroupsEnabled;
|
||||
}
|
||||
@ -54,4 +58,12 @@ public class CapabilitiesResponse extends BaseResponse {
|
||||
public void setUserPublicTemplateEnabled(boolean 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 ExternalDhcpServer = new Provider("ExternalDhcpServer");
|
||||
public static final Provider ExternalGateWay = new Provider("ExternalGateWay");
|
||||
public static final Provider ElasticLoadBalancerVm = new Provider("ElasticLoadBalancerVm");
|
||||
|
||||
public static final Provider None = new Provider("None");
|
||||
|
||||
private String name;
|
||||
|
||||
@ -19,9 +19,11 @@ package com.cloud.network.lb;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
|
||||
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
|
||||
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
|
||||
import com.cloud.api.commands.UpdateLoadBalancerRuleCmd;
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.rules.LoadBalancer;
|
||||
@ -32,8 +34,9 @@ public interface LoadBalancingRulesService {
|
||||
* Create a load balancer rule from the given ipAddress/port to the given private port
|
||||
* @param cmd the command specifying the ip address, public port, protocol, private port, and algorithm
|
||||
* @return the newly created LoadBalancerVO if successful, null otherwise
|
||||
* @throws InsufficientAddressCapacityException
|
||||
*/
|
||||
LoadBalancer createLoadBalancerRule(LoadBalancer lb) throws NetworkRuleConflictException;
|
||||
LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException, InsufficientAddressCapacityException;
|
||||
|
||||
LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd);
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ import com.cloud.vm.VirtualMachine;
|
||||
public interface VirtualRouter extends VirtualMachine {
|
||||
public enum Role {
|
||||
DHCP_FIREWALL_LB_PASSWD_USERDATA,
|
||||
DHCP_USERDATA
|
||||
DHCP_USERDATA, LB
|
||||
}
|
||||
Role getRole();
|
||||
boolean getIsRedundantRouter();
|
||||
|
||||
@ -176,6 +176,8 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject
|
||||
DomainRouter,
|
||||
ConsoleProxy,
|
||||
SecondaryStorageVm,
|
||||
ElasticIpVm,
|
||||
ElasticLoadBalancerVm,
|
||||
|
||||
/*
|
||||
* 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="Dhcp" class="com.cloud.network.element.DhcpElement"/>
|
||||
<adapter name="Ovs" class="com.cloud.network.element.OvsElement"/>
|
||||
<adapter name="ElasticLoadBalancer" class="com.cloud.network.element.ElasticLoadBalancerElement"/>
|
||||
|
||||
</adapters>
|
||||
<adapters key="com.cloud.acl.SecurityChecker">
|
||||
<adapter name="DomainChecker" class="com.cloud.acl.DomainChecker"/>
|
||||
|
||||
@ -85,6 +85,21 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter {
|
||||
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) {
|
||||
this.publicIpAddress = publicIpAddress;
|
||||
}
|
||||
|
||||
@ -457,6 +457,33 @@ setup_console_proxy() {
|
||||
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() {
|
||||
cat > /etc/network/interfaces << EOF
|
||||
auto lo eth0
|
||||
@ -491,6 +518,10 @@ start() {
|
||||
[ "$NAME" == "" ] && NAME=consoleproxy
|
||||
setup_console_proxy $hyp;
|
||||
;;
|
||||
elbvm)
|
||||
[ "$NAME" == "" ] && NAME=elb
|
||||
setup_elbvm
|
||||
;;
|
||||
unknown)
|
||||
[ "$NAME" == "" ] && NAME=systemvm
|
||||
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
|
||||
}
|
||||
|
||||
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() {
|
||||
sed -i -e "/acpiphp/d" /etc/modules
|
||||
sed -i -e "/pci_hotplug/d" /etc/modules
|
||||
@ -198,4 +208,14 @@ then
|
||||
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 $?
|
||||
|
||||
@ -27,48 +27,15 @@
|
||||
# @VERSION@
|
||||
|
||||
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
|
||||
|
||||
# check if gateway domain is up and running
|
||||
check_gw() {
|
||||
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() {
|
||||
# ensure that the nic has the public ip we are load balancing on
|
||||
ip_entry() {
|
||||
local added=$1
|
||||
local removed=$2
|
||||
local stats=$3
|
||||
|
||||
if [ "$added" == "none" ]
|
||||
then
|
||||
@ -83,24 +50,56 @@ fw_entry() {
|
||||
local a=$(echo $added | 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 vif in $VIF_LIST; do
|
||||
iptables -E load_balancer_$vif back_load_balancer_$vif 2> /dev/null
|
||||
iptables -N load_balancer_$vif 2> /dev/null
|
||||
iptables -A INPUT -i $vif -p tcp -j load_balancer_$vif
|
||||
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
|
||||
sudo ip addr add dev $vif $pubIp/32
|
||||
#ignore error since it is because the ip is already there
|
||||
done
|
||||
done
|
||||
iptables -E lb_stats back_lb_stats 2> /dev/null
|
||||
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
|
||||
do
|
||||
local pubIp=$(echo $i | cut -d: -f1)
|
||||
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
|
||||
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 ]
|
||||
then
|
||||
@ -108,10 +107,17 @@ fw_entry() {
|
||||
fi
|
||||
done
|
||||
done
|
||||
local pubIp=$(echo $stats | cut -d: -f1)
|
||||
local dport=$(echo $stats | cut -d: -f2)
|
||||
local cidrs=$(echo $stats | cut -d: -f3 | sed 's/-/,/')
|
||||
iptables -A lb_stats -s $cidrs -p tcp -m state --state NEW -d $pubIp --dport $dport -j ACCEPT
|
||||
|
||||
for i in $r
|
||||
do
|
||||
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
|
||||
}
|
||||
@ -124,6 +130,7 @@ reconfig_lb() {
|
||||
|
||||
# Restore the HA Proxy to its previous state, and revert iptables rules on DomR
|
||||
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
|
||||
cp /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg.new
|
||||
|
||||
@ -143,7 +150,12 @@ get_vif_list() {
|
||||
vif_list="$vif_list $vif";
|
||||
fi
|
||||
done
|
||||
if [ "$vif_list" == "" ]
|
||||
then
|
||||
vif_list="eth0"
|
||||
fi
|
||||
|
||||
logger -t cloud "Loadbalancer public interfaces = $vif_list"
|
||||
echo $vif_list
|
||||
}
|
||||
|
||||
@ -152,9 +164,8 @@ iflag=
|
||||
aflag=
|
||||
dflag=
|
||||
fflag=
|
||||
sflag=
|
||||
|
||||
while getopts 'i:a:d:f:s:' OPTION
|
||||
while getopts 'i:a:d:f:' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
i) iflag=1
|
||||
@ -169,28 +180,12 @@ do
|
||||
f) fflag=1
|
||||
cfgfile="$OPTARG"
|
||||
;;
|
||||
s) sflag=1
|
||||
statsIp="$OPTARG"
|
||||
;;
|
||||
?) usage
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
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" == "" ]
|
||||
then
|
||||
addedIps="none"
|
||||
@ -201,21 +196,61 @@ then
|
||||
removedIps="none"
|
||||
fi
|
||||
|
||||
# iptables entry to ensure that haproxy receives traffic
|
||||
fw_entry $addedIps $removedIps $statsIp
|
||||
VIF_LIST=$(get_vif_list)
|
||||
|
||||
|
||||
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 ]
|
||||
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_lb
|
||||
|
||||
# Revert iptables rules on DomR
|
||||
fw_restore
|
||||
logger -t cloud "Reverting firewall config"
|
||||
# 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
|
||||
else
|
||||
# Remove backedup iptable rules
|
||||
fw_remove_backup
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@ -362,11 +362,10 @@ def chain_name(vm_name):
|
||||
if vm_name.startswith('i-') or vm_name.startswith('r-'):
|
||||
if vm_name.endswith('untagged'):
|
||||
return '-'.join(vm_name.split('-')[:-1])
|
||||
return '-'.join(vm_name.split('-'))
|
||||
return 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'):
|
||||
return '-'.join(vm_name.split('-')[:-2]) + "-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'])
|
||||
except:
|
||||
result = 'false'
|
||||
|
||||
allow_egress_traffic(session)
|
||||
if not os.path.exists('/var/run/cloud'):
|
||||
os.makedirs('/var/run/cloud')
|
||||
|
||||
@ -401,6 +400,28 @@ def can_bridge_firewall(session, args):
|
||||
|
||||
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):
|
||||
try:
|
||||
@ -434,7 +455,7 @@ def destroy_network_rules_for_vm(session, args):
|
||||
vmchain_default = chain_name_def(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:
|
||||
util.pread2(['iptables', '-F', 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)
|
||||
|
||||
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'
|
||||
|
||||
try:
|
||||
@ -573,15 +594,18 @@ def default_network_rules_systemvm(session, args):
|
||||
except:
|
||||
util.pread2(['iptables', '-F', vmchain])
|
||||
|
||||
allow_egress_traffic(session)
|
||||
|
||||
for vif in vifs:
|
||||
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-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:
|
||||
util.SMlog("Failed to program default rules")
|
||||
return 'false'
|
||||
|
||||
|
||||
util.pread2(['iptables', '-A', vmchain, '-j', 'ACCEPT'])
|
||||
|
||||
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:
|
||||
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-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'])
|
||||
#allow dhcp
|
||||
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)
|
||||
|
||||
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})
|
||||
return True
|
||||
|
||||
@ -741,7 +765,7 @@ def network_rules_for_rebooted_vm(session, vmName):
|
||||
|
||||
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-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
|
||||
try:
|
||||
@ -812,7 +836,7 @@ def get_rule_logs_for_vms(session, args):
|
||||
result = []
|
||||
try:
|
||||
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
|
||||
network_rules_for_rebooted_vm(session, name)
|
||||
if name.startswith('i-'):
|
||||
@ -829,7 +853,7 @@ def cleanup_rules_for_dead_vms(session):
|
||||
vms = session.xenapi.VM.get_all()
|
||||
cleaned = 0
|
||||
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)
|
||||
if len(vm) != 1:
|
||||
continue
|
||||
@ -857,11 +881,11 @@ def cleanup_rules(session, args):
|
||||
cleaned = 0
|
||||
cleanup = []
|
||||
for chain in chains:
|
||||
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
|
||||
vm = session.xenapi.VM.get_by_name_label(vm_name)
|
||||
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]:
|
||||
vm = session.xenapi.VM.get_by_name_label(chain)
|
||||
if len(vm) != 1:
|
||||
util.SMlog("chain " + chain + " does not correspond to a vm, cleaning up")
|
||||
cleanup.append(vm_name)
|
||||
cleanup.append(chain)
|
||||
continue
|
||||
vm_rec = session.xenapi.VM.get_record(vm[0])
|
||||
state = vm_rec.get('power_state')
|
||||
@ -1058,6 +1082,16 @@ def checkRouter(session, args):
|
||||
return txt
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
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})
|
||||
|
||||
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})
|
||||
|
||||
@ -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"),
|
||||
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"),
|
||||
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
|
||||
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),
|
||||
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),
|
||||
|
||||
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.RemoteAccessVpnDaoImpl;
|
||||
import com.cloud.network.dao.VpnUserDaoImpl;
|
||||
import com.cloud.network.lb.ElasticLoadBalancerManagerImpl;
|
||||
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
|
||||
import com.cloud.network.lb.dao.ElasticLbVmMapDaoImpl;
|
||||
import com.cloud.network.ovs.OvsNetworkManagerImpl;
|
||||
import com.cloud.network.ovs.OvsTunnelManagerImpl;
|
||||
import com.cloud.network.ovs.dao.GreTunnelDaoImpl;
|
||||
@ -265,6 +267,8 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
||||
addDao("DcDetailsDao", DcDetailsDaoImpl.class);
|
||||
addDao("SwiftDao", SwiftDaoImpl.class);
|
||||
addDao("AgentTransferMapDao", HostTransferMapDaoImpl.class);
|
||||
addDao("ElasticLbVmMap", ElasticLbVmMapDaoImpl.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -312,6 +316,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
||||
ComponentInfo<? extends Manager> info = addManager("ConsoleProxyManager", ConsoleProxyManagerImpl.class);
|
||||
info.addParameter("consoleproxy.sslEnabled", "true");
|
||||
addManager("ClusteredAgentManager", ClusteredAgentManagerImpl.class);
|
||||
addManager("ElasticLoadBalancerManager", ElasticLoadBalancerManagerImpl.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -205,6 +205,7 @@ public class DataCenterVO implements DataCenter {
|
||||
dhcpProvider = Provider.DhcpServer.getName();
|
||||
dnsProvider = Provider.DhcpServer.getName();
|
||||
userDataProvider = Provider.DhcpServer.getName();
|
||||
loadBalancerProvider = Provider.ElasticLoadBalancerVm.getName();
|
||||
}
|
||||
|
||||
this.zoneToken = zoneToken;
|
||||
|
||||
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()) {
|
||||
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;
|
||||
|
||||
@ -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) {
|
||||
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,
|
||||
null, true, Availability.Required,
|
||||
// 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);
|
||||
_systemNetworks.put(NetworkOfferingVO.SystemGuestNetwork, guestNetworkOffering);
|
||||
|
||||
@ -757,8 +767,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
|
||||
defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestNetworkOffering);
|
||||
NetworkOfferingVO defaultGuestDirectNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultDirectNetworkOffering, "Direct", TrafficType.Guest, false, true, null, null, null, true,
|
||||
Availability.Optional,
|
||||
// services - all true except for firewall/lb/vpn and gateway services
|
||||
true, true, true, false, false, false, false, GuestIpType.Direct);
|
||||
// services - all true except for firewall/vpn and gateway services
|
||||
true, true, true, false, false, true, false, GuestIpType.Direct);
|
||||
defaultGuestDirectNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering);
|
||||
|
||||
AccountsUsingNetworkSearch = _accountDao.createSearchBuilder();
|
||||
|
||||
@ -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 com.cloud.api.commands.CreateLoadBalancerRuleCmd;
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
||||
import com.cloud.network.rules.LoadBalancer;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public interface LoadBalancingRulesManager extends LoadBalancingRulesService {
|
||||
|
||||
LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException;
|
||||
|
||||
boolean removeAllLoadBalanacersForIp(long ipId, Account caller, long callerUserId);
|
||||
boolean removeAllLoadBalanacersForNetwork(long networkId, Account caller, long callerUserId);
|
||||
List<LbDestination> getExistingDestinations(long lbId);
|
||||
|
||||
@ -30,6 +30,7 @@ import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
|
||||
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
|
||||
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
|
||||
import com.cloud.api.commands.UpdateLoadBalancerRuleCmd;
|
||||
@ -42,6 +43,7 @@ import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.UsageEventVO;
|
||||
import com.cloud.event.dao.EventDao;
|
||||
import com.cloud.event.dao.UsageEventDao;
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
@ -49,14 +51,15 @@ import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.IPAddressVO;
|
||||
import com.cloud.network.LoadBalancerVMMapVO;
|
||||
import com.cloud.network.LoadBalancerVO;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.Service;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.network.dao.FirewallRulesCidrsDao;
|
||||
import com.cloud.network.NetworkVO;
|
||||
import com.cloud.network.dao.FirewallRulesDao;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.LoadBalancerDao;
|
||||
import com.cloud.network.dao.LoadBalancerVMMapDao;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
||||
import com.cloud.network.rules.FirewallRule;
|
||||
import com.cloud.network.rules.FirewallRule.Purpose;
|
||||
@ -70,6 +73,7 @@ import com.cloud.user.UserContext;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.Adapters;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.db.DB;
|
||||
@ -122,6 +126,11 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
|
||||
UsageEventDao _usageEventDao;
|
||||
@Inject
|
||||
FirewallRulesCidrsDao _firewallCidrsDao;
|
||||
@Inject
|
||||
ElasticLoadBalancerManager _elbMgr;
|
||||
@Inject
|
||||
NetworkDao _networkDao;
|
||||
|
||||
|
||||
@Override
|
||||
@DB
|
||||
@ -340,23 +349,15 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
|
||||
}
|
||||
|
||||
_rulesDao.remove(lb.getId());
|
||||
_elbMgr.handleDeleteLoadBalancerRule(lb, callerUserId, caller);
|
||||
s_logger.debug("Load balancer with id " + lb.getId() + " is removed successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override @DB
|
||||
@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();
|
||||
|
||||
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 srcPortEnd = lb.getSourcePortEnd();
|
||||
int defPortStart = lb.getDefaultPortStart();
|
||||
@ -384,7 +385,29 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
|
||||
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) {
|
||||
throw new InvalidParameterValueException("Unable to create load balancer rule ; ip id=" + ipId + " is not associated with any network");
|
||||
|
||||
@ -393,9 +416,8 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
|
||||
_accountMgr.checkAccess(caller.getCaller(), ipAddr);
|
||||
|
||||
// verify that lb service is supported by the network
|
||||
Network network = _networkMgr.getNetwork(networkId);
|
||||
if (!_networkMgr.isServiceSupported(network.getNetworkOfferingId(), Service.Lb)) {
|
||||
throw new InvalidParameterValueException("LB service is not supported in network id=" + networkId);
|
||||
throw new InvalidParameterValueException("LB service is not supported in network id= " + networkId);
|
||||
}
|
||||
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
|
||||
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.dao.AccountVlanMapDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.DcDetailsDaoImpl;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.dc.dao.VlanDao;
|
||||
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", "local-ipv4", guestIpAddress);
|
||||
cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vmName));
|
||||
cmd.addVmData("metadata", "public-ipv4", router.getPublicIpAddress());
|
||||
cmd.addVmData("metadata", "public-hostname", router.getPublicIpAddress());
|
||||
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-hostname", router.getPublicIpAddress());
|
||||
}
|
||||
cmd.addVmData("metadata", "instance-id", vmInstanceName);
|
||||
cmd.addVmData("metadata", "vm-id", String.valueOf(vmId));
|
||||
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
|
||||
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);
|
||||
} else {
|
||||
routers = _routerDao.findByNetwork(guestNetwork.getId());
|
||||
|
||||
@ -810,7 +810,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
||||
true, false, null, null, null, true,
|
||||
Availability.Required,
|
||||
true, true, true, //services - all true except for lb/vpn and gateway
|
||||
false, true, false, false, GuestIpType.Direct);
|
||||
false, true, true, false, GuestIpType.Direct);
|
||||
|
||||
guestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(guestNetworkOffering);
|
||||
|
||||
@ -830,7 +830,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
||||
false, true, null, null, null, true,
|
||||
Availability.Optional,
|
||||
true, true, true, //services - all true except for firewall/lb/vpn and gateway
|
||||
false, false, false, false, GuestIpType.Direct);
|
||||
false, false, true, false, GuestIpType.Direct);
|
||||
defaultGuestNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultGuestDirectNetworkOffering);
|
||||
}
|
||||
|
||||
|
||||
@ -174,8 +174,10 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.info.ConsoleProxyInfo;
|
||||
import com.cloud.keystore.KeystoreManager;
|
||||
import com.cloud.network.IPAddressVO;
|
||||
import com.cloud.network.LoadBalancerVO;
|
||||
import com.cloud.network.NetworkVO;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.LoadBalancerDao;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.security.SecurityGroupVO;
|
||||
import com.cloud.network.security.dao.SecurityGroupDao;
|
||||
@ -325,6 +327,7 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
private final UploadMonitor _uploadMonitor;
|
||||
private final UploadDao _uploadDao;
|
||||
private final SSHKeyPairDao _sshKeyPairDao;
|
||||
private final LoadBalancerDao _loadbalancerDao;
|
||||
|
||||
private final KeystoreManager _ksMgr;
|
||||
|
||||
@ -338,7 +341,7 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
|
||||
private String _hashKey = null;
|
||||
|
||||
protected ManagementServerImpl() {
|
||||
public ManagementServerImpl() {
|
||||
ComponentLocator locator = ComponentLocator.getLocator(Name);
|
||||
_configDao = locator.getDao(ConfigurationDao.class);
|
||||
_routerDao = locator.getDao(DomainRouterDao.class);
|
||||
@ -354,6 +357,7 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
_clusterDao = locator.getDao(ClusterDao.class);
|
||||
_nicDao = locator.getDao(NicDao.class);
|
||||
_networkDao = locator.getDao(NetworkDao.class);
|
||||
_loadbalancerDao = locator.getDao(LoadBalancerDao.class);
|
||||
|
||||
_accountMgr = locator.getManager(AccountManager.class);
|
||||
_agentMgr = locator.getManager(AgentManager.class);
|
||||
@ -2501,6 +2505,7 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
Object address = cmd.getIpAddress();
|
||||
Object vlan = cmd.getVlanId();
|
||||
Object forVirtualNetwork = cmd.isForVirtualNetwork();
|
||||
Object forLoadBalancing = cmd.isForLoadBalancing();
|
||||
Object ipId = cmd.getId();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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>();
|
||||
|
||||
boolean securityGroupsEnabled = false;
|
||||
boolean elasticLoadBalancerEnabled = false;
|
||||
String supportELB = "false";
|
||||
List<DataCenterVO> dc = _dcDao.listSecurityGroupEnabledZones();
|
||||
if (dc != null && !dc.isEmpty()) {
|
||||
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());
|
||||
@ -4205,6 +4225,7 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
capabilities.put("securityGroupsEnabled", securityGroupsEnabled);
|
||||
capabilities.put("userPublicTemplateEnabled", (userPublicTemplateEnabled == null || userPublicTemplateEnabled.equals("false") ? false : true));
|
||||
capabilities.put("cloudStackVersion", getVersion());
|
||||
capabilities.put("supportELB", supportELB);
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
|
||||
@ -94,4 +94,10 @@ public interface DomainRouterDao extends GenericDao<DomainRouterVO, Long> {
|
||||
|
||||
List<DomainRouterVO> findByNetworkOutsideThePod(long networkId, long podId, 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);
|
||||
}
|
||||
|
||||
@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> DestroySearch;
|
||||
protected SearchBuilder<UserVmVO> AccountDataCenterVirtualSearch;
|
||||
protected SearchBuilder<UserVmVO> AccountDataCenterVirtualSearch = null;
|
||||
protected GenericSearchBuilder<UserVmVO, Long> CountByAccountPod;
|
||||
protected GenericSearchBuilder<UserVmVO, Long> CountByAccount;
|
||||
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`)
|
||||
) 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;
|
||||
|
||||
@ -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.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 ('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`.`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>
|
||||
</div>
|
||||
<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>
|
||||
<div class="content_tabs off" id="tab_port_range" style="display: none">
|
||||
<fmt:message key="label.port.range"/></div>
|
||||
@ -43,7 +43,7 @@ dictionary = {
|
||||
<div class="content_tabs off" id="tab_vpn" style="display: none">
|
||||
<fmt:message key="label.vpn"/></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 class="rightpanel_mainloaderbox">
|
||||
<div class="rightpanel_mainloader_animatedicon">
|
||||
@ -423,8 +423,11 @@ dictionary = {
|
||||
<input id="private_port" class="text" style="width: 70%; " type="text" />
|
||||
<div id="private_port_errormsg" class="errormsg" style="display: none;"></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%;">
|
||||
<option value='roundrobin'>roundrobin</option>
|
||||
<option value='leastconn'>leastconn</option>
|
||||
<option value='source'>source</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid_row_cell" style="width: 6%;">
|
||||
@ -495,6 +498,15 @@ dictionary = {
|
||||
</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>
|
||||
<!-- top buttons (end) -->
|
||||
|
||||
@ -548,8 +560,11 @@ dictionary = {
|
||||
<div class="grid_row_cell" style="width: 12%; ">
|
||||
<div class="row_celltitles" id="private_port"></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%;">
|
||||
<option value='roundrobin'>roundrobin</option>
|
||||
<option value='leastconn'>leastconn</option>
|
||||
<option value='source'>source</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid_row_cell" style="width: 6%; ">
|
||||
@ -782,6 +797,45 @@ dictionary = {
|
||||
</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) -->
|
||||
<div id="dialog_add_vpnuser" title="Add VPN User" style="display:none">
|
||||
<p>
|
||||
|
||||
@ -209,8 +209,12 @@ $(document).ready(function() {
|
||||
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_ip"), "listPublicIpAddresses&forvirtualnetwork=true", ipGetSearchParams, "listpublicipaddressesresponse", "publicipaddress", "jsp/ipaddress.jsp", afterLoadIpJSP, ipToMidmenu, ipToRightPanel, ipGetMidmenuId, false);
|
||||
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
|
||||
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_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_timezoneoffset = null;
|
||||
g_timezone = null;
|
||||
g_supportELB = null;
|
||||
|
||||
$.cookie('JSESSIONID', null);
|
||||
$.cookie('sessionKey', null);
|
||||
@ -601,6 +606,7 @@ $(document).ready(function() {
|
||||
$.cookie('networktype', null);
|
||||
$.cookie('timezoneoffset', null);
|
||||
$.cookie('timezone', null);
|
||||
$.cookie('supportELB', null);
|
||||
|
||||
$("body").stopTime();
|
||||
|
||||
@ -694,6 +700,13 @@ $(document).ready(function() {
|
||||
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 (json.listcapabilitiesresponse.capability.userpublictemplateenabled != null) {
|
||||
g_userPublicTemplateEnabled = ""+json.listcapabilitiesresponse.capability.userpublictemplateenabled;
|
||||
$.cookie('userpublictemplateenabled', g_userPublicTemplateEnabled, { expires: 1});
|
||||
@ -788,6 +801,9 @@ $(document).ready(function() {
|
||||
g_timezoneoffset = g_loginResponse.timezoneoffset;
|
||||
}
|
||||
|
||||
if(g_supportELB == null)
|
||||
g_supportELB = $.cookie("supportELB");
|
||||
|
||||
$.ajax({
|
||||
data: createURL("command=listCapabilities"),
|
||||
dataType: "json",
|
||||
|
||||
@ -73,154 +73,301 @@ function afterLoadIpJSP() {
|
||||
switchBetweenDifferentTabs(tabArray, tabContentArray, afterSwitchFnArray);
|
||||
//***** switch between different tabs (end) **********************************************************************
|
||||
|
||||
//dialogs
|
||||
initDialog("dialog_acquire_public_ip", 325);
|
||||
initDialog("dialog_enable_vpn");
|
||||
initDialog("dialog_disable_vpn");
|
||||
initDialog("dialog_add_vpnuser");
|
||||
initDialog("dialog_confirmation_remove_vpnuser");
|
||||
initDialog("dialog_enable_static_NAT");
|
||||
if(g_supportELB == "guest" || g_supportELB == "public") {
|
||||
$("#tab_details,#tab_port_range,#tab_port_forwarding,#tab_load_balancer,#tab_vpn").hide();
|
||||
|
||||
//*** Acquire New IP (begin) ***
|
||||
$.ajax({
|
||||
data: createURL("command=listZones&available=true"),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var zones = json.listzonesresponse.zone;
|
||||
var zoneSelect = $("#dialog_acquire_public_ip #acquire_zone").empty();
|
||||
if (zones != null && zones.length > 0) {
|
||||
for (var i = 0; i < zones.length; i++) {
|
||||
zoneSelect.append("<option value='" + zones[i].id + "'>" + fromdb(zones[i].name) + "</option>");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
$("#tab_content_details").hide();
|
||||
|
||||
$("#acquire_new_ip_button").unbind("click").bind("click", function(event) {
|
||||
var submenuContent = $("#submenu_content_network");
|
||||
$("#dialog_acquire_public_ip").dialog('option', 'buttons', {
|
||||
"Acquire": function() {
|
||||
var thisDialog = $(this);
|
||||
thisDialog.dialog("close");
|
||||
$("#acquire_new_ip_button").hide();
|
||||
$("#add_load_balancer_and_ip_button").show();
|
||||
|
||||
var zoneid = thisDialog.find("#acquire_zone").val();
|
||||
initDialog("dialog_add_load_balancer_and_ip");
|
||||
|
||||
var $midmenuItem1 = beforeAddingMidMenuItem() ;
|
||||
|
||||
$.ajax({
|
||||
data: createURL("command=associateIpAddress&zoneid="+zoneid),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var jobId = json.associateipaddressresponse.jobid;
|
||||
var timerKey = "associateIpJob_"+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
|
||||
ipToMidmenu(result.jobresult.ipaddress, $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));
|
||||
});
|
||||
$.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>");
|
||||
}
|
||||
});
|
||||
},
|
||||
"Cancel": function() {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
}).dialog("open");
|
||||
return false;
|
||||
});
|
||||
//*** Acquire New IP (end) ***
|
||||
});
|
||||
|
||||
//*** Port Range tab (begin) ***
|
||||
var $createPortRangeRow = $("#tab_content_port_range").find("#create_port_range_row");
|
||||
$("#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);
|
||||
|
||||
$createPortRangeRow.find("#add_link").bind("click", function(event){
|
||||
var isValid = true;
|
||||
isValid &= validateInteger("Start Port", $createPortRangeRow.find("#start_port"), $createPortRangeRow.find("#start_port_errormsg"), 1, 65535);
|
||||
isValid &= validateInteger("End Port", $createPortRangeRow.find("#end_port"), $createPortRangeRow.find("#end_port_errormsg"), 1, 65535);
|
||||
if (!isValid)
|
||||
return;
|
||||
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;
|
||||
|
||||
var $template = $("#port_range_template").clone();
|
||||
$("#tab_content_port_range #grid_content").append($template.show());
|
||||
$thisDialog.dialog("close");
|
||||
|
||||
var $spinningWheel = $template.find("#row_container").find("#spinning_wheel");
|
||||
$spinningWheel.find("#description").text(g_dictionary["label.adding.processing"]);
|
||||
$spinningWheel.show();
|
||||
var array1 = [];
|
||||
|
||||
var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
|
||||
var ipObj = $midmenuItem1.data("jsonObj");
|
||||
var zoneId = $thisDialog.find("#acquire_zone").val();
|
||||
array1.push("&zoneid="+zoneId);
|
||||
|
||||
var startPort = $createPortRangeRow.find("#start_port").val();
|
||||
var endPort = $createPortRangeRow.find("#end_port").val();
|
||||
var protocol = $createPortRangeRow.find("#protocol").val();
|
||||
var name = $thisDialog.find("#name").val();
|
||||
array1.push("&name="+todb(name));
|
||||
|
||||
var array1 = [];
|
||||
array1.push("&ipaddressid="+ipObj.id);
|
||||
array1.push("&startPort="+startPort);
|
||||
array1.push("&endPort="+endPort);
|
||||
array1.push("&protocol="+protocol);
|
||||
var publicPort = $thisDialog.find("#public_port").val();
|
||||
array1.push("&publicport="+publicPort);
|
||||
|
||||
$.ajax({
|
||||
data: createURL("command=createIpForwardingRule"+array1.join("")),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var jobId = json.createipforwardingruleresponse.jobid;
|
||||
var timerKey = "asyncJob_" + jobId;
|
||||
$("body").everyTime(
|
||||
10000,
|
||||
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);
|
||||
$spinningWheel.hide();
|
||||
if (result.jobstatus == 1) { // Succeeded
|
||||
var item = json.queryasyncjobresultresponse.jobresult.ipforwardingrule;
|
||||
portRangeJsonToTemplate(item, $template);
|
||||
$spinningWheel.hide();
|
||||
refreshCreatePortRangeRow();
|
||||
} else if (result.jobstatus == 2) { // Failed
|
||||
$template.slideUp("slow", function() {
|
||||
$(this).remove();
|
||||
});
|
||||
//var errorMsg = g_dictionary["label.failed"] + " - " + g_dictionary["label.error.code"] + " " + fromdb(result.jobresult.errorcode);
|
||||
var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
|
||||
$("#dialog_error").text(errorMsg).dialog("open");
|
||||
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
|
||||
initDialog("dialog_acquire_public_ip", 325);
|
||||
initDialog("dialog_enable_vpn");
|
||||
initDialog("dialog_disable_vpn");
|
||||
initDialog("dialog_add_vpnuser");
|
||||
initDialog("dialog_confirmation_remove_vpnuser");
|
||||
initDialog("dialog_enable_static_NAT");
|
||||
|
||||
//*** Acquire New IP (begin) ***
|
||||
$.ajax({
|
||||
data: createURL("command=listZones&available=true"),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var zones = json.listzonesresponse.zone;
|
||||
var zoneSelect = $("#dialog_acquire_public_ip #acquire_zone").empty();
|
||||
if (zones != null && zones.length > 0) {
|
||||
for (var i = 0; i < zones.length; i++) {
|
||||
zoneSelect.append("<option value='" + zones[i].id + "'>" + fromdb(zones[i].name) + "</option>");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#acquire_new_ip_button").unbind("click").bind("click", function(event) {
|
||||
$("#dialog_acquire_public_ip").dialog('option', 'buttons', {
|
||||
"Acquire": function() {
|
||||
var thisDialog = $(this);
|
||||
thisDialog.dialog("close");
|
||||
|
||||
var zoneid = thisDialog.find("#acquire_zone").val();
|
||||
|
||||
var $midmenuItem1 = beforeAddingMidMenuItem() ;
|
||||
|
||||
$.ajax({
|
||||
data: createURL("command=associateIpAddress&zoneid="+zoneid),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var jobId = json.associateipaddressresponse.jobid;
|
||||
var timerKey = "associateIpJob_"+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
|
||||
ipToMidmenu(result.jobresult.ipaddress, $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;
|
||||
});
|
||||
//*** Acquire New IP (end) ***
|
||||
|
||||
//*** Port Range tab (begin) ***
|
||||
var $createPortRangeRow = $("#tab_content_port_range").find("#create_port_range_row");
|
||||
|
||||
$createPortRangeRow.find("#add_link").bind("click", function(event){
|
||||
var isValid = true;
|
||||
isValid &= validateInteger("Start Port", $createPortRangeRow.find("#start_port"), $createPortRangeRow.find("#start_port_errormsg"), 1, 65535);
|
||||
isValid &= validateInteger("End Port", $createPortRangeRow.find("#end_port"), $createPortRangeRow.find("#end_port_errormsg"), 1, 65535);
|
||||
if (!isValid)
|
||||
return;
|
||||
|
||||
var $template = $("#port_range_template").clone();
|
||||
$("#tab_content_port_range #grid_content").append($template.show());
|
||||
|
||||
var $spinningWheel = $template.find("#row_container").find("#spinning_wheel");
|
||||
$spinningWheel.find("#description").text(g_dictionary["label.adding.processing"]);
|
||||
$spinningWheel.show();
|
||||
|
||||
var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
|
||||
var ipObj = $midmenuItem1.data("jsonObj");
|
||||
|
||||
var startPort = $createPortRangeRow.find("#start_port").val();
|
||||
var endPort = $createPortRangeRow.find("#end_port").val();
|
||||
var protocol = $createPortRangeRow.find("#protocol").val();
|
||||
|
||||
var array1 = [];
|
||||
array1.push("&ipaddressid="+ipObj.id);
|
||||
array1.push("&startPort="+startPort);
|
||||
array1.push("&endPort="+endPort);
|
||||
array1.push("&protocol="+protocol);
|
||||
|
||||
$.ajax({
|
||||
data: createURL("command=createIpForwardingRule"+array1.join("")),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var jobId = json.createipforwardingruleresponse.jobid;
|
||||
var timerKey = "asyncJob_" + jobId;
|
||||
$("body").everyTime(
|
||||
10000,
|
||||
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);
|
||||
$spinningWheel.hide();
|
||||
if (result.jobstatus == 1) { // Succeeded
|
||||
var item = json.queryasyncjobresultresponse.jobresult.ipforwardingrule;
|
||||
portRangeJsonToTemplate(item, $template);
|
||||
$spinningWheel.hide();
|
||||
refreshCreatePortRangeRow();
|
||||
} else if (result.jobstatus == 2) { // Failed
|
||||
$template.slideUp("slow", function() {
|
||||
$(this).remove();
|
||||
});
|
||||
//var errorMsg = g_dictionary["label.failed"] + " - " + g_dictionary["label.error.code"] + " " + fromdb(result.jobresult.errorcode);
|
||||
var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
|
||||
$("#dialog_error").text(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");
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
@ -290,109 +437,118 @@ function afterLoadIpJSP() {
|
||||
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"));
|
||||
if (!isValid)
|
||||
return;
|
||||
isValid &= validateCIDRList("CIDR", $createPortForwardingRow.find("#cidr"), $createPortForwardingRow.find("#cidr_errormsg"), true); //optional
|
||||
|
||||
var $template = $("#port_forwarding_template").clone();
|
||||
$("#tab_content_port_forwarding #grid_content").append($template.show());
|
||||
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
|
||||
|
||||
var $spinningWheel = $template.find("#row_container").find("#spinning_wheel");
|
||||
$spinningWheel.find("#description").text(g_dictionary["label.adding.processing"]);
|
||||
$spinningWheel.show();
|
||||
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
|
||||
|
||||
var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
|
||||
var ipObj = $midmenuItem1.data("jsonObj");
|
||||
isValid &= validateDropDownBox("Instance", $createPortForwardingRow.find("#vm"), $createPortForwardingRow.find("#vm_errormsg"));
|
||||
if (!isValid)
|
||||
return;
|
||||
|
||||
var array1 = [];
|
||||
array1.push("&ipaddressid="+ipObj.id);
|
||||
var $template = $("#port_forwarding_template").clone();
|
||||
$("#tab_content_port_forwarding #grid_content").append($template.show());
|
||||
|
||||
var cidr = $createPortForwardingRow.find("#cidr").val();
|
||||
if(cidr != null && cidr.length > 0)
|
||||
array1.push("&cidrlist="+cidr);
|
||||
var $spinningWheel = $template.find("#row_container").find("#spinning_wheel");
|
||||
$spinningWheel.find("#description").text(g_dictionary["label.adding.processing"]);
|
||||
$spinningWheel.show();
|
||||
|
||||
var publicPort = $createPortForwardingRow.find("#public_port").val();
|
||||
array1.push("&publicport="+publicPort);
|
||||
var publicEndPort = $createPortForwardingRow.find("#public_end_port").val();
|
||||
if(publicEndPort != null && publicEndPort.length > 0)
|
||||
array1.push("&publicendport="+publicEndPort);
|
||||
var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
|
||||
var ipObj = $midmenuItem1.data("jsonObj");
|
||||
|
||||
var privatePort = $createPortForwardingRow.find("#private_port").val();
|
||||
array1.push("&privateport="+privatePort);
|
||||
var privateEndPort = $createPortForwardingRow.find("#private_end_port").val();
|
||||
if(privateEndPort != null && privateEndPort.length > 0)
|
||||
array1.push("&privateendport="+privateEndPort);
|
||||
var array1 = [];
|
||||
array1.push("&ipaddressid="+ipObj.id);
|
||||
|
||||
var protocol = $createPortForwardingRow.find("#protocol").val();
|
||||
array1.push("&protocol="+protocol);
|
||||
var cidr = $createPortForwardingRow.find("#cidr").val();
|
||||
if(cidr != null && cidr.length > 0)
|
||||
array1.push("&cidrlist="+cidr);
|
||||
|
||||
var virtualMachineId = $createPortForwardingRow.find("#vm").val();
|
||||
array1.push("&virtualmachineid=" + virtualMachineId);
|
||||
var publicPort = $createPortForwardingRow.find("#public_port").val();
|
||||
array1.push("&publicport="+publicPort);
|
||||
var publicEndPort = $createPortForwardingRow.find("#public_end_port").val();
|
||||
if(publicEndPort != null && publicEndPort.length > 0)
|
||||
array1.push("&publicendport="+publicEndPort);
|
||||
|
||||
$.ajax({
|
||||
data: createURL("command=createPortForwardingRule"+array1.join("")),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var jobId = json.createportforwardingruleresponse.jobid;
|
||||
var timerKey = "asyncJob_" + jobId;
|
||||
$("body").everyTime(
|
||||
10000,
|
||||
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);
|
||||
$spinningWheel.hide();
|
||||
if (result.jobstatus == 1) { // Succeeded
|
||||
var item = json.queryasyncjobresultresponse.jobresult.portforwardingrule;
|
||||
portForwardingJsonToTemplate(item,$template);
|
||||
$spinningWheel.hide();
|
||||
refreshCreatePortForwardingRow();
|
||||
} else if (result.jobstatus == 2) { // Failed
|
||||
$template.slideUp("slow", function() {
|
||||
$(this).remove();
|
||||
});
|
||||
//var errorMsg = g_dictionary["label.failed"] + " - " + g_dictionary["label.error.code"] + " " + fromdb(result.jobresult.errorcode);
|
||||
var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
|
||||
$("#dialog_error").text(errorMsg).dialog("open");
|
||||
var privatePort = $createPortForwardingRow.find("#private_port").val();
|
||||
array1.push("&privateport="+privatePort);
|
||||
var privateEndPort = $createPortForwardingRow.find("#private_end_port").val();
|
||||
if(privateEndPort != null && privateEndPort.length > 0)
|
||||
array1.push("&privateendport="+privateEndPort);
|
||||
|
||||
var protocol = $createPortForwardingRow.find("#protocol").val();
|
||||
array1.push("&protocol="+protocol);
|
||||
|
||||
var virtualMachineId = $createPortForwardingRow.find("#vm").val();
|
||||
array1.push("&virtualmachineid=" + virtualMachineId);
|
||||
|
||||
$.ajax({
|
||||
data: createURL("command=createPortForwardingRule"+array1.join("")),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var jobId = json.createportforwardingruleresponse.jobid;
|
||||
var timerKey = "asyncJob_" + jobId;
|
||||
$("body").everyTime(
|
||||
10000,
|
||||
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);
|
||||
$spinningWheel.hide();
|
||||
if (result.jobstatus == 1) { // Succeeded
|
||||
var item = json.queryasyncjobresultresponse.jobresult.portforwardingrule;
|
||||
portForwardingJsonToTemplate(item,$template);
|
||||
$spinningWheel.hide();
|
||||
refreshCreatePortForwardingRow();
|
||||
} else if (result.jobstatus == 2) { // Failed
|
||||
$template.slideUp("slow", function() {
|
||||
$(this).remove();
|
||||
});
|
||||
//var errorMsg = g_dictionary["label.failed"] + " - " + g_dictionary["label.error.code"] + " " + fromdb(result.jobresult.errorcode);
|
||||
var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
|
||||
$("#dialog_error").text(errorMsg).dialog("open");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
$("body").stopTime(timerKey);
|
||||
handleError(XMLHttpResponse, function() {
|
||||
$template.slideUp("slow", function() {
|
||||
$(this).remove();
|
||||
},
|
||||
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");
|
||||
});
|
||||
var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
|
||||
$("#dialog_error").text(fromdb(errorMsg)).dialog("open");
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
0
|
||||
);
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
handleError(XMLHttpResponse, function() {
|
||||
$template.slideUp("slow", function() {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
},
|
||||
0
|
||||
);
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
handleError(XMLHttpResponse, function() {
|
||||
$template.slideUp("slow", function() {
|
||||
$(this).remove();
|
||||
});
|
||||
var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
|
||||
$("#dialog_error").text(fromdb(errorMsg)).dialog("open");
|
||||
});
|
||||
var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
|
||||
$("#dialog_error").text(fromdb(errorMsg)).dialog("open");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
//*** Port Forwarding tab (end) ***
|
||||
return false;
|
||||
});
|
||||
//*** Port Forwarding tab (end) ***
|
||||
}
|
||||
|
||||
//*** Load Balancer tab (begin) ***
|
||||
var createLoadBalancerRow = $("#tab_content_load_balancer #create_load_balancer_row");
|
||||
@ -439,13 +595,49 @@ function afterLoadIpJSP() {
|
||||
data: createURL("command=createLoadBalancerRule"+array1.join("")),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var item = json.createloadbalancerruleresponse.loadbalancer;
|
||||
loadBalancerJsonToTemplate(item, $template);
|
||||
$spinningWheel.hide();
|
||||
refreshCreateLoadBalancerRow();
|
||||
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);
|
||||
$spinningWheel.hide();
|
||||
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) {
|
||||
handleError(XMLHttpResponse, function() {
|
||||
error: function(XMLHttpResponse) {
|
||||
handleError(XMLHttpResponse, function() {
|
||||
$template.slideUp("slow", function() {
|
||||
$(this).remove();
|
||||
});
|
||||
@ -454,6 +646,7 @@ function afterLoadIpJSP() {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
//*** Load Balancer tab (end) ***
|
||||
@ -516,7 +709,11 @@ function ipToRightPanel($midmenuItem1) {
|
||||
copyActionInfoFromMidMenuToRightPanel($midmenuItem1);
|
||||
|
||||
$("#right_panel_content").data("$midmenuItem1", $midmenuItem1);
|
||||
$("#tab_details").click();
|
||||
|
||||
if(g_supportELB == "guest" || g_supportELB == "public")
|
||||
$("#tab_load_balancer").click();
|
||||
else
|
||||
$("#tab_details").click();
|
||||
|
||||
if(ipObj.isstaticnat == true) {
|
||||
$("#tab_port_range").show();
|
||||
@ -1184,14 +1381,30 @@ function ipJsonToDetailsTab() {
|
||||
|
||||
var networkObj = $midmenuItem1.data("networkObj");
|
||||
|
||||
var id = ipObj.id;
|
||||
var publicipid = ipObj.id;
|
||||
|
||||
var $thisTab = $("#right_panel_content").find("#tab_content_details");
|
||||
$thisTab.find("#tab_container").hide();
|
||||
$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({
|
||||
data: createURL("command=listPublicIpAddresses&id="+id),
|
||||
data: createURL(cmd),
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
@ -1744,8 +1957,21 @@ function loadBalancerJsonToTemplate(jsonObj, $template) {
|
||||
$("body").stopTime(timerKey);
|
||||
$spinningWheel.hide();
|
||||
if (result.jobstatus == 1) { // Succeeded
|
||||
var total_lbrules = $("#tab_content_load_balancer").find("#grid_content").find(".grid_rows").length;
|
||||
$template.slideUp("slow", function() {
|
||||
$(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
|
||||
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) {
|
||||
$leftmenu.bind("click", function(event) {
|
||||
$leftmenu.unbind().bind("click", function(event) {
|
||||
selectLeftSubMenu($(this));
|
||||
listMidMenuItems(commandString, getSearchParamsFn, jsonResponse1, jsonResponse2, rightPanelJSP, afterLoadRightPanelJSPFn, toMidmenuFn, toRightPanelFn, getMidmenuIdFn, isMultipleSelectionInMidMenu, $(this).attr("id"), null);
|
||||
return false;
|
||||
@ -1526,14 +1526,17 @@ var g_domainid = null;
|
||||
var g_enableLogging = false;
|
||||
var g_timezoneoffset = null;
|
||||
var g_timezone = null;
|
||||
var g_supportELB = null;
|
||||
|
||||
// capabilities
|
||||
var g_directAttachSecurityGroupsEnabled = "false";
|
||||
function getDirectAttachSecurityGroupsEnabled() { return g_directAttachSecurityGroupsEnabled; }
|
||||
|
||||
var g_userPublicTemplateEnabled = "true"
|
||||
var g_userPublicTemplateEnabled = "true";
|
||||
function getUserPublicTemplateEnabled() { return g_userPublicTemplateEnabled; }
|
||||
|
||||
var g_supportELB = null;
|
||||
|
||||
//keyboard keycode
|
||||
var keycode_Enter = 13;
|
||||
|
||||
|
||||
@ -1445,6 +1445,27 @@ function addZoneWizardSubmit($thisWizard) {
|
||||
listZonesUpdate();
|
||||
g_directAttachSecurityGroupsEnabled = true;
|
||||
$("#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) {
|
||||
handleError(XMLHttpResponse, function() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user