CLOUDSTACK-9174: A deleted account results in NPE

When an account is deleted from cloudstack for which quota is still
being calculated and if the quota reaches minimum threshold then
quota service will try to alert the user. This results in NPE and is
fixed by excluding such accounts from alerting and other quota related
mechanisms.

Quota service: Fix check for admin account
This commit is contained in:
Abhinandan Prateek 2015-12-17 10:32:33 +05:30
parent 94a14485f7
commit 983dee7f20
6 changed files with 21 additions and 20 deletions

View File

@ -153,6 +153,7 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
BigDecimal thresholdBalance = quotaAccount.getQuotaMinBalance(); BigDecimal thresholdBalance = quotaAccount.getQuotaMinBalance();
if (accountBalance != null) { if (accountBalance != null) {
AccountVO account = _accountDao.findById(quotaAccount.getId()); AccountVO account = _accountDao.findById(quotaAccount.getId());
if (account == null) continue; // the account is removed
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug("checkAndSendQuotaAlertEmails: Check id=" + account.getId() + " bal=" + accountBalance + ", alertDate=" + alertDate + ", lockable=" + lockable); s_logger.debug("checkAndSendQuotaAlertEmails: Check id=" + account.getId() + " bal=" + accountBalance + ", alertDate=" + alertDate + ", lockable=" + lockable);
} }

View File

@ -358,10 +358,11 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
BigDecimal rawusage; BigDecimal rawusage;
// get service offering details // get service offering details
ServiceOfferingVO serviceoffering = _serviceOfferingDao.findServiceOffering(usageRecord.getVmInstanceId(), usageRecord.getOfferingId()); ServiceOfferingVO serviceoffering = _serviceOfferingDao.findServiceOffering(usageRecord.getVmInstanceId(), usageRecord.getOfferingId());
if (serviceoffering == null) return quotalist;
rawusage = new BigDecimal(usageRecord.getRawUsage()); rawusage = new BigDecimal(usageRecord.getRawUsage());
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_NUMBER, usageRecord.getEndDate()); QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_NUMBER, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) { if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getCpu() != null) {
BigDecimal cpu = new BigDecimal(serviceoffering.getCpu()); BigDecimal cpu = new BigDecimal(serviceoffering.getCpu());
onehourcostpercpu = tariff.getCurrencyValue().multiply(aggregationRatio); onehourcostpercpu = tariff.getCurrencyValue().multiply(aggregationRatio);
cpuquotausgage = rawusage.multiply(onehourcostpercpu).multiply(cpu); cpuquotausgage = rawusage.multiply(onehourcostpercpu).multiply(cpu);
@ -371,7 +372,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
quotalist.add(quota_usage); quotalist.add(quota_usage);
} }
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_CLOCK_RATE, usageRecord.getEndDate()); tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_CLOCK_RATE, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) { if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getSpeed() != null) {
BigDecimal speed = new BigDecimal(serviceoffering.getSpeed() / 100.00); BigDecimal speed = new BigDecimal(serviceoffering.getSpeed() / 100.00);
onehourcostper100mhz = tariff.getCurrencyValue().multiply(aggregationRatio); onehourcostper100mhz = tariff.getCurrencyValue().multiply(aggregationRatio);
speedquotausage = rawusage.multiply(onehourcostper100mhz).multiply(speed); speedquotausage = rawusage.multiply(onehourcostper100mhz).multiply(speed);
@ -381,7 +382,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
quotalist.add(quota_usage); quotalist.add(quota_usage);
} }
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.MEMORY, usageRecord.getEndDate()); tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.MEMORY, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) { if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getRamSize() != null) {
BigDecimal memory = new BigDecimal(serviceoffering.getRamSize()); BigDecimal memory = new BigDecimal(serviceoffering.getRamSize());
onehourcostper1mb = tariff.getCurrencyValue().multiply(aggregationRatio); onehourcostper1mb = tariff.getCurrencyValue().multiply(aggregationRatio);
memoryquotausage = rawusage.multiply(onehourcostper1mb).multiply(memory); memoryquotausage = rawusage.multiply(onehourcostper1mb).multiply(memory);

View File

@ -122,15 +122,17 @@ public class QuotaStatementImpl extends ManagerBase implements QuotaStatement {
Date lastStatementDate = quotaAccount.getLastStatementDate(); Date lastStatementDate = quotaAccount.getLastStatementDate();
if (interval != null) { if (interval != null) {
AccountVO account = _accountDao.findById(quotaAccount.getId()); AccountVO account = _accountDao.findById(quotaAccount.getId());
if (lastStatementDate == null || getDifferenceDays(lastStatementDate, new Date()) >= s_LAST_STATEMENT_SENT_DAYS + 1) { if (account != null) {
BigDecimal quotaUsage = _quotaUsage.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, interval[0].getTime(), interval[1].getTime()); if (lastStatementDate == null || getDifferenceDays(lastStatementDate, new Date()) >= s_LAST_STATEMENT_SENT_DAYS + 1) {
s_logger.info("For account=" + quotaAccount.getId() + ", quota used = " + quotaUsage); BigDecimal quotaUsage = _quotaUsage.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, interval[0].getTime(), interval[1].getTime());
// send statement s_logger.info("For account=" + quotaAccount.getId() + ", quota used = " + quotaUsage);
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, quotaUsage, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT)); // send statement
} else { deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, quotaUsage, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT));
if (s_logger.isDebugEnabled()) { } else {
s_logger.debug("For " + quotaAccount.getId() + " the statement has been sent recently"); if (s_logger.isDebugEnabled()) {
s_logger.debug("For " + quotaAccount.getId() + " the statement has been sent recently");
}
} }
} }
} else if (lastStatementDate != null) { } else if (lastStatementDate != null) {

View File

@ -59,7 +59,7 @@ public class QuotaSummaryCmd extends BaseListCmd {
public void execute() { public void execute() {
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
List<QuotaSummaryResponse> responses; List<QuotaSummaryResponse> responses;
if (caller.getAccountId() <= 2) { //non root admin or system if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { //admin account
if (getAccountName() != null && getDomainId() != null) if (getAccountName() != null && getDomainId() != null)
responses = _responseBuilder.createQuotaSummaryResponse(caller.getAccountName(), caller.getDomainId()); responses = _responseBuilder.createQuotaSummaryResponse(caller.getAccountName(), caller.getDomainId());
else else

View File

@ -138,6 +138,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
} else { } else {
for (final QuotaAccountVO quotaAccount : _quotaAccountDao.listAllQuotaAccount()) { for (final QuotaAccountVO quotaAccount : _quotaAccountDao.listAllQuotaAccount()) {
AccountVO account = _accountDao.findById(quotaAccount.getId()); AccountVO account = _accountDao.findById(quotaAccount.getId());
if (account == null) continue;
QuotaSummaryResponse qr = getQuotaSummaryResponse(account); QuotaSummaryResponse qr = getQuotaSummaryResponse(account);
result.add(qr); result.add(qr);
} }
@ -167,7 +168,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
qr.setObjectName("summary"); qr.setObjectName("summary");
return qr; return qr;
} else { } else {
throw new InvalidParameterValueException("Quota summary response for an account requires a valid account."); return new QuotaSummaryResponse();
} }
} }
@ -396,6 +397,9 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
QuotaCreditsVO result = _quotaCreditsDao.saveCredits(credits); QuotaCreditsVO result = _quotaCreditsDao.saveCredits(credits);
final AccountVO account = _accountDao.findById(accountId); final AccountVO account = _accountDao.findById(accountId);
if (account == null) {
throw new InvalidParameterValueException("Account does not exist with account id " + accountId);
}
final boolean lockAccountEnforcement = "true".equalsIgnoreCase(QuotaConfig.QuotaEnableEnforcement.value()); final boolean lockAccountEnforcement = "true".equalsIgnoreCase(QuotaConfig.QuotaEnableEnforcement.value());
final BigDecimal currentAccountBalance = _quotaBalanceDao.lastQuotaBalance(accountId, domainId, startOfNextDay(new Date(despositedOn.getTime()))); final BigDecimal currentAccountBalance = _quotaBalanceDao.lastQuotaBalance(accountId, domainId, startOfNextDay(new Date(despositedOn.getTime())));
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {

View File

@ -329,13 +329,6 @@
}); });
}, },
detailView: { detailView: {
viewAll: [{
path: 'quota.quotastatement',
label: 'label.quota.statement.quota'
},{
path: 'quota.balancestatement',
label: 'label.quota.statement.balance'
}],
actions: { actions: {
add: { add: {
label: 'label.quota.add.credits', label: 'label.quota.add.credits',