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