diff --git a/api/src/com/cloud/api/ApiConstants.java b/api/src/com/cloud/api/ApiConstants.java
index b9183afa379..ef754ace4cf 100755
--- a/api/src/com/cloud/api/ApiConstants.java
+++ b/api/src/com/cloud/api/ApiConstants.java
@@ -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";
}
diff --git a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java
index fe5a2838be1..1e44db06aeb 100644
--- a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java
+++ b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java
@@ -189,5 +189,13 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.IpAddress;
+ }
+
+ public AssociateIPAddrCmd(String accountName, Long domainId, Long zoneId, Long networkId) {
+ super();
+ this.accountName = accountName;
+ this.domainId = domainId;
+ this.zoneId = zoneId;
+ this.networkId = networkId;
}
}
diff --git a/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java b/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java
index e7a0d1dbcb5..76a920c40a4 100644
--- a/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java
+++ b/api/src/com/cloud/api/commands/CreateLoadBalancerRuleCmd.java
@@ -16,31 +16,38 @@
*
*/
-package com.cloud.api.commands;
-
+package com.cloud.api.commands;
+
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 static final Logger s_logger = Logger.getLogger(CreateLoadBalancerRuleCmd.class.getName());
-
- private static final String s_name = "createloadbalancerruleresponse";
-
+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";
+
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@@ -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 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;
@@ -115,12 +127,12 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
/////////////////////////////////////////////////////
@Override
- public String getCommandName() {
- return s_name;
+ public String getCommandName() {
+ return s_name;
}
@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();
}
@@ -210,5 +216,38 @@ public class CreateLoadBalancerRuleCmd extends BaseCmd implements LoadBalancer
@Override
public long getEntityOwnerId() {
return getAccountId();
- }
-}
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ public void setPublicIpId(Long publicIpId) {
+ this.publicIpId = publicIpId;
+ }
+
+ @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;
+ }
+
+}
diff --git a/api/src/com/cloud/api/commands/DeleteLoadBalancerRuleCmd.java b/api/src/com/cloud/api/commands/DeleteLoadBalancerRuleCmd.java
index c08c2bc6538..0e870a0d2d2 100644
--- a/api/src/com/cloud/api/commands/DeleteLoadBalancerRuleCmd.java
+++ b/api/src/com/cloud/api/commands/DeleteLoadBalancerRuleCmd.java
@@ -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();
}
}
diff --git a/api/src/com/cloud/api/commands/ListCapabilitiesCmd.java b/api/src/com/cloud/api/commands/ListCapabilitiesCmd.java
index 22d44848484..8fcc16d353b 100644
--- a/api/src/com/cloud/api/commands/ListCapabilitiesCmd.java
+++ b/api/src/com/cloud/api/commands/ListCapabilitiesCmd.java
@@ -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);
diff --git a/api/src/com/cloud/api/commands/ListLoadBalancerRulesCmd.java b/api/src/com/cloud/api/commands/ListLoadBalancerRulesCmd.java
index 9bded66ae8b..002a6f057de 100644
--- a/api/src/com/cloud/api/commands/ListLoadBalancerRulesCmd.java
+++ b/api/src/com/cloud/api/commands/ListLoadBalancerRulesCmd.java
@@ -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;
+ }
+ */
}
diff --git a/api/src/com/cloud/api/commands/ListPublicIpAddressesCmd.java b/api/src/com/cloud/api/commands/ListPublicIpAddressesCmd.java
index 7aed38a8ce6..e5eb706eab1 100644
--- a/api/src/com/cloud/api/commands/ListPublicIpAddressesCmd.java
+++ b/api/src/com/cloud/api/commands/ListPublicIpAddressesCmd.java
@@ -65,6 +65,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 ///////////////////////
@@ -128,5 +131,34 @@ 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;
}
}
diff --git a/api/src/com/cloud/api/response/CapabilitiesResponse.java b/api/src/com/cloud/api/response/CapabilitiesResponse.java
index 808770b3edc..7202ce70c39 100644
--- a/api/src/com/cloud/api/response/CapabilitiesResponse.java
+++ b/api/src/com/cloud/api/response/CapabilitiesResponse.java
@@ -30,6 +30,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;
+ }
}
diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index 3287369ce53..9630d48e732 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -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;
diff --git a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java
index 1fb20959178..38bde4d6311 100644
--- a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java
+++ b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java
@@ -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);
diff --git a/api/src/com/cloud/network/router/VirtualRouter.java b/api/src/com/cloud/network/router/VirtualRouter.java
index 50048e29305..842fca594c5 100755
--- a/api/src/com/cloud/network/router/VirtualRouter.java
+++ b/api/src/com/cloud/network/router/VirtualRouter.java
@@ -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();
diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java
index 7de8016bec7..a763acc966b 100755
--- a/api/src/com/cloud/vm/VirtualMachine.java
+++ b/api/src/com/cloud/vm/VirtualMachine.java
@@ -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
diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in
index a6112b9e986..6fdc6ec5251 100755
--- a/client/tomcatconf/components.xml.in
+++ b/client/tomcatconf/components.xml.in
@@ -95,6 +95,8 @@
+
+
diff --git a/core/src/com/cloud/vm/DomainRouterVO.java b/core/src/com/cloud/vm/DomainRouterVO.java
index 34129cc4e3c..83c365fd7b2 100755
--- a/core/src/com/cloud/vm/DomainRouterVO.java
+++ b/core/src/com/cloud/vm/DomainRouterVO.java
@@ -84,6 +84,21 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter {
this.priority = priority;
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;
diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config
index 015976a381a..311a22ec0c4 100755
--- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config
+++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config
@@ -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;
diff --git a/patches/systemvm/debian/config/etc/iptables/iptables-elbvm b/patches/systemvm/debian/config/etc/iptables/iptables-elbvm
new file mode 100755
index 00000000000..30dbcc1013a
--- /dev/null
+++ b/patches/systemvm/debian/config/etc/iptables/iptables-elbvm
@@ -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
+
diff --git a/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh b/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh
index febbc344705..7d95d8bc12d 100755
--- a/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh
+++ b/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh
@@ -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 $?
diff --git a/patches/systemvm/debian/config/root/loadbalancer.sh b/patches/systemvm/debian/config/root/loadbalancer.sh
index 3c51832d30f..4a7d2c7cd48 100755
--- a/patches/systemvm/debian/config/root/loadbalancer.sh
+++ b/patches/systemvm/debian/config/root/loadbalancer.sh
@@ -27,48 +27,15 @@
# @VERSION@
usage() {
- printf "Usage: %s: -i -a -d -f -s \n" $(basename $0) >&2
+ printf "Usage: %s: -i -a -d -f \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
@@ -82,25 +49,57 @@ 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
- 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 $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 "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
+
+ 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)
+ 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
+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 $statsIp
+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
diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops
index 5056c88581e..8a622e5da63 100755
--- a/scripts/vm/hypervisor/xenserver/vmops
+++ b/scripts/vm/hypervisor/xenserver/vmops
@@ -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:
@@ -572,16 +593,19 @@ def default_network_rules_systemvm(session, args):
util.pread2(['iptables', '-N', vmchain])
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})
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index e7adc32bbef..482163896a2 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -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"),
diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java
index 33149c93600..ac5b680e753 100755
--- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java
+++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java
@@ -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
diff --git a/server/src/com/cloud/dc/DataCenterVO.java b/server/src/com/cloud/dc/DataCenterVO.java
index 301f90b7f60..d8900b9460d 100644
--- a/server/src/com/cloud/dc/DataCenterVO.java
+++ b/server/src/com/cloud/dc/DataCenterVO.java
@@ -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;
diff --git a/server/src/com/cloud/network/ElasticLbVmMapVO.java b/server/src/com/cloud/network/ElasticLbVmMapVO.java
new file mode 100644
index 00000000000..2c71309868e
--- /dev/null
+++ b/server/src/com/cloud/network/ElasticLbVmMapVO.java
@@ -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 .
+ *
+ */
+
+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;
+ }
+
+}
+
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index e8defdd9d09..cbbe3f7c065 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -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();
diff --git a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java
new file mode 100644
index 00000000000..63824448330
--- /dev/null
+++ b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java
@@ -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 .
+ *
+ */
+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> 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> getCapabilities() {
+ return capabilities;
+ }
+
+ private static Map> setCapabilities() {
+ Map> capabilities = new HashMap>();
+
+ Map lbCapabilities = new HashMap();
+ 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 params) throws ConfigurationException {
+
+ super.configure(name, params);
+ String enabled = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key());
+ _enabled = (enabled == null) ? false: Boolean.parseBoolean(enabled);
+ if (_enabled) {
+ String traffType = _configDao.getValue(Config.ElasticLoadBalancerNetwork.key());
+ if ("guest".equalsIgnoreCase(traffType)) {
+ _frontEndTrafficType = TrafficType.Guest;
+ } else if ("public".equalsIgnoreCase(traffType)){
+ _frontEndTrafficType = TrafficType.Public;
+ } else
+ throw new ConfigurationException("Traffic type for front end of load balancer has to be guest or public; found : " + traffType);
+ }
+ return true;
+ }
+}
diff --git a/server/src/com/cloud/network/lb/ElasticLoadBalancerManager.java b/server/src/com/cloud/network/lb/ElasticLoadBalancerManager.java
new file mode 100644
index 00000000000..e8785f3f2e4
--- /dev/null
+++ b/server/src/com/cloud/network/lb/ElasticLoadBalancerManager.java
@@ -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 .
+ *
+ */
+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);
+}
diff --git a/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
new file mode 100644
index 00000000000..55e2bd0f74f
--- /dev/null
+++ b/server/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java
@@ -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 .
+ *
+ */
+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 {
+ 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 _gcCandidateElbVmIds = Collections.newSetFromMap(new ConcurrentHashMap());
+
+ int _elasticLbVmRamSize;
+ int _elasticLbvmCpuMHz;
+ int _elasticLbvmNumCpu;
+
+ private Long getPodIdForDirectIp(IPAddressVO ipAddr) {
+ List 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 params = new HashMap(
+ 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 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 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 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 lbs = _lbDao.listByIpAddress(rules.get(0).getSourceIpAddressId());
+ List lbRules = new ArrayList();
+ for (LoadBalancerVO lb : lbs) {
+ List 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 params)
+ throws ConfigurationException {
+ _name = name;
+ final Map 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 unusedElbVms = _elbVmMapDao.listUnusedElbVms();
+ if (unusedElbVms.size() > 0) {
+ List candidateVms = new ArrayList();
+ 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 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 offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork);
+ NetworkOfferingVO controlOffering = offerings.get(0);
+ NetworkVO controlConfig = _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false, false).get(0);
+
+ List> networks = new ArrayList>(2);
+ NicProfile guestNic = new NicProfile();
+ guestNic.setDefaultNic(true);
+ networks.add(new Pair((NetworkVO) guestNetwork, guestNic));
+ networks.add(new Pair(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 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 findExistingLoadBalancers(String lbName, Long ipId, Long accountId, Long domainId, Integer publicPort) {
+ SearchBuilder sb = _lbDao.createSearchBuilder();
+ sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
+ sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
+ sb.and("publicPort", sb.entity().getSourcePortStart(), SearchCriteria.Op.EQ);
+ if (ipId != null) {
+ sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ);
+ }
+ if (domainId != null) {
+ sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
+ }
+ if (publicPort != null) {
+ sb.and("publicPort", sb.entity().getSourcePortStart(), SearchCriteria.Op.EQ);
+ }
+ SearchCriteria sc = sb.create();
+ sc.setParameters("name", lbName);
+ sc.setParameters("accountId", accountId);
+ if (ipId != null) {
+ sc.setParameters("sourceIpAddress", ipId);
+ }
+ if (domainId != null) {
+ sc.setParameters("domainId",domainId);
+ }
+ if (publicPort != null) {
+ sc.setParameters("publicPort", publicPort);
+ }
+ List lbs = _lbDao.search(sc, null);
+
+ return lbs == null || lbs.size()==0 ? null: lbs;
+ }
+
+ @DB
+ public PublicIp allocIp(CreateLoadBalancerRuleCmd lb, Account account) throws InsufficientAddressCapacityException {
+ //TODO: this only works in the guest network. Handle the public network case also.
+ List offerings = _networkOfferingDao.listByTrafficTypeAndGuestType(true, _frontendTrafficType, GuestIpType.Direct);
+ if (offerings == null || offerings.size() == 0) {
+ s_logger.warn("ELB: Could not find system offering for direct networks of type " + _frontendTrafficType);
+ return null;
+ }
+ NetworkOffering frontEndOffering = offerings.get(0);
+ List networks = _networksDao.listBy(Account.ACCOUNT_ID_SYSTEM, frontEndOffering.getId(), lb.getZoneId());
+ if (networks == null || networks.size() == 0) {
+ s_logger.warn("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 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 unusedElbVms = _elbVmMapDao.listUnusedElbVms();
+ if (unusedElbVms != null && unusedElbVms.size() > 0)
+ s_logger.info("Found " + unusedElbVms.size() + " unused ELB vms");
+ Set currentGcCandidates = new HashSet();
+ 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 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 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 profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException {
+ DomainRouterVO elbVm = profile.getVirtualMachine();
+
+ List 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 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 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 lbs = _elbVmMapDao.listLbsForElbVm(elbVm.getId());
+ List lbRules = new ArrayList();
+ for (LoadBalancerVO lb : lbs) {
+ List 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 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);
+ }
+}
diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java
index 61d61429639..8da4adb8a1a 100644
--- a/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java
+++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java
@@ -19,11 +19,17 @@ package com.cloud.network.lb;
import java.util.List;
+import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
+import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
+import com.cloud.network.rules.LoadBalancer;
import com.cloud.user.Account;
public interface LoadBalancingRulesManager extends LoadBalancingRulesService {
+
+ LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException;
+
boolean removeAllLoadBalanacersForIp(long ipId, Account caller, long callerUserId);
boolean removeAllLoadBalanacersForNetwork(long networkId, Account caller, long callerUserId);
List getExistingDestinations(long lbId);
diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
index 21c6ea6ec75..04cd7e0bbe0 100755
--- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
+++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
@@ -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,7 +126,12 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
UsageEventDao _usageEventDao;
@Inject
FirewallRulesCidrsDao _firewallCidrsDao;
-
+ @Inject
+ ElasticLoadBalancerManager _elbMgr;
+ @Inject
+ NetworkDao _networkDao;
+
+
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true)
@@ -326,7 +335,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
}
txn.commit();
-
+
if (apply) {
try {
if (!applyLoadBalancerConfig(loadBalancerId)) {
@@ -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();
@@ -383,8 +384,30 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
if ((lb.getAlgorithm() == null) || !NetUtils.isValidAlgorithm(lb.getAlgorithm())) {
throw new InvalidParameterValueException("Invalid algorithm: " + lb.getAlgorithm());
}
-
- Long networkId = ipAddr.getAssociatedWithNetworkId();
+
+ LoadBalancer result = _elbMgr.handleCreateLoadBalancerRule(lb, caller.getCaller());
+ if (result == null){
+ result = createLoadBalancer(lb);
+ }
+ return result;
+ }
+
+ @DB
+ public LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb) throws NetworkRuleConflictException {
+ long ipId = lb.getSourceIpAddressId();
+ UserContext caller = UserContext.current();
+ int srcPortStart = lb.getSourcePortStart();
+ int defPortStart = lb.getDefaultPortStart();
+
+ IPAddressVO ipAddr = _ipAddressDao.findById(lb.getSourceIpAddressId());
+ Long networkId = ipAddr.getSourceNetworkId();
+ NetworkVO network = _networkDao.findById(networkId);
+ // make sure ip address exists
+ if (ipAddr == null || !ipAddr.readyToUse()) {
+ throw new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id" + ipId);
+ }
+
+ networkId = ipAddr.getAssociatedWithNetworkId();
if (networkId == null) {
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();
@@ -554,7 +576,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
return true;
}
- @Override
+ @Override
public boolean stop() {
return true;
}
diff --git a/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java
new file mode 100644
index 00000000000..ff529012923
--- /dev/null
+++ b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDao.java
@@ -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 .
+ *
+ */
+
+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 findOneByLbIdAndElbVmId(long lbId, long elbVmId);
+ ElasticLbVmMapVO findOneByIpIdAndElbVmId(long ipId, long elbVmId);
+ ElasticLbVmMapVO findOneByIp(long ipId);
+
+ List listByElbVmId(long elbVmId);
+ List listByLbId(long lbId);
+ int deleteLB(long lbId);
+ List listUnusedElbVms();
+ List listLbsForElbVm(long elbVmId);
+
+}
diff --git a/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java
new file mode 100644
index 00000000000..9a753e63080
--- /dev/null
+++ b/server/src/com/cloud/network/lb/dao/ElasticLbVmMapDaoImpl.java
@@ -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 .
+ *
+ */
+
+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 implements ElasticLbVmMapDao {
+ protected final DomainRouterDao _routerDao = ComponentLocator.inject(DomainRouterDaoImpl.class);
+ protected final LoadBalancerDao _loadbalancerDao = ComponentLocator.inject(LoadBalancerDaoImpl.class);
+
+
+ protected final SearchBuilder AllFieldsSearch;
+ protected final SearchBuilder UnusedVmSearch;
+ protected final SearchBuilder LoadBalancersForElbVmSearch;
+
+
+ protected final SearchBuilder ElbVmSearch;
+
+ protected final SearchBuilder 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 sc = AllFieldsSearch.create();
+ sc.setParameters("lbId", lbId);
+ sc.setParameters("elbVmId", elbVmId);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public List listByLbId(long lbId) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("lbId", lbId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByElbVmId(long elbVmId) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("elbVmId", elbVmId);
+ return listBy(sc);
+ }
+
+ @Override
+ public int deleteLB(long lbId) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("lbId", lbId);
+ return super.expunge(sc);
+ }
+
+ @Override
+ public ElasticLbVmMapVO findOneByIpIdAndElbVmId(long ipId, long elbVmId) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("ipId", ipId);
+ sc.setParameters("elbVmId", elbVmId);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public ElasticLbVmMapVO findOneByIp(long ipId) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("ipId", ipId);
+ return findOneBy(sc);
+ }
+
+ public List listUnusedElbVms() {
+ SearchCriteria sc = ElbVmSearch.create();
+ sc.setParameters("role", Role.LB);
+ return _routerDao.search(sc, null);
+ }
+
+ @Override
+ public List listLbsForElbVm(long elbVmId) {
+ SearchCriteria sc = LoadBalancerSearch.create();
+ sc.setJoinParameters("LoadBalancersForElbVm", "elbVmId", elbVmId);
+ return _loadbalancerDao.search(sc, null);
+ }
+
+}
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 70902bcddaf..52b8e629cf3 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -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());
diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java
index b5f3dc70147..e10dbc7fa2c 100644
--- a/server/src/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/com/cloud/server/ConfigurationServerImpl.java
@@ -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);
}
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 25cc7a39acd..27eb51d899d 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -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 sb = _publicIpAddressDao.createSearchBuilder();
@@ -2516,6 +2521,12 @@ public class ManagementServerImpl implements ManagementServer {
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getAllocatedInDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
+
+ if (forLoadBalancing != null && (Boolean)forLoadBalancing) {
+ SearchBuilder 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 capabilities = new HashMap();
boolean securityGroupsEnabled = false;
+ boolean elasticLoadBalancerEnabled = false;
+ String supportELB = "false";
List 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;
}
diff --git a/server/src/com/cloud/vm/dao/DomainRouterDao.java b/server/src/com/cloud/vm/dao/DomainRouterDao.java
index 5c704e32e36..e6d8f8ec852 100755
--- a/server/src/com/cloud/vm/dao/DomainRouterDao.java
+++ b/server/src/com/cloud/vm/dao/DomainRouterDao.java
@@ -94,4 +94,10 @@ public interface DomainRouterDao extends GenericDao {
List findByNetworkOutsideThePod(long networkId, long podId, State state);
List listByNetworkAndState(long networkId, State state);
+
+ List listByNetworkAndPodAndRole(long networkId, long podId, Role role);
+
+ List listByNetworkAndRole(long networkId, Role role);
+
+
}
diff --git a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java
index 9f5ffd1d5b3..a8a5cc9b606 100755
--- a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java
+++ b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java
@@ -219,4 +219,21 @@ public class DomainRouterDaoImpl extends GenericDaoBase im
}
return listBy(sc);
}
+
+ @Override
+ public List listByNetworkAndPodAndRole(long networkId, long podId, Role role) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("network", networkId);
+ sc.setParameters("podId", podId);
+ sc.setParameters("role", role);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByNetworkAndRole(long networkId, Role role) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("network", networkId);
+ sc.setParameters("role", role);
+ return listBy(sc);
+ }
}
diff --git a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java
index b30f1ca44dd..1373d702a82 100755
--- a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java
+++ b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java
@@ -66,7 +66,7 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use
protected final SearchBuilder AccountHostSearch;
protected final SearchBuilder DestroySearch;
- protected SearchBuilder AccountDataCenterVirtualSearch;
+ protected SearchBuilder AccountDataCenterVirtualSearch = null;
protected GenericSearchBuilder CountByAccountPod;
protected GenericSearchBuilder CountByAccount;
protected GenericSearchBuilder PodsHavingVmsForAccount;
diff --git a/server/test/com/cloud/network/dao/ElbVmMapDaoTest.java b/server/test/com/cloud/network/dao/ElbVmMapDaoTest.java
new file mode 100644
index 00000000000..79277148532
--- /dev/null
+++ b/server/test/com/cloud/network/dao/ElbVmMapDaoTest.java
@@ -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 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 lbs = dao.listLbsForElbVm(12);
+ if (lbs == null) {
+ System.out.println("Not Found");
+ } else {
+ System.out.println("Found " + lbs.size() + " lbs");
+ }
+ }
+}
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index e354e890f01..603b8e7302e 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -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;
diff --git a/setup/db/db/schema-228to229.sql b/setup/db/db/schema-228to229.sql
index 92226ad7028..26cdc42e24d 100644
--- a/setup/db/db/schema-228to229.sql
+++ b/setup/db/db/schema-228to229.sql
@@ -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;
+
+
diff --git a/ui/jsp/ipaddress.jsp b/ui/jsp/ipaddress.jsp
index a0b4252d64e..428af847570 100644
--- a/ui/jsp/ipaddress.jsp
+++ b/ui/jsp/ipaddress.jsp
@@ -32,7 +32,7 @@ dictionary = {
-
+
@@ -43,7 +43,7 @@ dictionary = {
-
+
-
-
+
+
@@ -548,8 +560,11 @@ dictionary = {
-
-
+
+
+
+
+
@@ -782,6 +797,45 @@ dictionary = {
+
+
diff --git a/ui/scripts/cloud.core.init.js b/ui/scripts/cloud.core.init.js
index b40a5285e05..6440be35ac3 100644
--- a/ui/scripts/cloud.core.init.js
+++ b/ui/scripts/cloud.core.init.js
@@ -208,9 +208,13 @@ $(document).ready(function() {
bindAndListMidMenuItems($("#leftmenu_event"), "listEvents", eventGetSearchParams, "listeventsresponse", "event", "jsp/event.jsp", afterLoadEventJSP, eventToMidmenu, eventToRightPanel, getMidmenuId, false);
bindAndListMidMenuItems($("#leftmenu_volume"), "listVolumes", volumeGetSearchParams, "listvolumesresponse", "volume", "jsp/volume.jsp", afterLoadVolumeJSP, volumeToMidmenu, volumeToRightPanel, getMidmenuId, false);
bindAndListMidMenuItems($("#leftmenu_snapshot"), "listSnapshots", snapshotGetSearchParams, "listsnapshotsresponse", "snapshot", "jsp/snapshot.jsp", afterLoadSnapshotJSP, snapshotToMidmenu, snapshotToRightPanel, getMidmenuId, false);
-
- //bindAndListMidMenuItems($("#leftmenu_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();
@@ -687,13 +693,20 @@ $(document).ready(function() {
$.cookie('domainid', g_domainid, { expires: 1});
$.cookie('role', g_role, { expires: 1});
$.cookie('timezoneoffset', g_timezoneoffset, { expires: 1});
- $.cookie('timezone', g_timezone, { expires: 1});
-
+ $.cookie('timezone', g_timezone, { expires: 1});
+
$.ajax({
data: createURL("command=listCapabilities"),
dataType: "json",
async: false,
- success: function(json) {
+ success: function(json) {
+ /* g_supportELB: guest — ips are allocated on guest network (so use 'forvirtualnetwork' = false)
+ * g_supportELB: public - ips are allocated on public network (so use 'forvirtualnetwork' = true)
+ * g_supportELB: false – no ELB support
+ */
+ g_supportELB = json.listcapabilitiesresponse.capability.supportELB;
+ $.cookie('supportELB', g_supportELB, { expires: 1});
+
if (json.listcapabilitiesresponse.capability.userpublictemplateenabled != null) {
g_userPublicTemplateEnabled = ""+json.listcapabilitiesresponse.capability.userpublictemplateenabled;
$.cookie('userpublictemplateenabled', g_userPublicTemplateEnabled, { expires: 1});
@@ -765,8 +778,8 @@ $(document).ready(function() {
g_domainid = $.cookie("domainid");
g_timezone = $.cookie("timezone");
g_directAttachSecurityGroupsEnabled = $.cookie("directattachsecuritygroupsenabled");
- g_userPublicTemplateEnabled = $.cookie("userpublictemplateenabled");
-
+ g_userPublicTemplateEnabled = $.cookie("userpublictemplateenabled");
+
if($.cookie("timezoneoffset") != null)
g_timezoneoffset = isNaN($.cookie("timezoneoffset"))?null: parseFloat($.cookie("timezoneoffset"));
else
@@ -787,7 +800,10 @@ $(document).ready(function() {
g_timezone = g_loginResponse.timezone;
g_timezoneoffset = g_loginResponse.timezoneoffset;
}
-
+
+ if(g_supportELB == null)
+ g_supportELB = $.cookie("supportELB");
+
$.ajax({
data: createURL("command=listCapabilities"),
dataType: "json",
diff --git a/ui/scripts/cloud.core.ipaddress.js b/ui/scripts/cloud.core.ipaddress.js
index 65f7bb8855a..023fb57f920 100644
--- a/ui/scripts/cloud.core.ipaddress.js
+++ b/ui/scripts/cloud.core.ipaddress.js
@@ -1,21 +1,21 @@
- /**
- * 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 .
- *
- */
-
+ /**
+ * 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 .
+ *
+ */
+
function ipGetSearchParams() {
var moreCriteria = [];
@@ -63,305 +63,311 @@ function ipGetSearchParams() {
}
return moreCriteria.join("");
-}
-
-function afterLoadIpJSP() {
+}
+
+function afterLoadIpJSP() {
//***** switch between different tabs (begin) ********************************************************************
var tabArray = [$("#tab_details"), $("#tab_port_range"), $("#tab_port_forwarding"), $("#tab_load_balancer"), $("#tab_vpn")];
var tabContentArray = [$("#tab_content_details"), $("#tab_content_port_range"), $("#tab_content_port_forwarding"), $("#tab_content_load_balancer"), $("#tab_content_vpn")];
var afterSwitchFnArray = [ipJsonToDetailsTab, ipJsonToPortRangeTab, ipJsonToPortForwardingTab, ipJsonToLoadBalancerTab, ipJsonToVPNTab];
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");
-
- //*** 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("");
- }
- }
- }
- });
-
- $("#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");
-
- var zoneid = thisDialog.find("#acquire_zone").val();
+
+ if(g_supportELB == "guest" || g_supportELB == "public") {
+ $("#tab_details,#tab_port_range,#tab_port_forwarding,#tab_load_balancer,#tab_vpn").hide();
- var $midmenuItem1 = beforeAddingMidMenuItem() ;
+ $("#tab_content_details").hide();
- $.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));
- });
+ $("#acquire_new_ip_button").hide();
+ $("#add_load_balancer_and_ip_button").show();
+
+ initDialog("dialog_add_load_balancer_and_ip");
+
+ $.ajax({
+ data: createURL("command=listZones&available=true"),
+ dataType: "json",
+ success: function(json) {
+ var zones = json.listzonesresponse.zone;
+ var zoneSelect = $("#dialog_add_load_balancer_and_ip #acquire_zone").empty();
+ if (zones != null && zones.length > 0) {
+ for (var i = 0; i < zones.length; i++) {
+ if(zones[i].networktype == "Basic")
+ zoneSelect.append("");
}
- });
- },
- "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");
- });
- }
- });
- },
- 0
- );
- },
- error: function(XMLHttpResponse) {
- handleError(XMLHttpResponse, function() {
- $template.slideUp("slow", function() {
- $(this).remove();
- });
- var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
- $("#dialog_error").text(fromdb(errorMsg)).dialog("open");
- });
- }
- });
-
- return false;
- });
- //*** Port Range tab (end) ***
-
- //*** Port Forwarding tab (begin) ***
- var $createPortForwardingRow = $("#tab_content_port_forwarding").find("#create_port_forwarding_row");
-
- // If public end port gets filled, disable private ports and copy public ports over to private ports
- /*
- $createPortForwardingRow.find("#public_end_port").bind("keyup", function(event) {
- if($(this).val() != null && $(this).val().length > 0) {
- $createPortForwardingRow.find("#private_port").attr("readonly", true);
- $createPortForwardingRow.find("#private_end_port").attr("readonly", true);
-
- $createPortForwardingRow.find("#private_port").val($createPortForwardingRow.find("#public_port").val());
- $createPortForwardingRow.find("#private_end_port").val($(this).val());
- }
- else {
- $createPortForwardingRow.find("#private_port").removeAttr("readonly");
- $createPortForwardingRow.find("#private_end_port").removeAttr("readonly");
- }
- return true;
- });
- $createPortForwardingRow.find("#public_port").bind("keyup", function(event) {
- if($createPortForwardingRow.find("#private_port").attr("readonly") == true)
- $createPortForwardingRow.find("#private_port").val($(this).val());
- return true;
- });
- */
-
- $createPortForwardingRow.find("#add_link").bind("click", function(event){
- var isValid = true;
-
- isValid &= validateCIDRList("CIDR", $createPortForwardingRow.find("#cidr"), $createPortForwardingRow.find("#cidr_errormsg"), true); //optional
+ });
- isValid &= validateInteger("Public Port", $createPortForwardingRow.find("#public_port"), $createPortForwardingRow.find("#public_port_errormsg"), 1, 65535, false); //required
- isValid &= validateInteger("Public End Port", $createPortForwardingRow.find("#public_end_port"), $createPortForwardingRow.find("#public_end_port_errormsg"), 1, 65535, true); //optional
-
- isValid &= validateInteger("Private Port", $createPortForwardingRow.find("#private_port"), $createPortForwardingRow.find("#private_port_errormsg"), 1, 65535, false); //required
- isValid &= validateInteger("Private End Port", $createPortForwardingRow.find("#private_end_port"), $createPortForwardingRow.find("#private_end_port_errormsg"), 1, 65535, true); //optional
-
- isValid &= validateDropDownBox("Instance", $createPortForwardingRow.find("#vm"), $createPortForwardingRow.find("#vm_errormsg"));
- if (!isValid)
- return;
+ $("#add_load_balancer_and_ip_button").unbind("click").bind("click", function(event) {
+ $("#dialog_add_load_balancer_and_ip").dialog('option', 'buttons', {
+ "Acquire": function() {
+ var $thisDialog = $(this);
+
+ var isValid = true;
+ isValid &= validateString("Name", $thisDialog.find("#name"), $thisDialog.find("#name_errormsg"));
+ isValid &= validateInteger("Public Port", $thisDialog.find("#public_port"), $thisDialog.find("#public_port_errormsg"), 1, 65535);
+ isValid &= validateInteger("Private Port", $thisDialog.find("#private_port"), $thisDialog.find("#private_port_errormsg"), 1, 65535);
+ if (!isValid)
+ return;
+
+ $thisDialog.dialog("close");
+
+ var array1 = [];
+
+ var zoneId = $thisDialog.find("#acquire_zone").val();
+ array1.push("&zoneid="+zoneId);
+
+ var name = $thisDialog.find("#name").val();
+ array1.push("&name="+todb(name));
+
+ var publicPort = $thisDialog.find("#public_port").val();
+ array1.push("&publicport="+publicPort);
+
+ var privatePort = $thisDialog.find("#private_port").val();
+ array1.push("&privateport="+privatePort);
+
+ var algorithm = $thisDialog.find("#algorithm_select").val();
+ array1.push("&algorithm="+algorithm);
+
+ var $midmenuItem1 = beforeAddingMidMenuItem() ;
+ $.ajax({
+ data: createURL("command=createLoadBalancerRule"+array1.join("")),
+ dataType: "json",
+ success: function(json) {
+ var jobId = json.createloadbalancerruleresponse.jobid;
+ var timerKey = "addLbAndIpJob_"+jobId;
+
+ $("body").everyTime(2000, timerKey, function() {
+ $.ajax({
+ data: createURL("command=queryAsyncJobResult&jobId="+jobId),
+ dataType: "json",
+ success: function(json) {
+ var result = json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ } else {
+ $("body").stopTime(timerKey);
+ if (result.jobstatus == 1) {
+ // Succeeded
+ var publicipid = result.jobresult.loadbalancer.publicipid;
+
+ var cmd;
+ if(g_supportELB == "guest") {
+ cmd = "command=listPublicIpAddresses&forvirtualnetwork=false&id="+publicipid;
+ }
+ else if(g_supportELB == "public") {
+ cmd = "command=listPublicIpAddresses&forvirtualnetwork=true&id="+publicipid;
+ }
+ else {
+ if(g_supportELB == null)
+ alert("supportELB should be either guest or public. It should not be null.");
+ else
+ alert("supportELB should be either guest or public. It should not be " + g_supportELB);
+ return;
+ }
+
+ $.ajax({
+ data: createURL(cmd),
+ dataType: "json",
+ async: false,
+ success: function(json) {
+ var items = json.listpublicipaddressesresponse.publicipaddress;
+ if(items != null && items.length > 0) {
+ ipToMidmenu(items[0], $midmenuItem1);
+ bindClickToMidMenu($midmenuItem1, ipToRightPanel, ipGetMidmenuId);
+ afterAddingMidMenuItem($midmenuItem1, true);
+ }
+ }
+ });
+ } else if (result.jobstatus == 2) {
+ afterAddingMidMenuItem($midmenuItem1, false, fromdb(result.jobresult.errortext));
+ }
+ }
+ },
+ error: function(XMLHttpResponse) {
+ $("body").stopTime(timerKey);
+ handleError(XMLHttpResponse, function() {
+ afterAddingMidMenuItem($midmenuItem1, false, parseXMLHttpResponse(XMLHttpResponse));
+ });
+ }
+ });
+ }, 0);
+ },
+ error: function(XMLHttpResponse) {
+ handleError(XMLHttpResponse, function() {
+ afterAddingMidMenuItem($midmenuItem1, false, parseXMLHttpResponse(XMLHttpResponse));
+ });
+ }
+ });
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }).dialog("open");
+ return false;
+ });
+ }
+ else {
+ $("#tab_details,#tab_content_details").show();
+
+ //dialogs
+ 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");
- var $template = $("#port_forwarding_template").clone();
- $("#tab_content_port_forwarding #grid_content").append($template.show());
+ //*** 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("");
+ }
+ }
+ }
+ });
+
+ $("#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) ***
- 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 array1 = [];
- array1.push("&ipaddressid="+ipObj.id);
-
- var cidr = $createPortForwardingRow.find("#cidr").val();
- if(cidr != null && cidr.length > 0)
- array1.push("&cidrlist="+cidr);
-
- 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 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");
- }
+ //*** 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) {
@@ -369,9 +375,9 @@ function afterLoadIpJSP() {
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");
});
}
});
@@ -379,28 +385,178 @@ function afterLoadIpJSP() {
0
);
},
- error: function(XMLHttpResponse) {
+ 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) ***
-
- //*** Load Balancer tab (begin) ***
+ });
+ //*** Port Range tab (end) ***
+
+ //*** Port Forwarding tab (begin) ***
+ var $createPortForwardingRow = $("#tab_content_port_forwarding").find("#create_port_forwarding_row");
+
+ // If public end port gets filled, disable private ports and copy public ports over to private ports
+ /*
+ $createPortForwardingRow.find("#public_end_port").bind("keyup", function(event) {
+ if($(this).val() != null && $(this).val().length > 0) {
+ $createPortForwardingRow.find("#private_port").attr("readonly", true);
+ $createPortForwardingRow.find("#private_end_port").attr("readonly", true);
+
+ $createPortForwardingRow.find("#private_port").val($createPortForwardingRow.find("#public_port").val());
+ $createPortForwardingRow.find("#private_end_port").val($(this).val());
+ }
+ else {
+ $createPortForwardingRow.find("#private_port").removeAttr("readonly");
+ $createPortForwardingRow.find("#private_end_port").removeAttr("readonly");
+ }
+ return true;
+ });
+ $createPortForwardingRow.find("#public_port").bind("keyup", function(event) {
+ if($createPortForwardingRow.find("#private_port").attr("readonly") == true)
+ $createPortForwardingRow.find("#private_port").val($(this).val());
+ return true;
+ });
+ */
+
+ $createPortForwardingRow.find("#add_link").bind("click", function(event){
+ var isValid = true;
+
+ isValid &= validateCIDRList("CIDR", $createPortForwardingRow.find("#cidr"), $createPortForwardingRow.find("#cidr_errormsg"), true); //optional
+
+ isValid &= validateInteger("Public Port", $createPortForwardingRow.find("#public_port"), $createPortForwardingRow.find("#public_port_errormsg"), 1, 65535, false); //required
+ isValid &= validateInteger("Public End Port", $createPortForwardingRow.find("#public_end_port"), $createPortForwardingRow.find("#public_end_port_errormsg"), 1, 65535, true); //optional
+
+ isValid &= validateInteger("Private Port", $createPortForwardingRow.find("#private_port"), $createPortForwardingRow.find("#private_port_errormsg"), 1, 65535, false); //required
+ isValid &= validateInteger("Private End Port", $createPortForwardingRow.find("#private_end_port"), $createPortForwardingRow.find("#private_end_port_errormsg"), 1, 65535, true); //optional
+
+ isValid &= validateCIDRList("CIDR", $createPortForwardingRow.find("#cidr"), $createPortForwardingRow.find("#cidr_errormsg"), true); //optional
+
+ isValid &= validateInteger("Public Port", $createPortForwardingRow.find("#public_port"), $createPortForwardingRow.find("#public_port_errormsg"), 1, 65535, false); //required
+ //isValid &= validateInteger("Public End Port", $createPortForwardingRow.find("#public_end_port"), $createPortForwardingRow.find("#public_end_port_errormsg"), 1, 65535, true); //optional
+
+ isValid &= validateInteger("Private Port", $createPortForwardingRow.find("#private_port"), $createPortForwardingRow.find("#private_port_errormsg"), 1, 65535, false); //required
+ //isValid &= validateInteger("Private End Port", $createPortForwardingRow.find("#private_end_port"), $createPortForwardingRow.find("#private_end_port_errormsg"), 1, 65535, true); //optional
+
+ isValid &= validateDropDownBox("Instance", $createPortForwardingRow.find("#vm"), $createPortForwardingRow.find("#vm_errormsg"));
+ if (!isValid)
+ return;
+
+ var $template = $("#port_forwarding_template").clone();
+ $("#tab_content_port_forwarding #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 array1 = [];
+ array1.push("&ipaddressid="+ipObj.id);
+
+ var cidr = $createPortForwardingRow.find("#cidr").val();
+ if(cidr != null && cidr.length > 0)
+ array1.push("&cidrlist="+cidr);
+
+ 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 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();
+ });
+ var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
+ $("#dialog_error").text(fromdb(errorMsg)).dialog("open");
+ });
+ }
+ });
+ },
+ 0
+ );
+ },
+ error: function(XMLHttpResponse) {
+ handleError(XMLHttpResponse, function() {
+ $template.slideUp("slow", function() {
+ $(this).remove();
+ });
+ var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
+ $("#dialog_error").text(fromdb(errorMsg)).dialog("open");
+ });
+ }
+ });
+
+ return false;
+ });
+ //*** Port Forwarding tab (end) ***
+ }
+
+ //*** Load Balancer tab (begin) ***
var createLoadBalancerRow = $("#tab_content_load_balancer #create_load_balancer_row");
createLoadBalancerRow.find("#add_link").bind("click", function(event){
// validate values
- var isValid = true;
- isValid &= validateCIDRList("CIDR", createLoadBalancerRow.find("#cidr"), createLoadBalancerRow.find("#cidr_errormsg"), true); //optional
+ var isValid = true;
+ isValid &= validateCIDRList("CIDR", createLoadBalancerRow.find("#cidr"), createLoadBalancerRow.find("#cidr_errormsg"), true); //optional
isValid &= validateString("Name", createLoadBalancerRow.find("#name"), createLoadBalancerRow.find("#name_errormsg"));
isValid &= validateInteger("Public Port", createLoadBalancerRow.find("#public_port"), createLoadBalancerRow.find("#public_port_errormsg"), 1, 65535);
isValid &= validateInteger("Private Port", createLoadBalancerRow.find("#private_port"), createLoadBalancerRow.find("#private_port_errormsg"), 1, 65535);
@@ -417,73 +573,110 @@ function afterLoadIpJSP() {
var ipObj = $midmenuItem1.data("jsonObj");
var array1 = [];
- array1.push("&publicipid="+ipObj.id);
-
- var cidr = createLoadBalancerRow.find("#cidr").val();
- if(cidr != null && cidr.length > 0)
- array1.push("&cidrlist="+cidr);
-
+ array1.push("&publicipid="+ipObj.id);
+
+ var cidr = createLoadBalancerRow.find("#cidr").val();
+ if(cidr != null && cidr.length > 0)
+ array1.push("&cidrlist="+cidr);
+
var name = createLoadBalancerRow.find("#name").val();
- array1.push("&name="+todb(name));
-
+ array1.push("&name="+todb(name));
+
var publicPort = createLoadBalancerRow.find("#public_port").val();
- array1.push("&publicport="+publicPort);
-
+ array1.push("&publicport="+publicPort);
+
var privatePort = createLoadBalancerRow.find("#private_port").val();
- array1.push("&privateport="+privatePort);
-
+ array1.push("&privateport="+privatePort);
+
var algorithm = createLoadBalancerRow.find("#algorithm_select").val();
array1.push("&algorithm="+algorithm);
-
+
$.ajax({
data: createURL("command=createLoadBalancerRule"+array1.join("")),
dataType: "json",
- success: function(json) {
- var item = json.createloadbalancerruleresponse.loadbalancer;
- loadBalancerJsonToTemplate(item, $template);
- $spinningWheel.hide();
- refreshCreateLoadBalancerRow();
+ success: function(json) {
+ 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();
- });
- var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
- $("#dialog_error").text(fromdb(errorMsg)).dialog("open");
+ });
+ var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
+ $("#dialog_error").text(fromdb(errorMsg)).dialog("open");
});
- }
- });
+ }
+ });
+
return false;
- });
- //*** Load Balancer tab (end) ***
-}
-
-function ipGetMidmenuId(jsonObj) {
- return ipGetMidmenuId2(jsonObj.ipaddress);
-}
-
-function ipGetMidmenuId2(ipaddress) {
- return "midmenuItem_" + ipaddress.replace(/\./g, "_"); //e.g. "192.168.33.108" => "192_168_33_108"
-}
-
-function ipToMidmenu(jsonObj, $midmenuItem1) {
- var id = ipGetMidmenuId(jsonObj);
- $midmenuItem1.attr("id", id);
- $midmenuItem1.data("jsonObj", jsonObj);
-
- var $iconContainer = $midmenuItem1.find("#icon_container").show();
- $iconContainer.find("#icon").attr("src", "images/midmenuicon_network_networkgroup.png");
-
- var firstRowText = fromdb(jsonObj.ipaddress);
- if (jsonObj.issourcenat == true)
- firstRowText += "[source nat]";
- $midmenuItem1.find("#first_row").text(firstRowText.substring(0,midMenuFirstRowLength));
- $midmenuItem1.find("#first_row_container").attr("title", firstRowText);
-
- var secondRowText = "owned by: "+fromdb(jsonObj.account);
- $midmenuItem1.find("#second_row").text(secondRowText.substring(0,midMenuSecondRowLength));
- $midmenuItem1.find("#second_row_container").attr("title", secondRowText);
+ });
+ //*** Load Balancer tab (end) ***
+}
+
+function ipGetMidmenuId(jsonObj) {
+ return ipGetMidmenuId2(jsonObj.ipaddress);
+}
+
+function ipGetMidmenuId2(ipaddress) {
+ return "midmenuItem_" + ipaddress.replace(/\./g, "_"); //e.g. "192.168.33.108" => "192_168_33_108"
+}
+
+function ipToMidmenu(jsonObj, $midmenuItem1) {
+ var id = ipGetMidmenuId(jsonObj);
+ $midmenuItem1.attr("id", id);
+ $midmenuItem1.data("jsonObj", jsonObj);
+
+ var $iconContainer = $midmenuItem1.find("#icon_container").show();
+ $iconContainer.find("#icon").attr("src", "images/midmenuicon_network_networkgroup.png");
+
+ var firstRowText = fromdb(jsonObj.ipaddress);
+ if (jsonObj.issourcenat == true)
+ firstRowText += "[source nat]";
+ $midmenuItem1.find("#first_row").text(firstRowText.substring(0,midMenuFirstRowLength));
+ $midmenuItem1.find("#first_row_container").attr("title", firstRowText);
+
+ var secondRowText = "owned by: "+fromdb(jsonObj.account);
+ $midmenuItem1.find("#second_row").text(secondRowText.substring(0,midMenuSecondRowLength));
+ $midmenuItem1.find("#second_row_container").attr("title", secondRowText);
}
function isIpManageable(domainid, account) {
@@ -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();
@@ -525,64 +722,64 @@ function ipToRightPanel($midmenuItem1) {
else { //ipObj.isstaticnat == false
$("#tab_port_range").hide();
if(ipObj.forvirtualnetwork == true) { //(public network)
- if(isIpManageable(ipObj.domainid, ipObj.account) == true) {
- //Port Forwarding tab
- if(networkObj != null) {
- var firewallServiceObj = ipFindNetworkServiceByName("Firewall", networkObj);
- if(firewallServiceObj != null) {
- var portForwardingCapabilityObj = ipFindCapabilityByName("PortForwarding", firewallServiceObj);
- if(portForwardingCapabilityObj != null) {
- if(portForwardingCapabilityObj.value == "true")
- $("#tab_port_forwarding").show();
- else
- $("#tab_port_forwarding").hide();
- }
- else {
- $("#tab_port_forwarding").hide();
- }
- }
- else {
- $("#tab_port_forwarding").hide();
- }
- }
- else {
- $("#tab_port_forwarding").hide();
- }
-
- //Load Balancer tab
- if (ipObj.issourcenat == true) {
- var lbServiceObj = ipFindNetworkServiceByName("Lb", networkObj);
- if(lbServiceObj != null) {
- var LoadBalancingSupportedIpsCapabilityObj = ipFindCapabilityByName("LoadBalancingSupportedIps", lbServiceObj);
- if(LoadBalancingSupportedIpsCapabilityObj != null)
- $("#tab_load_balancer").hide();
- else
- $("#tab_load_balancer").show();
- }
- else {
- $("#tab_load_balancer").hide();
- }
- }
- else {
- if(networkObj != null) {
- var lbServiceObj = ipFindNetworkServiceByName("Lb", networkObj);
- if(lbServiceObj != null)
- $("#tab_load_balancer").show();
- else
- $("#tab_load_balancer").hide();
- }
- else {
- $("#tab_load_balancer").hide();
- }
- }
-
- //VPN tab
- if (ipObj.issourcenat == true) {
- var vpnServiceObj = ipFindNetworkServiceByName("Vpn", networkObj);
- if(vpnServiceObj != null)
- $("#tab_vpn").show();
- else
- $("#tab_vpn").hide();
+ if(isIpManageable(ipObj.domainid, ipObj.account) == true) {
+ //Port Forwarding tab
+ if(networkObj != null) {
+ var firewallServiceObj = ipFindNetworkServiceByName("Firewall", networkObj);
+ if(firewallServiceObj != null) {
+ var portForwardingCapabilityObj = ipFindCapabilityByName("PortForwarding", firewallServiceObj);
+ if(portForwardingCapabilityObj != null) {
+ if(portForwardingCapabilityObj.value == "true")
+ $("#tab_port_forwarding").show();
+ else
+ $("#tab_port_forwarding").hide();
+ }
+ else {
+ $("#tab_port_forwarding").hide();
+ }
+ }
+ else {
+ $("#tab_port_forwarding").hide();
+ }
+ }
+ else {
+ $("#tab_port_forwarding").hide();
+ }
+
+ //Load Balancer tab
+ if (ipObj.issourcenat == true) {
+ var lbServiceObj = ipFindNetworkServiceByName("Lb", networkObj);
+ if(lbServiceObj != null) {
+ var LoadBalancingSupportedIpsCapabilityObj = ipFindCapabilityByName("LoadBalancingSupportedIps", lbServiceObj);
+ if(LoadBalancingSupportedIpsCapabilityObj != null)
+ $("#tab_load_balancer").hide();
+ else
+ $("#tab_load_balancer").show();
+ }
+ else {
+ $("#tab_load_balancer").hide();
+ }
+ }
+ else {
+ if(networkObj != null) {
+ var lbServiceObj = ipFindNetworkServiceByName("Lb", networkObj);
+ if(lbServiceObj != null)
+ $("#tab_load_balancer").show();
+ else
+ $("#tab_load_balancer").hide();
+ }
+ else {
+ $("#tab_load_balancer").hide();
+ }
+ }
+
+ //VPN tab
+ if (ipObj.issourcenat == true) {
+ var vpnServiceObj = ipFindNetworkServiceByName("Vpn", networkObj);
+ if(vpnServiceObj != null)
+ $("#tab_vpn").show();
+ else
+ $("#tab_vpn").hide();
}
else {
$("#tab_vpn").hide();
@@ -598,7 +795,7 @@ function ipToRightPanel($midmenuItem1) {
}
}
-function ipJsonToPortRangeTab() {
+function ipJsonToPortRangeTab() {
var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
if($midmenuItem1 == null) {
@@ -612,14 +809,14 @@ function ipJsonToPortRangeTab() {
return;
}
- var $thisTab = $("#right_panel_content #tab_content_port_range");
+ var $thisTab = $("#right_panel_content #tab_content_port_range");
$thisTab.find("#tab_container").hide();
$thisTab.find("#tab_spinning_wheel").show();
var networkObj = $midmenuItem1.data("networkObj");
if(networkObj != null) {
- var firewallServiceObj = ipFindNetworkServiceByName("Firewall", networkObj);
- if(firewallServiceObj != null) {
+ var firewallServiceObj = ipFindNetworkServiceByName("Firewall", networkObj);
+ if(firewallServiceObj != null) {
var supportedProtocolsCapabilityObj = ipFindCapabilityByName("SupportedProtocols", firewallServiceObj);
if(supportedProtocolsCapabilityObj != null) {
var protocols = supportedProtocolsCapabilityObj.value.toUpperCase(); //e.g. "tcp,udp" => "TCP,UDP"
@@ -653,7 +850,7 @@ function ipJsonToPortRangeTab() {
});
}
-function ipJsonToPortForwardingTab() {
+function ipJsonToPortForwardingTab() {
var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
if($midmenuItem1 == null) {
ipClearPortForwardingTab();
@@ -666,14 +863,14 @@ function ipJsonToPortForwardingTab() {
return;
}
- var $thisTab = $("#right_panel_content #tab_content_port_forwarding");
+ var $thisTab = $("#right_panel_content #tab_content_port_forwarding");
$thisTab.find("#tab_container").hide();
$thisTab.find("#tab_spinning_wheel").show();
var networkObj = $midmenuItem1.data("networkObj");
if(networkObj != null) {
- var firewallServiceObj = ipFindNetworkServiceByName("Firewall", networkObj);
- if(firewallServiceObj != null) {
+ var firewallServiceObj = ipFindNetworkServiceByName("Firewall", networkObj);
+ if(firewallServiceObj != null) {
var supportedProtocolsCapabilityObj = ipFindCapabilityByName("SupportedProtocols", firewallServiceObj);
if(supportedProtocolsCapabilityObj != null) {
var protocols = supportedProtocolsCapabilityObj.value.toUpperCase(); //e.g. "tcp,udp" => "TCP,UDP"
@@ -719,29 +916,29 @@ function ipJsonToLoadBalancerTab() {
ipClearLoadBalancerTab();
return;
}
-
- var $thisTab = $("#right_panel_content #tab_content_load_balancer");
+
+ var $thisTab = $("#right_panel_content #tab_content_load_balancer");
$thisTab.find("#tab_container").hide();
- $thisTab.find("#tab_spinning_wheel").show();
-
- var networkObj = $midmenuItem1.data("networkObj");
- if(networkObj != null) {
- var lbServiceObj = ipFindNetworkServiceByName("Lb", networkObj);
- if(lbServiceObj != null) {
- var supportedLbAlgorithmsCapabilityObj = ipFindCapabilityByName("SupportedLbAlgorithms", lbServiceObj);
- if(supportedLbAlgorithmsCapabilityObj != null) {
- var algorithms = supportedLbAlgorithmsCapabilityObj.value; //e.g. "roundrobin,leastconn,sourceip"
- var array1 = algorithms.split(",");
- var $algorithmField1 = $("#create_load_balancer_row").find("#algorithm_select").empty();
- var $algorithmField2 = $("#load_balancer_template").find("#row_container_edit").find("#algorithm_select").empty();
- for(var i=0; i"+array1[i]+"");
- $algorithmField2.append("");
- }
- }
- }
- }
-
+ $thisTab.find("#tab_spinning_wheel").show();
+
+ var networkObj = $midmenuItem1.data("networkObj");
+ if(networkObj != null) {
+ var lbServiceObj = ipFindNetworkServiceByName("Lb", networkObj);
+ if(lbServiceObj != null) {
+ var supportedLbAlgorithmsCapabilityObj = ipFindCapabilityByName("SupportedLbAlgorithms", lbServiceObj);
+ if(supportedLbAlgorithmsCapabilityObj != null) {
+ var algorithms = supportedLbAlgorithmsCapabilityObj.value; //e.g. "roundrobin,leastconn,sourceip"
+ var array1 = algorithms.split(",");
+ var $algorithmField1 = $("#create_load_balancer_row").find("#algorithm_select").empty();
+ var $algorithmField2 = $("#load_balancer_template").find("#row_container_edit").find("#algorithm_select").empty();
+ for(var i=0; i"+array1[i]+"");
+ $algorithmField2.append("");
+ }
+ }
+ }
+ }
+
refreshCreateLoadBalancerRow();
$.ajax({
@@ -762,81 +959,81 @@ function ipJsonToLoadBalancerTab() {
$thisTab.find("#tab_container").show();
}
});
-}
-
-function showEnableVPNDialog($thisTab) {
- $("#dialog_enable_vpn")
- .dialog('option', 'buttons', {
- "Enable": function() {
- var $thisDialog = $(this);
- $thisDialog.find("#info_container").hide();
- $spinningWheel = $thisDialog.find("#spinning_wheel").show();
-
- var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
- var ipObj = $midmenuItem1.data("jsonObj");
-
- $.ajax({
- data: createURL("command=createRemoteAccessVpn&publicipid="+ipObj.id+"&account="+ipObj.account+"&domainid="+ipObj.domainid+"&zoneid="+ipObj.zoneid),
- dataType: "json",
- success: function(json) {
- var jobId = json.createremoteaccessvpnresponse.jobid;
- var timerKey = "asyncJob_" + jobId;
- $("body").everyTime(
- 5000,
- 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
- showVpnUsers(result.jobresult.remoteaccessvpn.presharedkey, result.jobresult.remoteaccessvpn.publicip);
- $thisDialog.dialog("close");
- $thisTab.find("#tab_container").show();
- $thisTab.find("#vpn_disabled_msg").hide();
- } else if (result.jobstatus == 2) { // Failed
- //var errorMsg = "We were unable to enable VPN access. Please contact support.";
- var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
- $thisDialog.find("#info_container").text(errorMsg).show();
- }
- }
- },
- error: function(XMLHttpResponse) {
- $("body").stopTime(timerKey);
- handleError(XMLHttpResponse, function() {
- handleErrorInDialog(XMLHttpResponse, $thisDialog);
- });
- }
- });
- },
- 0
- );
- },
- error: function(XMLHttpResponse) {
- handleError(XMLHttpResponse, function() {
- handleErrorInDialog(XMLHttpResponse, $thisDialog);
- });
- }
- });
- },
- "Cancel": function() {
- $thisTab.find("#tab_container").hide();
- $thisTab.find("#vpn_disabled_msg").show();
- $(this).dialog("close");
- $thisTab.find("#enable_vpn_link").unbind("click").bind("click", function(event) {
- showEnableVPNDialog($thisTab);
- });
- }
- }).dialog("open");
-}
-
-function ipJsonToVPNTab() {
+}
+
+function showEnableVPNDialog($thisTab) {
+ $("#dialog_enable_vpn")
+ .dialog('option', 'buttons', {
+ "Enable": function() {
+ var $thisDialog = $(this);
+ $thisDialog.find("#info_container").hide();
+ $spinningWheel = $thisDialog.find("#spinning_wheel").show();
+
+ var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
+ var ipObj = $midmenuItem1.data("jsonObj");
+
+ $.ajax({
+ data: createURL("command=createRemoteAccessVpn&publicipid="+ipObj.id+"&account="+ipObj.account+"&domainid="+ipObj.domainid+"&zoneid="+ipObj.zoneid),
+ dataType: "json",
+ success: function(json) {
+ var jobId = json.createremoteaccessvpnresponse.jobid;
+ var timerKey = "asyncJob_" + jobId;
+ $("body").everyTime(
+ 5000,
+ 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
+ showVpnUsers(result.jobresult.remoteaccessvpn.presharedkey, result.jobresult.remoteaccessvpn.publicip);
+ $thisDialog.dialog("close");
+ $thisTab.find("#tab_container").show();
+ $thisTab.find("#vpn_disabled_msg").hide();
+ } else if (result.jobstatus == 2) { // Failed
+ //var errorMsg = "We were unable to enable VPN access. Please contact support.";
+ var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
+ $thisDialog.find("#info_container").text(errorMsg).show();
+ }
+ }
+ },
+ error: function(XMLHttpResponse) {
+ $("body").stopTime(timerKey);
+ handleError(XMLHttpResponse, function() {
+ handleErrorInDialog(XMLHttpResponse, $thisDialog);
+ });
+ }
+ });
+ },
+ 0
+ );
+ },
+ error: function(XMLHttpResponse) {
+ handleError(XMLHttpResponse, function() {
+ handleErrorInDialog(XMLHttpResponse, $thisDialog);
+ });
+ }
+ });
+ },
+ "Cancel": function() {
+ $thisTab.find("#tab_container").hide();
+ $thisTab.find("#vpn_disabled_msg").show();
+ $(this).dialog("close");
+ $thisTab.find("#enable_vpn_link").unbind("click").bind("click", function(event) {
+ showEnableVPNDialog($thisTab);
+ });
+ }
+ }).dialog("open");
+}
+
+function ipJsonToVPNTab() {
var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
if($midmenuItem1 == null) {
ipClearVPNTab();
@@ -846,321 +1043,321 @@ function ipJsonToVPNTab() {
var ipObj = $midmenuItem1.data("jsonObj");
if(ipObj == null) {
ipClearVPNTab();
- return;
- }
-
- var $thisTab = $("#right_panel_content").find("#tab_content_vpn");
- $thisTab.find("#tab_spinning_wheel").show();
- $thisTab.find("#tab_container").hide();
-
- $.ajax({
- data: createURL("command=listRemoteAccessVpns&publicipid="+ipObj.id),
- dataType: "json",
- success: function(json) {
- var items = json.listremoteaccessvpnsresponse.remoteaccessvpn;
- if (items != null && items.length > 0) {
- showVpnUsers(items[0].presharedkey, items[0].publicip);
- } else {
- showEnableVPNDialog($thisTab);
- }
- $thisTab.find("#tab_spinning_wheel").hide();
- $thisTab.find("#tab_container").show();
- $thisTab.find("#vpn_disabled_msg").hide();
- }
- });
-}
-
-function ipClearVPNTab() {
- var $thisTab = $("#right_panel_content").find("#tab_content_vpn");
- showEnableVPNDialog($thisTab);
- $thisTab.find("#vpn_disabled_msg").hide();
-}
-
-function showVpnUsers(presharedkey, publicip) {
- var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
- var ipObj = $midmenuItem1.data("jsonObj");
- var $vpnTab = $("#right_panel_content #tab_content_vpn");
- var $actionMenu = $vpnTab.find("#vpn_action_menu");
- $actionMenu.find("#action_list").empty();
-
- $vpnTab.find("#vpn_key").text(presharedkey);
- $vpnTab.find("#vpn_ip").text(publicip);
-
- var $listItemTemplate = $("#action_list_item");
- var $listItem = $listItemTemplate.clone();
- $listItem.find("#link").text("Disable VPN");
- $listItem.bind("click", function(event) {
- $actionMenu.hide();
- $("#dialog_disable_vpn")
- .dialog('option', 'buttons', {
- "Disable": function() {
- var $thisDialog = $(this);
- $thisDialog.find("#info_container").hide();
- $spinningWheel = $thisDialog.find("#spinning_wheel").show();
- $.ajax({
- data: createURL("command=deleteRemoteAccessVpn&publicipid="+ipObj.id+"&account="+ipObj.account+"&domainid="+ipObj.domainid+"&zoneid="+ipObj.zoneid),
- dataType: "json",
- success: function(json) {
- var jobId = json.deleteremoteaccessvpnresponse.jobid;
- var timerKey = "asyncJob_" + jobId;
- $("body").everyTime(
- 5000,
- 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
- $thisDialog.dialog("close");
- $vpnTab.find("#vpn_help").hide();
- $vpnTab.find("#enable_vpn_link").unbind("click").bind("click", function(event) {
- showEnableVPNDialog($vpnTab);
- });
- $vpnTab.find("#tab_container").hide();
- $vpnTab.find("#vpn_disabled_msg").show();
- } else if (result.jobstatus == 2) { // Failed
- //var errorMsg = "We were unable to disable VPN access. Please contact support.";
- var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
- $thisDialog.find("#info_container").text(errorMsg).show();
- }
- }
- },
- error: function(XMLHttpResponse) {
- $("body").stopTime(timerKey);
- handleError(XMLHttpResponse, function() {
- handleErrorInDialog(XMLHttpResponse, $thisDialog);
- });
- }
- });
- },
- 0
- );
- },
- error: function(XMLHttpResponse) {
- handleError(XMLHttpResponse, function() {
- handleErrorInDialog(XMLHttpResponse, $thisDialog);
- });
- }
- });
- },
- "Cancel": function() {
- $(this).dialog("close");
- }
- }).dialog("open");
- return false;
- });
- $actionMenu.find("#action_list").append($listItem.show());
-
- $listItem = $listItemTemplate.clone();
- $listItem.find("#link").text("Add VPN User");
- $listItem.bind("click", function(event) {
- $actionMenu.hide();
- $vpnDialog = $("#dialog_add_vpnuser");
- $vpnDialog.find("#username").val("");
- $vpnDialog.find("#password").val("");
- $("#dialog_add_vpnuser")
- .dialog('option', 'buttons', {
- "Add": function() {
- var $thisDialog = $(this);
- $thisDialog.find("#info_container").hide();
-
- var isValid = true;
- isValid &= validateString("Username", $thisDialog.find("#username"), $thisDialog.find("#username_errormsg"));
- isValid &= validateString("Password", $thisDialog.find("#password"), $thisDialog.find("#password_errormsg"));
- if (!isValid) return;
-
- var username = todb($thisDialog.find("#username").val());
- var password = todb($thisDialog.find("#password").val());
-
- $spinningWheel = $thisDialog.find("#spinning_wheel").show();
- $.ajax({
- data: createURL("command=addVpnUser&username="+username+"&password="+password),
- dataType: "json",
- success: function(json) {
- var jobId = json.addvpnuserresponse.jobid;
- var timerKey = "asyncJob_" + jobId;
- $("body").everyTime(
- 5000,
- 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
- $thisDialog.dialog("close");
- $("#tab_content_vpn #grid_content").append(vpnUserJsonToTemplate(result.jobresult.vpnuser).fadeIn());
- } else if (result.jobstatus == 2) { // Failed
- //var errorMsg = "We were unable to add user access to your VPN. Please contact support.";
- var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
- $thisDialog.find("#info_container").text(errorMsg).show();
- }
- }
- },
- error: function(XMLHttpResponse) {
- $("body").stopTime(timerKey);
- handleError(XMLHttpResponse, function() {
- handleErrorInDialog(XMLHttpResponse, $thisDialog);
- });
- }
- });
- },
- 0
- );
- },
- error: function(XMLHttpResponse) {
- handleError(XMLHttpResponse, function() {
- handleErrorInDialog(XMLHttpResponse, $thisDialog);
- });
- }
- });
- },
- "Cancel": function() {
- $(this).dialog("close");
- }
- }).dialog("open");
- return false;
- });
- $actionMenu.find("#action_list").append($listItem.show());
-
- // Enable action menu for vpn
- var $actionLink = $vpnTab.find("#vpn_action_link");
- $actionLink.unbind("mouseover").bind("mouseover", function(event) {
- $(this).find("#vpn_action_menu").show();
- return false;
- });
- $actionLink.unbind("mouseout").bind("mouseout", function(event) {
- $(this).find("#vpn_action_menu").hide();
- return false;
- });
-
- $vpnTab.find("#vpn_help").show();
- enableDeleteUser();
- // List users
- $.ajax({
- data: createURL("command=listVpnUsers&account="+ipObj.account+"&domainid="+ipObj.domainid),
- dataType: "json",
- async: false,
- success: function(json) {
- var items = json.listvpnusersresponse.vpnuser;
- if(items != null && items.length > 0) {
- var $gridContent = $("#tab_content_vpn #grid_content").empty();
- for (var i = 0; i < items.length; i++) {
- $gridContent.append(vpnUserJsonToTemplate(items[i]).show());
- }
-
- //Enable delete user
-
- }
- }
- });
-}
-
-function enableDeleteUser() {
- $("#tab_content_vpn #grid_content").unbind("click").bind("click", function(event) {
- var target = $(event.target);
- var targetId = target.attr("id");
- if (targetId == "vpn_delete_user") {
- var id = target.data("id");
- var username = target.data("username");
- var account = target.data("account");
- var domainId = target.data("domainid");
- var params = [];
- params.push("&username="+username);
- params.push("&account="+account);
- params.push("&domainid="+domainId);
- var $thisDialog = $("#dialog_confirmation_remove_vpnuser");
- $thisDialog.find("#username").text(target.data("username"));
- $thisDialog.dialog('option', 'buttons', {
- "Ok": function() {
- $thisDialog.find("#info_container").hide();
- $spinningWheel = $thisDialog.find("#spinning_wheel").show();
- $.ajax({
- data: createURL("command=removeVpnUser"+params.join("")),
- dataType: "json",
- success: function(json) {
- var jobId = json.removevpnuserresponse.jobid;
- var timerKey = "asyncJob_" + jobId;
- $("body").everyTime(
- 5000,
- 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
- $thisDialog.dialog("close");
-
- //remove user from grid
- $("#right_panel_content #tab_content_vpn").find("#vpnuser"+id).slideUp();
- } else if (result.jobstatus == 2) { // Failed
- //var errorMsg = "We were unable to add user access to your VPN. Please contact support.";
- var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
- $thisDialog.find("#info_container").text(errorMsg).show();
- }
- }
- },
- error: function(XMLHttpResponse) {
- $("body").stopTime(timerKey);
- handleError(XMLHttpResponse, function() {
- handleErrorInDialog(XMLHttpResponse, $thisDialog);
- });
- }
- });
- },
- 0
- );
- },
- error: function(XMLHttpResponse) {
- handleError(XMLHttpResponse, function() {
- handleErrorInDialog(XMLHttpResponse, $thisDialog);
- });
- }
- });
- },
- "Cancel": function() {
- $(this).dialog("close");
- }
- }).dialog("open");
-
- }
- return false;
- });
-}
-
-
-var vpnItem = 1;
-function vpnUserJsonToTemplate(json) {
- var $template = $("#vpn_template").clone();
- if (vpnItem++ % 2 == 0) $template.removeClass("odd").addClass("even");
- $template.find("#username").text(json.username);
- $template.attr("id", "vpnuser"+json.id);
- $template.find("#vpn_delete_user").data("id", json.id).data("username", json.username).data("account", json.account).data("domainid", json.domainid);
- return $template;
-}
+ return;
+ }
+
+ var $thisTab = $("#right_panel_content").find("#tab_content_vpn");
+ $thisTab.find("#tab_spinning_wheel").show();
+ $thisTab.find("#tab_container").hide();
+
+ $.ajax({
+ data: createURL("command=listRemoteAccessVpns&publicipid="+ipObj.id),
+ dataType: "json",
+ success: function(json) {
+ var items = json.listremoteaccessvpnsresponse.remoteaccessvpn;
+ if (items != null && items.length > 0) {
+ showVpnUsers(items[0].presharedkey, items[0].publicip);
+ } else {
+ showEnableVPNDialog($thisTab);
+ }
+ $thisTab.find("#tab_spinning_wheel").hide();
+ $thisTab.find("#tab_container").show();
+ $thisTab.find("#vpn_disabled_msg").hide();
+ }
+ });
+}
+
+function ipClearVPNTab() {
+ var $thisTab = $("#right_panel_content").find("#tab_content_vpn");
+ showEnableVPNDialog($thisTab);
+ $thisTab.find("#vpn_disabled_msg").hide();
+}
+
+function showVpnUsers(presharedkey, publicip) {
+ var $midmenuItem1 = $("#right_panel_content").data("$midmenuItem1");
+ var ipObj = $midmenuItem1.data("jsonObj");
+ var $vpnTab = $("#right_panel_content #tab_content_vpn");
+ var $actionMenu = $vpnTab.find("#vpn_action_menu");
+ $actionMenu.find("#action_list").empty();
+
+ $vpnTab.find("#vpn_key").text(presharedkey);
+ $vpnTab.find("#vpn_ip").text(publicip);
+
+ var $listItemTemplate = $("#action_list_item");
+ var $listItem = $listItemTemplate.clone();
+ $listItem.find("#link").text("Disable VPN");
+ $listItem.bind("click", function(event) {
+ $actionMenu.hide();
+ $("#dialog_disable_vpn")
+ .dialog('option', 'buttons', {
+ "Disable": function() {
+ var $thisDialog = $(this);
+ $thisDialog.find("#info_container").hide();
+ $spinningWheel = $thisDialog.find("#spinning_wheel").show();
+ $.ajax({
+ data: createURL("command=deleteRemoteAccessVpn&publicipid="+ipObj.id+"&account="+ipObj.account+"&domainid="+ipObj.domainid+"&zoneid="+ipObj.zoneid),
+ dataType: "json",
+ success: function(json) {
+ var jobId = json.deleteremoteaccessvpnresponse.jobid;
+ var timerKey = "asyncJob_" + jobId;
+ $("body").everyTime(
+ 5000,
+ 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
+ $thisDialog.dialog("close");
+ $vpnTab.find("#vpn_help").hide();
+ $vpnTab.find("#enable_vpn_link").unbind("click").bind("click", function(event) {
+ showEnableVPNDialog($vpnTab);
+ });
+ $vpnTab.find("#tab_container").hide();
+ $vpnTab.find("#vpn_disabled_msg").show();
+ } else if (result.jobstatus == 2) { // Failed
+ //var errorMsg = "We were unable to disable VPN access. Please contact support.";
+ var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
+ $thisDialog.find("#info_container").text(errorMsg).show();
+ }
+ }
+ },
+ error: function(XMLHttpResponse) {
+ $("body").stopTime(timerKey);
+ handleError(XMLHttpResponse, function() {
+ handleErrorInDialog(XMLHttpResponse, $thisDialog);
+ });
+ }
+ });
+ },
+ 0
+ );
+ },
+ error: function(XMLHttpResponse) {
+ handleError(XMLHttpResponse, function() {
+ handleErrorInDialog(XMLHttpResponse, $thisDialog);
+ });
+ }
+ });
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }).dialog("open");
+ return false;
+ });
+ $actionMenu.find("#action_list").append($listItem.show());
+
+ $listItem = $listItemTemplate.clone();
+ $listItem.find("#link").text("Add VPN User");
+ $listItem.bind("click", function(event) {
+ $actionMenu.hide();
+ $vpnDialog = $("#dialog_add_vpnuser");
+ $vpnDialog.find("#username").val("");
+ $vpnDialog.find("#password").val("");
+ $("#dialog_add_vpnuser")
+ .dialog('option', 'buttons', {
+ "Add": function() {
+ var $thisDialog = $(this);
+ $thisDialog.find("#info_container").hide();
+
+ var isValid = true;
+ isValid &= validateString("Username", $thisDialog.find("#username"), $thisDialog.find("#username_errormsg"));
+ isValid &= validateString("Password", $thisDialog.find("#password"), $thisDialog.find("#password_errormsg"));
+ if (!isValid) return;
+
+ var username = todb($thisDialog.find("#username").val());
+ var password = todb($thisDialog.find("#password").val());
+
+ $spinningWheel = $thisDialog.find("#spinning_wheel").show();
+ $.ajax({
+ data: createURL("command=addVpnUser&username="+username+"&password="+password),
+ dataType: "json",
+ success: function(json) {
+ var jobId = json.addvpnuserresponse.jobid;
+ var timerKey = "asyncJob_" + jobId;
+ $("body").everyTime(
+ 5000,
+ 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
+ $thisDialog.dialog("close");
+ $("#tab_content_vpn #grid_content").append(vpnUserJsonToTemplate(result.jobresult.vpnuser).fadeIn());
+ } else if (result.jobstatus == 2) { // Failed
+ //var errorMsg = "We were unable to add user access to your VPN. Please contact support.";
+ var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
+ $thisDialog.find("#info_container").text(errorMsg).show();
+ }
+ }
+ },
+ error: function(XMLHttpResponse) {
+ $("body").stopTime(timerKey);
+ handleError(XMLHttpResponse, function() {
+ handleErrorInDialog(XMLHttpResponse, $thisDialog);
+ });
+ }
+ });
+ },
+ 0
+ );
+ },
+ error: function(XMLHttpResponse) {
+ handleError(XMLHttpResponse, function() {
+ handleErrorInDialog(XMLHttpResponse, $thisDialog);
+ });
+ }
+ });
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }).dialog("open");
+ return false;
+ });
+ $actionMenu.find("#action_list").append($listItem.show());
+
+ // Enable action menu for vpn
+ var $actionLink = $vpnTab.find("#vpn_action_link");
+ $actionLink.unbind("mouseover").bind("mouseover", function(event) {
+ $(this).find("#vpn_action_menu").show();
+ return false;
+ });
+ $actionLink.unbind("mouseout").bind("mouseout", function(event) {
+ $(this).find("#vpn_action_menu").hide();
+ return false;
+ });
+
+ $vpnTab.find("#vpn_help").show();
+ enableDeleteUser();
+ // List users
+ $.ajax({
+ data: createURL("command=listVpnUsers&account="+ipObj.account+"&domainid="+ipObj.domainid),
+ dataType: "json",
+ async: false,
+ success: function(json) {
+ var items = json.listvpnusersresponse.vpnuser;
+ if(items != null && items.length > 0) {
+ var $gridContent = $("#tab_content_vpn #grid_content").empty();
+ for (var i = 0; i < items.length; i++) {
+ $gridContent.append(vpnUserJsonToTemplate(items[i]).show());
+ }
+
+ //Enable delete user
+
+ }
+ }
+ });
+}
+
+function enableDeleteUser() {
+ $("#tab_content_vpn #grid_content").unbind("click").bind("click", function(event) {
+ var target = $(event.target);
+ var targetId = target.attr("id");
+ if (targetId == "vpn_delete_user") {
+ var id = target.data("id");
+ var username = target.data("username");
+ var account = target.data("account");
+ var domainId = target.data("domainid");
+ var params = [];
+ params.push("&username="+username);
+ params.push("&account="+account);
+ params.push("&domainid="+domainId);
+ var $thisDialog = $("#dialog_confirmation_remove_vpnuser");
+ $thisDialog.find("#username").text(target.data("username"));
+ $thisDialog.dialog('option', 'buttons', {
+ "Ok": function() {
+ $thisDialog.find("#info_container").hide();
+ $spinningWheel = $thisDialog.find("#spinning_wheel").show();
+ $.ajax({
+ data: createURL("command=removeVpnUser"+params.join("")),
+ dataType: "json",
+ success: function(json) {
+ var jobId = json.removevpnuserresponse.jobid;
+ var timerKey = "asyncJob_" + jobId;
+ $("body").everyTime(
+ 5000,
+ 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
+ $thisDialog.dialog("close");
+
+ //remove user from grid
+ $("#right_panel_content #tab_content_vpn").find("#vpnuser"+id).slideUp();
+ } else if (result.jobstatus == 2) { // Failed
+ //var errorMsg = "We were unable to add user access to your VPN. Please contact support.";
+ var errorMsg = g_dictionary["label.failed"] + " - " + fromdb(result.jobresult.errortext);
+ $thisDialog.find("#info_container").text(errorMsg).show();
+ }
+ }
+ },
+ error: function(XMLHttpResponse) {
+ $("body").stopTime(timerKey);
+ handleError(XMLHttpResponse, function() {
+ handleErrorInDialog(XMLHttpResponse, $thisDialog);
+ });
+ }
+ });
+ },
+ 0
+ );
+ },
+ error: function(XMLHttpResponse) {
+ handleError(XMLHttpResponse, function() {
+ handleErrorInDialog(XMLHttpResponse, $thisDialog);
+ });
+ }
+ });
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }).dialog("open");
+
+ }
+ return false;
+ });
+}
+
+
+var vpnItem = 1;
+function vpnUserJsonToTemplate(json) {
+ var $template = $("#vpn_template").clone();
+ if (vpnItem++ % 2 == 0) $template.removeClass("odd").addClass("even");
+ $template.find("#username").text(json.username);
+ $template.attr("id", "vpnuser"+json.id);
+ $template.find("#vpn_delete_user").data("id", json.id).data("username", json.username).data("account", json.account).data("domainid", json.domainid);
+ return $template;
+}
function ipClearRightPanel() {
ipClearDetailsTab();
@@ -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) {
@@ -1239,26 +1452,26 @@ function ipJsonToDetailsTab() {
ipPopulateVMDropdown($vmSelect);
if(ipObj.isstaticnat == true) {
- buildActionLinkForTab("label.action.disable.static.NAT", ipActionMap, $actionMenu, $midmenuItem1, $thisTab);
- buildActionLinkForTab("label.action.release.ip", ipActionMap, $actionMenu, $midmenuItem1, $thisTab);
+ buildActionLinkForTab("label.action.disable.static.NAT", ipActionMap, $actionMenu, $midmenuItem1, $thisTab);
+ buildActionLinkForTab("label.action.release.ip", ipActionMap, $actionMenu, $midmenuItem1, $thisTab);
noAvailableActions = false;
} else {
- if(ipObj.issourcenat != true) {
- if(networkObj != null) {
- var firewallServiceObj = ipFindNetworkServiceByName("Firewall", networkObj);
- if(firewallServiceObj != null) {
- var staticNatCapabilityObj = ipFindCapabilityByName("StaticNat", firewallServiceObj);
- if(staticNatCapabilityObj != null) {
- if(staticNatCapabilityObj.value == "true")
- buildActionLinkForTab("label.action.enable.static.NAT", ipActionMap, $actionMenu, $midmenuItem1, $thisTab);
- }
- }
- }
-
- buildActionLinkForTab("label.action.release.ip", ipActionMap, $actionMenu, $midmenuItem1, $thisTab);
- noAvailableActions = false;
- }
- }
+ if(ipObj.issourcenat != true) {
+ if(networkObj != null) {
+ var firewallServiceObj = ipFindNetworkServiceByName("Firewall", networkObj);
+ if(firewallServiceObj != null) {
+ var staticNatCapabilityObj = ipFindCapabilityByName("StaticNat", firewallServiceObj);
+ if(staticNatCapabilityObj != null) {
+ if(staticNatCapabilityObj.value == "true")
+ buildActionLinkForTab("label.action.enable.static.NAT", ipActionMap, $actionMenu, $midmenuItem1, $thisTab);
+ }
+ }
+ }
+
+ buildActionLinkForTab("label.action.release.ip", ipActionMap, $actionMenu, $midmenuItem1, $thisTab);
+ noAvailableActions = false;
+ }
+ }
}
// no available actions
@@ -1305,27 +1518,27 @@ function setNetworkTypeField(value, $field) {
$field.text("");
}
-var ipActionMap = {
- "label.action.release.ip": {
- isAsyncJob: true,
- asyncJobResponse: "disassociateipaddressresponse",
- dialogBeforeActionFn : doReleaseIp,
- inProcessText: "label.action.release.ip.processing",
- afterActionSeccessFn: function(json, $midmenuItem1, id) {
- $midmenuItem1.slideUp("slow", function(){
- $(this).remove();
- if(id.toString() == $("#right_panel_content").find("#tab_content_details").find("#id").text()) {
- clearRightPanel();
- ipClearRightPanel();
- }
- });
-
- }
- },
- "label.action.enable.static.NAT": {
- isAsyncJob: false,
- dialogBeforeActionFn: doEnableStaticNAT,
- inProcessText: "label.action.enable.static.NAT.processing",
+var ipActionMap = {
+ "label.action.release.ip": {
+ isAsyncJob: true,
+ asyncJobResponse: "disassociateipaddressresponse",
+ dialogBeforeActionFn : doReleaseIp,
+ inProcessText: "label.action.release.ip.processing",
+ afterActionSeccessFn: function(json, $midmenuItem1, id) {
+ $midmenuItem1.slideUp("slow", function(){
+ $(this).remove();
+ if(id.toString() == $("#right_panel_content").find("#tab_content_details").find("#id").text()) {
+ clearRightPanel();
+ ipClearRightPanel();
+ }
+ });
+
+ }
+ },
+ "label.action.enable.static.NAT": {
+ isAsyncJob: false,
+ dialogBeforeActionFn: doEnableStaticNAT,
+ inProcessText: "label.action.enable.static.NAT.processing",
afterActionSeccessFn: function(json, $midmenuItem1, id) {
if(id.toString() == $("#right_panel_content").find("#tab_content_details").find("#id").text()) {
$.ajax({
@@ -1338,15 +1551,15 @@ var ipActionMap = {
ipToMidmenu(items[0], $midmenuItem1);
}
}
- });
- }
- }
- },
- "label.action.disable.static.NAT": {
- isAsyncJob: true,
- asyncJobResponse: "disablestaticnatresponse",
- dialogBeforeActionFn: doDisableStaticNAT,
- inProcessText: "label.action.disable.static.NAT.processing",
+ });
+ }
+ }
+ },
+ "label.action.disable.static.NAT": {
+ isAsyncJob: true,
+ asyncJobResponse: "disablestaticnatresponse",
+ dialogBeforeActionFn: doDisableStaticNAT,
+ inProcessText: "label.action.disable.static.NAT.processing",
afterActionSeccessFn: function(json, $midmenuItem1, id) {
if(id.toString() == $("#right_panel_content").find("#tab_content_details").find("#id").text()) {
$.ajax({
@@ -1359,11 +1572,11 @@ var ipActionMap = {
ipToMidmenu(items[0], $midmenuItem1);
}
}
- });
- }
- }
- }
-}
+ });
+ }
+ }
+ }
+}
function doReleaseIp($actionLink, $detailsTab, $midmenuItem1) {
var jsonObj = $midmenuItem1.data("jsonObj");
@@ -1428,9 +1641,9 @@ function doDisableStaticNAT($actionLink, $detailsTab, $midmenuItem1) {
function ipSetRuleState(stateValue, $stateField) {
$stateField.text(stateValue);
- if(stateValue == "Active") //green
- $stateField.removeClass("status_red status_gray").addClass("status_green");
- else if(stateValue == "Deleting") //red
+ if(stateValue == "Active") //green
+ $stateField.removeClass("status_red status_gray").addClass("status_green");
+ else if(stateValue == "Deleting") //red
$stateField.removeClass("status_green status_gray").addClass("status_red");
else //gray
$stateField.removeClass("status_red status_green").addClass("status_gray");
@@ -1502,7 +1715,7 @@ function portRangeJsonToTemplate(jsonObj, $template) {
return false;
});
-}
+}
function refreshCreatePortRangeRow() {
var $createPortRangeRow = $("#create_port_range_row");
@@ -1520,18 +1733,18 @@ function ipClearPortForwardingTab() {
function portForwardingJsonToTemplate(jsonObj, $template) {
$template.attr("id", "portForwarding_" + fromdb(jsonObj.id)).data("portForwardingId", fromdb(jsonObj.id));
-
- $template.find("#cidr").text(fromdb(jsonObj.cidrlist));
-
- var publicPort = fromdb(jsonObj.publicport);
- if(jsonObj.publicendport != null && jsonObj.publicendport.length > 0)
+
+ $template.find("#cidr").text(fromdb(jsonObj.cidrlist));
+
+ var publicPort = fromdb(jsonObj.publicport);
+ if(jsonObj.publicendport != null && jsonObj.publicendport.length > 0)
publicPort += (" - " + fromdb(jsonObj.publicendport));
- $template.find("#public_port").text(publicPort);
-
- var privatePort = fromdb(jsonObj.privateport);
- if(jsonObj.privateendport != null && jsonObj.privateendport.length > 0)
- privatePort += (" - " + fromdb(jsonObj.privateendport));
- $template.find("#private_port").text(privatePort);
+ $template.find("#public_port").text(publicPort);
+
+ var privatePort = fromdb(jsonObj.privateport);
+ if(jsonObj.privateendport != null && jsonObj.privateendport.length > 0)
+ privatePort += (" - " + fromdb(jsonObj.privateendport));
+ $template.find("#private_port").text(privatePort);
$template.find("#protocol").text(fromdb(jsonObj.protocol));
@@ -1602,13 +1815,13 @@ function portForwardingJsonToTemplate(jsonObj, $template) {
return false;
});
-}
+}
function refreshCreatePortForwardingRow() {
var $createPortForwardingRow = $("#create_port_forwarding_row");
- $createPortForwardingRow.find("#public_port").val("");
+ $createPortForwardingRow.find("#public_port").val("");
$createPortForwardingRow.find("#public_end_port").val("");
- $createPortForwardingRow.find("#private_port").val("");
+ $createPortForwardingRow.find("#private_port").val("");
$createPortForwardingRow.find("#private_end_port").val("");
var $vmSelect = $createPortForwardingRow.find("#vm").empty();
@@ -1664,9 +1877,9 @@ function ipClearLoadBalancerTab() {
function loadBalancerJsonToTemplate(jsonObj, $template) {
var loadBalancerId = fromdb(jsonObj.id);
$template.attr("id", "loadBalancer_" + loadBalancerId).data("loadBalancerId", loadBalancerId);
-
- $template.find("#row_container #cidr").text(fromdb(jsonObj.cidrlist));
- $template.find("#row_container_edit #cidr").text(fromdb(jsonObj.cidrlist));
+
+ $template.find("#row_container #cidr").text(fromdb(jsonObj.cidrlist));
+ $template.find("#row_container_edit #cidr").text(fromdb(jsonObj.cidrlist));
$template.find("#row_container #name").text(fromdb(jsonObj.name));
$template.find("#row_container_edit #name").val(fromdb(jsonObj.name));
@@ -1743,10 +1956,23 @@ function loadBalancerJsonToTemplate(jsonObj, $template) {
} else {
$("body").stopTime(timerKey);
$spinningWheel.hide();
- if (result.jobstatus == 1) { // Succeeded
+ if (result.jobstatus == 1) { // Succeeded
+ var total_lbrules = $("#tab_content_load_balancer").find("#grid_content").find(".grid_rows").length;
$template.slideUp("slow", function() {
- $(this).remove();
- });
+ $(this).remove();
+
+ if(g_supportELB == "guest" || g_supportELB == "public") {
+ var count_lb = $("div[id*='loadBalancer_']").length;
+ if(count_lb == 0) {
+ var params = $("#middle_menu_pagination").data("params");
+ if(params == null)
+ return;
+ listMidMenuItems2(params.commandString, params.getSearchParamsFn, params.jsonResponse1, params.jsonResponse2, params.toMidmenuFn, params.toRightPanelFn, params.getMidmenuIdFn, params.isMultipleSelectionInMidMenu, 1);
+ if($("div[id*='midmenuItem_']").length == 0)
+ $("#tab_content_load_balancer").hide();
+ }
+ }
+ });
} else if (result.jobstatus == 2) { // Failed
var errorMsg = g_dictionary["label.deleting.failed"] + " - " + fromdb(result.jobresult.errortext);
$("#dialog_error").text(errorMsg).dialog("open");
@@ -1920,7 +2146,7 @@ function loadBalancerJsonToTemplate(jsonObj, $template) {
}
function refreshCreateLoadBalancerRow() {
- var createLoadBalancerRow = $("#tab_content_load_balancer #create_load_balancer_row");
+ var createLoadBalancerRow = $("#tab_content_load_balancer #create_load_balancer_row");
createLoadBalancerRow.find("#cidr").val("");
createLoadBalancerRow.find("#name").val("");
createLoadBalancerRow.find("#public_port").val("");
diff --git a/ui/scripts/cloud.core.js b/ui/scripts/cloud.core.js
index a0f7371dd0d..06dd351862e 100644
--- a/ui/scripts/cloud.core.js
+++ b/ui/scripts/cloud.core.js
@@ -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;
diff --git a/ui/scripts/cloud.core.resource.js b/ui/scripts/cloud.core.resource.js
index be701f3e346..fe209c9fc4b 100644
--- a/ui/scripts/cloud.core.resource.js
+++ b/ui/scripts/cloud.core.resource.js
@@ -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() {