diff --git a/plugins/database/quota/resources/META-INF/cloudstack/quota/spring-quota-context.xml b/plugins/database/quota/resources/META-INF/cloudstack/quota/spring-quota-context.xml index 11db47a723c..521529d2fa6 100644 --- a/plugins/database/quota/resources/META-INF/cloudstack/quota/spring-quota-context.xml +++ b/plugins/database/quota/resources/META-INF/cloudstack/quota/spring-quota-context.xml @@ -26,6 +26,7 @@ http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaBalanceCmd.java b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaBalanceCmd.java index 8d230eb03be..00eb492085b 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaBalanceCmd.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaBalanceCmd.java @@ -32,7 +32,7 @@ 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.quota.QuotaService; import org.apache.cloudstack.api.response.QuotaStatementItemResponse; import com.cloud.user.Account; @@ -60,7 +60,7 @@ public class QuotaBalanceCmd extends BaseCmd { private Long accountId; @Inject - QuotaManager _quotaManager; + QuotaService _quotaManager; @Inject QuotaDBUtils _quotaDBUtils; diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaRefreshCmd.java b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaRefreshCmd.java index 418cb93b8bf..86b9d0abd55 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaRefreshCmd.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaRefreshCmd.java @@ -17,6 +17,7 @@ package org.apache.cloudstack.api.command; import com.cloud.user.Account; + import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaStatementCmd.java b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaStatementCmd.java index 5cb9d131bf4..b244be2f671 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaStatementCmd.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaStatementCmd.java @@ -31,7 +31,7 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.QuotaStatementResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.quota.QuotaDBUtils; -import org.apache.cloudstack.quota.QuotaManager; +import org.apache.cloudstack.quota.QuotaService; import org.apache.cloudstack.quota.QuotaUsageVO; import org.apache.cloudstack.api.response.QuotaStatementItemResponse; @@ -63,7 +63,7 @@ public class QuotaStatementCmd extends BaseCmd { private Long accountId; @Inject - QuotaManager _quotaManager; + QuotaService _quotaManager; @Inject QuotaDBUtils _quotaDBUtils; diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaDBUtils.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaDBUtils.java index 7705cd8bdd2..731a28cfc37 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaDBUtils.java +++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaDBUtils.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.quota; import com.cloud.utils.Pair; import com.cloud.usage.UsageVO; -import com.cloud.user.AccountVO; import com.cloud.service.ServiceOfferingVO; import org.apache.cloudstack.api.command.QuotaTariffListCmd; @@ -48,10 +47,6 @@ public interface QuotaDBUtils { QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy); - boolean accountLockNoCredit(AccountVO account); - - boolean accountUnlockCredit(AccountVO account); - QuotaBalanceResponse createQuotaLastBalanceResponse(List quotaBalance); } diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaDBUtilsImpl.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaDBUtilsImpl.java index 450b6b012c1..38a4c0815d0 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaDBUtilsImpl.java +++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaDBUtilsImpl.java @@ -17,16 +17,11 @@ package org.apache.cloudstack.quota; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.PermissionDeniedException; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.usage.UsageVO; import com.cloud.usage.dao.UsageDao; -import com.cloud.user.Account; -import com.cloud.user.Account.State; -import com.cloud.user.AccountVO; import com.cloud.user.User; -import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.utils.Pair; import com.cloud.utils.db.Filter; @@ -72,8 +67,6 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils { private UserDao _userDao; @Inject private UsageDao _usageDao; - @Inject - private AccountDao _accountDao; static Long s_recordtofetch = 1000L; @@ -291,74 +284,4 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils { return result; } - @Override - public boolean accountLockNoCredit(AccountVO account) { - short opendb=TransactionLegacy.currentTxn().getDatabaseId(); - boolean success = false; - - if (account == null) { - s_logger.warn("The account parameter is null"); - return false; - } - - if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { - throw new InvalidParameterValueException("Project accounts cannot be locked " + account.getAccountName()); - } - - if (account.getId() == Account.ACCOUNT_ID_SYSTEM) { - throw new PermissionDeniedException("Account name : " + account.getAccountName() + " is a system account, lock is not allowed"); - } - - if (account.getState().equals(State.locked)) { - if (s_logger.isInfoEnabled()) { - s_logger.warn("The account is locked cannot put it in nocredit state (accountId: " + account.getId() + "), locking failed."); - } - } else if (account.getState().equals(State.enabled)) { - TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB); - try { - AccountVO acctForUpdate = _accountDao.createForUpdate(); - acctForUpdate.setState(State.nocredit); - success = _accountDao.update(Long.valueOf(account.getId()), acctForUpdate); - } finally { - txn.close(); - } - } else { - if (s_logger.isInfoEnabled()) { - s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + account.getId() + "), locking failed."); - } - } - - TransactionLegacy.open(opendb).close(); - return success; - } - - @Override - public boolean accountUnlockCredit(AccountVO account) { - short opendb=TransactionLegacy.currentTxn().getDatabaseId(); - boolean success = false; - - if (account == null) { - s_logger.warn("The account parameter is null"); - return success; - } - - if (account.getState().equals(State.nocredit)) { - TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB); - try { - AccountVO acctForUpdate = _accountDao.createForUpdate(); - acctForUpdate.setState(State.enabled); - success = _accountDao.update(Long.valueOf(account.getId()), acctForUpdate); - } finally { - txn.close(); - } - } else { - if (s_logger.isInfoEnabled()) { - s_logger.info("Attempting to unlock a account that is not locked due to no credits, current state is " + account.getState() + " (accountId: " + account.getId() - + "), unlocking failed."); - } - } - TransactionLegacy.open(opendb).close(); - return success; - } - } diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManager.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManager.java index 11ab126ed59..982d63336de 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManager.java +++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManager.java @@ -4,7 +4,7 @@ //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 +//the License. You may obtain a copy of the License at // //http://www.apache.org/licenses/LICENSE-2.0 // @@ -16,19 +16,10 @@ //under the License. package org.apache.cloudstack.quota; -import com.cloud.utils.component.PluggableService; +import com.cloud.utils.component.Manager; -import org.apache.cloudstack.api.command.QuotaBalanceCmd; -import org.apache.cloudstack.api.command.QuotaStatementCmd; - -import java.util.List; - -public interface QuotaManager extends PluggableService { +public interface QuotaManager extends Manager { public boolean calculateQuotaUsage(); - public List getQuotaUsage(QuotaStatementCmd cmd); - - List getQuotaBalance(QuotaBalanceCmd cmd); - } diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java index 73ed95c2929..bf9a4d83109 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java +++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java @@ -16,57 +16,36 @@ //under the License. package org.apache.cloudstack.quota; -import com.cloud.configuration.Config; -import com.cloud.domain.dao.DomainDao; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.PermissionDeniedException; 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.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.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; -import org.apache.cloudstack.api.command.QuotaStatementCmd; -import org.apache.cloudstack.api.command.QuotaTariffListCmd; -import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd; -import org.apache.cloudstack.context.CallContext; -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; 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; -import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.TimeZone; @Component @Local(value = QuotaManager.class) -public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Configurable, QuotaConfig { +public class QuotaManagerImpl extends ManagerBase implements QuotaManager { private static final Logger s_logger = Logger.getLogger(QuotaManagerImpl.class.getName()); @Inject @@ -78,10 +57,6 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi @Inject private QuotaUsageDao _quotaUsageDao; @Inject - private DomainDao _domainDao; - @Inject - private ConfigurationDao _configDao; - @Inject private QuotaDBUtils _quotaDBUtils; @Inject private QuotaBalanceDao _quotaBalanceDao; @@ -97,49 +72,6 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi super(); } - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - super.configure(name, params); - String timeZoneStr = _configDao.getValue(Config.UsageAggregationTimezone.toString()); - String aggregationRange = _configDao.getValue(Config.UsageStatsJobAggregationRange.toString()); - if (timeZoneStr == null) { - timeZoneStr = "GMT"; - } - _usageTimezone = TimeZone.getTimeZone(timeZoneStr); - - _aggregationDuration = Integer.parseInt(aggregationRange); - if (_aggregationDuration < UsageUtils.USAGE_AGGREGATION_RANGE_MIN) { - s_logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + UsageUtils.USAGE_AGGREGATION_RANGE_MIN); - _aggregationDuration = UsageUtils.USAGE_AGGREGATION_RANGE_MIN; - } - s_logger.info("Usage timezone = " + _usageTimezone + " AggregationDuration=" + _aggregationDuration); - return true; - } - - @Override - public List> getCommands() { - final List> cmdList = new ArrayList>(); - cmdList.add(QuotaTariffListCmd.class); - cmdList.add(QuotaTariffUpdateCmd.class); - cmdList.add(QuotaCreditsCmd.class); - cmdList.add(QuotaEmailTemplateAddCmd.class); - cmdList.add(QuotaRefreshCmd.class); - cmdList.add(QuotaStatementCmd.class); - cmdList.add(QuotaBalanceCmd.class); - return cmdList; - } - - @Override - public String getConfigComponentName() { - return "QUOTA-PLUGIN"; - } - - @Override - public ConfigKey[] getConfigKeys() { - return new ConfigKey[] { QuotaPluginEnabled, QuotaPeriodType, QuotaPeriod, QuotaGenerateActivity, QuotaEmailRecordOutgoing, QuotaEnableEnforcement, QuotaCurrencySymbol, QuotaLimitCritical, - QuotaLimitIncremental, QuotaSmtpHost, QuotaSmtpTimeout, QuotaSmtpUser, QuotaSmtpPassword, QuotaSmtpPort, QuotaSmtpAuthType }; - } - @Override public boolean calculateQuotaUsage() { short opendb = TransactionLegacy.currentTxn().getDatabaseId(); @@ -262,98 +194,6 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi return jobResult; } - @Override - public List getQuotaBalance(QuotaBalanceCmd cmd) { - short opendb = TransactionLegacy.currentTxn().getDatabaseId(); - TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close(); - - 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 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"); - } - } - TransactionLegacy.open(opendb).close(); - - Date startDate = cmd.getStartDate(); - Date endDate = cmd.getEndDate(); - startDate = startDate == null ? new Date() : startDate; - - TimeZone usageTZ = getUsageTimezone(); - Date adjustedStartDate = computeAdjustedTime(startDate, usageTZ); - - if (endDate == null) { - s_logger.debug("getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", on or before " + adjustedStartDate); - return _quotaBalanceDao.getQuotaBalance(accountId, domainId, adjustedStartDate); - } else if (startDate.before(endDate)) { - 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); - } else { - throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate); - } - } - - @Override - public List getQuotaUsage(QuotaStatementCmd cmd) { - short opendb = TransactionLegacy.currentTxn().getDatabaseId(); - TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close(); - Long accountId = cmd.getAccountId(); - String accountName = cmd.getAccountName(); - Long domainId = cmd.getDomainId(); - Account userAccount = null; - Account caller = CallContext.current().getCallingAccount(); - Integer usageType = cmd.getUsageType(); - - // 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 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"); - } - } - TransactionLegacy.open(opendb).close(); - - 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 records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and " + adjustedEndDate); - return _quotaUsageDao.getQuotaUsage(accountId, domainId, usageType, adjustedStartDate, adjustedEndDate); - } - @DB private QuotaUsageVO updateQuotaDiskUsage(UsageVO usageRecord, HashMap quotaTariffMap, BigDecimal aggregationRatio, int quotaType) { QuotaUsageVO quota_usage = null; @@ -491,28 +331,4 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Confi return _usageTimezone; } - private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ) { - Calendar cal = Calendar.getInstance(); - cal.setTime(initialDate); - TimeZone localTZ = cal.getTimeZone(); - int timezoneOffset = cal.get(Calendar.ZONE_OFFSET); - if (localTZ.inDaylightTime(initialDate)) { - timezoneOffset += (60 * 60 * 1000); - } - cal.add(Calendar.MILLISECOND, timezoneOffset); - - Date newTime = cal.getTime(); - - Calendar calTS = Calendar.getInstance(targetTZ); - calTS.setTime(newTime); - timezoneOffset = calTS.get(Calendar.ZONE_OFFSET); - if (targetTZ.inDaylightTime(initialDate)) { - timezoneOffset += (60 * 60 * 1000); - } - - calTS.add(Calendar.MILLISECOND, -1 * timezoneOffset); - - return calTS.getTime(); - } - } diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaService.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaService.java new file mode 100644 index 00000000000..8b9447647a8 --- /dev/null +++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaService.java @@ -0,0 +1,32 @@ +//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.quota; + +import com.cloud.utils.component.PluggableService; + +import org.apache.cloudstack.api.command.QuotaBalanceCmd; +import org.apache.cloudstack.api.command.QuotaStatementCmd; + +import java.util.List; + +public interface QuotaService extends PluggableService { + + public List getQuotaUsage(QuotaStatementCmd cmd); + + List getQuotaBalance(QuotaBalanceCmd cmd); + +} diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaServiceImpl.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaServiceImpl.java new file mode 100644 index 00000000000..eda4b0d27bb --- /dev/null +++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaServiceImpl.java @@ -0,0 +1,249 @@ +//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.quota; + +import com.cloud.configuration.Config; +import com.cloud.domain.dao.DomainDao; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.user.Account; +import com.cloud.user.AccountVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.db.Filter; +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; +import org.apache.cloudstack.api.command.QuotaStatementCmd; +import org.apache.cloudstack.api.command.QuotaTariffListCmd; +import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd; +import org.apache.cloudstack.context.CallContext; +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.QuotaBalanceDao; +import org.apache.cloudstack.quota.dao.QuotaUsageDao; +import org.apache.cloudstack.utils.usage.UsageUtils; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +@Component +@Local(value = QuotaService.class) +public class QuotaServiceImpl extends ManagerBase implements QuotaService, Configurable, QuotaConfig { + private static final Logger s_logger = Logger.getLogger(QuotaServiceImpl.class.getName()); + + @Inject + private AccountDao _accountDao; + @Inject + private QuotaUsageDao _quotaUsageDao; + @Inject + private DomainDao _domainDao; + @Inject + private ConfigurationDao _configDao; + @Inject + private QuotaBalanceDao _quotaBalanceDao; + + private TimeZone _usageTimezone; + private int _aggregationDuration = 0; + + static BigDecimal s_hoursInMonth = new BigDecimal(30 * 24); + static BigDecimal s_minutesInMonth = new BigDecimal(30 * 24 * 60); + static BigDecimal s_gb = new BigDecimal(1024 * 1024 * 1024); + + public QuotaServiceImpl() { + super(); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + String timeZoneStr = _configDao.getValue(Config.UsageAggregationTimezone.toString()); + String aggregationRange = _configDao.getValue(Config.UsageStatsJobAggregationRange.toString()); + if (timeZoneStr == null) { + timeZoneStr = "GMT"; + } + _usageTimezone = TimeZone.getTimeZone(timeZoneStr); + + _aggregationDuration = Integer.parseInt(aggregationRange); + if (_aggregationDuration < UsageUtils.USAGE_AGGREGATION_RANGE_MIN) { + s_logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + UsageUtils.USAGE_AGGREGATION_RANGE_MIN); + _aggregationDuration = UsageUtils.USAGE_AGGREGATION_RANGE_MIN; + } + s_logger.info("Usage timezone = " + _usageTimezone + " AggregationDuration=" + _aggregationDuration); + return true; + } + + @Override + public List> getCommands() { + final List> cmdList = new ArrayList>(); + cmdList.add(QuotaTariffListCmd.class); + cmdList.add(QuotaTariffUpdateCmd.class); + cmdList.add(QuotaCreditsCmd.class); + cmdList.add(QuotaEmailTemplateAddCmd.class); + cmdList.add(QuotaRefreshCmd.class); + cmdList.add(QuotaStatementCmd.class); + cmdList.add(QuotaBalanceCmd.class); + return cmdList; + } + + @Override + public String getConfigComponentName() { + return "QUOTA-PLUGIN"; + } + + @Override + public ConfigKey[] getConfigKeys() { + return new ConfigKey[] { QuotaPluginEnabled, QuotaPeriodType, QuotaPeriod, QuotaGenerateActivity, QuotaEmailRecordOutgoing, QuotaEnableEnforcement, QuotaCurrencySymbol, QuotaLimitCritical, + QuotaLimitIncremental, QuotaSmtpHost, QuotaSmtpTimeout, QuotaSmtpUser, QuotaSmtpPassword, QuotaSmtpPort, QuotaSmtpAuthType }; + } + + @Override + public List getQuotaBalance(QuotaBalanceCmd cmd) { + short opendb = TransactionLegacy.currentTxn().getDatabaseId(); + TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close(); + + 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 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"); + } + } + TransactionLegacy.open(opendb).close(); + + Date startDate = cmd.getStartDate(); + Date endDate = cmd.getEndDate(); + startDate = startDate == null ? new Date() : startDate; + + TimeZone usageTZ = getUsageTimezone(); + Date adjustedStartDate = computeAdjustedTime(startDate, usageTZ); + + if (endDate == null) { + s_logger.debug("getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", on or before " + adjustedStartDate); + return _quotaBalanceDao.getQuotaBalance(accountId, domainId, adjustedStartDate); + } else if (startDate.before(endDate)) { + 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); + } else { + throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate); + } + } + + @Override + public List getQuotaUsage(QuotaStatementCmd cmd) { + short opendb = TransactionLegacy.currentTxn().getDatabaseId(); + TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close(); + Long accountId = cmd.getAccountId(); + String accountName = cmd.getAccountName(); + Long domainId = cmd.getDomainId(); + Account userAccount = null; + Account caller = CallContext.current().getCallingAccount(); + Integer usageType = cmd.getUsageType(); + + // 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 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"); + } + } + TransactionLegacy.open(opendb).close(); + + 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 records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and " + adjustedEndDate); + return _quotaUsageDao.getQuotaUsage(accountId, domainId, usageType, adjustedStartDate, adjustedEndDate); + } + + public TimeZone getUsageTimezone() { + return _usageTimezone; + } + + private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ) { + Calendar cal = Calendar.getInstance(); + cal.setTime(initialDate); + TimeZone localTZ = cal.getTimeZone(); + int timezoneOffset = cal.get(Calendar.ZONE_OFFSET); + if (localTZ.inDaylightTime(initialDate)) { + timezoneOffset += (60 * 60 * 1000); + } + cal.add(Calendar.MILLISECOND, timezoneOffset); + + Date newTime = cal.getTime(); + + Calendar calTS = Calendar.getInstance(targetTZ); + calTS.setTime(newTime); + timezoneOffset = calTS.get(Calendar.ZONE_OFFSET); + if (targetTZ.inDaylightTime(initialDate)) { + timezoneOffset += (60 * 60 * 1000); + } + + calTS.add(Calendar.MILLISECOND, -1 * timezoneOffset); + + return calTS.getTime(); + } + +}