Skip to content

Commit bb32371

Browse files
committed
Address reviews + other improvements
1 parent 412a4bd commit bb32371

File tree

11 files changed

+115
-101
lines changed

11 files changed

+115
-101
lines changed

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ public class ApiConstants {
134134
public static final String CUSTOMIZED_IOPS = "customizediops";
135135
public static final String CUSTOM_ID = "customid";
136136
public static final String CUSTOM_JOB_ID = "customjobid";
137+
public static final String CURRENCY = "currency";
137138
public static final String CURRENT_START_IP = "currentstartip";
138139
public static final String CURRENT_END_IP = "currentendip";
139140
public static final String ENCRYPT = "encrypt";
@@ -514,9 +515,11 @@ public class ApiConstants {
514515
public static final String TIMEZONEOFFSET = "timezoneoffset";
515516
public static final String TOTAL = "total";
516517
public static final String TOTAL_SUBNETS = "totalsubnets";
518+
public static final String TOTAL_QUOTA = "totalquota";
517519
public static final String TYPE = "type";
518520
public static final String TRUST_STORE = "truststore";
519521
public static final String TRUST_STORE_PASSWORD = "truststorepass";
522+
public static final String UNIT = "unit";
520523
public static final String URL = "url";
521524
public static final String USAGE_INTERFACE = "usageinterface";
522525
public static final String USED_SUBNETS = "usedsubnets";
@@ -1162,6 +1165,8 @@ public class ApiConstants {
11621165
public static final String OBJECT_LOCKING = "objectlocking";
11631166
public static final String ENCRYPTION = "encryption";
11641167
public static final String QUOTA = "quota";
1168+
public static final String QUOTA_CONSUMED = "quotaconsumed";
1169+
public static final String QUOTA_USAGE = "quotausage";
11651170
public static final String ACCESS_KEY = "accesskey";
11661171

11671172
public static final String SOURCE_NAT_IP = "sourcenatipaddress";

engine/schema/src/main/java/com/cloud/user/dao/AccountDao.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ public interface AccountDao extends GenericDao<AccountVO, Long> {
4949

5050
List<AccountVO> listAccounts(String accountName, Long domainId, Filter filter);
5151

52-
AccountVO findAccountByNameAndDomainIncludingRemoved(String accountName, Long domainId);
53-
5452
List<AccountVO> findCleanupsForDisabledAccounts();
5553

5654
//return account only in enabled state

engine/schema/src/main/java/com/cloud/user/dao/AccountDaoImpl.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -304,13 +304,6 @@ public List<AccountVO> findAccountsByRole(Long roleId) {
304304
return listBy(sc);
305305
}
306306

307-
@Override
308-
public AccountVO findAccountByNameAndDomainIncludingRemoved(String accountName, Long domainId) {
309-
SearchCriteria<AccountVO> sc = AllFieldsSearch.create("accountName", accountName);
310-
sc.setParameters("domainId", domainId);
311-
return findOneIncludingRemovedBy(sc);
312-
}
313-
314307
@Override
315308
public void markForCleanup(long accountId) {
316309
AccountVO account = findByIdIncludingRemoved(accountId);

plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaStatementCmd.java

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.cloudstack.api.command;
1818

1919
import java.util.Date;
20-
import java.util.List;
2120

2221
import javax.inject.Inject;
2322

@@ -28,24 +27,24 @@
2827
import org.apache.cloudstack.api.Parameter;
2928
import org.apache.cloudstack.api.response.AccountResponse;
3029
import org.apache.cloudstack.api.response.DomainResponse;
30+
import org.apache.cloudstack.api.response.ProjectResponse;
3131
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
3232
import org.apache.cloudstack.api.response.QuotaStatementItemResponse;
3333
import org.apache.cloudstack.api.response.QuotaStatementResponse;
34-
import org.apache.cloudstack.quota.vo.QuotaUsageJoinVO;
3534

36-
import com.cloud.user.Account;
35+
import org.apache.commons.lang3.ObjectUtils;
3736

38-
@APICommand(name = "quotaStatement", responseObject = QuotaStatementItemResponse.class, description = "Create a quota statement", since = "4.7.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
37+
@APICommand(name = "quotaStatement", responseObject = QuotaStatementItemResponse.class, description = "Create a Quota statement for the provided Account, Project, or Domain.", since = "4.7.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
3938
public class QuotaStatementCmd extends BaseCmd {
4039

41-
42-
43-
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "Account name for which statement will be generated.")
40+
@ACL
41+
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
42+
description = "Name of the Account for which the Quota statement will be generated. Deprecated, please use accountid instead.")
4443
private String accountName;
4544

4645
@ACL
47-
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "If domain Id is given and the caller is "
48-
+ "domain admin then the statement is generated for domain.")
46+
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class,
47+
description = "ID of the Domain for which the Quota statement will be generated. May be used individually or with account.")
4948
private Long domainId;
5049

5150
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = true, description = "End of the period of the Quota statement. " +
@@ -56,14 +55,21 @@ public class QuotaStatementCmd extends BaseCmd {
5655
ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS)
5756
private Date startDate;
5857

59-
@Parameter(name = ApiConstants.TYPE, type = CommandType.INTEGER, description = "List quota usage records for the specified usage type.")
58+
@Parameter(name = ApiConstants.TYPE, type = CommandType.INTEGER,
59+
description = "Consider only Quota usage records for the specified usage type in the statement.")
6060
private Integer usageType;
6161

6262
@ACL
63-
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "List usage records for the specified account")
63+
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class,
64+
description = "ID of the Account for which the Quota statement will be generated. Can not be specified with projectid.")
6465
private Long accountId;
6566

66-
@Parameter(name = ApiConstants.SHOW_RESOURCES, type = CommandType.BOOLEAN, description = "List the resources of each quota type in the period.")
67+
@ACL
68+
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class,
69+
description = "ID of the Project for which the Quota statement will be generated. Can not be specified with accountid.", , since = "4.23.0")
70+
private Long projectId;
71+
72+
@Parameter(name = ApiConstants.SHOW_RESOURCES, type = CommandType.BOOLEAN, description = "List the resources of each Quota type in the period.", since = "4.23.0")
6773
private boolean showResources;
6874

6975
@Inject
@@ -113,32 +119,35 @@ public Date getStartDate() {
113119
return startDate;
114120
}
115121

116-
public void setStartDate(Date startDate) { this.startDate = startDate; }
122+
public void setStartDate(Date startDate) {
123+
this.startDate = startDate;
124+
}
117125

118-
public boolean isShowResources() { return showResources; }
126+
public boolean isShowResources() {
127+
return showResources;
128+
}
119129

120-
public void setShowResources(boolean showResources) { this.showResources = showResources; }
130+
public void setShowResources(boolean showResources) {
131+
this.showResources = showResources;
132+
}
133+
134+
public Long getProjectId() {
135+
return projectId;
136+
}
121137

122138
@Override
123139
public long getEntityOwnerId() {
124-
if (accountId != null) {
125-
return accountId;
140+
if (ObjectUtils.allNull(accountId, accountName, projectId)) {
141+
return -1;
126142
}
127-
Account activeAccountByName = _accountService.getActiveAccountByName(accountName, domainId);
128-
if (activeAccountByName != null) {
129-
return activeAccountByName.getAccountId();
130-
}
131-
return Account.ACCOUNT_ID_SYSTEM;
143+
return _accountService.finalizeAccountId(accountId, accountName, domainId, projectId);
132144
}
133145

134146
@Override
135147
public void execute() {
136-
List<QuotaUsageJoinVO> quotaUsage = responseBuilder.getQuotaUsage(this);
137-
138-
QuotaStatementResponse response = responseBuilder.createQuotaStatementResponse(quotaUsage, this);
148+
QuotaStatementResponse response = responseBuilder.createQuotaStatementResponse(this);
139149
response.setStartDate(startDate);
140150
response.setEndDate(endDate);
141-
142151
response.setResponseName(getCommandName());
143152
setResponseObject(response);
144153
}

plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilder.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public interface QuotaResponseBuilder {
4848

4949
boolean isUserAllowedToSeeActivationRules(User user);
5050

51-
QuotaStatementResponse createQuotaStatementResponse(List<QuotaUsageJoinVO> quotaUsage, QuotaStatementCmd cmd);
51+
QuotaStatementResponse createQuotaStatementResponse(QuotaStatementCmd cmd);
5252

5353
QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaUsage, Date startDate, Date endDate);
5454

@@ -60,8 +60,6 @@ public interface QuotaResponseBuilder {
6060

6161
QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate);
6262

63-
List<QuotaUsageJoinVO> getQuotaUsage(QuotaStatementCmd cmd);
64-
6563
List<QuotaBalanceVO> getQuotaBalance(QuotaBalanceCmd cmd);
6664

6765
QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy, Boolean enforce);

plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -371,42 +371,69 @@ public int compare(QuotaBalanceVO o1, QuotaBalanceVO o2) {
371371
}
372372

373373
@Override
374-
public QuotaStatementResponse createQuotaStatementResponse(final List<QuotaUsageJoinVO> quotaUsages, QuotaStatementCmd cmd) {
374+
public QuotaStatementResponse createQuotaStatementResponse(QuotaStatementCmd cmd) {
375+
Long accountId = getAccountIdForQuotaStatement(cmd);
376+
long domainId = getDomainIdForQuotaStatement(cmd);
377+
List<QuotaUsageJoinVO> quotaUsages = _quotaService.getQuotaUsage(accountId, null, domainId, cmd.getUsageType(), cmd.getStartDate(), cmd.getEndDate());
378+
379+
logger.debug("Creating quota statement from [{}] usage records for parameters [{}].", quotaUsages.size(),
380+
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(cmd, "accountName", "accountId", "projectId", "domainId", "startDate", "endDate", "usageType", "showResources"));
381+
375382
if (CollectionUtils.isEmpty(quotaUsages)) {
376-
throw new InvalidParameterValueException(String.format("There is no usage data for parameters [%s].", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(cmd,
377-
"accountName", "accountId", "domainId", "startDate", "endDate", "type", "showDetails")));
383+
throw new InvalidParameterValueException("There is no usage data for the provided parameters.");
378384
}
379-
logger.debug("Creating quota statement from [{}] usage records for parameters [{}].", quotaUsages.size(),
380-
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(cmd, "accountName", "accountId", "domainId", "startDate", "endDate", "type", "showDetails"));
381385

382386
createDummyRecordForEachQuotaTypeIfUsageTypeIsNotInformed(quotaUsages, cmd.getUsageType());
383387

384-
Map<Integer, List<QuotaUsageJoinVO>> recordsPerUsageTypes = quotaUsages
385-
.stream()
388+
Map<Integer, List<QuotaUsageJoinVO>> recordsPerUsageTypes = quotaUsages.stream()
386389
.sorted(Comparator.comparingInt(QuotaUsageJoinVO::getUsageType))
387390
.collect(Collectors.groupingBy(QuotaUsageJoinVO::getUsageType));
388391

389392
List<QuotaStatementItemResponse> items = new ArrayList<>();
390-
391393
recordsPerUsageTypes.forEach((key, value) -> items.add(createStatementItem(key, value, cmd.isShowResources())));
392394

393395
QuotaStatementResponse statement = new QuotaStatementResponse();
394-
395396
statement.setLineItem(items);
396397
statement.setTotalQuota(items.stream().map(QuotaStatementItemResponse::getQuotaUsed).reduce(BigDecimal.ZERO, BigDecimal::add));
397398
statement.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
398399
statement.setObjectName("statement");
399400

400-
AccountVO account = _accountDao.findAccountByNameAndDomainIncludingRemoved(cmd.getAccountName(), cmd.getDomainId());
401-
DomainVO domain = domainDao.findByIdIncludingRemoved(cmd.getDomainId());
402-
403-
statement.setAccountId(account.getUuid());
404-
statement.setAccountName(account.getAccountName());
401+
if (accountId != null) {
402+
Account account = _accountDao.findAccountIncludingRemoved(cmd.getAccountName(), cmd.getDomainId());
403+
statement.setAccountId(account.getUuid());
404+
statement.setAccountName(account.getAccountName());
405+
}
406+
DomainVO domain = domainDao.findByIdIncludingRemoved(domainId);
405407
statement.setDomainId(domain.getUuid());
406408

407409
return statement;
408410
}
409411

412+
protected Long getAccountIdForQuotaStatement(QuotaStatementCmd cmd) { // TODO: tests pra esse e pro debaixo
413+
long accountId = cmd.getEntityOwnerId();
414+
if (accountId != -1) {
415+
return accountId;
416+
}
417+
418+
if (Account.Type.NORMAL.equals(CallContext.current().getCallingAccount().getType())) {
419+
logger.debug("Limiting the Quota statement for the calling Cccount, as they are a User Account.");
420+
return CallContext.current().getCallingAccountId();
421+
}
422+
423+
logger.debug("Allowing admin/domain admin to generate the Quota statement for the provided Domain.");
424+
return null;
425+
}
426+
427+
protected long getDomainIdForQuotaStatement(QuotaStatementCmd cmd) {
428+
long domainId = cmd.getDomainId();
429+
if (domainId != -1) {
430+
return domainId;
431+
}
432+
433+
logger.debug("Limiting the Quota statement for the calling Account's Domain.");
434+
return CallContext.current().getCallingAccount().getDomainId();
435+
}
436+
410437
protected void createDummyRecordForEachQuotaTypeIfUsageTypeIsNotInformed(List<QuotaUsageJoinVO> quotaUsages, Integer usageType) {
411438
if (usageType != null) {
412439
logger.debug("As the usage type [{}] was informed as parameter of the API quotaStatement, we will not create dummy records.", usageType);
@@ -427,7 +454,6 @@ protected QuotaStatementItemResponse createStatementItem(int usageType, List<Quo
427454
QuotaUsageJoinVO firstRecord = usageRecords.get(0);
428455
int type = firstRecord.getUsageType();
429456

430-
431457
QuotaTypes quotaType = QuotaTypes.listQuotaTypes().get(type);
432458

433459
QuotaStatementItemResponse item = new QuotaStatementItemResponse(type);
@@ -473,7 +499,6 @@ protected void setStatementItemResources(QuotaStatementItemResponse statementIte
473499
statementItem.setResources(itemDetails);
474500
}
475501

476-
477502
protected Long getResourceIdByUsageType(QuotaUsageJoinVO quotaUsageJoinVo, int usageType) {
478503
switch (usageType) {
479504
case QuotaTypes.NETWORK_BYTES_SENT:
@@ -790,11 +815,6 @@ public QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO>
790815
return resp;
791816
}
792817

793-
@Override
794-
public List<QuotaUsageJoinVO> getQuotaUsage(QuotaStatementCmd cmd) {
795-
return _quotaService.getQuotaUsage(cmd.getAccountId(), cmd.getAccountName(), cmd.getDomainId(), cmd.getUsageType(), cmd.getStartDate(), cmd.getEndDate());
796-
}
797-
798818
@Override
799819
public List<QuotaBalanceVO> getQuotaBalance(QuotaBalanceCmd cmd) {
800820
return _quotaService.findQuotaBalanceVO(cmd.getAccountId(), cmd.getAccountName(), cmd.getDomainId(), cmd.getStartDate(), cmd.getEndDate());

plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaStatementItemResourceResponse.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@
2727

2828
public class QuotaStatementItemResourceResponse extends BaseResponse {
2929

30-
@SerializedName("quotaconsumed")
30+
@SerializedName(ApiConstants.QUOTA_CONSUMED)
3131
@Param(description = "Quota consumed.")
3232
private BigDecimal quotaUsed;
3333

3434
@SerializedName(ApiConstants.RESOURCE_ID)
35-
@Param(description = "Resources's id.")
35+
@Param(description = "Resources's ID.")
3636
private String resourceId;
3737

3838
@SerializedName(ApiConstants.DISPLAY_NAME)
3939
@Param(description = "Resource's display name.")
4040
private String displayName;
4141

4242
@SerializedName(ApiConstants.REMOVED)
43-
@Param(description = "Indicates if the resource is removed or active.")
43+
@Param(description = "Indicates whether the resource is removed or active.")
4444
private boolean removed;
4545

4646
public void setQuotaUsed(BigDecimal quotaUsed) {

plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaStatementItemResponse.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,20 @@
2828

2929
public class QuotaStatementItemResponse extends BaseResponse {
3030

31-
@SerializedName("type")
32-
@Param(description = "usage type")
31+
@SerializedName(ApiConstants.TYPE)
32+
@Param(description = "Usage type.")
3333
private int usageType;
3434

35-
@SerializedName("name")
36-
@Param(description = "usage type name")
35+
@SerializedName(ApiConstants.NAME)
36+
@Param(description = "Name of the Usage type.")
3737
private String usageName;
3838

39-
@SerializedName("unit")
40-
@Param(description = "usage unit")
39+
@SerializedName(ApiConstants.UNIT)
40+
@Param(description = "Unit of the Usage type.")
4141
private String usageUnit;
4242

43-
@SerializedName("quota")
44-
@Param(description = "quota consumed")
43+
@SerializedName(ApiConstants.QUOTA)
44+
@Param(description = "Quota consumed.")
4545
private BigDecimal quotaUsed;
4646

4747
@SerializedName(ApiConstants.RESOURCES)

0 commit comments

Comments
 (0)