|
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