|
34 | 34 | import org.apache.cloudstack.quota.constant.QuotaConfig; |
35 | 35 | import org.apache.cloudstack.quota.constant.QuotaConfig.QuotaEmailTemplateTypes; |
36 | 36 | import org.apache.cloudstack.quota.dao.QuotaAccountDao; |
| 37 | +import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDao; |
37 | 38 | import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao; |
38 | 39 | import org.apache.cloudstack.quota.vo.QuotaAccountVO; |
| 40 | +import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO; |
39 | 41 | import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO; |
40 | 42 | import org.apache.commons.lang.StringEscapeUtils; |
41 | 43 | import org.apache.commons.lang.text.StrSubstitutor; |
@@ -80,7 +82,10 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana |
80 | 82 | @Inject |
81 | 83 | private QuotaManager _quotaManager; |
82 | 84 |
|
83 | | - private boolean _lockAccountEnforcement = false; |
| 85 | + @Inject |
| 86 | + private QuotaEmailConfigurationDao quotaEmailConfigurationDao; |
| 87 | + |
| 88 | + protected boolean _lockAccountEnforcement = false; |
84 | 89 | private String senderAddress; |
85 | 90 | protected SMTPMailSender mailSender; |
86 | 91 |
|
@@ -139,55 +144,100 @@ public boolean stop() { |
139 | 144 | return true; |
140 | 145 | } |
141 | 146 |
|
| 147 | + /** |
| 148 | + * Returns whether a Quota email type is enabled or not for the provided account. |
| 149 | + */ |
| 150 | + @Override |
| 151 | + public boolean isQuotaEmailTypeEnabledForAccount(AccountVO account, QuotaEmailTemplateTypes quotaEmailTemplateType) { |
| 152 | + boolean quotaEmailsEnabled = QuotaConfig.QuotaEnableEmails.valueIn(account.getAccountId()); |
| 153 | + if (!quotaEmailsEnabled) { |
| 154 | + logger.debug("Configuration [{}] is disabled for account [{}]. Therefore, the account will not receive Quota email of type [{}].", QuotaConfig.QuotaEnableEmails.key(), account, quotaEmailTemplateType); |
| 155 | + return false; |
| 156 | + } |
| 157 | + |
| 158 | + QuotaEmailConfigurationVO quotaEmail = quotaEmailConfigurationDao.findByAccountIdAndEmailTemplateType(account.getAccountId(), quotaEmailTemplateType); |
| 159 | + |
| 160 | + boolean emailEnabled = quotaEmail == null || quotaEmail.isEnabled(); |
| 161 | + if (emailEnabled) { |
| 162 | + logger.debug("Quota email [{}] is enabled for account [{}].", quotaEmailTemplateType, account); |
| 163 | + } else { |
| 164 | + logger.debug("Quota email [{}] has been manually disabled for account [{}] through the API quotaConfigureEmail.", quotaEmailTemplateType, account); |
| 165 | + } |
| 166 | + return emailEnabled; |
| 167 | + } |
| 168 | + |
| 169 | + |
142 | 170 | @Override |
143 | 171 | public void checkAndSendQuotaAlertEmails() { |
144 | 172 | List<DeferredQuotaEmail> deferredQuotaEmailList = new ArrayList<DeferredQuotaEmail>(); |
145 | | - final BigDecimal zeroBalance = new BigDecimal(0); |
| 173 | + |
| 174 | + logger.info("Checking and sending quota alert emails."); |
146 | 175 | for (final QuotaAccountVO quotaAccount : _quotaAcc.listAllQuotaAccount()) { |
147 | | - if (logger.isDebugEnabled()) { |
148 | | - logger.debug("checkAndSendQuotaAlertEmails accId=" + quotaAccount.getId()); |
149 | | - } |
150 | | - BigDecimal accountBalance = quotaAccount.getQuotaBalance(); |
151 | | - Date balanceDate = quotaAccount.getQuotaBalanceDate(); |
152 | | - Date alertDate = quotaAccount.getQuotaAlertDate(); |
153 | | - int lockable = quotaAccount.getQuotaEnforce(); |
154 | | - BigDecimal thresholdBalance = quotaAccount.getQuotaMinBalance(); |
155 | | - if (accountBalance != null) { |
156 | | - AccountVO account = _accountDao.findById(quotaAccount.getId()); |
157 | | - if (account == null) { |
158 | | - continue; // the account is removed |
159 | | - } |
160 | | - logger.debug("checkAndSendQuotaAlertEmails: Check id={} bal={}, alertDate={}, lockable={}", account.getId(), |
161 | | - accountBalance, DateUtil.displayDateInTimezone(QuotaManagerImpl.getUsageAggregationTimeZone(), alertDate), |
162 | | - lockable); |
163 | | - if (accountBalance.compareTo(zeroBalance) < 0) { |
164 | | - if (_lockAccountEnforcement && (lockable == 1)) { |
165 | | - if (_quotaManager.isLockable(account)) { |
166 | | - logger.info("Locking account " + account.getAccountName() + " due to quota < 0."); |
167 | | - lockAccount(account.getId()); |
168 | | - } |
169 | | - } |
170 | | - if (alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1)) { |
171 | | - logger.info("Sending alert " + account.getAccountName() + " due to quota < 0."); |
172 | | - deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_EMPTY)); |
173 | | - } |
174 | | - } else if (accountBalance.compareTo(thresholdBalance) < 0) { |
175 | | - if (alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1)) { |
176 | | - logger.info("Sending alert " + account.getAccountName() + " due to quota below threshold."); |
177 | | - deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW)); |
178 | | - } |
179 | | - } |
180 | | - } |
| 176 | + checkQuotaAlertEmailForAccount(deferredQuotaEmailList, quotaAccount); |
181 | 177 | } |
182 | 178 |
|
183 | 179 | for (DeferredQuotaEmail emailToBeSent : deferredQuotaEmailList) { |
184 | | - if (logger.isDebugEnabled()) { |
185 | | - logger.debug("checkAndSendQuotaAlertEmails: Attempting to send quota alert email to users of account: " + emailToBeSent.getAccount().getAccountName()); |
186 | | - } |
| 180 | + logger.debug("Attempting to send a quota alert email to users of account [{}].", emailToBeSent.getAccount().getAccountName()); |
187 | 181 | sendQuotaAlert(emailToBeSent); |
188 | 182 | } |
189 | 183 | } |
190 | 184 |
|
| 185 | + /** |
| 186 | + * Checks a given quota account to see if they should receive any emails. First by checking if it has any balance at all, if its account can be found, then checks |
| 187 | + * if they should receive either QUOTA_EMPTY or QUOTA_LOW emails, taking into account if these email templates are disabled or not for that account. |
| 188 | + * */ |
| 189 | + protected void checkQuotaAlertEmailForAccount(List<DeferredQuotaEmail> deferredQuotaEmailList, QuotaAccountVO quotaAccount) { |
| 190 | + logger.debug("Checking {} for email alerts.", quotaAccount); |
| 191 | + BigDecimal accountBalance = quotaAccount.getQuotaBalance(); |
| 192 | + |
| 193 | + if (accountBalance == null) { |
| 194 | + logger.debug("{} has a null balance, therefore it will not receive quota alert emails.", quotaAccount); |
| 195 | + return; |
| 196 | + } |
| 197 | + |
| 198 | + AccountVO account = _accountDao.findById(quotaAccount.getId()); |
| 199 | + if (account == null) { |
| 200 | + logger.debug("Account of {} is removed, thus it will not receive quota alert emails.", quotaAccount); |
| 201 | + return; |
| 202 | + } |
| 203 | + |
| 204 | + checkBalanceAndAddToEmailList(deferredQuotaEmailList, quotaAccount, account, accountBalance); |
| 205 | + } |
| 206 | + |
| 207 | + private void checkBalanceAndAddToEmailList(List<DeferredQuotaEmail> deferredQuotaEmailList, QuotaAccountVO quotaAccount, AccountVO account, BigDecimal accountBalance) { |
| 208 | + Date balanceDate = quotaAccount.getQuotaBalanceDate(); |
| 209 | + Date alertDate = quotaAccount.getQuotaAlertDate(); |
| 210 | + int lockable = quotaAccount.getQuotaEnforce(); |
| 211 | + BigDecimal thresholdBalance = quotaAccount.getQuotaMinBalance(); |
| 212 | + |
| 213 | + logger.debug("Checking {} with accountBalance [{}], alertDate [{}] and lockable [{}] to see if a quota alert email should be sent.", account, |
| 214 | + accountBalance, DateUtil.displayDateInTimezone(QuotaManagerImpl.getUsageAggregationTimeZone(), alertDate), lockable); |
| 215 | + |
| 216 | + boolean shouldSendEmail = alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1); |
| 217 | + |
| 218 | + if (accountBalance.compareTo(BigDecimal.ZERO) < 0) { |
| 219 | + if (_lockAccountEnforcement && lockable == 1 && _quotaManager.isLockable(account)) { |
| 220 | + logger.info("Locking {}, as quota balance is lower than 0.", account); |
| 221 | + lockAccount(account.getId()); |
| 222 | + } |
| 223 | + |
| 224 | + boolean quotaEmptyEmailEnabled = isQuotaEmailTypeEnabledForAccount(account, QuotaEmailTemplateTypes.QUOTA_EMPTY); |
| 225 | + if (quotaEmptyEmailEnabled && shouldSendEmail) { |
| 226 | + logger.debug("Adding {} to the deferred emails list, as quota balance is lower than 0.", account); |
| 227 | + deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaEmailTemplateTypes.QUOTA_EMPTY)); |
| 228 | + return; |
| 229 | + } |
| 230 | + } else if (accountBalance.compareTo(thresholdBalance) < 0) { |
| 231 | + boolean quotaLowEmailEnabled = isQuotaEmailTypeEnabledForAccount(account, QuotaEmailTemplateTypes.QUOTA_LOW); |
| 232 | + if (quotaLowEmailEnabled && shouldSendEmail) { |
| 233 | + logger.debug("Adding {} to the deferred emails list, as quota balance [{}] is below the threshold [{}].", account, accountBalance, thresholdBalance); |
| 234 | + deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaEmailTemplateTypes.QUOTA_LOW)); |
| 235 | + return; |
| 236 | + } |
| 237 | + } |
| 238 | + logger.debug("{} will not receive any quota alert emails in this round.", account); |
| 239 | + } |
| 240 | + |
191 | 241 | @Override |
192 | 242 | public void sendQuotaAlert(DeferredQuotaEmail emailToBeSent) { |
193 | 243 | final AccountVO account = emailToBeSent.getAccount(); |
@@ -285,7 +335,7 @@ public Map<String, String> generateOptionMap(AccountVO accountVO, String userNam |
285 | 335 | return optionMap; |
286 | 336 | } |
287 | 337 |
|
288 | | - public static long getDifferenceDays(Date d1, Date d2) { |
| 338 | + public long getDifferenceDays(Date d1, Date d2) { |
289 | 339 | long diff = d2.getTime() - d1.getTime(); |
290 | 340 | return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS); |
291 | 341 | } |
|
0 commit comments