From 93090aa7c53c6fdc869e59e04e584d410503b145 Mon Sep 17 00:00:00 2001 From: Murali Reddy Date: Tue, 2 Jul 2013 17:53:42 +0530 Subject: [PATCH] CLOUDSTACK-1959: GSLB: add capability to provide weights to the sites involved in the GSLB add weights to each site participating in the GSLB. Traffic will be load balanced across the sites based on the weigths associated with each site. If not specified weight of site is defaulted to 1. --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../AssignToGlobalLoadBalancerRuleCmd.java | 45 +++++++++++++++++++ .../api/routing/SiteLoadBalancerConfig.java | 13 ++++++ .../gslb/GlobalLoadBalancerLbRuleMapVO.java | 16 ++++++- .../network/resource/NetscalerResource.java | 7 ++- .../GlobalLoadBalancingRulesServiceImpl.java | 6 +++ ...obalLoadBalancingRulesServiceImplTest.java | 4 +- setup/db/db/schema-410to420.sql | 1 + 8 files changed, 87 insertions(+), 6 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index dd876f75ed3..e2857b8165e 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -94,6 +94,7 @@ public class ApiConstants { public static final String GSLB_SERVICE_DOMAIN_NAME = "gslbdomainname"; public static final String GSLB_SERVICE_TYPE = "gslbservicetype"; public static final String GSLB_STICKY_SESSION_METHOD = "gslbstickysessionmethodname"; + public static final String GSLB_LBRULE_WEIGHT_MAP = "gslblbruleweightsmap"; public static final String GUEST_CIDR_ADDRESS = "guestcidraddress"; public static final String GUEST_VLAN_RANGE = "guestvlanrange"; public static final String HA_ENABLE = "haenable"; diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java index 1575cd34d07..c66cc4637f4 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java @@ -17,8 +17,10 @@ package org.apache.cloudstack.api.command.user.region.ha.gslb; +import com.cloud.dao.EntityManager; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.rules.LoadBalancer; import com.cloud.region.ha.GlobalLoadBalancerRule; import com.cloud.region.ha.GlobalLoadBalancingRulesService; import com.cloud.user.Account; @@ -31,7 +33,12 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.log4j.Logger; import javax.inject.Inject; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.UUID; @APICommand(name = "assignToGlobalLoadBalancerRule", description="Assign load balancer rule or list of load " + "balancer rules to a global load balancer rules.", responseObject=SuccessResponse.class) @@ -41,6 +48,8 @@ public class AssignToGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { private static final String s_name = "assigntogloballoadbalancerruleresponse"; + @Inject public EntityManager _entityMgr; + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// @@ -54,6 +63,12 @@ public class AssignToGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { "will be assigned to gloabal load balacner rule") private List loadBalancerRulesIds; + @Parameter(name=ApiConstants.GSLB_LBRULE_WEIGHT_MAP, type= CommandType.MAP, + description = "Map of LB rule id's and corresponding weights (between 1-100) in the GSLB rule, if not specified weight of " + + "a LB rule is defaulted to 1. Specified as 'gslblbruleweightsmap[0].loadbalancerid=UUID" + + "&gslblbruleweightsmap[0].weight=10'", required=false) + private Map gslbLbRuleWieghtMap; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -66,6 +81,36 @@ public class AssignToGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { return loadBalancerRulesIds; } + public Map getLoadBalancerRuleWeightMap() { + Map lbRuleWeightMap = new HashMap(); + + if (gslbLbRuleWieghtMap == null || gslbLbRuleWieghtMap.isEmpty()) { + return null; + } + + Collection lbruleWeightsCollection = gslbLbRuleWieghtMap.values(); + Iterator iter = lbruleWeightsCollection.iterator(); + while (iter.hasNext()) { + HashMap map = (HashMap) iter.next(); + Long weight; + LoadBalancer lbrule = _entityMgr.findByUuid(LoadBalancer.class, map.get("loadbalancerid")); + if (lbrule == null) { + throw new InvalidParameterValueException("Unable to find load balancer rule with ID: " + map.get("loadbalancerid")); + } + try { + weight = Long.parseLong(map.get("weight")); + if (weight < 1 || weight > 100) { + throw new InvalidParameterValueException("Invalid weight " + weight + " given for the LB rule id: " + map.get("loadbalancerid")); + } + } catch (NumberFormatException nfe) { + throw new InvalidParameterValueException("Unable to translate weight given for the LB rule id: " + map.get("loadbalancerid")); + } + lbRuleWeightMap.put(lbrule.getId(), weight); + } + + return lbRuleWeightMap; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/core/src/com/cloud/agent/api/routing/SiteLoadBalancerConfig.java b/core/src/com/cloud/agent/api/routing/SiteLoadBalancerConfig.java index cca5de83102..44268e4cc1d 100644 --- a/core/src/com/cloud/agent/api/routing/SiteLoadBalancerConfig.java +++ b/core/src/com/cloud/agent/api/routing/SiteLoadBalancerConfig.java @@ -45,6 +45,9 @@ public class SiteLoadBalancerConfig { // zone id in which site is located long dataCenterId; + // wight corresponding to this site + long weight = 1; + public SiteLoadBalancerConfig(boolean revoked, String serviceType, String servicePublicIp, String servicePort, long dataCenterId) { this.revoked = revoked; @@ -118,4 +121,14 @@ public class SiteLoadBalancerConfig { public boolean forRevoke() { return revoked; } + + public void setWeight(long weight) { + assert(weight >= 1 && weight <= 100); + this.weight = weight; + } + + public long getWeight() { + return weight; + } + } \ No newline at end of file diff --git a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapVO.java b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapVO.java index 6a1e17decc3..b9c89a739b7 100644 --- a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapVO.java +++ b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapVO.java @@ -40,17 +40,21 @@ public class GlobalLoadBalancerLbRuleMapVO implements InternalIdentity { @Column(name="gslb_rule_id") private long gslbLoadBalancerId; + @Column(name="weight") + private long weight; + @Column(name="revoke") private boolean revoke = false; public GlobalLoadBalancerLbRuleMapVO() { - + this.weight = 1; } - public GlobalLoadBalancerLbRuleMapVO(long loadBalancerId, long gslbLoadBalancerId) { + public GlobalLoadBalancerLbRuleMapVO(long loadBalancerId, long gslbLoadBalancerId, long weight) { this.loadBalancerId = loadBalancerId; this.gslbLoadBalancerId = gslbLoadBalancerId; this.revoke = false; + this.weight = weight; } public long getId() { @@ -80,4 +84,12 @@ public class GlobalLoadBalancerLbRuleMapVO implements InternalIdentity { public void setRevoke(boolean revoke) { this.revoke = revoke; } + + public void setWeight(long weight) { + this.weight = weight; + } + + public long getWeight() { + return weight; + } } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java index d25d4160e6b..eecae8a7ba5 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java @@ -902,7 +902,7 @@ public class NetscalerResource implements ServerResource { servicePublicIp, servicePublicPort, siteName); // Bind 'gslbservice' service object to GSLB virtual server - GSLB.createVserverServiceBinding(_netscalerService, serviceName, vserverName); + GSLB.createVserverServiceBinding(_netscalerService, serviceName, vserverName, site.getWeight()); // create a monitor for the service running on the site GSLB.createGslbServiceMonitor(_netscalerService, servicePublicIp, serviceName); @@ -1334,13 +1334,16 @@ public class NetscalerResource implements ServerResource { } } - private static void createVserverServiceBinding(nitro_service client, String serviceName, String vserverName) + private static void createVserverServiceBinding(nitro_service client, String serviceName, String vserverName, + long weight) throws ExecutionException { String errMsg; try { + assert(weight >= 1 && weight <= 100); gslbvserver_gslbservice_binding binding = new gslbvserver_gslbservice_binding(); binding.set_name(vserverName); binding.set_servicename(serviceName); + binding.set_weight(weight); gslbvserver_gslbservice_binding.add(client, binding); if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully created service: " + serviceName + " and virtual server: " diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index d6e8d2d0cec..ad36fae60ec 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -235,6 +235,8 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR } } + Map lbRuleWeightMap = assignToGslbCmd.getLoadBalancerRuleWeightMap(); + Transaction txn = Transaction.currentTxn(); txn.start(); @@ -243,6 +245,9 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR GlobalLoadBalancerLbRuleMapVO newGslbLbMap = new GlobalLoadBalancerLbRuleMapVO(); newGslbLbMap.setGslbLoadBalancerId(gslbRuleId); newGslbLbMap.setLoadBalancerId(lbRuleId); + if (lbRuleWeightMap != null && lbRuleWeightMap.get(lbRuleId) != null) { + newGslbLbMap.setWeight(lbRuleWeightMap.get(lbRuleId)); + } _gslbLbMapDao.persist(newGslbLbMap); } @@ -633,6 +638,7 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR siteLb.setGslbProviderPublicIp(_gslbProvider.getZoneGslbProviderPublicIp(dataCenterId, physicalNetworkId)); siteLb.setGslbProviderPrivateIp(_gslbProvider.getZoneGslbProviderPrivateIp(dataCenterId, physicalNetworkId)); + siteLb.setWeight(gslbLbMapVo.getWeight()); zoneSiteLoadbalancerMap.put(network.getDataCenterId(), siteLb); } diff --git a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java index ab545342cfa..6d49ec01c8c 100644 --- a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java +++ b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java @@ -748,7 +748,7 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { phyNetworkId.set(networkVo, new Long(200)); when(gslbServiceImpl._networkDao.findById(new Long(1))).thenReturn(networkVo); - GlobalLoadBalancerLbRuleMapVO gslbLbMap = new GlobalLoadBalancerLbRuleMapVO(1, 1); + GlobalLoadBalancerLbRuleMapVO gslbLbMap = new GlobalLoadBalancerLbRuleMapVO(1, 1, 1); List listSslbLbMap = new ArrayList(); listSslbLbMap.add(gslbLbMap); when(gslbServiceImpl._gslbLbMapDao.listByGslbRuleId(new Long(1))).thenReturn(listSslbLbMap); @@ -950,7 +950,7 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); - GlobalLoadBalancerLbRuleMapVO gslbLmMap = new GlobalLoadBalancerLbRuleMapVO(1,1); + GlobalLoadBalancerLbRuleMapVO gslbLmMap = new GlobalLoadBalancerLbRuleMapVO(1,1,1); List gslbLbMapVos = new ArrayList(); gslbLbMapVos.add(gslbLmMap); when(gslbServiceImpl._gslbLbMapDao.listByGslbRuleId(new Long(1))).thenReturn(gslbLbMapVos); diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 0c1d753486e..f5b79e9a027 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -513,6 +513,7 @@ CREATE TABLE `cloud`.`global_load_balancer_lb_rule_map` ( `id` bigint unsigned NOT NULL auto_increment, `gslb_rule_id` bigint unsigned NOT NULL, `lb_rule_id` bigint unsigned NOT NULL, + `weight` bigint unsigned NOT NULL DEFAULT 1 COMMENT 'weight of the site in gslb', `revoke` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 is when rule is set for Revoke', PRIMARY KEY (`id`), UNIQUE KEY (`gslb_rule_id`, `lb_rule_id`),