CLOUDSTACK-8592: calculating balance, adjusting credits and API commands for getting quota statement and balances

This commit is contained in:
Abhinandan Prateek 2015-07-16 17:31:14 +05:30
parent 7c10013bd7
commit a2143e3f98
17 changed files with 457 additions and 149 deletions

View File

@ -789,6 +789,7 @@ quotaTariffUpdate=7
quotaRefresh=15
quotaCredits=15
quotaStatement=15
quotaBalance=15
quotaEmailTemplateUpdate=15
quotaEmailTemplateDelete=15
quotaEmailTemplateAdd=15

View File

@ -0,0 +1,135 @@
//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.api.command;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.QuotaBalanceResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.quota.QuotaBalanceVO;
import org.apache.cloudstack.quota.QuotaDBUtils;
import org.apache.cloudstack.quota.QuotaManager;
import org.apache.cloudstack.api.response.QuotaStatementItemResponse;
import com.cloud.user.Account;
@APICommand(name = "quotaBalance", responseObject = QuotaStatementItemResponse.class, description = "Create a quota balance statement", since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class QuotaBalanceCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(QuotaBalanceCmd.class.getName());
private static final String s_name = "quotabalanceresponse";
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "Optional, Account Id for which statement needs to be generated")
private String accountName;
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.")
private Long domainId;
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = true, description = "End date range for quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.")
private Date endDate;
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = true, description = "Start date range quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.")
private Date startDate;
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "List usage records for the specified account")
private Long accountId;
@Inject
QuotaManager _quotaManager;
@Inject
QuotaDBUtils _quotaDBUtils;
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Long getDomainId() {
return domainId;
}
public void setDomainId(Long domainId) {
this.domainId = domainId;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public QuotaBalanceCmd() {
super();
}
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
Long accountId = _accountService.finalyzeAccountId(accountName, domainId, null, true);
if (accountId == null) {
return CallContext.current().getCallingAccount().getId();
}
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public void execute() {
List<QuotaBalanceVO> quotaUsage = _quotaManager.getQuotaBalance(this);
QuotaBalanceResponse response = _quotaDBUtils.createQuotaBalanceResponse(quotaUsage);
response.setResponseName(getCommandName());
setResponseObject(response);
}
}

View File

@ -36,7 +36,6 @@ import org.apache.cloudstack.quota.QuotaUsageVO;
import org.apache.cloudstack.api.response.QuotaStatementItemResponse;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
@APICommand(name = "quotaStatement", responseObject = QuotaStatementItemResponse.class, description = "Create a quota statement", since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class QuotaStatementCmd extends BaseCmd {
@ -136,9 +135,9 @@ public class QuotaStatementCmd extends BaseCmd {
@Override
public void execute() {
Pair<List<QuotaUsageVO>, Integer> result = _quotaManager.getQuotaUsage(this);
List<QuotaUsageVO> quotaUsage = _quotaManager.getQuotaUsage(this);
QuotaStatementResponse response = _quotaDBUtils.createQuotaStatementResponse(result.first());
QuotaStatementResponse response = _quotaDBUtils.createQuotaStatementResponse(quotaUsage);
response.setResponseName(getCommandName());
setResponseObject(response);

View File

@ -17,15 +17,18 @@
package org.apache.cloudstack.api.response;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.quota.QuotaBalanceVO;
import com.cloud.serializer.Param;
public class QuotaStatementBalanceResponse extends BaseResponse {
public class QuotaBalanceResponse extends BaseResponse {
@SerializedName("accountid")
@Param(description = "account id")
@ -39,13 +42,17 @@ public class QuotaStatementBalanceResponse extends BaseResponse {
@Param(description = "domain id")
private Long domainId;
@SerializedName("usedquota")
@Param(description = "quota consumed")
private BigDecimal quotaUsed;
@SerializedName("startquota")
@Param(description = "quota started with")
private BigDecimal startQuota;
@SerializedName("quotabalance")
@Param(description = "remaining quota")
private BigDecimal quotaBalance;
@SerializedName("endquota")
@Param(description = "quota by end of this period")
private BigDecimal endQuota;
@SerializedName("credits")
@Param(description = "list of credits made during this period")
private List<QuotaCreditsResponse> credits = null;
@SerializedName("startdate")
@Param(description = "start date")
@ -55,8 +62,9 @@ public class QuotaStatementBalanceResponse extends BaseResponse {
@Param(description = "end date")
private Date endDate = null;
public QuotaStatementBalanceResponse() {
public QuotaBalanceResponse() {
super();
credits = new ArrayList<QuotaCreditsResponse>();
}
public Long getAccountId() {
@ -83,20 +91,35 @@ public class QuotaStatementBalanceResponse extends BaseResponse {
this.domainId = domainId;
}
public BigDecimal getQuotaUsed() {
return quotaUsed;
public BigDecimal getStartQuota() {
return startQuota;
}
public void setQuotaUsed(BigDecimal quotaUsed) {
this.quotaUsed = quotaUsed;
public void setStartQuota(BigDecimal startQuota) {
this.startQuota = startQuota;
}
public BigDecimal getQuotaBalance() {
return quotaBalance;
public BigDecimal getEndQuota() {
return endQuota;
}
public void setQuotaBalance(BigDecimal quotaBalance) {
this.quotaBalance = quotaBalance;
public void setEndQuota(BigDecimal endQuota) {
this.endQuota = endQuota;
}
public List<QuotaCreditsResponse> getCredits() {
return credits;
}
public void setCredits(List<QuotaCreditsResponse> credits) {
this.credits = credits;
}
public void addCredits(QuotaBalanceVO credit) {
QuotaCreditsResponse cr = new QuotaCreditsResponse();
cr.setCredits(credit.getCreditBalance());
cr.setUpdatedOn(credit.getUpdatedOn());
credits.add(cr);
}
public Date getStartDate() {
@ -115,5 +138,4 @@ public class QuotaStatementBalanceResponse extends BaseResponse {
this.endDate = endDate;
}
}

View File

@ -24,7 +24,7 @@ import org.apache.cloudstack.quota.QuotaCreditsVO;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.Date;
public class QuotaCreditsResponse extends BaseResponse {
@ -38,7 +38,7 @@ public class QuotaCreditsResponse extends BaseResponse {
@SerializedName("updated_on")
@Param(description = "the account name of the admin who updated the credits")
private Timestamp updatedOn;
private Date updatedOn;
public QuotaCreditsResponse() {
super();
@ -49,7 +49,7 @@ public class QuotaCreditsResponse extends BaseResponse {
if (result != null) {
this.credits = result.getCredit().setScale(2, RoundingMode.HALF_EVEN);
this.updatedBy = updatedBy;
this.updatedOn = new Timestamp(System.currentTimeMillis());
this.updatedOn = new Date();
}
}
@ -69,11 +69,11 @@ public class QuotaCreditsResponse extends BaseResponse {
this.updatedBy = updatedBy;
}
public Timestamp getUpdatedOn() {
public Date getUpdatedOn() {
return updatedOn;
}
public void setUpdatedOn(Timestamp updatedOn) {
public void setUpdatedOn(Date updatedOn) {
this.updatedOn = updatedOn;
}

View File

@ -16,6 +16,7 @@
//under the License.
package org.apache.cloudstack.api.response;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@ -42,6 +43,10 @@ public class QuotaStatementResponse extends BaseResponse {
@Param(description = "list of quota usage under variosu types", responseObject = QuotaStatementItemResponse.class)
private List<QuotaStatementItemResponse> lineItem;
@SerializedName("totalquota")
@Param(description = "total quota used during this period")
private BigDecimal totalQuota;
@SerializedName("startdate")
@Param(description = "start date")
private Date startDate = null;
@ -50,10 +55,6 @@ public class QuotaStatementResponse extends BaseResponse {
@Param(description = "end date")
private Date endDate = null;
@SerializedName("balance")
@Param(description = "The balance of quota reamining", responseObject = QuotaStatementBalanceResponse.class)
private QuotaStatementBalanceResponse balance;
public QuotaStatementResponse() {
super();
}
@ -106,12 +107,12 @@ public class QuotaStatementResponse extends BaseResponse {
this.endDate = endDate;
}
public QuotaStatementBalanceResponse getBalance() {
return balance;
public BigDecimal getTotalQuota() {
return totalQuota;
}
public void setBalance(QuotaStatementBalanceResponse balance) {
this.balance = balance;
public void setTotalQuota(BigDecimal totalQuota) {
this.totalQuota = totalQuota;
}
}

View File

@ -79,6 +79,7 @@ public class QuotaBalanceVO implements InternalIdentity {
this.accountId = accountId;
this.domainId = domainId;
this.creditBalance = creditBalance;
this.creditsId=0L;
this.updatedOn = updatedOn;
this.previousUpdateId = previousUpdateId;
this.previousUpdateOn = previousUpdateOn;

View File

@ -22,6 +22,7 @@ import com.cloud.service.ServiceOfferingVO;
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
import org.apache.cloudstack.api.response.QuotaBalanceResponse;
import org.apache.cloudstack.api.response.QuotaCreditsResponse;
import org.apache.cloudstack.api.response.QuotaStatementResponse;
import org.apache.cloudstack.api.response.QuotaTariffResponse;
@ -38,6 +39,8 @@ public interface QuotaDBUtils {
QuotaStatementResponse createQuotaStatementResponse(List<QuotaUsageVO> quotaUsage);
QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaUsage);
Pair<List<? extends UsageVO>, Integer> getUsageRecords(long accountId, long domainId);
ServiceOfferingVO findServiceOffering(Long vmId, long serviceOfferingId);

View File

@ -27,15 +27,15 @@ import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
import org.apache.cloudstack.api.response.QuotaTariffResponse;
import org.apache.cloudstack.api.response.QuotaCreditsResponse;
import org.apache.cloudstack.api.response.QuotaStatementBalanceResponse;
import org.apache.cloudstack.api.response.QuotaBalanceResponse;
import org.apache.cloudstack.api.response.QuotaStatementItemResponse;
import org.apache.cloudstack.api.response.QuotaStatementResponse;
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
import org.apache.cloudstack.quota.dao.QuotaCreditsDao;
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
import org.apache.log4j.Logger;
@ -50,6 +50,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@Component
@ -63,8 +64,6 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils {
@Inject
private QuotaCreditsDao _quotaCreditsDao;
@Inject
private QuotaBalanceDao _quotaBalanceDao;
@Inject
private ServiceOfferingDao _serviceOfferingDao;
@Inject
private UserDao _userDao;
@ -86,6 +85,38 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils {
return response;
}
@Override
public QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaBalance) {
Collections.sort(quotaBalance, new Comparator<QuotaBalanceVO>() {
public int compare(QuotaBalanceVO o1, QuotaBalanceVO o2) {
return o1.getUpdatedOn().compareTo(o2.getUpdatedOn());
}
});
QuotaBalanceResponse resp = new QuotaBalanceResponse();
for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) {
QuotaBalanceVO entry = it.next();
if (entry.getCreditsId() > 0) {
resp.addCredits(entry);
it.remove();
}
}
if (quotaBalance.size() > 0) {
QuotaBalanceVO startItem = quotaBalance.get(0);
QuotaBalanceVO endItem = quotaBalance.get(quotaBalance.size() - 1);
resp.setStartDate(startItem.getUpdatedOn());
resp.setStartQuota(startItem.getCreditBalance());
resp.setEndDate(endItem.getUpdatedOn());
resp.setEndQuota(endItem.getCreditBalance());
} else {
new CloudRuntimeException("The request period is small and does not contain balance entries to provide any meaningful values.");
}
resp.setObjectName("balance");
return resp;
}
@Override
public QuotaStatementResponse createQuotaStatementResponse(List<QuotaUsageVO> quotaUsage) {
QuotaStatementResponse statement = new QuotaStatementResponse();
@ -109,7 +140,7 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils {
int type = -1;
BigDecimal usage = new BigDecimal(0);
BigDecimal totalUsage = new BigDecimal(0);
quotaUsage.add(new QuotaUsageVO());// boundry
quotaUsage.add(new QuotaUsageVO());// boundary
QuotaUsageVO prev = quotaUsage.get(0);
for (final QuotaUsageVO quotaRecord : quotaUsage) {
if (type != quotaRecord.getUsageType()) {
@ -135,12 +166,8 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils {
}
statement.setLineItem(items);
// calculate total quota used and balance
QuotaStatementBalanceResponse balance = new QuotaStatementBalanceResponse();
balance.setObjectName("balance");
balance.setQuotaUsed(totalUsage);
statement.setBalance(balance);
statement.setTotalQuota(totalUsage);
statement.setObjectName("statement");
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
return statement;
}

View File

@ -16,8 +16,9 @@
//under the License.
package org.apache.cloudstack.quota;
import com.cloud.utils.Pair;
import com.cloud.utils.component.PluggableService;
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
import org.apache.cloudstack.api.command.QuotaStatementCmd;
import java.util.List;
@ -26,6 +27,8 @@ public interface QuotaManager extends PluggableService {
public boolean calculateQuotaUsage();
public Pair<List<QuotaUsageVO>,Integer> getQuotaUsage(QuotaStatementCmd cmd);
public List<QuotaUsageVO> getQuotaUsage(QuotaStatementCmd cmd);
List<QuotaBalanceVO> getQuotaBalance(QuotaBalanceCmd cmd);
}

View File

@ -24,15 +24,15 @@ import com.cloud.service.ServiceOfferingVO;
import com.cloud.usage.UsageVO;
import com.cloud.usage.dao.UsageDao;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
import org.apache.cloudstack.api.command.QuotaCreditsCmd;
import org.apache.cloudstack.api.command.QuotaEmailTemplateAddCmd;
import org.apache.cloudstack.api.command.QuotaRefreshCmd;
@ -44,6 +44,7 @@ import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
import org.apache.cloudstack.utils.usage.UsageUtils;
import org.apache.log4j.Logger;
@ -52,6 +53,7 @@ import org.springframework.stereotype.Component;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
@ -80,9 +82,9 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi
@Inject
private ConfigurationDao _configDao;
@Inject
private AccountService _accountService;
@Inject
private QuotaDBUtils _quotaDBUtils;
@Inject
private QuotaBalanceDao _quotaBalanceDao;
private TimeZone _usageTimezone;
private int _aggregationDuration = 0;
@ -123,6 +125,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi
cmdList.add(QuotaEmailTemplateAddCmd.class);
cmdList.add(QuotaRefreshCmd.class);
cmdList.add(QuotaStatementCmd.class);
cmdList.add(QuotaBalanceCmd.class);
return cmdList;
}
@ -202,10 +205,10 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi
quotalistforaccount.add(updateQuotaRaw(usageRecord, quotaTariffMap, aggregationRatio, QuotaTypes.VPN_USERS));
break;
case QuotaTypes.NETWORK_BYTES_RECEIVED:
quotalistforaccount.add(updateQuotaRaw(usageRecord, quotaTariffMap, aggregationRatio, QuotaTypes.NETWORK_BYTES_RECEIVED));
quotalistforaccount.add(updateQuotaNetwork(usageRecord, quotaTariffMap, QuotaTypes.NETWORK_BYTES_RECEIVED));
break;
case QuotaTypes.NETWORK_BYTES_SENT:
quotalistforaccount.add(updateQuotaRaw(usageRecord, quotaTariffMap, aggregationRatio, QuotaTypes.NETWORK_BYTES_SENT));
quotalistforaccount.add(updateQuotaNetwork(usageRecord, quotaTariffMap, QuotaTypes.NETWORK_BYTES_SENT));
break;
case QuotaTypes.VM_DISK_IO_READ:
case QuotaTypes.VM_DISK_IO_WRITE:
@ -218,19 +221,33 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi
} while ((usageRecords != null) && !usageRecords.first().isEmpty());
// list of quotas for this account
s_logger.info("Quota entries size = " + quotalistforaccount.size());
Date startDate = new Date();
Date endDate = new Date();
int count = 0;
quotalistforaccount.add(new QuotaUsageVO());
Date startDate = new Date(0);
Date endDate = new Date(0);
BigDecimal aggrUsage = new BigDecimal(0);
for (QuotaUsageVO entry : quotalistforaccount) {
if (startDate.compareTo(entry.getStartDate()) != 0) {
startDate = entry.getStartDate();
endDate = entry.getEndDate();
s_logger.info("Start Date=" + startDate.toString() + " to endDate=" + endDate.toString() + "record count=" + count);
aggrUsage = aggrUsage.add(entry.getQuotaUsed());
count = 0;
QuotaBalanceVO lastrealbalanceentry = _quotaBalanceDao.getLastBalanceEntry(account.getAccountId(), account.getDomainId(), startDate);
Date lastbalancedate;
if (lastrealbalanceentry != null) {
lastbalancedate = lastrealbalanceentry.getUpdatedOn();
aggrUsage = aggrUsage.add(lastrealbalanceentry.getCreditBalance());
} else {
lastbalancedate = new Date(0);
}
List<QuotaBalanceVO> creditsrcvd = _quotaBalanceDao.getCreditBalance(account.getAccountId(), account.getDomainId(), lastbalancedate, endDate);
for (QuotaBalanceVO credit : creditsrcvd) {
aggrUsage = aggrUsage.add(credit.getCreditBalance());
}
QuotaBalanceVO newbalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, endDate, null, null);
_quotaBalanceDao.persist(newbalance);
aggrUsage = new BigDecimal(0);
}
count++;
startDate = entry.getStartDate();
endDate = entry.getEndDate();
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
}
} // END ACCOUNT
jobResult = true;
@ -243,9 +260,47 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi
return jobResult;
}
@SuppressWarnings("deprecation")
@Override
public Pair<List<QuotaUsageVO>, Integer> getQuotaUsage(QuotaStatementCmd cmd) {
public List<QuotaBalanceVO> getQuotaBalance(QuotaBalanceCmd cmd) {
Long accountId = cmd.getAccountId();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
Account userAccount = null;
Account caller = CallContext.current().getCallingAccount();
// if accountId is not specified, use accountName and domainId
if ((accountId == null) && (accountName != null) && (domainId != null)) {
if (_domainDao.isChildDomain(caller.getDomainId(), domainId)) {
Filter filter = new Filter(AccountVO.class, "id", Boolean.FALSE, null, null);
List<AccountVO> accounts = _accountDao.listAccounts(accountName, domainId, filter);
if (accounts.size() > 0) {
userAccount = accounts.get(0);
}
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
} else {
throw new PermissionDeniedException("Invalid Domain Id or Account");
}
}
Date startDate = cmd.getStartDate();
Date endDate = cmd.getEndDate();
if (startDate.after(endDate)) {
throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate);
}
TimeZone usageTZ = getUsageTimezone();
Date adjustedStartDate = computeAdjustedTime(startDate, usageTZ);
Date adjustedEndDate = computeAdjustedTime(endDate, usageTZ);
s_logger.debug("getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and " + adjustedEndDate);
return _quotaBalanceDao.getQuotaBalance(accountId, domainId, adjustedStartDate, adjustedEndDate);
}
@Override
public List<QuotaUsageVO> getQuotaUsage(QuotaStatementCmd cmd) {
Long accountId = cmd.getAccountId();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
@ -271,26 +326,6 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi
}
}
boolean isAdmin = false;
boolean isDomainAdmin = false;
// If accountId couldn't be found using accountName and domainId, get it
// from userContext
if (accountId == null) {
accountId = caller.getId();
// List records for all the accounts if the caller account is of
// type admin.
// If account_id or account_name is explicitly mentioned, list
// records for the specified account only even if the caller is of
// type admin
if (_accountService.isRootAdmin(caller.getId())) {
isAdmin = true;
} else if (_accountService.isDomainAdmin(caller.getId())) {
isDomainAdmin = true;
}
s_logger.debug("Account details not available. Using userContext accountId: " + accountId);
}
Date startDate = cmd.getStartDate();
Date endDate = cmd.getEndDate();
if (startDate.after(endDate)) {
@ -301,52 +336,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi
Date adjustedEndDate = computeAdjustedTime(endDate, usageTZ);
s_logger.debug("getting quota records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and " + adjustedEndDate);
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
Pair<List<QuotaUsageVO>, Integer> quotaUsageRecords = null;
try {
// TODO instead of max value query with reasonable number and
// iterate
Filter usageFilter = new Filter(QuotaUsageVO.class, "id", true, 0L, Long.MAX_VALUE);
SearchCriteria<QuotaUsageVO> sc = _quotaUsageDao.createSearchCriteria();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
s_logger.debug("Account ID=" + accountId);
}
/*
* if (isDomainAdmin) { SearchCriteria<DomainVO> sdc =
* _domainDao.createSearchCriteria(); sdc.addOr("path",
* SearchCriteria.Op.LIKE,
* _domainDao.findById(caller.getDomainId()).getPath() + "%");
* List<DomainVO> domains = _domainDao.search(sdc, null); List<Long>
* domainIds = new ArrayList<Long>(); for (DomainVO domain :
* domains) domainIds.add(domain.getId()); sc.addAnd("domainId",
* SearchCriteria.Op.IN, domainIds.toArray());
* s_logger.debug("Account ID=" + accountId); }
*/
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
s_logger.debug("Domain ID=" + domainId);
}
if (usageType != null) {
sc.addAnd("usageType", SearchCriteria.Op.EQ, usageType);
s_logger.debug("usageType ID=" + usageType);
}
if ((adjustedStartDate != null) && (adjustedEndDate != null) && adjustedStartDate.before(adjustedEndDate)) {
sc.addAnd("startDate", SearchCriteria.Op.BETWEEN, adjustedStartDate, adjustedEndDate);
sc.addAnd("endDate", SearchCriteria.Op.BETWEEN, adjustedStartDate, adjustedEndDate);
s_logger.debug("start Date=" + adjustedStartDate + ", enddate=" + adjustedEndDate);
} else {
s_logger.debug("Screwed up start Date=" + adjustedStartDate + ", enddate=" + adjustedEndDate);
return new Pair<List<QuotaUsageVO>, Integer>(new ArrayList<QuotaUsageVO>(), new Integer(0));
}
quotaUsageRecords = _quotaUsageDao.searchAndCountAllRecords(sc, usageFilter);
} finally {
txn.close();
}
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
return quotaUsageRecords;
return _quotaUsageDao.getQuotaUsage(accountId, domainId, usageType, adjustedStartDate, adjustedEndDate);
}
@DB

View File

@ -67,6 +67,7 @@ public class QuotaUsageVO implements InternalIdentity {
public QuotaUsageVO() {
usageType=-1;
quotaUsed = new BigDecimal(0);
endDate = startDate = new Date();
}
public QuotaUsageVO(Long usageItemId, Long zoneId, Long accountId, Long domainId, int usageType, BigDecimal quotaUsed, Date startDate, Date endDate) {

View File

@ -16,19 +16,21 @@
//under the License.
package org.apache.cloudstack.quota.dao;
import java.util.Date;
import java.util.List;
import org.apache.cloudstack.quota.QuotaBalanceVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.SearchCriteria;
public interface QuotaBalanceDao extends GenericDao<QuotaBalanceVO, Long> {
Pair<List<QuotaBalanceVO>, Integer> searchBalance(SearchCriteria<QuotaBalanceVO> sc, Filter filter);
void saveQuotaBalance(List<QuotaBalanceVO> credits);
List<QuotaBalanceVO> getCreditBalance(long accountId, long domainId, Date startDate, Date endDate);
QuotaBalanceVO getLastBalanceEntry(long accountId, long domainId, Date beforeThis);
List<QuotaBalanceVO> getQuotaBalance(Long accountId, Long domainId, Date startDate, Date endDate);
}

View File

@ -16,6 +16,8 @@
//under the License.
package org.apache.cloudstack.quota.dao;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Local;
@ -23,25 +25,90 @@ import javax.ejb.Local;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.quota.QuotaBalanceVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
@Component
@Local(value = { QuotaBalanceDao.class })
public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> implements QuotaBalanceDao {
@SuppressWarnings("deprecation")
@Override
public Pair<List<QuotaBalanceVO>, Integer> searchBalance(SearchCriteria<QuotaBalanceVO> sc, Filter filter) {
// TODO Auto-generated method stub
return null;
public QuotaBalanceVO getLastBalanceEntry(long accountId, long domainId, Date beforeThis) {
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 1L);
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
sc.addAnd("creditsId", SearchCriteria.Op.EQ, 0);
sc.addAnd("updatedOn", SearchCriteria.Op.LT, beforeThis);
List<QuotaBalanceVO> quotab = this.search(sc, filter);
return quotab.size() > 0 ? quotab.get(0) : null;
}
@Override
public void saveQuotaBalance(List<QuotaBalanceVO> credits) {
// TODO Auto-generated method stub
for (QuotaBalanceVO credit : credits) {
persist(credit);
}
}
@SuppressWarnings("deprecation")
@Override
public List<QuotaBalanceVO> getCreditBalance(long accountId, long domainId, Date lastbalancedate, Date beforeThis) {
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, Long.MAX_VALUE);
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
sc.addAnd("creditsId", SearchCriteria.Op.GT, 0);
if ((lastbalancedate != null) && (beforeThis != null) && lastbalancedate.before(beforeThis)) {
sc.addAnd("updatedOn", SearchCriteria.Op.BETWEEN, lastbalancedate, beforeThis);
} else {
return new ArrayList<QuotaBalanceVO>();
}
return search(sc, filter);
}
@SuppressWarnings("deprecation")
@Override
public List<QuotaBalanceVO> getQuotaBalance(Long accountId, Long domainId, Date startDate, Date endDate) {
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
List<QuotaBalanceVO> quotaUsageRecords = null;
try {
// TODO instead of max value query with reasonable number and
// iterate
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
/*
* if (isDomainAdmin) { SearchCriteria<DomainVO> sdc =
* _domainDao.createSearchCriteria(); sdc.addOr("path",
* SearchCriteria.Op.LIKE,
* _domainDao.findById(caller.getDomainId()).getPath() + "%");
* List<DomainVO> domains = _domainDao.search(sdc, null); List<Long>
* domainIds = new ArrayList<Long>(); for (DomainVO domain :
* domains) domainIds.add(domain.getId()); sc.addAnd("domainId",
* SearchCriteria.Op.IN, domainIds.toArray());
* s_logger.debug("Account ID=" + accountId); }
*/
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
sc.addAnd("updatedOn", SearchCriteria.Op.BETWEEN, startDate, endDate);
} else {
return new ArrayList<QuotaBalanceVO>();
}
quotaUsageRecords = listBy(sc);
} finally {
txn.close();
}
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
return quotaUsageRecords;
}
}

View File

@ -27,6 +27,7 @@ import org.springframework.stereotype.Component;
import org.apache.cloudstack.quota.QuotaBalanceVO;
import org.apache.cloudstack.quota.QuotaCreditsVO;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchCriteria;
@ -39,14 +40,16 @@ public class QuotaCreditsDaoImpl extends GenericDaoBase<QuotaCreditsVO, Long> im
@SuppressWarnings("deprecation")
@Override
public List<QuotaCreditsVO> getCredits(long accountId, long domainId, Date startDate, Date endDate) {
Filter filter = new Filter(QuotaCreditsVO.class, "updatedOn", true, 0L, Long.MAX_VALUE);
SearchCriteria<QuotaCreditsVO> sc = createSearchCriteria();
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
sc.addAnd("startDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
sc.addAnd("endDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
sc.addAnd("updatedOn", SearchCriteria.Op.BETWEEN, startDate, endDate);
} else {
return new ArrayList<QuotaCreditsVO>();
}
return listBy(sc);
return this.search(sc, filter);
}
@Override

View File

@ -16,6 +16,7 @@
//under the License.
package org.apache.cloudstack.quota.dao;
import java.util.Date;
import java.util.List;
import org.apache.cloudstack.quota.QuotaUsageVO;
@ -27,6 +28,8 @@ import com.cloud.utils.db.SearchCriteria;
public interface QuotaUsageDao extends GenericDao<QuotaUsageVO, Long> {
List<QuotaUsageVO> getQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate);
Pair<List<QuotaUsageVO>, Integer> searchAndCountAllRecords(SearchCriteria<QuotaUsageVO> sc, Filter filter);
void saveQuotaUsage(List<QuotaUsageVO> credits);

View File

@ -16,15 +16,20 @@
//under the License.
package org.apache.cloudstack.quota.dao;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Local;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.quota.QuotaUsageVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchCriteria;
import org.apache.cloudstack.quota.QuotaUsageVO;
import org.springframework.stereotype.Component;
import javax.ejb.Local;
import java.util.List;
import com.cloud.utils.db.TransactionLegacy;
@Component
@Local(value = { QuotaUsageDao.class })
@ -42,4 +47,49 @@ public class QuotaUsageDaoImpl extends GenericDaoBase<QuotaUsageVO, Long> implem
}
}
@SuppressWarnings("deprecation")
@Override
public List<QuotaUsageVO> getQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate) {
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
List<QuotaUsageVO> quotaUsageRecords = null;
try {
// TODO instead of max value query with reasonable number and
// iterate
SearchCriteria<QuotaUsageVO> sc = createSearchCriteria();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
/*
* if (isDomainAdmin) { SearchCriteria<DomainVO> sdc =
* _domainDao.createSearchCriteria(); sdc.addOr("path",
* SearchCriteria.Op.LIKE,
* _domainDao.findById(caller.getDomainId()).getPath() + "%");
* List<DomainVO> domains = _domainDao.search(sdc, null); List<Long>
* domainIds = new ArrayList<Long>(); for (DomainVO domain :
* domains) domainIds.add(domain.getId()); sc.addAnd("domainId",
* SearchCriteria.Op.IN, domainIds.toArray());
* s_logger.debug("Account ID=" + accountId); }
*/
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if (usageType != null) {
sc.addAnd("usageType", SearchCriteria.Op.EQ, usageType);
}
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
sc.addAnd("startDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
sc.addAnd("endDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
} else {
return new ArrayList<QuotaUsageVO>();
}
quotaUsageRecords = listBy(sc);
} finally {
txn.close();
}
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
return quotaUsageRecords;
}
}