Updated Branches: refs/heads/4.1 17e3313e6 -> 0afc2d003
CLOUDSTACK-1484: provide api.throttling.enabled gloabl configuration settings to enable/disable api throttling feature. Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/0afc2d00 Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/0afc2d00 Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/0afc2d00 Branch: refs/heads/4.1 Commit: 0afc2d00330e2d0ef911d9c25af3e4c8d76b9109 Parents: 22d017d Author: Min Chen <[email protected]> Authored: Mon Mar 4 16:31:58 2013 -0800 Committer: Chip Childers <[email protected]> Committed: Tue Mar 5 11:26:20 2013 -0500 ---------------------------------------------------------------------- .../command/user/config/ListCapabilitiesCmd.java | 8 +++- .../command/admin/ratelimit/ResetApiLimitCmd.java | 9 +++++ .../api/command/user/ratelimit/GetApiLimitCmd.java | 11 ++++++ .../cloudstack/ratelimit/ApiRateLimitService.java | 2 + .../ratelimit/ApiRateLimitServiceImpl.java | 19 +++++++++++ .../cloudstack/ratelimit/ApiRateLimitTest.java | 25 +++++++++++++++ server/src/com/cloud/configuration/Config.java | 3 +- .../src/com/cloud/server/ManagementServerImpl.java | 7 +++- setup/db/db/schema-40to410.sql | 1 + 9 files changed, 80 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java index eb862e6..a30e26c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java @@ -52,8 +52,12 @@ public class ListCapabilitiesCmd extends BaseCmd { response.setProjectInviteRequired((Boolean)capabilities.get("projectInviteRequired")); response.setAllowUsersCreateProjects((Boolean)capabilities.get("allowusercreateprojects")); response.setDiskOffMaxSize((Long)capabilities.get("customDiskOffMaxSize")); - response.setApiLimitInterval((Integer)capabilities.get("apiLimitInterval")); - response.setApiLimitMax((Integer)capabilities.get("apiLimitMax")); + if (capabilities.containsKey("apiLimitInterval")) { + response.setApiLimitInterval((Integer) capabilities.get("apiLimitInterval")); + } + if (capabilities.containsKey("apiLimitMax")) { + response.setApiLimitMax((Integer) capabilities.get("apiLimitMax")); + } response.setObjectName("capability"); response.setResponseName(getCommandName()); this.setResponseObject(response); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/admin/ratelimit/ResetApiLimitCmd.java ---------------------------------------------------------------------- diff --git a/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/admin/ratelimit/ResetApiLimitCmd.java b/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/admin/ratelimit/ResetApiLimitCmd.java index 5a7ac86..7ec5316 100644 --- a/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/admin/ratelimit/ResetApiLimitCmd.java +++ b/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/admin/ratelimit/ResetApiLimitCmd.java @@ -29,6 +29,8 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.ratelimit.ApiRateLimitService; import org.apache.log4j.Logger; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.user.Account; import com.cloud.user.UserContext; @@ -43,6 +45,9 @@ public class ResetApiLimitCmd extends BaseCmd { @Inject ApiRateLimitService _apiLimitService; + @Inject + ConfigurationDao _configDao; + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// @@ -89,6 +94,10 @@ public class ResetApiLimitCmd extends BaseCmd { @Override public void execute(){ + boolean apiLimitEnabled = Boolean.parseBoolean(_configDao.getValue(Config.ApiLimitEnabled.key())); + if ( !apiLimitEnabled ){ + throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "This api is only available when api.throttling.enabled = true."); + } boolean result = _apiLimitService.resetApiLimit(this.accountId); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/user/ratelimit/GetApiLimitCmd.java ---------------------------------------------------------------------- diff --git a/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/user/ratelimit/GetApiLimitCmd.java b/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/user/ratelimit/GetApiLimitCmd.java index 1afa932..ba92e8b 100644 --- a/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/user/ratelimit/GetApiLimitCmd.java +++ b/plugins/api/rate-limit/src/org/apache/cloudstack/api/command/user/ratelimit/GetApiLimitCmd.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; @@ -35,6 +36,9 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.ratelimit.ApiRateLimitService; + +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -55,6 +59,9 @@ public class GetApiLimitCmd extends BaseCmd { @Inject ApiRateLimitService _apiLimitService; + @Inject + ConfigurationDao _configDao; + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -76,6 +83,10 @@ public class GetApiLimitCmd extends BaseCmd { @Override public void execute(){ + boolean apiLimitEnabled = Boolean.parseBoolean(_configDao.getValue(Config.ApiLimitEnabled.key())); + if ( !apiLimitEnabled ){ + throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "This api is only available when api.throttling.enabled = true."); + } Account caller = UserContext.current().getCaller(); ApiLimitResponse response = _apiLimitService.searchApiLimit(caller); response.setResponseName(getCommandName()); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitService.java ---------------------------------------------------------------------- diff --git a/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitService.java b/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitService.java index a135556..ad421b6 100644 --- a/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitService.java +++ b/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitService.java @@ -33,4 +33,6 @@ public interface ApiRateLimitService extends PluggableService{ public void setTimeToLive(int timeToLive); public void setMaxAllowed(int max); + + public void setEnabled(boolean enabled); } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java ---------------------------------------------------------------------- diff --git a/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java b/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java index d23a11d..7d1b43a 100644 --- a/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java +++ b/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java @@ -50,6 +50,11 @@ public class ApiRateLimitServiceImpl extends AdapterBase implements APIChecker, private static final Logger s_logger = Logger.getLogger(ApiRateLimitServiceImpl.class); /** + * True if api rate limiting is enabled + */ + private boolean enabled = false; + + /** * Fixed time duration where api rate limit is set, in seconds */ private int timeToLive = 1; @@ -73,6 +78,10 @@ public class ApiRateLimitServiceImpl extends AdapterBase implements APIChecker, if (_store == null) { // get global configured duration and max values + String isEnabled = _configDao.getValue(Config.ApiLimitEnabled.key()); + if ( isEnabled != null ){ + enabled = Boolean.parseBoolean(isEnabled); + } String duration = _configDao.getValue(Config.ApiLimitInterval.key()); if (duration != null) { timeToLive = Integer.parseInt(duration); @@ -140,6 +149,10 @@ public class ApiRateLimitServiceImpl extends AdapterBase implements APIChecker, @Override public boolean checkAccess(User user, String apiCommandName) throws PermissionDeniedException { + // check if api rate limiting is enabled or not + if (!enabled){ + return true; + } Long accountId = user.getAccountId(); Account account = _accountService.getAccount(accountId); if ( _accountService.isRootAdmin(account.getType())){ @@ -192,5 +205,11 @@ public class ApiRateLimitServiceImpl extends AdapterBase implements APIChecker, } + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + + } + } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/plugins/api/rate-limit/test/org/apache/cloudstack/ratelimit/ApiRateLimitTest.java ---------------------------------------------------------------------- diff --git a/plugins/api/rate-limit/test/org/apache/cloudstack/ratelimit/ApiRateLimitTest.java b/plugins/api/rate-limit/test/org/apache/cloudstack/ratelimit/ApiRateLimitTest.java index 1a77a4e..3c6cadf 100644 --- a/plugins/api/rate-limit/test/org/apache/cloudstack/ratelimit/ApiRateLimitTest.java +++ b/plugins/api/rate-limit/test/org/apache/cloudstack/ratelimit/ApiRateLimitTest.java @@ -55,6 +55,7 @@ public class ApiRateLimitTest { when(_configDao.getValue(Config.ApiLimitInterval.key())).thenReturn(null); when(_configDao.getValue(Config.ApiLimitMax.key())).thenReturn(null); when(_configDao.getValue(Config.ApiLimitCacheSize.key())).thenReturn(null); + when(_configDao.getValue(Config.ApiLimitEnabled.key())).thenReturn("true"); // enable api rate limiting _limitService._configDao = _configDao; _limitService.configure("ApiRateLimitTest", Collections.<String, Object> emptyMap()); @@ -106,6 +107,8 @@ public class ApiRateLimitTest { + " accesses take less than a second to perform", isUnderLimit(key)); } + + @Test public void canDoReasonableNumberOfApiAccessPerSecond() throws Exception { int allowedRequests = 200; @@ -232,4 +235,26 @@ public class ApiRateLimitTest { } + @Test + public void disableApiLimit() throws Exception { + try { + int allowedRequests = 200; + _limitService.setMaxAllowed(allowedRequests); + _limitService.setTimeToLive(1); + _limitService.setEnabled(false); + + User key = createFakeUser(); + + for (int i = 0; i < allowedRequests + 1; i++) { + assertTrue("We should allow more than " + allowedRequests + " requests per second when api throttling is disabled.", + isUnderLimit(key)); + } + } finally { + _limitService.setEnabled(true); // enable api throttling to avoid + // impacting other testcases + } + + } + + } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/server/src/com/cloud/configuration/Config.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 7811b04..5313129 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -365,7 +365,8 @@ public enum Config { IntervalToEchoBaremetalSecurityGroupAgent("Advanced", ManagementServer.class, Integer.class, "interval.baremetal.securitygroup.agent.echo", "10", "Interval to echo baremetal security group agent, in seconds", null), TimeoutToEchoBaremetalSecurityGroupAgent("Advanced", ManagementServer.class, Integer.class, "timeout.baremetal.securitygroup.agent.echo", "3600", "Timeout to echo baremetal security group agent, in seconds, the provisioning process will be treated as a failure", null), - ApiLimitInterval("Advanced", ManagementServer.class, Integer.class, "api.throttling.interval", "1", "Time interval (in seconds) to reset API count", null), + ApiLimitEnabled("Advanced", ManagementServer.class, Boolean.class, "api.throttling.enabled", "true", "Enable/disable Api rate limit", null), + ApiLimitInterval("Advanced", ManagementServer.class, Integer.class, "api.throttling.interval", "1", "Time interval (in seconds) to reset API count", null), ApiLimitMax("Advanced", ManagementServer.class, Integer.class, "api.throttling.max", "25", "Max allowed number of APIs within fixed interval", null), ApiLimitCacheSize("Advanced", ManagementServer.class, Integer.class, "api.throttling.cachesize", "50000", "Account based API count cache size", null); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/server/src/com/cloud/server/ManagementServerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 52099ca..f03f5b8 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2510,6 +2510,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe String userPublicTemplateEnabled = _configs.get(Config.AllowPublicUserTemplates.key()); // add some parameters UI needs to handle API throttling + boolean apiLimitEnabled = Boolean.parseBoolean(_configDao.getValue(Config.ApiLimitEnabled.key())); Integer apiLimitInterval = Integer.valueOf(_configDao.getValue(Config.ApiLimitInterval.key())); Integer apiLimitMax = Integer.valueOf(_configDao.getValue(Config.ApiLimitMax.key())); @@ -2521,8 +2522,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe capabilities.put("projectInviteRequired", _projectMgr.projectInviteRequired()); capabilities.put("allowusercreateprojects", _projectMgr.allowUserToCreateProject()); capabilities.put("customDiskOffMaxSize", diskOffMaxSize); - capabilities.put("apiLimitInterval", apiLimitInterval); - capabilities.put("apiLimitMax", apiLimitMax); + if (apiLimitEnabled) { + capabilities.put("apiLimitInterval", apiLimitInterval); + capabilities.put("apiLimitMax", apiLimitMax); + } return capabilities; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/0afc2d00/setup/db/db/schema-40to410.sql ---------------------------------------------------------------------- diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index b45482f..822eae3 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -241,6 +241,7 @@ UPDATE `cloud`.`volumes` set uuid=id WHERE uuid is NULL; -- UPDATE `cloud`.`conditions` set uuid=id WHERE uuid is NULL; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'detail.batch.query.size', '2000', 'Default entity detail batch query size for listing'); +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'api.throttling.enabled', 'false', 'Enable/Disable Api rate limit'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'api.throttling.interval', '1', 'Time interval (in seconds) to reset API count'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'api.throttling.max', '25', 'Max allowed number of APIs within fixed interval'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'api.throttling.cachesize', '50000', 'Account based API count cache size');
