api: don't throttle api discovery for listApis command (#2894)

Users reported that they weren't getting all apis listed in cloudmonkey when running a sync. After some debugging, I found that the problem is that the ApiDiscoveryService is calling ApiRateLimitServiceImpl.checkAccess(), so the results of the listApis command are being truncated because Cloudstack believes the user has exceeded their API throttling rate.

I enabled throttling with a 25 request per second limit. I then created a test role with only list* permissions and assigned it to a test user. When this user calls listApis, they will typically receive anywhere from 15-18 results. Checking the logs, you see The given user has reached his/her account api limit, please retry after 218 ms..

I raised the limit to 200 requests per second, restarted the management server and tried again. This time I got 143 results and no log messages about the user being throttled.
This commit is contained in:
Craig Squire 2018-12-12 12:25:32 -06:00 committed by Rohit Yadav
parent 408cce48a5
commit 8d53557ba7
6 changed files with 36 additions and 3 deletions

View File

@ -0,0 +1,23 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.acl;
/**
* Marker interface to differentiate ACL APICheckers from others (for example, a rate limit checker)
*/
public interface APIAclChecker extends APIChecker {
}

View File

@ -52,6 +52,11 @@
<property name="typeClass" value="org.apache.cloudstack.acl.APIChecker" />
</bean>
<bean class="org.apache.cloudstack.spring.lifecycle.registry.RegistryLifecycle">
<property name="registry" ref="apiAclCheckersRegistry" />
<property name="typeClass" value="org.apache.cloudstack.acl.APIAclChecker" />
</bean>
<bean class="org.apache.cloudstack.spring.lifecycle.registry.RegistryLifecycle">
<property name="registry" ref="querySelectorsRegistry" />
<property name="typeClass" value="org.apache.cloudstack.acl.QuerySelector" />

View File

@ -265,6 +265,11 @@
<property name="excludeKey" value="api.checkers.exclude" />
</bean>
<bean id="apiAclCheckersRegistry"
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
<property name="excludeKey" value="api.checkers.acl.exclude" />
</bean>
<bean id="querySelectorsRegistry"
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
<property name="excludeKey" value="query.selectors.exclude" />

View File

@ -36,7 +36,7 @@ import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.PluggableService;
import com.google.common.base.Strings;
public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements APIChecker {
public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements APIAclChecker {
@Inject
private AccountService accountService;

View File

@ -41,7 +41,7 @@ import com.cloud.utils.component.PluggableService;
// This is the default API access checker that grab's the user's account
// based on the account type, access is granted
@Deprecated
public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIChecker {
public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIAclChecker {
protected static final Logger LOGGER = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class);

View File

@ -44,7 +44,7 @@
<bean id="apiDiscoveryServiceImpl"
class="org.apache.cloudstack.discovery.ApiDiscoveryServiceImpl">
<property name="apiAccessCheckers" value="#{apiCheckersRegistry.registered}" />
<property name="apiAccessCheckers" value="#{apiAclCheckersRegistry.registered}" />
<property name="services" value="#{apiCommandsRegistry.registered}" />
</bean>