mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-8592: Add more unit tests
- unit tests for UsageTypes - unit tests for all Cmd classes - unit tests for all service and manager impls - try-catch-finally or try-with-resource in dao impls for failsafe db switching - remove dead code - add missing quota calculation case (regression fixed) - replace tabs with spaces in pom.xmls Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
9808321cf3
commit
892a6ebbe5
|
|
@ -38,7 +38,6 @@ import com.cloud.utils.Pair;
|
|||
@APICommand(name = "listUsageRecords", description = "Lists usage records for accounts", responseObject = UsageRecordResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class GetUsageRecordsCmd extends BaseListCmd {
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(GetUsageRecordsCmd.class.getName());
|
||||
|
||||
private static final String s_name = "listusagerecordsresponse";
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import java.util.List;
|
|||
import org.apache.cloudstack.api.response.UsageTypeResponse;
|
||||
|
||||
public class UsageTypes {
|
||||
|
||||
/* Any changes here should also reflect in cloud_usage.quota_mapping table */
|
||||
public static final int RUNNING_VM = 1;
|
||||
public static final int ALLOCATED_VM = 2; // used for tracking how long storage has been allocated for a VM
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.apache.cloudstack.api.command.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
|
@ -70,4 +71,22 @@ public class UsageCmdTest extends TestCase {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCrud() {
|
||||
getUsageRecordsCmd.setDomainId(1L);
|
||||
assertTrue(getUsageRecordsCmd.getDomainId().equals(1L));
|
||||
|
||||
getUsageRecordsCmd.setAccountName("someAccount");
|
||||
assertTrue(getUsageRecordsCmd.getAccountName().equals("someAccount"));
|
||||
|
||||
Date d = new Date();
|
||||
getUsageRecordsCmd.setStartDate(d);
|
||||
getUsageRecordsCmd.setEndDate(d);
|
||||
assertTrue(getUsageRecordsCmd.getStartDate().equals(d));
|
||||
assertTrue(getUsageRecordsCmd.getEndDate().equals(d));
|
||||
|
||||
getUsageRecordsCmd.setUsageId("someId");
|
||||
assertTrue(getUsageRecordsCmd.getUsageId().equals("someId"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -339,4 +339,48 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public void setZoneId(Long zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public void setRawUsage(Double rawUsage) {
|
||||
this.rawUsage = rawUsage;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void setVirtualSize(Long virtualSize) {
|
||||
this.virtualSize = virtualSize;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,30 +42,35 @@ import com.cloud.utils.db.TransactionLegacy;
|
|||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Component
|
||||
@Local(value = { UsageDao.class })
|
||||
@Local(value = {UsageDao.class})
|
||||
public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements UsageDao {
|
||||
public static final Logger s_logger = Logger.getLogger(UsageDaoImpl.class.getName());
|
||||
private static final String DELETE_ALL = "DELETE FROM cloud_usage";
|
||||
private static final String DELETE_ALL_BY_ACCOUNTID = "DELETE FROM cloud_usage WHERE account_id = ?";
|
||||
private static final String INSERT_ACCOUNT = "INSERT INTO cloud_usage.account (id, account_name, type, domain_id, removed, cleanup_needed) VALUES (?,?,?,?,?,?)";
|
||||
private static final String INSERT_USER_STATS = "INSERT INTO cloud_usage.user_statistics (id, data_center_id, account_id, public_ip_address, device_id, device_type, network_id, net_bytes_received,"
|
||||
+ " net_bytes_sent, current_bytes_received, current_bytes_sent, agg_bytes_received, agg_bytes_sent) VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?)";
|
||||
private static final String INSERT_USER_STATS =
|
||||
"INSERT INTO cloud_usage.user_statistics (id, data_center_id, account_id, public_ip_address, device_id, device_type, network_id, net_bytes_received,"
|
||||
+ " net_bytes_sent, current_bytes_received, current_bytes_sent, agg_bytes_received, agg_bytes_sent) VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?)";
|
||||
|
||||
private static final String UPDATE_ACCOUNT = "UPDATE cloud_usage.account SET account_name=?, removed=? WHERE id=?";
|
||||
private static final String UPDATE_USER_STATS = "UPDATE cloud_usage.user_statistics SET net_bytes_received=?, net_bytes_sent=?, current_bytes_received=?, current_bytes_sent=?, agg_bytes_received=?, agg_bytes_sent=? WHERE id=?";
|
||||
private static final String UPDATE_USER_STATS =
|
||||
"UPDATE cloud_usage.user_statistics SET net_bytes_received=?, net_bytes_sent=?, current_bytes_received=?, current_bytes_sent=?, agg_bytes_received=?, agg_bytes_sent=? WHERE id=?";
|
||||
|
||||
private static final String GET_LAST_ACCOUNT = "SELECT id FROM cloud_usage.account ORDER BY id DESC LIMIT 1";
|
||||
private static final String GET_LAST_USER_STATS = "SELECT id FROM cloud_usage.user_statistics ORDER BY id DESC LIMIT 1";
|
||||
private static final String GET_PUBLIC_TEMPLATES_BY_ACCOUNTID = "SELECT id FROM cloud.vm_template WHERE account_id = ? AND public = '1' AND removed IS NULL";
|
||||
|
||||
private static final String GET_LAST_VM_DISK_STATS = "SELECT id FROM cloud_usage.vm_disk_statistics ORDER BY id DESC LIMIT 1";
|
||||
private static final String INSERT_VM_DISK_STATS = "INSERT INTO cloud_usage.vm_disk_statistics (id, data_center_id, account_id, vm_id, volume_id, net_io_read, net_io_write, current_io_read, "
|
||||
+ "current_io_write, agg_io_read, agg_io_write, net_bytes_read, net_bytes_write, current_bytes_read, current_bytes_write, agg_bytes_read, agg_bytes_write) "
|
||||
+ " VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?, ?,?, ?, ?)";
|
||||
private static final String UPDATE_VM_DISK_STATS = "UPDATE cloud_usage.vm_disk_statistics SET net_io_read=?, net_io_write=?, current_io_read=?, current_io_write=?, agg_io_read=?, agg_io_write=?, "
|
||||
+ "net_bytes_read=?, net_bytes_write=?, current_bytes_read=?, current_bytes_write=?, agg_bytes_read=?, agg_bytes_write=? WHERE id=?";
|
||||
private static final String INSERT_VM_DISK_STATS =
|
||||
"INSERT INTO cloud_usage.vm_disk_statistics (id, data_center_id, account_id, vm_id, volume_id, net_io_read, net_io_write, current_io_read, "
|
||||
+ "current_io_write, agg_io_read, agg_io_write, net_bytes_read, net_bytes_write, current_bytes_read, current_bytes_write, agg_bytes_read, agg_bytes_write) "
|
||||
+ " VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?, ?,?, ?, ?)";
|
||||
private static final String UPDATE_VM_DISK_STATS =
|
||||
"UPDATE cloud_usage.vm_disk_statistics SET net_io_read=?, net_io_write=?, current_io_read=?, current_io_write=?, agg_io_read=?, agg_io_write=?, "
|
||||
+ "net_bytes_read=?, net_bytes_write=?, current_bytes_read=?, current_bytes_write=?, agg_bytes_read=?, agg_bytes_write=? WHERE id=?";
|
||||
private static final String INSERT_USAGE_RECORDS = "INSERT INTO cloud_usage.cloud_usage (zone_id, account_id, domain_id, description, usage_display, "
|
||||
+ "usage_type, raw_usage, vm_instance_id, vm_name, offering_id, template_id, "
|
||||
+
|
||||
"usage_type, raw_usage, vm_instance_id, vm_name, offering_id, template_id, "
|
||||
+ "usage_id, type, size, network_id, start_date, end_date, virtual_size) VALUES (?,?,?,?,?,?,?,?,?, ?, ?, ?,?,?,?,?,?,?)";
|
||||
|
||||
protected final static TimeZone s_gmtTimeZone = TimeZone.getTimeZone("GMT");
|
||||
|
|
@ -106,9 +111,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
txn.start();
|
||||
String sql = INSERT_ACCOUNT;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
|
||||
// want CLOUD_USAGE
|
||||
// dataSource connection
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (AccountVO acct : accounts) {
|
||||
pstmt.setLong(1, acct.getId());
|
||||
pstmt.setString(2, acct.getAccountName());
|
||||
|
|
@ -142,9 +145,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
txn.start();
|
||||
String sql = UPDATE_ACCOUNT;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
|
||||
// want CLOUD_USAGE
|
||||
// dataSource connection
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (AccountVO acct : accounts) {
|
||||
pstmt.setString(1, acct.getAccountName());
|
||||
|
||||
|
|
@ -174,9 +175,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
txn.start();
|
||||
String sql = INSERT_USER_STATS;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
|
||||
// want CLOUD_USAGE
|
||||
// dataSource connection
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (UserStatisticsVO userStat : userStats) {
|
||||
pstmt.setLong(1, userStat.getId());
|
||||
pstmt.setLong(2, userStat.getDataCenterId());
|
||||
|
|
@ -217,9 +216,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
txn.start();
|
||||
String sql = UPDATE_USER_STATS;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
|
||||
// want CLOUD_USAGE
|
||||
// dataSource connection
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (UserStatisticsVO userStat : userStats) {
|
||||
pstmt.setLong(1, userStat.getNetBytesReceived());
|
||||
pstmt.setLong(2, userStat.getNetBytesSent());
|
||||
|
|
@ -316,9 +313,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
txn.start();
|
||||
String sql = UPDATE_VM_DISK_STATS;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
|
||||
// want CLOUD_USAGE
|
||||
// dataSource connection
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (VmDiskStatisticsVO vmDiskStat : vmDiskStats) {
|
||||
pstmt.setLong(1, vmDiskStat.getNetIORead());
|
||||
pstmt.setLong(2, vmDiskStat.getNetIOWrite());
|
||||
|
|
@ -352,9 +347,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
txn.start();
|
||||
String sql = INSERT_VM_DISK_STATS;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
|
||||
// want CLOUD_USAGE
|
||||
// dataSource connection
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (VmDiskStatisticsVO vmDiskStat : vmDiskStats) {
|
||||
pstmt.setLong(1, vmDiskStat.getId());
|
||||
pstmt.setLong(2, vmDiskStat.getDataCenterId());
|
||||
|
|
@ -400,9 +393,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
txn.start();
|
||||
String sql = INSERT_USAGE_RECORDS;
|
||||
PreparedStatement pstmt = null;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
|
||||
// want CLOUD_USAGE
|
||||
// dataSource connection
|
||||
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
|
||||
for (UsageVO usageRecord : usageRecords) {
|
||||
pstmt.setLong(1, usageRecord.getZoneId());
|
||||
pstmt.setLong(2, usageRecord.getAccountId());
|
||||
|
|
@ -464,26 +455,32 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Pair<List<? extends UsageVO>, Integer> getUsageRecordsPendingQuotaAggregation(final long accountId, final long domainId) {
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Getting usage records for account: " + accountId + ", domainId: " + domainId);
|
||||
}
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("getting usage records for account: " + accountId + ", domainId: " + domainId);
|
||||
Pair<List<UsageVO>, Integer> usageRecords = new Pair<List<UsageVO>, Integer>(new ArrayList<UsageVO>(), 0);
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
Filter usageFilter = new Filter(UsageVO.class, "startDate", true, 0L, 10000L);
|
||||
SearchCriteria<UsageVO> sc = createSearchCriteria();
|
||||
if (accountId != -1) {
|
||||
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
|
||||
}
|
||||
if (domainId != -1) {
|
||||
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
|
||||
}
|
||||
sc.addAnd("quotaCalculated", SearchCriteria.Op.NULL);
|
||||
sc.addOr("quotaCalculated", SearchCriteria.Op.EQ, 0);
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Getting usage records" + usageFilter.getOrderBy());
|
||||
}
|
||||
usageRecords = searchAndCountAllRecords(sc, usageFilter);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("getUsageRecordsPendingQuotaAggregation failed due to: " + e.getMessage());
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
Filter usageFilter = new Filter(UsageVO.class, "startDate", true, 0L, 10000L);
|
||||
SearchCriteria<UsageVO> sc = createSearchCriteria();
|
||||
if (accountId != -1) {
|
||||
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
|
||||
}
|
||||
if (domainId != -1) {
|
||||
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
|
||||
}
|
||||
sc.addAnd("quotaCalculated", SearchCriteria.Op.NULL);
|
||||
sc.addOr("quotaCalculated", SearchCriteria.Op.EQ, 0);
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("Getting usage records" + usageFilter.getOrderBy());
|
||||
}
|
||||
Pair<List<UsageVO>, Integer> usageRecords = searchAndCountAllRecords(sc, usageFilter);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return new Pair<List<? extends UsageVO>, Integer>(usageRecords.first(), usageRecords.second());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,5 +37,28 @@
|
|||
<artifactId>cloud-engine-schema</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${cs.junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>${cs.mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>${cs.powermock.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>${cs.powermock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -90,6 +90,10 @@ public class QuotaTypes extends UsageTypes {
|
|||
}
|
||||
|
||||
static public String getDescription(int quotaType) {
|
||||
return listQuotaTypes().get(quotaType).getDescription();
|
||||
HashMap<Integer, QuotaTypes> quotaMap = listQuotaTypes();
|
||||
if (quotaMap.containsKey(quotaType)) {
|
||||
return quotaMap.get(quotaType).getDescription();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,27 +16,34 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.quota.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Local(value = { QuotaAccountDao.class })
|
||||
public class QuotaAccountDaoImpl extends GenericDaoBase<QuotaAccountVO, Long> implements QuotaAccountDao {
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaAccountDaoImpl.class.getName());
|
||||
|
||||
@Override
|
||||
public List<QuotaAccountVO> listAll() {
|
||||
List<QuotaAccountVO> result = null;
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
result = super.listAll();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
result = super.listAll();
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaAccountDaoImpl::listAll() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to list Quota Accounts");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -44,9 +51,15 @@ public class QuotaAccountDaoImpl extends GenericDaoBase<QuotaAccountVO, Long> im
|
|||
public QuotaAccountVO findById(Long id) {
|
||||
QuotaAccountVO result = null;
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
result = super.findById(id);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
result = super.findById(id);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaAccountDaoImpl::findById() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to find Quota Account by ID");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -54,9 +67,15 @@ public class QuotaAccountDaoImpl extends GenericDaoBase<QuotaAccountVO, Long> im
|
|||
public QuotaAccountVO persist(QuotaAccountVO entity) {
|
||||
QuotaAccountVO result = null;
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
result = super.persist(entity);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
result = super.persist(entity);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaAccountDaoImpl::persist() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to save Quota Account");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -64,9 +83,15 @@ public class QuotaAccountDaoImpl extends GenericDaoBase<QuotaAccountVO, Long> im
|
|||
public boolean update(Long id, QuotaAccountVO entity) {
|
||||
boolean result = false;
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
result = super.update(id, entity);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
result = super.update(id, entity);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaAccountDaoImpl::update() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to update Quota Account");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,23 +16,21 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.quota.dao;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Local(value = { QuotaBalanceDao.class })
|
||||
|
|
@ -42,78 +40,97 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
|
|||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public QuotaBalanceVO findLastBalanceEntry(final Long accountId, final Long domainId, final Date beforeThis) {
|
||||
List<QuotaBalanceVO> quotaBalanceEntries = new ArrayList<>();
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
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);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return quotab.size() > 0 ? quotab.get(0) : null;
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
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);
|
||||
quotaBalanceEntries = this.search(sc, filter);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaBalanceDaoImpl::findLastBalanceEntry() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to find last quota balance entry for account");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return quotaBalanceEntries.size() > 0 ? quotaBalanceEntries.get(0) : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public QuotaBalanceVO findLaterBalanceEntry(final Long accountId, final Long domainId, final Date afterThis) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 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.GT, afterThis);
|
||||
List<QuotaBalanceVO> quotab = this.search(sc, filter);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return quotab.size() > 0 ? quotab.get(0) : null;
|
||||
List<QuotaBalanceVO> quotaBalanceEntries = new ArrayList<>();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 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.GT, afterThis);
|
||||
quotaBalanceEntries = this.search(sc, filter);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaBalanceDaoImpl::findLaterBalanceEntry() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to find later quota balance entry");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return quotaBalanceEntries.size() > 0 ? quotaBalanceEntries.get(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveQuotaBalance(final List<QuotaBalanceVO> credits) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
for (QuotaBalanceVO credit : credits) {
|
||||
persist(credit);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Unable to save quota balance");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public List<QuotaBalanceVO> findCreditBalance(final Long accountId, final Long domainId, final Date lastbalancedate, final Date beforeThis) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
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>();
|
||||
List<QuotaBalanceVO> quotaBalances = new ArrayList<>();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
|
||||
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>();
|
||||
}
|
||||
quotaBalances = search(sc, filter);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaBalanceDaoImpl::findCreditBalance() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to find quota credit balance");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
List<QuotaBalanceVO> qb = search(sc, filter);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return qb;
|
||||
return quotaBalances;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public List<QuotaBalanceVO> findQuotaBalance(final Long accountId, final Long domainId, final Date startDate, final Date endDate) {
|
||||
// TODO account for series of credits around boundaries
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
List<QuotaBalanceVO> quotaUsageRecords = null;
|
||||
try {
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
|
||||
if (accountId != null) {
|
||||
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
|
||||
|
|
@ -130,11 +147,12 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
|
|||
if (quotaUsageRecords.size() == 0) {
|
||||
quotaUsageRecords.addAll(lastQuotaBalanceVO(accountId, domainId, startDate));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Unable to find quota balance");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return quotaUsageRecords;
|
||||
}
|
||||
|
||||
|
|
@ -143,11 +161,9 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
|
|||
@Override
|
||||
public List<QuotaBalanceVO> lastQuotaBalanceVO(final Long accountId, final Long domainId, final Date pivotDate) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
List<QuotaBalanceVO> quotaUsageRecords = null;
|
||||
List<QuotaBalanceVO> trimmedRecords = new ArrayList<QuotaBalanceVO>();
|
||||
try {
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 100L);
|
||||
// ASSUMPTION there will be less than 100 continuous credit
|
||||
// transactions
|
||||
|
|
@ -164,8 +180,7 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
|
|||
quotaUsageRecords = search(sc, filter);
|
||||
|
||||
// get records before startDate to find start balance
|
||||
for (Iterator<QuotaBalanceVO> it = quotaUsageRecords.iterator(); it.hasNext();) {
|
||||
QuotaBalanceVO entry = it.next();
|
||||
for (QuotaBalanceVO entry : quotaUsageRecords) {
|
||||
s_logger.info("findQuotaBalance Date=" + entry.getUpdatedOn().toGMTString() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
|
||||
if (entry.getCreditsId() > 0) {
|
||||
trimmedRecords.add(entry);
|
||||
|
|
@ -174,12 +189,11 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
|
|||
break; // add only consecutive credit entries and last balance entry
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Unable to get last quota balance");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return trimmedRecords;
|
||||
}
|
||||
|
||||
|
|
@ -190,10 +204,9 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
|
|||
new InvalidParameterValueException("There are no balance entries on or before the requested date.");
|
||||
}
|
||||
BigDecimal finalBalance = new BigDecimal(0);
|
||||
for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) {
|
||||
QuotaBalanceVO entry = it.next();
|
||||
s_logger.info("lastQuotaBalance Date=" + entry.getUpdatedOn().toGMTString() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
|
||||
finalBalance.add(entry.getCreditBalance());
|
||||
for (QuotaBalanceVO entry : quotaBalance) {
|
||||
s_logger.debug("lastQuotaBalance Date=" + entry.getUpdatedOn().toGMTString() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
|
||||
finalBalance = finalBalance.add(entry.getCreditBalance());
|
||||
}
|
||||
return finalBalance;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import java.util.List;
|
|||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
||||
|
|
@ -35,6 +37,8 @@ import com.cloud.utils.db.TransactionLegacy;
|
|||
@Component
|
||||
@Local(value = { QuotaCreditsDao.class })
|
||||
public class QuotaCreditsDaoImpl extends GenericDaoBase<QuotaCreditsVO, Long> implements QuotaCreditsDao {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaCreditsDaoImpl.class.getName());
|
||||
|
||||
@Inject
|
||||
QuotaBalanceDao _quotaBalanceDao;
|
||||
|
||||
|
|
@ -42,31 +46,43 @@ public class QuotaCreditsDaoImpl extends GenericDaoBase<QuotaCreditsVO, Long> im
|
|||
@Override
|
||||
public List<QuotaCreditsVO> findCredits(final long accountId, final long domainId, final Date startDate, final Date endDate) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
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("updatedOn", SearchCriteria.Op.BETWEEN, startDate, endDate);
|
||||
} else {
|
||||
return new ArrayList<QuotaCreditsVO>();
|
||||
List<QuotaCreditsVO> qc = new ArrayList<>();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
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("updatedOn", SearchCriteria.Op.BETWEEN, startDate, endDate);
|
||||
} else {
|
||||
return new ArrayList<QuotaCreditsVO>();
|
||||
}
|
||||
qc = search(sc, filter);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaCreditsDaoImpl::findCredits() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to find quota credits");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
List<QuotaCreditsVO> qc = search(sc, filter);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return qc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaCreditsVO saveCredits(final QuotaCreditsVO credits) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
persist(credits);
|
||||
// make an entry in the balance table
|
||||
QuotaBalanceVO bal = new QuotaBalanceVO(credits);
|
||||
_quotaBalanceDao.persist(bal);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
super.persist(credits);
|
||||
// make an entry in the balance table
|
||||
QuotaBalanceVO bal = new QuotaBalanceVO(credits);
|
||||
_quotaBalanceDao.persist(bal);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaCreditsDaoImpl::saveCredits() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to save quota credits");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return credits;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,15 +20,19 @@ import com.cloud.utils.db.GenericDaoBase;
|
|||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Local(value = { QuotaEmailTemplatesDao.class })
|
||||
public class QuotaEmailTemplatesDaoImpl extends GenericDaoBase<QuotaEmailTemplatesVO, Long> implements QuotaEmailTemplatesDao {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaEmailTemplatesDaoImpl.class.getName());
|
||||
|
||||
protected SearchBuilder<QuotaEmailTemplatesVO> QuotaEmailTemplateSearch;
|
||||
|
||||
|
|
@ -43,22 +47,36 @@ public class QuotaEmailTemplatesDaoImpl extends GenericDaoBase<QuotaEmailTemplat
|
|||
@Override
|
||||
public List<QuotaEmailTemplatesVO> listAllQuotaEmailTemplates(String templateName) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
SearchCriteria<QuotaEmailTemplatesVO> sc = QuotaEmailTemplateSearch.create();
|
||||
if (templateName != null) {
|
||||
sc.setParameters("template_name", templateName);
|
||||
List<QuotaEmailTemplatesVO> result = new ArrayList<>();
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
SearchCriteria<QuotaEmailTemplatesVO> sc = QuotaEmailTemplateSearch.create();
|
||||
if (templateName != null) {
|
||||
sc.setParameters("template_name", templateName);
|
||||
}
|
||||
result = this.listBy(sc);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaEmailTemplatesDaoImpl::listAllQuotaEmailTemplates() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to list quota email templates");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
List<QuotaEmailTemplatesVO> result = this.listBy(sc);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateQuotaEmailTemplate(QuotaEmailTemplatesVO template) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
final boolean result = this.update(template.getId(), template);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
boolean result = false;
|
||||
try {
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
result = this.update(template.getId(), template);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaEmailTemplatesDaoImpl::updateQuotaEmailTemplate() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to update quota email template");
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.cloud.utils.db.SearchBuilder;
|
|||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
|
@ -56,27 +57,26 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
|
|||
@Override
|
||||
public QuotaTariffVO findTariffPlanByUsageType(final int quotaType, final Date effectiveDate) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
List<QuotaTariffVO> result = null;
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
List<QuotaTariffVO> result = new ArrayList<>();
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
final Filter filter = new Filter(QuotaTariffVO.class, "effectiveOn", false, 0L, 1L);
|
||||
final SearchCriteria<QuotaTariffVO> sc = listAllIncludedUsageType.create();
|
||||
sc.setParameters("onorbefore", effectiveDate);
|
||||
sc.setParameters("quotatype", quotaType);
|
||||
result = search(sc, filter);
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Unable to find tariff plan by usage type");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
// Switch back
|
||||
TransactionLegacy.open(opendb).close();
|
||||
if (result.size() > 0) {
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("findTariffPlanByUsageType: " + effectiveDate + "quota type " + quotaType + " val=" + result.get(0).getCurrencyValue());
|
||||
s_logger.debug("QuotaTariffDaoImpl::findTariffPlanByUsageType: " + effectiveDate + "quota type " + quotaType + " val=" + result.get(0).getCurrencyValue());
|
||||
}
|
||||
return result.get(0);
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()){
|
||||
s_logger.info("Missing quota type " + quotaType);
|
||||
s_logger.info("QuotaTariffDaoImpl::findTariffPlanByUsageType: Missing quota type " + quotaType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -86,8 +86,7 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
|
|||
public List<QuotaTariffVO> listAllTariffPlans(final Date effectiveDate) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
List<QuotaTariffVO> tariffs = new ArrayList<QuotaTariffVO>();
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
final Filter filter = new Filter(QuotaTariffVO.class, "effectiveOn", false, 0L, 1L);
|
||||
final SearchCriteria<QuotaTariffVO> sc = listAllIncludedUsageType.create();
|
||||
sc.setParameters("onorbefore", effectiveDate);
|
||||
|
|
@ -96,47 +95,43 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
|
|||
List<QuotaTariffVO> result = search(sc, filter);
|
||||
if (result.size() > 0) {
|
||||
tariffs.add(result.get(0));
|
||||
s_logger.info("listAllTariffPlans onorbefore" + effectiveDate + "quota type " + result.get(0).getDescription() + " , effective Date=" + result.get(0).getEffectiveOn() + " val=" + result.get(0).getCurrencyValue());
|
||||
s_logger.info("listAllTariffPlans onorbefore" + effectiveDate + "quota type " + result.get(0).getDescription() + " , effective Date=" + result.get(0).getEffectiveOn() + " val=" + result.get(0).getCurrencyValue());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Unable to list all tariff plans");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
// Switch back
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return tariffs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateQuotaTariff(QuotaTariffVO plan) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); // Switch
|
||||
// to
|
||||
boolean result = false;
|
||||
try {
|
||||
// Usage DB
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
result = this.update(plan.getId(), plan);
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Unable to update quota tariff");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
TransactionLegacy.open(opendb).close(); // Switch back
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaTariffVO addQuotaTariff(QuotaTariffVO plan) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); // Switch
|
||||
// to
|
||||
QuotaTariffVO result = null;
|
||||
try {
|
||||
// Usage DB
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
plan.setId(null);
|
||||
result = this.persist(plan);
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Unable to save quota tariff");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
TransactionLegacy.open(opendb).close(); // Switch back
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,25 +16,14 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.quota.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
|
||||
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 QuotaUsageDao extends GenericDao<QuotaUsageVO, Long> {
|
||||
|
||||
List<QuotaUsageVO> findQuotaUsage(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);
|
||||
|
||||
BigDecimal findTotalQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,43 +16,30 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.quota.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import java.math.BigDecimal;
|
||||
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.vo.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 com.cloud.utils.db.TransactionLegacy;
|
||||
|
||||
@Component
|
||||
@Local(value = { QuotaUsageDao.class })
|
||||
public class QuotaUsageDaoImpl extends GenericDaoBase<QuotaUsageVO, Long> implements QuotaUsageDao {
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaUsageVO>, Integer> searchAndCountAllRecords(SearchCriteria<QuotaUsageVO> sc, Filter filter) {
|
||||
return listAndCountIncludingRemovedBy(sc, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveQuotaUsage(List<QuotaUsageVO> records) {
|
||||
for (QuotaUsageVO usageRecord : records) {
|
||||
persist(usageRecord);
|
||||
}
|
||||
}
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaUsageDaoImpl.class.getName());
|
||||
|
||||
@Override
|
||||
public BigDecimal findTotalQuotaUsage(final Long accountId, final Long domainId, final Integer usageType, final Date startDate, final Date endDate) {
|
||||
List<QuotaUsageVO> quotaUsage = findQuotaUsage(accountId, domainId, null, startDate, endDate);
|
||||
BigDecimal total = new BigDecimal(0);
|
||||
for (final QuotaUsageVO quotaRecord : quotaUsage) {
|
||||
for (QuotaUsageVO quotaRecord: quotaUsage) {
|
||||
total = total.add(quotaRecord.getQuotaUsed());
|
||||
}
|
||||
return total;
|
||||
|
|
@ -62,11 +49,9 @@ public class QuotaUsageDaoImpl extends GenericDaoBase<QuotaUsageVO, Long> implem
|
|||
@Override
|
||||
public List<QuotaUsageVO> findQuotaUsage(final Long accountId, final Long domainId, final Integer usageType, final Date startDate, final Date endDate) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
List<QuotaUsageVO> quotaUsageRecords = null;
|
||||
try {
|
||||
// TODO instead of max value query with reasonable number and
|
||||
// iterate
|
||||
List<QuotaUsageVO> quotaUsageRecords = new ArrayList<QuotaUsageVO>();
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
// 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);
|
||||
|
|
@ -84,11 +69,12 @@ public class QuotaUsageDaoImpl extends GenericDaoBase<QuotaUsageVO, Long> implem
|
|||
return new ArrayList<QuotaUsageVO>();
|
||||
}
|
||||
quotaUsageRecords = listBy(sc);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("QuotaUsageDaoImpl::findQuotaUsage() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to find quota usage");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return quotaUsageRecords;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,5 @@ import org.apache.cloudstack.quota.vo.ServiceOfferingVO;
|
|||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface ServiceOfferingDao extends GenericDao<ServiceOfferingVO, Long> {
|
||||
|
||||
ServiceOfferingVO findServiceOffering(Long vmId, long serviceOfferingId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,18 +43,19 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
|
|||
@Override
|
||||
public ServiceOfferingVO findServiceOffering(final Long vmId, final long serviceOfferingId) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
|
||||
ServiceOfferingVO result;
|
||||
try {
|
||||
ServiceOfferingVO result = null;
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) {
|
||||
result = findById(vmId, serviceOfferingId);
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Quota ServiceOfferingDaoImpl::findServiceOffering() failed due to: " + e.getMessage());
|
||||
throw new CloudRuntimeException("Unable to find service offering for quota calculations");
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public ServiceOfferingVO findById(Long vmId, long serviceOfferingId) {
|
||||
private ServiceOfferingVO findById(Long vmId, long serviceOfferingId) {
|
||||
ServiceOfferingVO offering = super.findById(serviceOfferingId);
|
||||
if (offering.isDynamic()) {
|
||||
if (vmId == null) {
|
||||
|
|
@ -67,7 +68,7 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
|
|||
return offering;
|
||||
}
|
||||
|
||||
public ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map<String, String> customParameters) {
|
||||
private ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map<String, String> customParameters) {
|
||||
ServiceOfferingVO dummyoffering = new ServiceOfferingVO(serviceOffering);
|
||||
dummyoffering.setDynamicFlag(true);
|
||||
if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) {
|
||||
|
|
|
|||
|
|
@ -24,8 +24,5 @@ import com.cloud.utils.db.GenericDao;
|
|||
import org.apache.cloudstack.quota.vo.UserVmDetailVO;
|
||||
|
||||
public interface UserVmDetailsDao extends GenericDao<UserVmDetailVO, Long> {
|
||||
|
||||
Map<String, String> listDetailsKeyPairs(long resourceId);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ public class UserVmDetailsDaoImpl extends GenericDaoBase<UserVmDetailVO, Long> i
|
|||
|
||||
@Override
|
||||
public Map<String, String> listDetailsKeyPairs(long resourceId) {
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
SearchCriteria<UserVmDetailVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("resourceId", resourceId);
|
||||
|
||||
List<UserVmDetailVO> results = search(sc, null);
|
||||
Map<String, String> details = new HashMap<String, String>(results.size());
|
||||
for (UserVmDetailVO result : results) {
|
||||
details.put(result.getName(), result.getValue());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
// 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.constant;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.response.UsageTypeResponse;
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaTypesTest extends TestCase {
|
||||
|
||||
@Test
|
||||
public void testQuotaTypesList() {
|
||||
HashMap<Integer, QuotaTypes> quotaTypes = QuotaTypes.listQuotaTypes();
|
||||
List<UsageTypeResponse> usageTypesResponseList = UsageTypes.listUsageTypes();
|
||||
for (UsageTypeResponse usageTypeResponse: usageTypesResponseList) {
|
||||
final Integer usageTypeInt = usageTypeResponse.getUsageType();
|
||||
assertTrue(quotaTypes.containsKey(usageTypeInt));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuotaTypeDescription() {
|
||||
assertNull(QuotaTypes.getDescription(-1));
|
||||
assertNotNull(QuotaTypes.getDescription(QuotaTypes.MEMORY));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,102 +1,99 @@
|
|||
<!-- 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. -->
|
||||
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. -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-database-quota</artifactId>
|
||||
<name>Apache CloudStack Plugin - Quota Service</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-plugins</artifactId>
|
||||
<version>4.6.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-engine-schema</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-framework-quota</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${cs.commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>${cs.joda-time.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${cs.junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>${cs.hamcrest.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>${cs.mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>${cs.powermock.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>${cs.powermock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-database-quota</artifactId>
|
||||
<name>Apache CloudStack Plugin - Quota Service</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-plugins</artifactId>
|
||||
<version>4.6.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-engine-schema</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-framework-quota</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${cs.commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>${cs.joda-time.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${cs.junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>${cs.hamcrest.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>${cs.mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>${cs.powermock.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>${cs.powermock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -112,11 +112,15 @@ public class QuotaCreditsCmd extends BaseCmd {
|
|||
|
||||
@Override
|
||||
public void execute() {
|
||||
Long accountId = _accountService.getActiveAccountByName(accountName, domainId).getAccountId();
|
||||
Long accountId = null;
|
||||
Account account = _accountService.getActiveAccountByName(accountName, domainId);
|
||||
if (account != null) {
|
||||
accountId = account.getAccountId();
|
||||
}
|
||||
if (accountId == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "The account does not exists or has been removed/disabled");
|
||||
}
|
||||
if (value == null) {
|
||||
if (getValue() == null) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please send a valid non-empty quota value");
|
||||
}
|
||||
if (getQuotaEnforce() != null) {
|
||||
|
|
@ -126,10 +130,10 @@ public class QuotaCreditsCmd extends BaseCmd {
|
|||
_quotaService.setMinBalance(accountId, getMinBalance());
|
||||
}
|
||||
else {
|
||||
_quotaService.setMinBalance(accountId, 0.2 * value);
|
||||
_quotaService.setMinBalance(accountId, 0.2 * getValue());
|
||||
}
|
||||
|
||||
final QuotaCreditsResponse response = _responseBuilder.addQuotaCredits(accountId, domainId, value, CallContext.current().getCallingUserId());
|
||||
final QuotaCreditsResponse response = _responseBuilder.addQuotaCredits(accountId, getDomainId(), getValue(), CallContext.current().getCallingUserId());
|
||||
response.setResponseName(getCommandName());
|
||||
response.setObjectName("quotacredits");
|
||||
setResponseObject(response);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ public class QuotaEmailTemplateListCmd extends BaseListCmd {
|
|||
return templateName;
|
||||
}
|
||||
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final ListResponse<QuotaEmailTemplateResponse> response = new ListResponse<QuotaEmailTemplateResponse>();
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public class QuotaEmailTemplateUpdateCmd extends BaseCmd {
|
|||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
private void setTemplateName(String templateName) {
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
|
|
@ -108,4 +108,15 @@ public class QuotaEmailTemplateUpdateCmd extends BaseCmd {
|
|||
return locale;
|
||||
}
|
||||
|
||||
public void setTemplateSubject(String templateSubject) {
|
||||
this.templateSubject = templateSubject;
|
||||
}
|
||||
|
||||
public void setTemplateBody(String templateBody) {
|
||||
this.templateBody = templateBody;
|
||||
}
|
||||
|
||||
public void setLocale(String locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -298,16 +298,15 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
public QuotaCreditsResponse addQuotaCredits(final Long accountId, final Long domainId, final Double amount, final Long updatedBy, final Date despositedOn) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
QuotaCreditsVO result = null;
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
QuotaCreditsVO credits = new QuotaCreditsVO(accountId, domainId, new BigDecimal(amount), updatedBy);
|
||||
s_logger.info("addQuotaCredits: Depositing " + amount + " on adjusted date " + despositedOn);
|
||||
credits.setUpdatedOn(despositedOn);
|
||||
result = _quotaCreditsDao.saveCredits(credits);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
|
||||
|
||||
final AccountVO account = _accountDao.findById(accountId);
|
||||
final boolean lockAccountEnforcement = "true".equalsIgnoreCase(QuotaConfig.QuotaEnableEnforcement.value());
|
||||
final BigDecimal currentAccountBalance = _quotaBalanceDao.lastQuotaBalance(accountId, domainId, startOfNextDay(despositedOn));
|
||||
|
|
@ -372,16 +371,15 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
@Override
|
||||
public QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate) {
|
||||
if (quotaBalance == null || quotaBalance.size() == 0) {
|
||||
new InvalidParameterValueException("There are no balance entries on or before the requested date.");
|
||||
throw new InvalidParameterValueException("There are no balance entries on or before the requested date.");
|
||||
}
|
||||
if (startDate == null) {
|
||||
startDate = new Date();
|
||||
}
|
||||
QuotaBalanceResponse resp = new QuotaBalanceResponse();
|
||||
BigDecimal lastCredits = new BigDecimal(0);
|
||||
for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) {
|
||||
QuotaBalanceVO entry = it.next();
|
||||
if (s_logger.isDebugEnabled()){
|
||||
for (QuotaBalanceVO entry : quotaBalance) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.info("createQuotaLastBalanceResponse Date=" + entry.getUpdatedOn() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
|
||||
}
|
||||
lastCredits = lastCredits.add(entry.getCreditBalance());
|
||||
|
|
|
|||
|
|
@ -150,11 +150,10 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
|||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
|
||||
|
||||
Account userAccount = null;
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
// if accountId is not specified, use accountName and domainId
|
||||
if ((accountId == null) && (accountName != null) && (domainId != null)) {
|
||||
Account userAccount = null;
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
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);
|
||||
|
|
@ -211,18 +210,17 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
|||
throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaUsageVO> getQuotaUsage(Long accountId, String accountName, Long domainId, Integer usageType, Date startDate, Date endDate) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
|
||||
Account userAccount = null;
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
// if accountId is not specified, use accountName and domainId
|
||||
if ((accountId == null) && (accountName != null) && (domainId != null)) {
|
||||
Account userAccount = null;
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
// 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 junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.response.QuotaBalanceResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaBalanceCmdTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Test
|
||||
public void testQuotaBalanceCmd() throws NoSuchFieldException, IllegalAccessException {
|
||||
QuotaBalanceCmd cmd = new QuotaBalanceCmd();
|
||||
Field rbField = QuotaBalanceCmd.class.getDeclaredField("_responseBuilder");
|
||||
rbField.setAccessible(true);
|
||||
rbField.set(cmd, responseBuilder);
|
||||
|
||||
List<QuotaBalanceVO> quotaBalanceVOList = new ArrayList<QuotaBalanceVO>();
|
||||
Mockito.when(responseBuilder.getQuotaBalance(Mockito.any(cmd.getClass()))).thenReturn(quotaBalanceVOList);
|
||||
Mockito.when(responseBuilder.createQuotaLastBalanceResponse(Mockito.eq(quotaBalanceVOList), Mockito.any(Date.class))).thenReturn(new QuotaBalanceResponse());
|
||||
Mockito.when(responseBuilder.createQuotaBalanceResponse(Mockito.eq(quotaBalanceVOList), Mockito.any(Date.class), Mockito.any(Date.class))).thenReturn(new QuotaBalanceResponse());
|
||||
Mockito.when(responseBuilder.startOfNextDay(Mockito.any(Date.class))).thenReturn(new Date());
|
||||
|
||||
// end date not specified
|
||||
cmd.setStartDate(new Date());
|
||||
cmd.setEndDate(null);
|
||||
cmd.execute();
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).createQuotaLastBalanceResponse(Mockito.eq(quotaBalanceVOList), Mockito.any(Date.class));
|
||||
Mockito.verify(responseBuilder, Mockito.times(0)).createQuotaBalanceResponse(Mockito.eq(quotaBalanceVOList), Mockito.any(Date.class), Mockito.any(Date.class));
|
||||
|
||||
// end date specified
|
||||
cmd.setEndDate(new Date());
|
||||
cmd.execute();
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).createQuotaBalanceResponse(Mockito.eq(quotaBalanceVOList), Mockito.any(Date.class), Mockito.any(Date.class));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// 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 com.cloud.user.AccountService;
|
||||
import com.cloud.user.AccountVO;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.QuotaCreditsResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaCreditsCmdTest extends TestCase {
|
||||
@Mock
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
@Mock
|
||||
QuotaService quotaService;
|
||||
@Mock
|
||||
AccountService accountService;
|
||||
|
||||
@Test
|
||||
public void testQuotaCreditsCmd() throws NoSuchFieldException, IllegalAccessException {
|
||||
QuotaCreditsCmd cmd = new QuotaCreditsCmd();
|
||||
cmd.setAccountName("admin");
|
||||
|
||||
Field rbField = QuotaCreditsCmd.class.getDeclaredField("_responseBuilder");
|
||||
rbField.setAccessible(true);
|
||||
rbField.set(cmd, responseBuilder);
|
||||
|
||||
Field qsbField = QuotaCreditsCmd.class.getDeclaredField("_quotaService");
|
||||
qsbField.setAccessible(true);
|
||||
qsbField.set(cmd, quotaService);
|
||||
|
||||
Field asField = BaseCmd.class.getDeclaredField("_accountService");
|
||||
asField.setAccessible(true);
|
||||
asField.set(cmd, accountService);
|
||||
|
||||
AccountVO acc = new AccountVO();
|
||||
acc.setId(2L);
|
||||
Mockito.when(accountService.getActiveAccountByName(Mockito.anyString(), Mockito.anyLong())).thenReturn(acc);
|
||||
Mockito.when(responseBuilder.addQuotaCredits(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyDouble(), Mockito.anyLong())).thenReturn(new QuotaCreditsResponse());
|
||||
|
||||
// No value provided test
|
||||
try {
|
||||
cmd.execute();
|
||||
} catch (ServerApiException e) {
|
||||
assertTrue(e.getErrorCode().equals(ApiErrorCode.PARAM_ERROR));
|
||||
}
|
||||
|
||||
// With value provided test
|
||||
cmd.setValue(11.80);
|
||||
cmd.execute();
|
||||
Mockito.verify(quotaService, Mockito.times(0)).setLockAccount(Mockito.anyLong(), Mockito.anyBoolean());
|
||||
Mockito.verify(quotaService, Mockito.times(1)).setMinBalance(Mockito.anyLong(), Mockito.anyDouble());
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).addQuotaCredits(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyDouble(), Mockito.anyLong());
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// 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 junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.response.QuotaEmailTemplateResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaEmailTemplateListCmdTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Test
|
||||
public void testQuotaEmailTemplateListCmd() throws NoSuchFieldException, IllegalAccessException {
|
||||
QuotaEmailTemplateListCmd cmd = new QuotaEmailTemplateListCmd();
|
||||
Field rbField = QuotaEmailTemplateListCmd.class.getDeclaredField("_quotaResponseBuilder");
|
||||
rbField.setAccessible(true);
|
||||
rbField.set(cmd, responseBuilder);
|
||||
|
||||
List<QuotaEmailTemplateResponse> responses = new ArrayList<QuotaEmailTemplateResponse>();
|
||||
Mockito.when(responseBuilder.listQuotaEmailTemplates(Mockito.eq(cmd))).thenReturn(responses);
|
||||
cmd.execute();
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).listQuotaEmailTemplates(cmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// 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 junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaEmailTemplateUpdateCmdTest extends TestCase {
|
||||
@Mock
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Test
|
||||
public void testQuotaEmailTemplateUpdateCmd () throws NoSuchFieldException, IllegalAccessException {
|
||||
QuotaEmailTemplateUpdateCmd cmd = new QuotaEmailTemplateUpdateCmd();
|
||||
|
||||
Field rbField = QuotaEmailTemplateUpdateCmd.class.getDeclaredField("_quotaResponseBuilder");
|
||||
rbField.setAccessible(true);
|
||||
rbField.set(cmd, responseBuilder);
|
||||
|
||||
// templatename parameter check
|
||||
try {
|
||||
cmd.execute();
|
||||
} catch (ServerApiException e) {
|
||||
assertTrue(e.getErrorCode().equals(ApiErrorCode.PARAM_ERROR));
|
||||
}
|
||||
|
||||
// invalid template name test
|
||||
cmd.setTemplateName("randomTemplate");
|
||||
cmd.setTemplateBody("some body");
|
||||
cmd.setTemplateSubject("some subject");
|
||||
try {
|
||||
cmd.execute();
|
||||
} catch (ServerApiException e) {
|
||||
assertTrue(e.getErrorCode().equals(ApiErrorCode.PARAM_ERROR));
|
||||
}
|
||||
|
||||
// valid template test
|
||||
cmd.setTemplateName(QuotaConfig.QuotaEmailTemplateTypes.QUOTA_EMPTY.toString());
|
||||
Mockito.when(responseBuilder.updateQuotaEmailTemplate(Mockito.eq(cmd))).thenReturn(true);
|
||||
cmd.execute();
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).updateQuotaEmailTemplate(Mockito.eq(cmd));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// 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 junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaStatementResponse;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaStatementCmdTest extends TestCase {
|
||||
@Mock
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Test
|
||||
public void testQuotaStatementCmd() throws NoSuchFieldException, IllegalAccessException {
|
||||
QuotaStatementCmd cmd = new QuotaStatementCmd();
|
||||
cmd.setAccountName("admin");
|
||||
|
||||
Field rbField = QuotaStatementCmd.class.getDeclaredField("_responseBuilder");
|
||||
rbField.setAccessible(true);
|
||||
rbField.set(cmd, responseBuilder);
|
||||
|
||||
List<QuotaUsageVO> quotaUsageVOList = new ArrayList<QuotaUsageVO>();
|
||||
Mockito.when(responseBuilder.getQuotaUsage(Mockito.eq(cmd))).thenReturn(quotaUsageVOList);
|
||||
Mockito.when(responseBuilder.createQuotaStatementResponse(Mockito.eq(quotaUsageVOList))).thenReturn(new QuotaStatementResponse());
|
||||
cmd.execute();
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).getQuotaUsage(Mockito.eq(cmd));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// 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 junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaTariffResponse;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaTariffListCmdTest extends TestCase {
|
||||
@Mock
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Test
|
||||
public void testQuotaTariffListCmd() throws NoSuchFieldException, IllegalAccessException {
|
||||
QuotaTariffListCmd cmd = new QuotaTariffListCmd();
|
||||
|
||||
Field rbField = QuotaTariffListCmd.class.getDeclaredField("_responseBuilder");
|
||||
rbField.setAccessible(true);
|
||||
rbField.set(cmd, responseBuilder);
|
||||
|
||||
List<QuotaTariffVO> quotaTariffVOList = new ArrayList<QuotaTariffVO>();
|
||||
QuotaTariffVO tariff = new QuotaTariffVO();
|
||||
tariff.setEffectiveOn(new Date());
|
||||
tariff.setCurrencyValue(new BigDecimal(100));
|
||||
tariff.setUsageType(QuotaTypes.MEMORY);
|
||||
|
||||
quotaTariffVOList.add(new QuotaTariffVO());
|
||||
Mockito.when(responseBuilder.listQuotaTariffPlans(Mockito.eq(cmd))).thenReturn(quotaTariffVOList);
|
||||
Mockito.when(responseBuilder.createQuotaTariffResponse(Mockito.any(QuotaTariffVO.class))).thenReturn(new QuotaTariffResponse());
|
||||
|
||||
cmd.execute();
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).createQuotaTariffResponse(Mockito.any(QuotaTariffVO.class));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// 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 junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaTariffResponse;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaTariffUpdateCmdTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Test
|
||||
public void testQuotaTariffUpdateCmd() throws NoSuchFieldException, IllegalAccessException {
|
||||
QuotaTariffUpdateCmd cmd = new QuotaTariffUpdateCmd();
|
||||
|
||||
Field rbField = QuotaTariffUpdateCmd.class.getDeclaredField("_responseBuilder");
|
||||
rbField.setAccessible(true);
|
||||
rbField.set(cmd, responseBuilder);
|
||||
|
||||
QuotaTariffVO tariff = new QuotaTariffVO();
|
||||
tariff.setEffectiveOn(new Date());
|
||||
tariff.setCurrencyValue(new BigDecimal(100));
|
||||
tariff.setUsageType(QuotaTypes.MEMORY);
|
||||
|
||||
Mockito.when(responseBuilder.updateQuotaTariffPlan(Mockito.eq(cmd))).thenReturn(null);
|
||||
try {
|
||||
cmd.execute();
|
||||
} catch (ServerApiException e) {
|
||||
assertTrue(e.getErrorCode().equals(ApiErrorCode.INTERNAL_ERROR));
|
||||
}
|
||||
|
||||
Mockito.when(responseBuilder.updateQuotaTariffPlan(Mockito.eq(cmd))).thenReturn(tariff);
|
||||
Mockito.when(responseBuilder.createQuotaTariffResponse(Mockito.eq(tariff))).thenReturn(new QuotaTariffResponse());
|
||||
cmd.execute();
|
||||
Mockito.verify(responseBuilder, Mockito.times(1)).createQuotaTariffResponse(Mockito.eq(tariff));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
// 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.response;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaCreditsDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.region.RegionManager;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
QuotaTariffDao quotaTariffDao;
|
||||
@Mock
|
||||
QuotaBalanceDao quotaBalanceDao;
|
||||
@Mock
|
||||
QuotaCreditsDao quotaCreditsDao;
|
||||
@Mock
|
||||
QuotaEmailTemplatesDao quotaEmailTemplateDao;
|
||||
|
||||
@Mock
|
||||
UserDao userDao;
|
||||
@Mock
|
||||
QuotaService quotaService;
|
||||
@Mock
|
||||
AccountDao accountDao;
|
||||
@Mock
|
||||
RegionManager regionMgr;
|
||||
|
||||
QuotaResponseBuilderImpl quotaResponseBuilder = new QuotaResponseBuilderImpl();
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException {
|
||||
// Dummy transaction stack setup
|
||||
TransactionLegacy.open("QuotaResponseBuilderImplTest");
|
||||
|
||||
Field tariffDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaTariffDao");
|
||||
tariffDaoField.setAccessible(true);
|
||||
tariffDaoField.set(quotaResponseBuilder, quotaTariffDao);
|
||||
|
||||
Field balanceDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaBalanceDao");
|
||||
balanceDaoField.setAccessible(true);
|
||||
balanceDaoField.set(quotaResponseBuilder, quotaBalanceDao);
|
||||
|
||||
Field quotaCreditsDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaCreditsDao");
|
||||
quotaCreditsDaoField.setAccessible(true);
|
||||
quotaCreditsDaoField.set(quotaResponseBuilder, quotaCreditsDao);
|
||||
|
||||
Field quotaEmailTemplateDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaEmailTemplateDao");
|
||||
quotaEmailTemplateDaoField.setAccessible(true);
|
||||
quotaEmailTemplateDaoField.set(quotaResponseBuilder, quotaEmailTemplateDao);
|
||||
|
||||
Field userDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_userDao");
|
||||
userDaoField.setAccessible(true);
|
||||
userDaoField.set(quotaResponseBuilder, userDao);
|
||||
|
||||
Field quotaServiceField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaService");
|
||||
quotaServiceField.setAccessible(true);
|
||||
quotaServiceField.set(quotaResponseBuilder, quotaService);
|
||||
|
||||
Field accountDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_accountDao");
|
||||
accountDaoField.setAccessible(true);
|
||||
accountDaoField.set(quotaResponseBuilder, accountDao);
|
||||
|
||||
Field regionMgrField = QuotaResponseBuilderImpl.class.getDeclaredField("_regionMgr");
|
||||
regionMgrField.setAccessible(true);
|
||||
regionMgrField.set(quotaResponseBuilder, regionMgr);
|
||||
}
|
||||
|
||||
private QuotaTariffVO makeTariffTestData() {
|
||||
QuotaTariffVO tariffVO = new QuotaTariffVO();
|
||||
tariffVO.setUsageType(QuotaTypes.IP_ADDRESS);
|
||||
tariffVO.setUsageName("ip address");
|
||||
tariffVO.setUsageUnit("IP-Month");
|
||||
tariffVO.setCurrencyValue(new BigDecimal(100.19));
|
||||
tariffVO.setEffectiveOn(new Date());
|
||||
tariffVO.setUsageDiscriminator("");
|
||||
return tariffVO;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuotaResponse() {
|
||||
QuotaTariffVO tariffVO = makeTariffTestData();
|
||||
QuotaTariffResponse response = quotaResponseBuilder.createQuotaTariffResponse(tariffVO);
|
||||
assertTrue(tariffVO.getUsageType() == response.getUsageType());
|
||||
assertTrue(tariffVO.getCurrencyValue().equals(response.getTariffValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddQuotaCredits() {
|
||||
final long accountId = 2L;
|
||||
final long domainId = 2L;
|
||||
final double amount = 11.0;
|
||||
final long updatedBy = 2L;
|
||||
final Date now = new Date();
|
||||
|
||||
QuotaCreditsVO credit = new QuotaCreditsVO();
|
||||
credit.setCredit(new BigDecimal(amount));
|
||||
|
||||
Mockito.when(quotaCreditsDao.saveCredits(Mockito.any(QuotaCreditsVO.class))).thenReturn(credit);
|
||||
Mockito.when(quotaBalanceDao.lastQuotaBalance(Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Date.class))).thenReturn(new BigDecimal(111));
|
||||
|
||||
AccountVO account = new AccountVO();
|
||||
account.setState(Account.State.locked);
|
||||
Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(account);
|
||||
|
||||
QuotaCreditsResponse resp = quotaResponseBuilder.addQuotaCredits(accountId, domainId, amount, updatedBy, now);
|
||||
assertTrue(resp.getCredits().compareTo(credit.getCredit()) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListQuotaEmailTemplates() {
|
||||
QuotaEmailTemplateListCmd cmd = new QuotaEmailTemplateListCmd();
|
||||
cmd.setTemplateName("some name");
|
||||
List<QuotaEmailTemplatesVO> templates = new ArrayList<>();
|
||||
QuotaEmailTemplatesVO template = new QuotaEmailTemplatesVO();
|
||||
template.setTemplateName("template");
|
||||
templates.add(template);
|
||||
Mockito.when(quotaEmailTemplateDao.listAllQuotaEmailTemplates(Mockito.anyString())).thenReturn(templates);
|
||||
|
||||
assertTrue(quotaResponseBuilder.listQuotaEmailTemplates(cmd).size() == 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateQuotaEmailTemplate() {
|
||||
QuotaEmailTemplateUpdateCmd cmd = new QuotaEmailTemplateUpdateCmd();
|
||||
cmd.setTemplateBody("some body");
|
||||
cmd.setTemplateName("some name");
|
||||
cmd.setTemplateSubject("some subject");
|
||||
|
||||
List<QuotaEmailTemplatesVO> templates = new ArrayList<>();
|
||||
|
||||
Mockito.when(quotaEmailTemplateDao.listAllQuotaEmailTemplates(Mockito.anyString())).thenReturn(templates);
|
||||
Mockito.when(quotaEmailTemplateDao.updateQuotaEmailTemplate(Mockito.any(QuotaEmailTemplatesVO.class))).thenReturn(true);
|
||||
|
||||
// invalid template test
|
||||
assertFalse(quotaResponseBuilder.updateQuotaEmailTemplate(cmd));
|
||||
|
||||
// valid template test
|
||||
QuotaEmailTemplatesVO template = new QuotaEmailTemplatesVO();
|
||||
template.setTemplateName("template");
|
||||
templates.add(template);
|
||||
assertTrue(quotaResponseBuilder.updateQuotaEmailTemplate(cmd));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateQuotaLastBalanceResponse() {
|
||||
List<QuotaBalanceVO> quotaBalance = new ArrayList<>();
|
||||
// null balance test
|
||||
try {
|
||||
quotaResponseBuilder.createQuotaLastBalanceResponse(null, new Date());
|
||||
} catch (InvalidParameterValueException e) {
|
||||
assertTrue(e.getMessage().equals("There are no balance entries on or before the requested date."));
|
||||
}
|
||||
|
||||
// empty balance test
|
||||
try {
|
||||
quotaResponseBuilder.createQuotaLastBalanceResponse(quotaBalance, new Date());
|
||||
} catch (InvalidParameterValueException e) {
|
||||
assertTrue(e.getMessage().equals("There are no balance entries on or before the requested date."));
|
||||
}
|
||||
|
||||
// valid balance test
|
||||
QuotaBalanceVO entry = new QuotaBalanceVO();
|
||||
entry.setAccountId(2L);
|
||||
entry.setCreditBalance(new BigDecimal(100));
|
||||
quotaBalance.add(entry);
|
||||
quotaBalance.add(entry);
|
||||
Mockito.when(quotaService.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date());
|
||||
QuotaBalanceResponse resp = quotaResponseBuilder.createQuotaLastBalanceResponse(quotaBalance, null);
|
||||
assertTrue(resp.getStartQuota().compareTo(new BigDecimal(200)) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartOfNextDay() {
|
||||
DateTime now = new DateTime();
|
||||
DateTime nextDay = new DateTime(quotaResponseBuilder.startOfNextDay(now.toDate()));
|
||||
DateTime nextDay2 = new DateTime(quotaResponseBuilder.startOfNextDay());
|
||||
assertTrue(now.toLocalDate().equals(nextDay.minusDays(1).toLocalDate()));
|
||||
assertTrue(now.toLocalDate().equals(nextDay2.minusDays(1).toLocalDate()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
// 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.user.dao.AccountDao;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaServiceImplTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
AccountDao accountDao;
|
||||
@Mock
|
||||
QuotaAccountDao quotaAcc;
|
||||
@Mock
|
||||
QuotaUsageDao quotaUsageDao;
|
||||
@Mock
|
||||
DomainDao domainDao;
|
||||
@Mock
|
||||
ConfigurationDao configDao;
|
||||
@Mock
|
||||
QuotaBalanceDao quotaBalanceDao;
|
||||
@Mock
|
||||
QuotaResponseBuilder respBldr;
|
||||
|
||||
QuotaServiceImpl quotaService = new QuotaServiceImpl();
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
|
||||
// Dummy transaction stack setup
|
||||
TransactionLegacy.open("QuotaServiceImplTest");
|
||||
|
||||
Field accountDaoField = QuotaServiceImpl.class.getDeclaredField("_accountDao");
|
||||
accountDaoField.setAccessible(true);
|
||||
accountDaoField.set(quotaService, accountDao);
|
||||
|
||||
Field quotaAccountDaoField = QuotaServiceImpl.class.getDeclaredField("_quotaAcc");
|
||||
quotaAccountDaoField.setAccessible(true);
|
||||
quotaAccountDaoField.set(quotaService, quotaAcc);
|
||||
|
||||
Field quotaUsageDaoField = QuotaServiceImpl.class.getDeclaredField("_quotaUsageDao");
|
||||
quotaUsageDaoField.setAccessible(true);
|
||||
quotaUsageDaoField.set(quotaService, quotaUsageDao);
|
||||
|
||||
Field domainDaoField = QuotaServiceImpl.class.getDeclaredField("_domainDao");
|
||||
domainDaoField.setAccessible(true);
|
||||
domainDaoField.set(quotaService, domainDao);
|
||||
|
||||
Field configDaoField = QuotaServiceImpl.class.getDeclaredField("_configDao");
|
||||
configDaoField.setAccessible(true);
|
||||
configDaoField.set(quotaService, configDao);
|
||||
|
||||
Field balanceDaoField = QuotaServiceImpl.class.getDeclaredField("_quotaBalanceDao");
|
||||
balanceDaoField.setAccessible(true);
|
||||
balanceDaoField.set(quotaService, quotaBalanceDao);
|
||||
|
||||
Field QuotaResponseBuilderField = QuotaServiceImpl.class.getDeclaredField("_respBldr");
|
||||
QuotaResponseBuilderField.setAccessible(true);
|
||||
QuotaResponseBuilderField.set(quotaService, respBldr);
|
||||
|
||||
Mockito.when(configDao.getValue(Mockito.eq(Config.UsageAggregationTimezone.toString()))).thenReturn("IST");
|
||||
Mockito.when(configDao.getValue(Mockito.eq(Config.UsageStatsJobAggregationRange.toString()))).thenReturn("1");
|
||||
quotaService.configure("randomName", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComputeAdjustedTime() {
|
||||
DateTime now = new DateTime(DateTimeZone.UTC);
|
||||
DateTime result = new DateTime(quotaService.computeAdjustedTime(now.toDate())); // IST
|
||||
// Jodatime's compareTo counts for the the different timezones
|
||||
assertTrue(now.compareTo(result) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindQuotaBalanceVO() {
|
||||
final long accountId = 2L;
|
||||
final String accountName = "admin123";
|
||||
final long domainId = 1L;
|
||||
final Date startDate = new DateTime().minusDays(2).toDate();
|
||||
final Date endDate = new Date();
|
||||
|
||||
List<QuotaBalanceVO> records = new ArrayList<>();
|
||||
QuotaBalanceVO qb = new QuotaBalanceVO();
|
||||
qb.setCreditBalance(new BigDecimal(100));
|
||||
qb.setAccountId(accountId);
|
||||
records.add(qb);
|
||||
|
||||
Mockito.when(respBldr.startOfNextDay()).thenReturn(endDate);
|
||||
Mockito.when(respBldr.startOfNextDay(Mockito.any(Date.class))).thenReturn(startDate);
|
||||
Mockito.when(quotaBalanceDao.findQuotaBalance(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.any(Date.class), Mockito.any(Date.class))).thenReturn(records);
|
||||
Mockito.when(quotaBalanceDao.lastQuotaBalanceVO(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.any(Date.class))).thenReturn(records);
|
||||
|
||||
// with enddate
|
||||
assertTrue(quotaService.findQuotaBalanceVO(accountId, accountName, domainId, startDate, endDate).get(0).equals(qb));
|
||||
// without enddate
|
||||
assertTrue(quotaService.findQuotaBalanceVO(accountId, accountName, domainId, startDate, null).get(0).equals(qb));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetQuotaUsage() {
|
||||
final long accountId = 2L;
|
||||
final String accountName = "admin123";
|
||||
final long domainId = 1L;
|
||||
final Date startDate = new DateTime().minusDays(2).toDate();
|
||||
final Date endDate = new Date();
|
||||
|
||||
Mockito.when(respBldr.startOfNextDay()).thenReturn(endDate);
|
||||
quotaService.getQuotaUsage(accountId, accountName, domainId, QuotaTypes.IP_ADDRESS, startDate, endDate);
|
||||
Mockito.verify(quotaUsageDao, Mockito.times(1)).findQuotaUsage(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.eq(QuotaTypes.IP_ADDRESS), Mockito.any(Date.class), Mockito.any(Date.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetLockAccount() {
|
||||
// existing account
|
||||
QuotaAccountVO quotaAccountVO = new QuotaAccountVO();
|
||||
Mockito.when(quotaAcc.findById(Mockito.anyLong())).thenReturn(quotaAccountVO);
|
||||
quotaService.setLockAccount(2L, true);
|
||||
Mockito.verify(quotaAcc, Mockito.times(0)).persist(Mockito.any(QuotaAccountVO.class));
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).update(Mockito.anyLong(), Mockito.any(QuotaAccountVO.class));
|
||||
|
||||
// new account
|
||||
Mockito.when(quotaAcc.findById(Mockito.anyLong())).thenReturn(null);
|
||||
quotaService.setLockAccount(2L, true);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persist(Mockito.any(QuotaAccountVO.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMinBalance() {
|
||||
final long accountId = 2L;
|
||||
final double balance = 10.3F;
|
||||
|
||||
// existing account setting
|
||||
QuotaAccountVO quotaAccountVO = new QuotaAccountVO();
|
||||
Mockito.when(quotaAcc.findById(Mockito.anyLong())).thenReturn(quotaAccountVO);
|
||||
quotaService.setMinBalance(accountId, balance);
|
||||
Mockito.verify(quotaAcc, Mockito.times(0)).persist(Mockito.any(QuotaAccountVO.class));
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).update(Mockito.anyLong(), Mockito.any(QuotaAccountVO.class));
|
||||
|
||||
// no account with limit set
|
||||
Mockito.when(quotaAcc.findById(Mockito.anyLong())).thenReturn(null);
|
||||
quotaService.setMinBalance(accountId, balance);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persist(Mockito.any(QuotaAccountVO.class));
|
||||
}
|
||||
}
|
||||
|
|
@ -62,6 +62,9 @@ public class ParamProcessWorkerTest {
|
|||
@Parameter(name = "boolparam1", type = CommandType.BOOLEAN)
|
||||
boolean boolparam1;
|
||||
|
||||
@Parameter(name = "doubleparam1", type = CommandType.DOUBLE)
|
||||
double doubleparam1;
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
|
||||
ResourceAllocationException, NetworkRuleConflictException {
|
||||
|
|
@ -98,10 +101,12 @@ public class ParamProcessWorkerTest {
|
|||
params.put("strparam1", "foo");
|
||||
params.put("intparam1", "100");
|
||||
params.put("boolparam1", "true");
|
||||
params.put("doubleparam1", "11.89");
|
||||
final TestCmd cmd = new TestCmd();
|
||||
paramProcessWorker.processParameters(cmd, params);
|
||||
Assert.assertEquals("foo", cmd.strparam1);
|
||||
Assert.assertEquals(100, cmd.intparam1);
|
||||
Assert.assertTrue(Double.compare(cmd.doubleparam1, 11.89) == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
|
|||
}
|
||||
try {
|
||||
_alertManager.checkAndSendQuotaAlertEmails();
|
||||
_alertManager.sendMonthlyStatement();
|
||||
_alertManager.sendMonthlyStatement(new Date());
|
||||
} catch (Exception e) {
|
||||
s_logger.fatal("Exception received while sending alerts " + e.getMessage());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
|
|
|
|||
|
|
@ -18,10 +18,9 @@ package org.apache.cloudstack.quota;
|
|||
|
||||
import com.cloud.utils.component.Manager;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface QuotaAlertManager extends Manager {
|
||||
|
||||
public void checkAndSendQuotaAlertEmails();
|
||||
|
||||
void sendMonthlyStatement();
|
||||
|
||||
void checkAndSendQuotaAlertEmails();
|
||||
void sendMonthlyStatement(Date now);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ package org.apache.cloudstack.quota;
|
|||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.Account.State;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.Account.State;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.DateUtil;
|
||||
|
|
@ -32,7 +32,6 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
|||
import com.sun.mail.smtp.SMTPMessage;
|
||||
import com.sun.mail.smtp.SMTPSSLTransport;
|
||||
import com.sun.mail.smtp.SMTPTransport;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig.QuotaEmailTemplateTypes;
|
||||
|
|
@ -55,7 +54,6 @@ import javax.mail.Session;
|
|||
import javax.mail.URLName;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -150,8 +148,7 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
|||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void sendMonthlyStatement() {
|
||||
Date now = new Date();
|
||||
public void sendMonthlyStatement(Date now) {
|
||||
Calendar aCalendar = Calendar.getInstance();
|
||||
aCalendar.add(Calendar.MONTH, -1);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
|
|
@ -170,22 +167,17 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
|||
Date lastStatementDate = quotaAccount.getLastStatementDate();
|
||||
if (now.getDate() < 6) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (lastStatementDate == null) {
|
||||
if (lastStatementDate == null || getDifferenceDays(lastStatementDate, new Date()) >= 7) {
|
||||
BigDecimal quotaUsage = _quotaUsage.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, firstDateOfPreviousMonth, lastDateOfPreviousMonth);
|
||||
s_logger.info("For account=" + quotaAccount.getId() + ", quota used = " + quotaUsage);
|
||||
// send statement
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, quotaUsage, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT));
|
||||
} else if (getDifferenceDays(lastStatementDate, new Date()) < 7) {
|
||||
s_logger.debug("For " + quotaAccount.getId() + " the statement has been sent recently");
|
||||
} else {
|
||||
BigDecimal quotaUsage = _quotaUsage.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, firstDateOfPreviousMonth, lastDateOfPreviousMonth);
|
||||
s_logger.info("For account=" + quotaAccount.getId() + ", quota used = " + quotaUsage);
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, quotaUsage, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT));
|
||||
s_logger.debug("For " + quotaAccount.getId() + " the statement has been sent recently");
|
||||
}
|
||||
} else {
|
||||
s_logger.info("For " + quotaAccount.getId() + " it is already more than " + getDifferenceDays(lastStatementDate, new Date()) + " days, will send statement in next cycle");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (DeferredQuotaEmail emailToBeSent : deferredQuotaEmailList) {
|
||||
|
|
@ -209,7 +201,7 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
|||
if (accountBalance != null) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Check id " + account.getId() + " bal=" + accountBalance + " alertDate" + alertDate + " diff" + getDifferenceDays(alertDate, new Date()));
|
||||
s_logger.debug("Check id " + account.getId() + " bal=" + accountBalance + " alertDate" + alertDate + " current date" + new Date());
|
||||
}
|
||||
if (accountBalance.compareTo(zeroBalance) <= 0) {
|
||||
if (_lockAccountEnforcement && (lockable == 1)) {
|
||||
|
|
@ -234,7 +226,7 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
|||
}
|
||||
}
|
||||
|
||||
private void sendQuotaAlert(DeferredQuotaEmail emailToBeSent) {
|
||||
public void sendQuotaAlert(DeferredQuotaEmail emailToBeSent) {
|
||||
final AccountVO account = emailToBeSent.getAccount();
|
||||
final BigDecimal balance = emailToBeSent.getQuotaBalance();
|
||||
final BigDecimal usage = emailToBeSent.getQuotaUsage();
|
||||
|
|
@ -278,7 +270,7 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
|||
final String body = templateEngine.replace(emailTemplate.getTemplateBody());
|
||||
try {
|
||||
_emailQuotaAlert.sendQuotaAlert(emailRecipients, subject, body);
|
||||
emailToBeSent.sentSuccessfully();
|
||||
emailToBeSent.sentSuccessfully(_quotaAcc);
|
||||
} catch (Exception e) {
|
||||
s_logger.error(String.format("Unable to send quota alert email (subject=%s; body=%s) to account %s (%s) recipients (%s) due to error (%s)", subject, body, account.getAccountName(),
|
||||
account.getUuid(), emailRecipients, e));
|
||||
|
|
@ -288,7 +280,36 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
|||
}
|
||||
}
|
||||
|
||||
class DeferredQuotaEmail {
|
||||
public static long getDifferenceDays(Date d1, Date d2) {
|
||||
long diff = d2.getTime() - d1.getTime();
|
||||
return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
protected boolean lockAccount(long accountId) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
|
||||
boolean success = false;
|
||||
Account account = _accountDao.findById(accountId);
|
||||
if (account != null) {
|
||||
if (account.getState().equals(State.locked)) {
|
||||
return true; // already locked, no-op
|
||||
} else if (account.getState().equals(State.enabled)) {
|
||||
AccountVO acctForUpdate = _accountDao.createForUpdate();
|
||||
acctForUpdate.setState(State.locked);
|
||||
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
|
||||
} else {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_logger.warn("Failed to lock account " + accountId + ", account not found.");
|
||||
}
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return success;
|
||||
}
|
||||
|
||||
public static class DeferredQuotaEmail {
|
||||
private AccountVO account;
|
||||
private QuotaAccountVO quotaAccount;
|
||||
private QuotaConfig.QuotaEmailTemplateTypes emailTemplateType;
|
||||
|
|
@ -324,15 +345,14 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
|||
return emailTemplateType;
|
||||
}
|
||||
|
||||
public void sentSuccessfully() {
|
||||
public void sentSuccessfully(final QuotaAccountDao quotaAccountDao) {
|
||||
if (emailTemplateType == QuotaEmailTemplateTypes.QUOTA_STATEMENT) {
|
||||
quotaAccount.setLastStatementDate(new Date());
|
||||
_quotaAcc.update(quotaAccount.getAccountId(), quotaAccount);
|
||||
} else {
|
||||
quotaAccount.setQuotaAlertDate(new Date());
|
||||
quotaAccount.setQuotaAlertType(emailTemplateType.ordinal());
|
||||
_quotaAcc.update(quotaAccount.getAccountId(), quotaAccount);
|
||||
}
|
||||
quotaAccountDao.update(quotaAccount.getAccountId(), quotaAccount);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -421,54 +441,4 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Date startOfNextDay() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(new Date());
|
||||
c.add(Calendar.DATE, 1);
|
||||
Date dt = c.getTime();
|
||||
return dt;
|
||||
}
|
||||
|
||||
public static long getDifferenceDays(Date d1, Date d2) {
|
||||
long diff = d2.getTime() - d1.getTime();
|
||||
return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
protected boolean lockAccount(long accountId) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
|
||||
boolean success = false;
|
||||
Account account = _accountDao.findById(accountId);
|
||||
if (account != null) {
|
||||
if (account.getState().equals(State.locked)) {
|
||||
return true; // already locked, no-op
|
||||
} else if (account.getState().equals(State.enabled)) {
|
||||
AccountVO acctForUpdate = _accountDao.createForUpdate();
|
||||
acctForUpdate.setState(State.locked);
|
||||
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
|
||||
} else {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_logger.warn("Failed to lock account " + accountId + ", account not found.");
|
||||
}
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean enableAccount(long accountId) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
|
||||
boolean success = false;
|
||||
AccountVO acctForUpdate = _accountDao.createForUpdate();
|
||||
acctForUpdate.setState(State.enabled);
|
||||
acctForUpdate.setNeedsCleanup(false);
|
||||
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return success;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,27 +18,24 @@ package org.apache.cloudstack.quota;
|
|||
|
||||
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.Account.State;
|
||||
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.TransactionLegacy;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.dao.ServiceOfferingDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.quota.vo.ServiceOfferingVO;
|
||||
import org.apache.cloudstack.quota.dao.ServiceOfferingDao;
|
||||
import org.apache.cloudstack.utils.usage.UsageUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
@ -46,11 +43,9 @@ 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.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -142,122 +137,130 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
|||
return true;
|
||||
}
|
||||
|
||||
public List<QuotaUsageVO> aggregatePendingQuotaRecordsForAccount(final AccountVO account, final Pair<List<? extends UsageVO>, Integer> usageRecords) {
|
||||
List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
|
||||
if (usageRecords == null || usageRecords.first() == null || usageRecords.first().isEmpty()) {
|
||||
return quotaListForAccount;
|
||||
}
|
||||
s_logger.info("Getting pending quota records for account=" + account.getAccountName());
|
||||
for (UsageVO usageRecord: usageRecords.first()) {
|
||||
BigDecimal aggregationRatio = new BigDecimal(_aggregationDuration).divide(s_minutesInMonth, 8, RoundingMode.HALF_EVEN);
|
||||
switch (usageRecord.getUsageType()) {
|
||||
case QuotaTypes.RUNNING_VM:
|
||||
quotaListForAccount.addAll(updateQuotaRunningVMUsage(usageRecord, aggregationRatio));
|
||||
break;
|
||||
case QuotaTypes.ALLOCATED_VM:
|
||||
quotaListForAccount.add(updateQuotaAllocatedVMUsage(usageRecord, aggregationRatio));
|
||||
break;
|
||||
case QuotaTypes.SNAPSHOT:
|
||||
case QuotaTypes.TEMPLATE:
|
||||
case QuotaTypes.ISO:
|
||||
case QuotaTypes.VOLUME:
|
||||
case QuotaTypes.VM_SNAPSHOT:
|
||||
quotaListForAccount.add(updateQuotaDiskUsage(usageRecord, aggregationRatio, usageRecord.getUsageType()));
|
||||
break;
|
||||
case QuotaTypes.LOAD_BALANCER_POLICY:
|
||||
case QuotaTypes.PORT_FORWARDING_RULE:
|
||||
case QuotaTypes.IP_ADDRESS:
|
||||
case QuotaTypes.NETWORK_OFFERING:
|
||||
case QuotaTypes.SECURITY_GROUP:
|
||||
case QuotaTypes.VPN_USERS:
|
||||
quotaListForAccount.add(updateQuotaRaw(usageRecord, aggregationRatio, usageRecord.getUsageType()));
|
||||
break;
|
||||
case QuotaTypes.NETWORK_BYTES_RECEIVED:
|
||||
case QuotaTypes.NETWORK_BYTES_SENT:
|
||||
quotaListForAccount.add(updateQuotaNetwork(usageRecord, usageRecord.getUsageType()));
|
||||
break;
|
||||
case QuotaTypes.VM_DISK_IO_READ:
|
||||
case QuotaTypes.VM_DISK_IO_WRITE:
|
||||
case QuotaTypes.VM_DISK_BYTES_READ:
|
||||
case QuotaTypes.VM_DISK_BYTES_WRITE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return quotaListForAccount;
|
||||
}
|
||||
|
||||
public void processQuotaBalanceForAccount(final AccountVO account, final List<QuotaUsageVO> quotaListForAccount) {
|
||||
if (quotaListForAccount == null || quotaListForAccount.size() < 1) {
|
||||
return;
|
||||
}
|
||||
quotaListForAccount.add(new QuotaUsageVO());
|
||||
Date startDate = quotaListForAccount.get(0).getStartDate();
|
||||
Date endDate = quotaListForAccount.get(0).getEndDate();
|
||||
BigDecimal aggrUsage = new BigDecimal(0);
|
||||
for (QuotaUsageVO entry: quotaListForAccount) {
|
||||
if (startDate.compareTo(entry.getStartDate()) != 0) {
|
||||
QuotaBalanceVO lastRealBalanceEntry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), startDate);
|
||||
Date lastBalanceDate = new Date(0);
|
||||
if (lastRealBalanceEntry != null) {
|
||||
lastBalanceDate = lastRealBalanceEntry.getUpdatedOn();
|
||||
aggrUsage = aggrUsage.add(lastRealBalanceEntry.getCreditBalance());
|
||||
}
|
||||
|
||||
List<QuotaBalanceVO> creditsReceived = _quotaBalanceDao.findCreditBalance(account.getAccountId(), account.getDomainId(), lastBalanceDate, endDate);
|
||||
if (creditsReceived != null) {
|
||||
for (QuotaBalanceVO credit : creditsReceived) {
|
||||
aggrUsage = aggrUsage.add(credit.getCreditBalance());
|
||||
}
|
||||
}
|
||||
|
||||
QuotaBalanceVO newBalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, endDate);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Balance entry=" + aggrUsage + " on Date=" + endDate);
|
||||
}
|
||||
_quotaBalanceDao.persist(newBalance);
|
||||
aggrUsage = new BigDecimal(0);
|
||||
}
|
||||
startDate = entry.getStartDate();
|
||||
endDate = entry.getEndDate();
|
||||
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
|
||||
}
|
||||
|
||||
// update quota_accounts
|
||||
QuotaAccountVO quota_account = _quotaAcc.findById(account.getAccountId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Updating quota account bal=" + aggrUsage + " date=" + endDate);
|
||||
}
|
||||
if (quota_account == null) {
|
||||
quota_account = new QuotaAccountVO(account.getAccountId());
|
||||
quota_account.setQuotaBalance(aggrUsage);
|
||||
quota_account.setQuotaBalanceDate(endDate);
|
||||
_quotaAcc.persist(quota_account);
|
||||
} else {
|
||||
quota_account.setQuotaBalance(aggrUsage);
|
||||
quota_account.setQuotaBalanceDate(endDate);
|
||||
_quotaAcc.update(account.getAccountId(), quota_account);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean calculateQuotaUsage() {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
boolean jobResult = false;
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
// get all the active accounts for which there is usage
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB)) {
|
||||
List<AccountVO> accounts = _accountDao.listAll();
|
||||
for (AccountVO account : accounts) { // START ACCOUNT
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = null;
|
||||
List<QuotaUsageVO> quotalistforaccount = new ArrayList<QuotaUsageVO>();
|
||||
do {
|
||||
s_logger.info("Account =" + account.getAccountName());
|
||||
usageRecords = _usageDao.getUsageRecordsPendingQuotaAggregation(account.getAccountId(), account.getDomainId());
|
||||
s_logger.debug("Usage records found " + usageRecords.second());
|
||||
for (UsageVO usageRecord : usageRecords.first()) {
|
||||
BigDecimal aggregationRatio = new BigDecimal(_aggregationDuration).divide(s_minutesInMonth, 8, RoundingMode.HALF_EVEN);
|
||||
switch (usageRecord.getUsageType()) {
|
||||
case QuotaTypes.RUNNING_VM:
|
||||
case QuotaTypes.ALLOCATED_VM:
|
||||
quotalistforaccount.add(updateQuotaAllocatedVMUsage(usageRecord, aggregationRatio));
|
||||
break;
|
||||
case QuotaTypes.SNAPSHOT:
|
||||
case QuotaTypes.TEMPLATE:
|
||||
case QuotaTypes.ISO:
|
||||
case QuotaTypes.VOLUME:
|
||||
case QuotaTypes.VM_SNAPSHOT:
|
||||
quotalistforaccount.add(updateQuotaDiskUsage(usageRecord, aggregationRatio, usageRecord.getUsageType()));
|
||||
break;
|
||||
case QuotaTypes.LOAD_BALANCER_POLICY:
|
||||
case QuotaTypes.PORT_FORWARDING_RULE:
|
||||
case QuotaTypes.IP_ADDRESS:
|
||||
case QuotaTypes.NETWORK_OFFERING:
|
||||
case QuotaTypes.SECURITY_GROUP:
|
||||
case QuotaTypes.VPN_USERS:
|
||||
quotalistforaccount.add(updateQuotaRaw(usageRecord, aggregationRatio, usageRecord.getUsageType()));
|
||||
break;
|
||||
case QuotaTypes.NETWORK_BYTES_RECEIVED:
|
||||
case QuotaTypes.NETWORK_BYTES_SENT:
|
||||
quotalistforaccount.add(updateQuotaNetwork(usageRecord, usageRecord.getUsageType()));
|
||||
break;
|
||||
case QuotaTypes.VM_DISK_IO_READ:
|
||||
case QuotaTypes.VM_DISK_IO_WRITE:
|
||||
case QuotaTypes.VM_DISK_BYTES_READ:
|
||||
case QuotaTypes.VM_DISK_BYTES_WRITE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while ((usageRecords != null) && !usageRecords.first().isEmpty());
|
||||
// list of quotas for this account
|
||||
for (AccountVO account : accounts) {
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = _usageDao.getUsageRecordsPendingQuotaAggregation(account.getAccountId(), account.getDomainId());
|
||||
List<QuotaUsageVO> quotaListForAccount = aggregatePendingQuotaRecordsForAccount(account, usageRecords);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Quota entries size = " + quotalistforaccount.size() + ", accId" + account.getAccountId() + ", domId" + account.getDomainId());
|
||||
s_logger.debug("Quota entries size = " + quotaListForAccount.size() + ", accId" + account.getAccountId() + ", domId" + account.getDomainId());
|
||||
}
|
||||
if (quotalistforaccount.size() > 0) { // balance to be processed
|
||||
quotalistforaccount.add(new QuotaUsageVO());
|
||||
Date startDate = quotalistforaccount.get(0).getStartDate();
|
||||
Date endDate = quotalistforaccount.get(0).getEndDate();
|
||||
BigDecimal aggrUsage = new BigDecimal(0);
|
||||
for (QuotaUsageVO entry : quotalistforaccount) {
|
||||
if (startDate.compareTo(entry.getStartDate()) != 0) {
|
||||
QuotaBalanceVO lastrealbalanceentry = _quotaBalanceDao.findLastBalanceEntry(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.findCreditBalance(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);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Balance entry=" + aggrUsage + " on Date=" + endDate);
|
||||
}
|
||||
_quotaBalanceDao.persist(newbalance);
|
||||
aggrUsage = new BigDecimal(0);
|
||||
}
|
||||
startDate = entry.getStartDate();
|
||||
endDate = entry.getEndDate();
|
||||
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
|
||||
}
|
||||
// update is quota_accounts
|
||||
QuotaAccountVO quota_account = _quotaAcc.findById(account.getAccountId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Updating quota account bal=" + aggrUsage + " date=" + endDate);
|
||||
}
|
||||
if (quota_account == null) {
|
||||
quota_account = new QuotaAccountVO(account.getAccountId());
|
||||
quota_account.setQuotaBalance(aggrUsage);
|
||||
quota_account.setQuotaBalanceDate(endDate);
|
||||
_quotaAcc.persist(quota_account);
|
||||
} else {
|
||||
quota_account.setQuotaBalance(aggrUsage);
|
||||
quota_account.setQuotaBalanceDate(endDate);
|
||||
_quotaAcc.update(account.getAccountId(), quota_account);
|
||||
}
|
||||
}// balance processed
|
||||
} // END ACCOUNT
|
||||
processQuotaBalanceForAccount(account, quotaListForAccount);
|
||||
}
|
||||
jobResult = true;
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Quota Manager error", e);
|
||||
} finally {
|
||||
txn.close();
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return jobResult;
|
||||
}
|
||||
|
||||
@DB
|
||||
private QuotaUsageVO updateQuotaDiskUsage(UsageVO usageRecord, final BigDecimal aggregationRatio, final int quotaType) {
|
||||
public QuotaUsageVO updateQuotaDiskUsage(UsageVO usageRecord, final BigDecimal aggregationRatio, final int quotaType) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(quotaType, usageRecord.getEndDate());
|
||||
if (tariff != null && !tariff.getCurrencyValue().equals(0)) {
|
||||
|
|
@ -277,7 +280,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
|||
}
|
||||
|
||||
@DB
|
||||
private List<QuotaUsageVO> updateQuotaRunningVMUsage(UsageVO usageRecord, final BigDecimal aggregationRatio) {
|
||||
public List<QuotaUsageVO> updateQuotaRunningVMUsage(UsageVO usageRecord, final BigDecimal aggregationRatio) {
|
||||
List<QuotaUsageVO> quotalist = new ArrayList<QuotaUsageVO>();
|
||||
QuotaUsageVO quota_usage;
|
||||
BigDecimal cpuquotausgage, speedquotausage, memoryquotausage, vmusage;
|
||||
|
|
@ -333,7 +336,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
|||
}
|
||||
|
||||
@DB
|
||||
private QuotaUsageVO updateQuotaAllocatedVMUsage(UsageVO usageRecord, final BigDecimal aggregationRatio) {
|
||||
public QuotaUsageVO updateQuotaAllocatedVMUsage(UsageVO usageRecord, final BigDecimal aggregationRatio) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.ALLOCATED_VM, usageRecord.getEndDate());
|
||||
if (tariff != null && !tariff.getCurrencyValue().equals(0)) {
|
||||
|
|
@ -352,7 +355,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
|||
}
|
||||
|
||||
@DB
|
||||
private QuotaUsageVO updateQuotaRaw(UsageVO usageRecord, final BigDecimal aggregationRatio, final int ruleType) {
|
||||
public QuotaUsageVO updateQuotaRaw(UsageVO usageRecord, final BigDecimal aggregationRatio, final int ruleType) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(ruleType, usageRecord.getEndDate());
|
||||
if (tariff != null && !tariff.getCurrencyValue().equals(0)) {
|
||||
|
|
@ -371,7 +374,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
|||
}
|
||||
|
||||
@DB
|
||||
private QuotaUsageVO updateQuotaNetwork(UsageVO usageRecord, final int transferType) {
|
||||
public QuotaUsageVO updateQuotaNetwork(UsageVO usageRecord, final int transferType) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(transferType, usageRecord.getEndDate());
|
||||
if (tariff != null && !tariff.getCurrencyValue().equals(0)) {
|
||||
|
|
@ -391,47 +394,4 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
|||
return quota_usage;
|
||||
}
|
||||
|
||||
public Date startOfNextDay() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(new Date());
|
||||
c.add(Calendar.DATE, 1);
|
||||
Date dt = c.getTime();
|
||||
return dt;
|
||||
}
|
||||
|
||||
protected boolean lockAccount(long accountId) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
|
||||
boolean success = false;
|
||||
Account account = _accountDao.findById(accountId);
|
||||
if (account != null) {
|
||||
if (account.getState().equals(State.locked)) {
|
||||
return true; // already locked, no-op
|
||||
} else if (account.getState().equals(State.enabled)) {
|
||||
AccountVO acctForUpdate = _accountDao.createForUpdate();
|
||||
acctForUpdate.setState(State.locked);
|
||||
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
|
||||
} else {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_logger.warn("Failed to lock account " + accountId + ", account not found.");
|
||||
}
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean enableAccount(long accountId) {
|
||||
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
|
||||
boolean success = false;
|
||||
AccountVO acctForUpdate = _accountDao.createForUpdate();
|
||||
acctForUpdate.setState(State.enabled);
|
||||
acctForUpdate.setNeedsCleanup(false);
|
||||
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
|
||||
TransactionLegacy.open(opendb).close();
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,239 @@
|
|||
// 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.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import javax.mail.MessagingException;
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaAlertManagerImplTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
AccountDao accountDao;
|
||||
@Mock
|
||||
QuotaAccountDao quotaAcc;
|
||||
@Mock
|
||||
UserDao userDao;
|
||||
@Mock
|
||||
DomainDao domainDao;
|
||||
@Mock
|
||||
QuotaEmailTemplatesDao quotaEmailTemplateDao;
|
||||
@Mock
|
||||
ConfigurationDao configDao;
|
||||
@Mock
|
||||
QuotaUsageDao quotaUsage;
|
||||
@Mock
|
||||
QuotaAlertManagerImpl.EmailQuotaAlert emailQuotaAlert;
|
||||
|
||||
@Spy
|
||||
QuotaAlertManagerImpl quotaAlertManager = new QuotaAlertManagerImpl();
|
||||
|
||||
private void injectMockToField(Object mock, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field f = QuotaAlertManagerImpl.class.getDeclaredField(fieldName);
|
||||
f.setAccessible(true);
|
||||
f.set(quotaAlertManager, mock);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
|
||||
// Dummy transaction stack setup
|
||||
TransactionLegacy.open("QuotaAlertManagerImplTest");
|
||||
|
||||
injectMockToField(accountDao, "_accountDao");
|
||||
injectMockToField(quotaAcc, "_quotaAcc");
|
||||
injectMockToField(userDao, "_userDao");
|
||||
injectMockToField(domainDao, "_domainDao");
|
||||
injectMockToField(quotaEmailTemplateDao, "_quotaEmailTemplateDao");
|
||||
injectMockToField(configDao, "_configDao");
|
||||
injectMockToField(quotaUsage, "_quotaUsage");
|
||||
injectMockToField(emailQuotaAlert, "_emailQuotaAlert");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartStop() {
|
||||
try {
|
||||
quotaAlertManager.start(); // expected to fail as pid is not available
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
assertTrue(quotaAlertManager.stop());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendMonthlyStatement() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO);
|
||||
|
||||
QuotaAccountVO acc = new QuotaAccountVO(2L);
|
||||
acc.setQuotaBalance(new BigDecimal(404));
|
||||
acc.setLastStatementDate(null);
|
||||
List<QuotaAccountVO> accounts = new ArrayList<>();
|
||||
accounts.add(acc);
|
||||
Mockito.when(quotaAcc.listAll()).thenReturn(accounts);
|
||||
|
||||
Mockito.when(quotaUsage.findTotalQuotaUsage(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyInt(),
|
||||
Mockito.any(Date.class), Mockito.any(Date.class))).thenReturn(new BigDecimal(100));
|
||||
|
||||
// Don't test sendQuotaAlert yet
|
||||
Mockito.doNothing().when(quotaAlertManager).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
|
||||
// call real method on send monthly statement
|
||||
Mockito.doCallRealMethod().when(quotaAlertManager).sendMonthlyStatement(Mockito.any(Date.class));
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(new Date());
|
||||
cal.set(Calendar.DATE, 1); // simulate sending statement on 1st of the month
|
||||
Date nowDate = cal.getTime();
|
||||
|
||||
assertTrue(nowDate.getDate() < 6);
|
||||
quotaAlertManager.sendMonthlyStatement(nowDate);
|
||||
Mockito.verify(quotaAlertManager, Mockito.times(accounts.size())).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckAndSendQuotaAlertEmails() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
|
||||
Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO);
|
||||
|
||||
QuotaAccountVO acc = new QuotaAccountVO(2L);
|
||||
acc.setQuotaBalance(new BigDecimal(404));
|
||||
acc.setQuotaMinBalance(new BigDecimal(100));
|
||||
acc.setQuotaBalanceDate(new Date());
|
||||
acc.setQuotaAlertDate(null);
|
||||
acc.setQuotaEnforce(0);
|
||||
List<QuotaAccountVO> accounts = new ArrayList<>();
|
||||
accounts.add(acc);
|
||||
Mockito.when(quotaAcc.listAll()).thenReturn(accounts);
|
||||
|
||||
// Don't test sendQuotaAlert yet
|
||||
Mockito.doNothing().when(quotaAlertManager).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
Mockito.doReturn(true).when(quotaAlertManager).lockAccount(Mockito.anyLong());
|
||||
|
||||
// call real method on send monthly statement
|
||||
Mockito.doCallRealMethod().when(quotaAlertManager).checkAndSendQuotaAlertEmails();
|
||||
|
||||
// Case1: valid balance, no email should be sent
|
||||
quotaAlertManager.checkAndSendQuotaAlertEmails();
|
||||
Mockito.verify(quotaAlertManager, Mockito.times(0)).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
|
||||
// Case2: low balance, email should be sent
|
||||
accounts.get(0).setQuotaBalance(new BigDecimal(99));
|
||||
//Mockito.when(quotaAcc.listAll()).thenReturn(accounts);
|
||||
quotaAlertManager.checkAndSendQuotaAlertEmails();
|
||||
Mockito.verify(quotaAlertManager, Mockito.times(1)).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSendQuotaAlert() throws UnsupportedEncodingException, MessagingException {
|
||||
Mockito.doCallRealMethod().when(quotaAlertManager).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
|
||||
AccountVO account = new AccountVO();
|
||||
account.setId(2L);
|
||||
account.setDomainId(1L);
|
||||
account.setType(Account.ACCOUNT_TYPE_NORMAL);
|
||||
account.setAccountName("admin");
|
||||
account.setUuid("uuid");
|
||||
|
||||
QuotaAccountVO quotaAccount = new QuotaAccountVO(2L);
|
||||
quotaAccount.setQuotaBalance(new BigDecimal(404));
|
||||
quotaAccount.setQuotaMinBalance(new BigDecimal(100));
|
||||
quotaAccount.setQuotaBalanceDate(new Date());
|
||||
quotaAccount.setQuotaAlertDate(null);
|
||||
quotaAccount.setQuotaEnforce(0);
|
||||
|
||||
QuotaAlertManagerImpl.DeferredQuotaEmail email = new QuotaAlertManagerImpl.DeferredQuotaEmail(account, quotaAccount, new BigDecimal(100), QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW);
|
||||
|
||||
QuotaEmailTemplatesVO quotaEmailTemplatesVO = new QuotaEmailTemplatesVO();
|
||||
quotaEmailTemplatesVO.setTemplateSubject("Low quota");
|
||||
quotaEmailTemplatesVO.setTemplateBody("Low quota {{accountID}}");
|
||||
List<QuotaEmailTemplatesVO> emailTemplates = new ArrayList<>();
|
||||
emailTemplates.add(quotaEmailTemplatesVO);
|
||||
Mockito.when(quotaEmailTemplateDao.listAllQuotaEmailTemplates(Mockito.anyString())).thenReturn(emailTemplates);
|
||||
|
||||
DomainVO domain = new DomainVO();
|
||||
domain.setUuid("uuid");
|
||||
domain.setName("/domain");
|
||||
Mockito.when(domainDao.findByIdIncludingRemoved(Mockito.anyLong())).thenReturn(new DomainVO());
|
||||
|
||||
UserVO user = new UserVO();
|
||||
user.setUsername("user1");
|
||||
user.setEmail("user1@apache.org");
|
||||
List<UserVO> users = new ArrayList<>();
|
||||
users.add(user);
|
||||
Mockito.when(userDao.listByAccount(Mockito.anyLong())).thenReturn(users);
|
||||
|
||||
quotaAlertManager.sendQuotaAlert(email);
|
||||
Mockito.verify(emailQuotaAlert, Mockito.times(1)).sendQuotaAlert(Mockito.anyList(), Mockito.anyString(), Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDifferenceDays() {
|
||||
Date now = new Date();
|
||||
assertTrue(QuotaAlertManagerImpl.getDifferenceDays(now, now) == 0L);
|
||||
assertTrue(QuotaAlertManagerImpl.getDifferenceDays(now, new DateTime(now).plusDays(1).toDate()) == 1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockAccount() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
|
||||
accountVO.setState(Account.State.enabled);
|
||||
Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO);
|
||||
Mockito.when(accountDao.createForUpdate()).thenReturn(accountVO);
|
||||
Mockito.when(accountDao.update(Mockito.eq(accountVO.getId()), Mockito.eq(accountVO))).thenReturn(true);
|
||||
assertTrue(quotaAlertManager.lockAccount(accountVO.getId()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
// 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.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.db.TransactionLegacy;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.dao.ServiceOfferingDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaManagerImplTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
private AccountDao accountDao;
|
||||
@Mock
|
||||
private QuotaAccountDao quotaAcc;
|
||||
@Mock
|
||||
private UsageDao usageDao;
|
||||
@Mock
|
||||
private QuotaTariffDao quotaTariffDao;
|
||||
@Mock
|
||||
private QuotaUsageDao quotaUsageDao;
|
||||
@Mock
|
||||
private ServiceOfferingDao serviceOfferingDao;
|
||||
@Mock
|
||||
private QuotaBalanceDao quotaBalanceDao;
|
||||
@Mock
|
||||
private ConfigurationDao configDao;
|
||||
|
||||
@Spy
|
||||
QuotaManagerImpl quotaManager = new QuotaManagerImpl();
|
||||
|
||||
private void injectMockToField(Object mock, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field f = QuotaManagerImpl.class.getDeclaredField(fieldName);
|
||||
f.setAccessible(true);
|
||||
f.set(quotaManager, mock);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
|
||||
// Dummy transaction stack setup
|
||||
TransactionLegacy.open("QuotaManagerImplTest");
|
||||
|
||||
injectMockToField(accountDao, "_accountDao");
|
||||
injectMockToField(quotaAcc, "_quotaAcc");
|
||||
injectMockToField(usageDao, "_usageDao");
|
||||
injectMockToField(quotaTariffDao, "_quotaTariffDao");
|
||||
injectMockToField(quotaUsageDao, "_quotaUsageDao");
|
||||
injectMockToField(serviceOfferingDao, "_serviceOfferingDao");
|
||||
injectMockToField(quotaBalanceDao, "_quotaBalanceDao");
|
||||
injectMockToField(configDao, "_configDao");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartStop() {
|
||||
try {
|
||||
quotaManager.start(); // expected to fail as pid is not available
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
assertTrue(quotaManager.stop());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfig() throws ConfigurationException {
|
||||
Mockito.when(configDao.getConfiguration(Mockito.anyMapOf(String.class, Object.class))).thenReturn(new HashMap<String, String>());
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("usage.stats.job.aggregation.range", "0");
|
||||
assertTrue(quotaManager.configure("quotaManager", map));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateQuotaUsage() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
|
||||
List<AccountVO> accountVOList = new ArrayList<>();
|
||||
accountVOList.add(accountVO);
|
||||
Mockito.when(accountDao.listAll()).thenReturn(accountVOList);
|
||||
|
||||
UsageVO usageVO = new UsageVO();
|
||||
usageVO.setQuotaCalculated(0);
|
||||
List<UsageVO> usageVOList = new ArrayList<UsageVO>();
|
||||
usageVOList.add(usageVO);
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = new Pair<List<? extends UsageVO>, Integer>(usageVOList, usageVOList.size());
|
||||
Mockito.when(usageDao.getUsageRecordsPendingQuotaAggregation(Mockito.anyLong(), Mockito.anyLong())).thenReturn(usageRecords);
|
||||
|
||||
QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
|
||||
quotaUsageVO.setAccountId(2L);
|
||||
List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
|
||||
quotaListForAccount.add(quotaUsageVO);
|
||||
Mockito.doReturn(quotaListForAccount).when(quotaManager).aggregatePendingQuotaRecordsForAccount(Mockito.eq(accountVO), Mockito.eq(usageRecords));
|
||||
Mockito.doNothing().when(quotaManager).processQuotaBalanceForAccount(Mockito.eq(accountVO), Mockito.eq(quotaListForAccount));
|
||||
|
||||
assertTrue(quotaManager.calculateQuotaUsage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAggregatePendingQuotaRecordsForAccount() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
|
||||
|
||||
UsageVO usageVO = new UsageVO();
|
||||
usageVO.setQuotaCalculated(0);
|
||||
usageVO.setUsageType(UsageTypes.ALLOCATED_VM);
|
||||
List<UsageVO> usageVOList = new ArrayList<UsageVO>();
|
||||
usageVOList.add(usageVO);
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = new Pair<List<? extends UsageVO>, Integer>(usageVOList, usageVOList.size());
|
||||
|
||||
QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
|
||||
quotaUsageVO.setAccountId(2L);
|
||||
Mockito.doReturn(quotaUsageVO).when(quotaManager).updateQuotaAllocatedVMUsage(Mockito.eq(usageVO), Mockito.any(BigDecimal.class));
|
||||
|
||||
assertTrue(quotaManager.aggregatePendingQuotaRecordsForAccount(accountVO, new Pair<List<? extends UsageVO>, Integer>(null, 0)).size() == 0);
|
||||
assertTrue(quotaManager.aggregatePendingQuotaRecordsForAccount(accountVO, usageRecords).size() == 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessQuotaBalanceForAccount() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.ACCOUNT_TYPE_NORMAL);
|
||||
|
||||
QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
|
||||
quotaUsageVO.setAccountId(2L);
|
||||
quotaUsageVO.setStartDate(new Date());
|
||||
quotaUsageVO.setEndDate(new Date());
|
||||
List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
|
||||
quotaListForAccount.add(quotaUsageVO);
|
||||
|
||||
quotaManager.processQuotaBalanceForAccount(accountVO, quotaListForAccount);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persist(Mockito.any(QuotaAccountVO.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateQuotaRecords() {
|
||||
UsageVO usageVO = new UsageVO();
|
||||
usageVO.setId(100L);
|
||||
usageVO.setQuotaCalculated(0);
|
||||
usageVO.setUsageType(UsageTypes.NETWORK_BYTES_SENT);
|
||||
usageVO.setRawUsage(9000000000.0);
|
||||
usageVO.setSize(1010101010L);
|
||||
|
||||
QuotaTariffVO tariffVO = new QuotaTariffVO();
|
||||
tariffVO.setCurrencyValue(new BigDecimal(1));
|
||||
Mockito.when(quotaTariffDao.findTariffPlanByUsageType(Mockito.anyInt(), Mockito.any(Date.class))).thenReturn(tariffVO);
|
||||
|
||||
quotaManager.updateQuotaNetwork(usageVO, UsageTypes.NETWORK_BYTES_SENT);
|
||||
quotaManager.updateQuotaAllocatedVMUsage(usageVO, new BigDecimal(0.5));
|
||||
quotaManager.updateQuotaDiskUsage(usageVO, new BigDecimal(0.5), UsageTypes.VOLUME);
|
||||
quotaManager.updateQuotaRaw(usageVO, new BigDecimal(0.5), UsageTypes.VPN_USERS);
|
||||
|
||||
Mockito.verify(quotaUsageDao, Mockito.times(4)).persist(Mockito.any(QuotaUsageVO.class));
|
||||
Mockito.verify(usageDao, Mockito.times(4)).persist(Mockito.any(UsageVO.class));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue