mirror of https://github.com/apache/cloudstack.git
Merge pull request #768 from shapeblue/quota-master
Implement Quota serviceThis pull request is for quota service implementation, divided into following commits: Quota server side implementation a. Quota Framework plugin containing Daos b. Quota database plugin for quota APIs c. Quota Usage server enhancements d. Quota UI plugin e. Tests * pr/768: CLOUDSTACK-8592: Implement Quota service Signed-off-by: Remi Bergsma <github@remi.nl>
This commit is contained in:
commit
24d06099ff
|
|
@ -273,6 +273,7 @@ public class ApiConstants {
|
|||
public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
|
||||
public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount";
|
||||
public static final String USAGE_ID = "usageid";
|
||||
public static final String USAGE_TYPE = "usagetype";
|
||||
|
||||
public static final String VLAN = "vlan";
|
||||
public static final String VLAN_RANGE = "vlanrange";
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ public abstract class BaseCmd {
|
|||
GET, POST, PUT, DELETE
|
||||
}
|
||||
public static enum CommandType {
|
||||
BOOLEAN, DATE, FLOAT, INTEGER, SHORT, LIST, LONG, OBJECT, MAP, STRING, TZDATE, UUID
|
||||
BOOLEAN, DATE, FLOAT, DOUBLE, INTEGER, SHORT, LIST, LONG, OBJECT, MAP, STRING, TZDATE, UUID
|
||||
}
|
||||
|
||||
private Object _responseObject;
|
||||
|
|
|
|||
|
|
@ -111,6 +111,30 @@ public class GetUsageRecordsCmd extends BaseListCmd {
|
|||
public String getUsageId() {
|
||||
return usageId;
|
||||
}
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public void setUsageId(String usageId) {
|
||||
this.usageId = usageId;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ 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
|
||||
public static final int IP_ADDRESS = 3;
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1423,6 +1423,47 @@ label.show.advanced.settings=Show advanced settings
|
|||
label.delete.OpenDaylight.device=Delete OpenDaylight Controller
|
||||
label.polling.interval.sec=Polling Interval (in sec)
|
||||
label.quiet.time.sec=Quiet Time (in sec)
|
||||
label.usage.type=Usage Type
|
||||
label.usage.unit=Unit
|
||||
label.quota.value=Quota Value
|
||||
label.quota.description=Quota Description
|
||||
label.quota.configuration=Quota Configuration
|
||||
label.quota.configure=Configure Quota
|
||||
label.quota.remove=Remove Quota
|
||||
label.quota.totalusage=Total Usage
|
||||
label.quota.balance=Balance
|
||||
label.quota.minbalance=Min Balance
|
||||
label.quota.enforcequota=Enforce Quota
|
||||
label.quota.summary=Summary
|
||||
label.quota.fullsummary=All Accounts
|
||||
label.quota.tariff=Tariff
|
||||
label.quota.state=State
|
||||
label.quota.startdate=Start Date
|
||||
label.quota.enddate=End Date
|
||||
label.quota.total=Total
|
||||
label.quota.startquota=Start Quota
|
||||
label.quota.endquota=End Quota
|
||||
label.quota.type.name=Usage Type
|
||||
label.quota.type.unit=Usage Unit
|
||||
label.quota.usage=Quota Consumption
|
||||
label.quota.add.credits=Add Credits
|
||||
label.quota.email.template=Email Template
|
||||
label.quota.statement=Statement
|
||||
label.quota.statement.balance=Quota Balance
|
||||
label.quota.statement.quota=Quota Usage
|
||||
label.quota.statement.tariff=Quota Tariff
|
||||
label.quota.tariff.value=Tariff Value
|
||||
label.quota.tariff.edit=Edit Tariff
|
||||
label.quota.tariff.effectivedate=Effective Date
|
||||
label.quota.date=Date
|
||||
label.quota.dates=Update Dates
|
||||
label.quota.credit=Credit
|
||||
label.quota.credits=Credits
|
||||
label.quota.value=Quota Value
|
||||
label.quota.statement.bydates=Statement
|
||||
label.quota.email.subject=Subject
|
||||
label.quota.email.body=Body
|
||||
label.quota.email.lastupdated=Last Update
|
||||
label.destroy.vm.graceperiod=Destroy VM Grace Period
|
||||
label.SNMP.community=SNMP Community
|
||||
label.SNMP.port=SNMP Port
|
||||
|
|
|
|||
|
|
@ -256,6 +256,11 @@
|
|||
<artifactId>cloud-framework-ipc</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-framework-quota</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-framework-rest</artifactId>
|
||||
|
|
@ -366,6 +371,11 @@
|
|||
<artifactId>cloud-plugin-network-globodns</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-database-quota</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
|||
|
|
@ -787,3 +787,14 @@ addGloboDnsHost=1
|
|||
### volume/template post upload
|
||||
getUploadParamsForVolume=15
|
||||
getUploadParamsForTemplate=15
|
||||
|
||||
### Quota Service
|
||||
quotaStatement=15
|
||||
quotaBalance=15
|
||||
quotaSummary=15
|
||||
quotaUpdate=1
|
||||
quotaTariffList=15
|
||||
quotaTariffUpdate=1
|
||||
quotaCredits=1
|
||||
quotaEmailTemplateList=1
|
||||
quotaEmailTemplateUpdate=1
|
||||
|
|
|
|||
|
|
@ -340,4 +340,4 @@ public class Upgrade452to460 implements DbUpgrade {
|
|||
}
|
||||
s_logger.debug("Updating System Vm Template IDs Complete");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import org.apache.log4j.Logger;
|
|||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class Upgrade461to470 implements DbUpgrade {
|
||||
final static Logger s_logger = Logger.getLogger(Upgrade461to470.class);
|
||||
|
|
@ -51,8 +53,23 @@ public class Upgrade461to470 implements DbUpgrade {
|
|||
return new File[] {new File(script)};
|
||||
}
|
||||
|
||||
public void alterAddColumnToCloudUsage(final Connection conn) {
|
||||
final String alterTableSql = "ALTER TABLE `cloud_usage`.`cloud_usage` ADD COLUMN `quota_calculated` tinyint(1) DEFAULT 0 NOT NULL COMMENT 'quota calculation status'";
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(alterTableSql)) {
|
||||
pstmt.executeUpdate();
|
||||
s_logger.info("Altered cloud_usage.cloud_usage table and added column quota_calculated");
|
||||
} catch (SQLException e) {
|
||||
if (e.getMessage().contains("quota_calculated")) {
|
||||
s_logger.warn("cloud_usage.cloud_usage table already has a column called quota_calculated");
|
||||
} else {
|
||||
throw new CloudRuntimeException("Unable to create column quota_calculated in table cloud_usage.cloud_usage", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performDataMigration(Connection conn) {
|
||||
alterAddColumnToCloudUsage(conn);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -103,6 +103,17 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date endDate = null;
|
||||
|
||||
@Column(name = "quota_calculated")
|
||||
private Integer quotaCalculated = 0;
|
||||
|
||||
public Integer getQuotaCalculated() {
|
||||
return quotaCalculated;
|
||||
}
|
||||
|
||||
public void setQuotaCalculated(Integer quotaCalculated) {
|
||||
this.quotaCalculated = quotaCalculated;
|
||||
}
|
||||
|
||||
public UsageVO() {
|
||||
}
|
||||
|
||||
|
|
@ -121,8 +132,8 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
this.templateId = templateId;
|
||||
this.usageId = usageId;
|
||||
this.size = size;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public UsageVO(Long zoneId, Long accountId, Long domainId, String description, String usageDisplay, int usageType, Double rawUsage, Long vmId, String vmName,
|
||||
|
|
@ -141,8 +152,8 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
this.usageId = usageId;
|
||||
this.size = size;
|
||||
this.virtualSize = virtualSize;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public UsageVO(Long zoneId, Long accountId, Long domainId, String description, String usageDisplay, int usageType, Double rawUsage, Long usageId, String type,
|
||||
|
|
@ -157,8 +168,8 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
this.usageId = usageId;
|
||||
this.type = type;
|
||||
this.networkId = networkId;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public UsageVO(Long zoneId, Long accountId, Long domainId, String description, String usageDisplay, int usageType, Double rawUsage, Long vmId, String vmName,
|
||||
|
|
@ -176,8 +187,8 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
this.templateId = templateId;
|
||||
this.usageId = usageId;
|
||||
this.type = type;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public UsageVO(Long zoneId, Long accountId, Long domainId, String description, String usageDisplay, int usageType, Double rawUsage, Long vmId, String vmName,
|
||||
|
|
@ -198,8 +209,8 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
this.templateId = templateId;
|
||||
this.usageId = usageId;
|
||||
this.type = type;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
//IPAddress Usage
|
||||
|
|
@ -215,8 +226,8 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
this.usageId = usageId;
|
||||
this.size = size;
|
||||
this.type = type;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -321,11 +332,55 @@ public class UsageVO implements Usage, InternalIdentity {
|
|||
|
||||
@Override
|
||||
public Date getStartDate() {
|
||||
return startDate;
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
return endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,4 +55,8 @@ public interface UsageDao extends GenericDao<UsageVO, Long> {
|
|||
void saveUsageRecords(List<UsageVO> usageRecords);
|
||||
|
||||
void removeOldUsageRecords(int days);
|
||||
|
||||
UsageVO persistUsage(final UsageVO usage);
|
||||
|
||||
Pair<List<? extends UsageVO>, Integer> getUsageRecordsPendingQuotaAggregation(long accountId, long domainId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,14 @@ import com.cloud.utils.DateUtil;
|
|||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.QueryBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
|
@ -45,29 +50,24 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
private static final String DELETE_ALL_BY_ACCOUNTID = "DELETE FROM cloud_usage WHERE account_id = ?";
|
||||
private static final String DELETE_ALL_BY_INTERVAL = "DELETE FROM cloud_usage WHERE end_date < DATE_SUB(CURRENT_DATE(), INTERVAL ? DAY)";
|
||||
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");
|
||||
|
|
@ -213,7 +213,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());
|
||||
|
|
@ -310,7 +310,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());
|
||||
|
|
@ -467,4 +467,40 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
txn.close();
|
||||
}
|
||||
}
|
||||
|
||||
public UsageVO persistUsage(final UsageVO usage) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<UsageVO>() {
|
||||
@Override
|
||||
public UsageVO doInTransaction(final TransactionStatus status) {
|
||||
return persist(usage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<Pair<List<? extends UsageVO>, Integer>>() {
|
||||
@Override
|
||||
public Pair<List<? extends UsageVO>, Integer> doInTransaction(final TransactionStatus status) {
|
||||
Pair<List<UsageVO>, Integer> usageRecords = new Pair<List<UsageVO>, Integer>(new ArrayList<UsageVO>(), 0);
|
||||
Filter usageFilter = new Filter(UsageVO.class, "startDate", true, 0L, Long.MAX_VALUE);
|
||||
QueryBuilder<UsageVO> qb = QueryBuilder.create(UsageVO.class);
|
||||
if (accountId != -1) {
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
}
|
||||
if (domainId != -1) {
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
}
|
||||
qb.and(qb.entity().getQuotaCalculated(), SearchCriteria.Op.NEQ, 1);
|
||||
qb.and(qb.entity().getRawUsage(), SearchCriteria.Op.GT, 0);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Getting usage records" + usageFilter.getOrderBy());
|
||||
}
|
||||
usageRecords = searchAndCountAllRecords(qb.create(), usageFilter);
|
||||
return new Pair<List<? extends UsageVO>, Integer>(usageRecords.first(), usageRecords.second());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,18 +35,11 @@ public class Transaction {
|
|||
if (currentTxn != null) {
|
||||
databaseId = currentTxn.getDatabaseId();
|
||||
}
|
||||
TransactionLegacy txn = TransactionLegacy.open(name, databaseId, false);
|
||||
try {
|
||||
// if (txn.dbTxnStarted()){
|
||||
// String warnMsg = "Potential Wrong Usage: TRANSACTION.EXECUTE IS WRAPPED INSIDE ANOTHER DB TRANSACTION!";
|
||||
// s_logger.warn(warnMsg, new CloudRuntimeException(warnMsg));
|
||||
// }
|
||||
try (final TransactionLegacy txn = TransactionLegacy.open(name, databaseId, false)) {
|
||||
txn.start();
|
||||
T result = callback.doInTransaction(STATUS);
|
||||
txn.commit();
|
||||
return result;
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,4 +52,28 @@ public class Transaction {
|
|||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static <T, E extends Throwable> T execute(final short databaseId, TransactionCallbackWithException<T, E> callback) throws E {
|
||||
String name = "tx-" + counter.incrementAndGet();
|
||||
TransactionLegacy currentTxn = TransactionLegacy.currentTxn(false);
|
||||
short outer_txn_databaseId = (currentTxn != null ? currentTxn.getDatabaseId() : databaseId);
|
||||
try (final TransactionLegacy txn = TransactionLegacy.open(name, databaseId, true)) {
|
||||
txn.start();
|
||||
T result = callback.doInTransaction(STATUS);
|
||||
txn.commit();
|
||||
return result;
|
||||
} finally {
|
||||
TransactionLegacy.open(outer_txn_databaseId).close();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T execute(final short databaseId, final TransactionCallback<T> callback) {
|
||||
return execute(databaseId, new TransactionCallbackWithException<T, RuntimeException>() {
|
||||
@Override
|
||||
public T doInTransaction(TransactionStatus status) throws RuntimeException {
|
||||
return callback.doInTransaction(status);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
<module>rest</module>
|
||||
<module>events</module>
|
||||
<module>jobs</module>
|
||||
<module>quota</module>
|
||||
<module>cluster</module>
|
||||
<module>db</module>
|
||||
<module>config</module>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<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-framework-quota</artifactId>
|
||||
<name>Apache CloudStack Framework - Quota</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-framework</artifactId>
|
||||
<version>4.7.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<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>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${cs.commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<!-- 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. -->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<bean id="QuotaTariffDao" class="org.apache.cloudstack.quota.dao.QuotaTariffDaoImpl" />
|
||||
<bean id="QuotaAccountDao" class="org.apache.cloudstack.quota.dao.QuotaAccountDaoImpl" />
|
||||
<bean id="QuotaBalanceDao" class="org.apache.cloudstack.quota.dao.QuotaBalanceDaoImpl" />
|
||||
<bean id="QuotaCreditsDao" class="org.apache.cloudstack.quota.dao.QuotaCreditsDaoImpl" />
|
||||
<bean id="QuotaEmailTemplatesDao"
|
||||
class="org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDaoImpl" />
|
||||
<bean id="QuotaUsageDao" class="org.apache.cloudstack.quota.dao.QuotaUsageDaoImpl" />
|
||||
<bean id="ServiceOfferingDao" class="org.apache.cloudstack.quota.dao.ServiceOfferingDaoImpl" />
|
||||
<bean id="UserVmDetailsDao" class="org.apache.cloudstack.quota.dao.UserVmDetailsDaoImpl" />
|
||||
|
||||
<bean id="QuotaManager" class="org.apache.cloudstack.quota.QuotaManagerImpl" />
|
||||
<bean id="QuotaAlertManager" class="org.apache.cloudstack.quota.QuotaAlertManagerImpl" />
|
||||
<bean id="QuotaStatement" class="org.apache.cloudstack.quota.QuotaStatementImpl" />
|
||||
|
||||
</beans>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
//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
|
||||
//the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import com.cloud.utils.component.Manager;
|
||||
|
||||
import org.apache.cloudstack.quota.QuotaAlertManagerImpl.DeferredQuotaEmail;
|
||||
|
||||
public interface QuotaAlertManager extends Manager {
|
||||
void checkAndSendQuotaAlertEmails();
|
||||
void sendQuotaAlert(DeferredQuotaEmail emailToBeSent);
|
||||
}
|
||||
|
|
@ -0,0 +1,418 @@
|
|||
//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.Account.State;
|
||||
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.NumbersUtil;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.google.common.base.Strings;
|
||||
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;
|
||||
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.apache.commons.lang3.text.StrSubstitutor;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.Authenticator;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.PasswordAuthentication;
|
||||
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;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
@Local(value = QuotaAlertManager.class)
|
||||
public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertManager {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaAlertManagerImpl.class);
|
||||
|
||||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private QuotaAccountDao _quotaAcc;
|
||||
@Inject
|
||||
private UserDao _userDao;
|
||||
@Inject
|
||||
private DomainDao _domainDao;
|
||||
@Inject
|
||||
private QuotaEmailTemplatesDao _quotaEmailTemplateDao;
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsage;
|
||||
|
||||
private EmailQuotaAlert _emailQuotaAlert;
|
||||
private boolean _lockAccountEnforcement = false;
|
||||
|
||||
boolean _smtpDebug = false;
|
||||
|
||||
public QuotaAlertManagerImpl() {
|
||||
super();
|
||||
}
|
||||
|
||||
private void mergeConfigs(Map<String, String> dbParams, Map<String, Object> xmlParams) {
|
||||
for (Map.Entry<String, Object> param : xmlParams.entrySet()) {
|
||||
dbParams.put(param.getKey(), (String)param.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
|
||||
Map<String, String> configs = _configDao.getConfiguration(params);
|
||||
|
||||
if (params != null) {
|
||||
mergeConfigs(configs, params);
|
||||
}
|
||||
|
||||
final String smtpHost = configs.get(QuotaConfig.QuotaSmtpHost.key());
|
||||
int smtpPort = NumbersUtil.parseInt(configs.get(QuotaConfig.QuotaSmtpPort.key()), 25);
|
||||
String useAuthStr = configs.get(QuotaConfig.QuotaSmtpAuthType.key());
|
||||
boolean useAuth = ((useAuthStr != null) && Boolean.parseBoolean(useAuthStr));
|
||||
String smtpUsername = configs.get(QuotaConfig.QuotaSmtpUser.key());
|
||||
String smtpPassword = configs.get(QuotaConfig.QuotaSmtpPassword.key());
|
||||
String emailSender = configs.get(QuotaConfig.QuotaSmtpSender.key());
|
||||
_lockAccountEnforcement = "true".equalsIgnoreCase(configs.get(QuotaConfig.QuotaEnableEnforcement.key()));
|
||||
_emailQuotaAlert = new EmailQuotaAlert(smtpHost, smtpPort, useAuth, smtpUsername, smtpPassword, emailSender, _smtpDebug);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Starting Alert Manager");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Stopping Alert Manager");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAndSendQuotaAlertEmails() {
|
||||
List<DeferredQuotaEmail> deferredQuotaEmailList = new ArrayList<DeferredQuotaEmail>();
|
||||
final BigDecimal zeroBalance = new BigDecimal(0);
|
||||
for (final QuotaAccountVO quotaAccount : _quotaAcc.listAllQuotaAccount()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("checkAndSendQuotaAlertEmails accId=" + quotaAccount.getId());
|
||||
}
|
||||
BigDecimal accountBalance = quotaAccount.getQuotaBalance();
|
||||
Date balanceDate = quotaAccount.getQuotaBalanceDate();
|
||||
Date alertDate = quotaAccount.getQuotaAlertDate();
|
||||
int lockable = quotaAccount.getQuotaEnforce();
|
||||
BigDecimal thresholdBalance = quotaAccount.getQuotaMinBalance();
|
||||
if (accountBalance != null) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("checkAndSendQuotaAlertEmails: Check id=" + account.getId() + " bal=" + accountBalance + ", alertDate=" + alertDate + ", lockable=" + lockable);
|
||||
}
|
||||
if (accountBalance.compareTo(zeroBalance) < 0) {
|
||||
if (_lockAccountEnforcement && (lockable == 1)) {
|
||||
if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) {
|
||||
s_logger.info("Locking account " + account.getAccountName() + " due to quota < 0.");
|
||||
lockAccount(account.getId());
|
||||
}
|
||||
}
|
||||
if (alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1)) {
|
||||
s_logger.info("Sending alert " + account.getAccountName() + " due to quota < 0.");
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_EMPTY));
|
||||
}
|
||||
} else if (accountBalance.compareTo(thresholdBalance) < 0) {
|
||||
if (alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1)) {
|
||||
s_logger.info("Sending alert " + account.getAccountName() + " due to quota below threshold.");
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (DeferredQuotaEmail emailToBeSent : deferredQuotaEmailList) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("checkAndSendQuotaAlertEmails: Attempting to send quota alert email to users of account: " + emailToBeSent.getAccount().getAccountName());
|
||||
}
|
||||
sendQuotaAlert(emailToBeSent);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendQuotaAlert(DeferredQuotaEmail emailToBeSent) {
|
||||
final AccountVO account = emailToBeSent.getAccount();
|
||||
final BigDecimal balance = emailToBeSent.getQuotaBalance();
|
||||
final BigDecimal usage = emailToBeSent.getQuotaUsage();
|
||||
final QuotaConfig.QuotaEmailTemplateTypes emailType = emailToBeSent.getEmailTemplateType();
|
||||
|
||||
final List<QuotaEmailTemplatesVO> emailTemplates = _quotaEmailTemplateDao.listAllQuotaEmailTemplates(emailType.toString());
|
||||
if (emailTemplates != null && emailTemplates.get(0) != null) {
|
||||
final QuotaEmailTemplatesVO emailTemplate = emailTemplates.get(0);
|
||||
|
||||
final DomainVO accountDomain = _domainDao.findByIdIncludingRemoved(account.getDomainId());
|
||||
final List<UserVO> usersInAccount = _userDao.listByAccount(account.getId());
|
||||
|
||||
String userNames = "";
|
||||
final List<String> emailRecipients = new ArrayList<String>();
|
||||
for (UserVO user : usersInAccount) {
|
||||
userNames += String.format("%s <%s>,", user.getUsername(), user.getEmail());
|
||||
emailRecipients.add(user.getEmail());
|
||||
}
|
||||
if (userNames.endsWith(",")) {
|
||||
userNames = userNames.substring(0, userNames.length() - 1);
|
||||
}
|
||||
|
||||
final Map<String, String> optionMap = new HashMap<String, String>();
|
||||
optionMap.put("accountName", account.getAccountName());
|
||||
optionMap.put("accountID", account.getUuid());
|
||||
optionMap.put("accountUsers", userNames);
|
||||
optionMap.put("domainName", accountDomain.getName());
|
||||
optionMap.put("domainID", accountDomain.getUuid());
|
||||
optionMap.put("quotaBalance", QuotaConfig.QuotaCurrencySymbol.value() + " " + balance.toString());
|
||||
if (emailType == QuotaEmailTemplateTypes.QUOTA_STATEMENT) {
|
||||
optionMap.put("quotaUsage", QuotaConfig.QuotaCurrencySymbol.value() + " " + usage.toString());
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("accountName" + account.getAccountName() + "accountID" + account.getUuid() + "accountUsers" + userNames + "domainName" + accountDomain.getName()
|
||||
+ "domainID" + accountDomain.getUuid());
|
||||
}
|
||||
|
||||
final StrSubstitutor templateEngine = new StrSubstitutor(optionMap);
|
||||
final String subject = templateEngine.replace(emailTemplate.getTemplateSubject());
|
||||
final String body = templateEngine.replace(emailTemplate.getTemplateBody());
|
||||
try {
|
||||
_emailQuotaAlert.sendQuotaAlert(emailRecipients, subject, body);
|
||||
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));
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Exception", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_logger.error(String.format("No quota email template found for type %s, cannot send quota alert email to account %s(%s)", emailType, account.getAccountName(),
|
||||
account.getUuid()));
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
boolean success = false;
|
||||
try (TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB)) {
|
||||
Account account = _accountDao.findById(accountId);
|
||||
if (account != null) {
|
||||
if (account.getState() == State.locked) {
|
||||
return true; // already locked, no-op
|
||||
} else if (account.getState() == 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.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Exception occured while locking account by Quota Alert Manager", e);
|
||||
throw e;
|
||||
} finally {
|
||||
TransactionLegacy.open(opendb).close();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public static class DeferredQuotaEmail {
|
||||
private AccountVO account;
|
||||
private QuotaAccountVO quotaAccount;
|
||||
private QuotaConfig.QuotaEmailTemplateTypes emailTemplateType;
|
||||
private BigDecimal quotaUsage;
|
||||
|
||||
public DeferredQuotaEmail(AccountVO account, QuotaAccountVO quotaAccount, BigDecimal quotaUsage, QuotaConfig.QuotaEmailTemplateTypes emailTemplateType) {
|
||||
this.account = account;
|
||||
this.quotaAccount = quotaAccount;
|
||||
this.emailTemplateType = emailTemplateType;
|
||||
this.quotaUsage = quotaUsage;
|
||||
}
|
||||
|
||||
public DeferredQuotaEmail(AccountVO account, QuotaAccountVO quotaAccount, QuotaConfig.QuotaEmailTemplateTypes emailTemplateType) {
|
||||
this.account = account;
|
||||
this.quotaAccount = quotaAccount;
|
||||
this.emailTemplateType = emailTemplateType;
|
||||
this.quotaUsage = new BigDecimal(-1);
|
||||
}
|
||||
|
||||
public AccountVO getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaBalance() {
|
||||
return quotaAccount.getQuotaBalance();
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaUsage() {
|
||||
return quotaUsage;
|
||||
}
|
||||
|
||||
public Date getSendDate() {
|
||||
if (emailTemplateType == QuotaEmailTemplateTypes.QUOTA_STATEMENT) {
|
||||
return quotaAccount.getLastStatementDate();
|
||||
} else {
|
||||
return quotaAccount.getQuotaAlertDate();
|
||||
}
|
||||
}
|
||||
|
||||
public QuotaConfig.QuotaEmailTemplateTypes getEmailTemplateType() {
|
||||
return emailTemplateType;
|
||||
}
|
||||
|
||||
public void sentSuccessfully(final QuotaAccountDao quotaAccountDao) {
|
||||
if (emailTemplateType == QuotaEmailTemplateTypes.QUOTA_STATEMENT) {
|
||||
quotaAccount.setLastStatementDate(new Date());
|
||||
} else {
|
||||
quotaAccount.setQuotaAlertDate(new Date());
|
||||
quotaAccount.setQuotaAlertType(emailTemplateType.ordinal());
|
||||
}
|
||||
quotaAccountDao.updateQuotaAccount(quotaAccount.getAccountId(), quotaAccount);
|
||||
}
|
||||
};
|
||||
|
||||
static class EmailQuotaAlert {
|
||||
private final Session _smtpSession;
|
||||
private final String _smtpHost;
|
||||
private final int _smtpPort;
|
||||
private final boolean _smtpUseAuth;
|
||||
private final String _smtpUsername;
|
||||
private final String _smtpPassword;
|
||||
private final String _emailSender;
|
||||
|
||||
public EmailQuotaAlert(String smtpHost, int smtpPort, boolean smtpUseAuth, final String smtpUsername, final String smtpPassword, String emailSender, boolean smtpDebug) {
|
||||
_smtpHost = smtpHost;
|
||||
_smtpPort = smtpPort;
|
||||
_smtpUseAuth = smtpUseAuth;
|
||||
_smtpUsername = smtpUsername;
|
||||
_smtpPassword = smtpPassword;
|
||||
_emailSender = emailSender;
|
||||
|
||||
if (!Strings.isNullOrEmpty(_smtpHost)) {
|
||||
Properties smtpProps = new Properties();
|
||||
smtpProps.put("mail.smtp.host", smtpHost);
|
||||
smtpProps.put("mail.smtp.port", smtpPort);
|
||||
smtpProps.put("mail.smtp.auth", "" + smtpUseAuth);
|
||||
if (smtpUsername != null) {
|
||||
smtpProps.put("mail.smtp.user", smtpUsername);
|
||||
}
|
||||
|
||||
smtpProps.put("mail.smtps.host", smtpHost);
|
||||
smtpProps.put("mail.smtps.port", smtpPort);
|
||||
smtpProps.put("mail.smtps.auth", "" + smtpUseAuth);
|
||||
if (!Strings.isNullOrEmpty(smtpUsername)) {
|
||||
smtpProps.put("mail.smtps.user", smtpUsername);
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(smtpUsername) && !Strings.isNullOrEmpty(smtpPassword)) {
|
||||
_smtpSession = Session.getInstance(smtpProps, new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(smtpUsername, smtpPassword);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_smtpSession = Session.getInstance(smtpProps);
|
||||
}
|
||||
_smtpSession.setDebug(smtpDebug);
|
||||
} else {
|
||||
_smtpSession = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendQuotaAlert(List<String> emails, String subject, String body) throws MessagingException, UnsupportedEncodingException {
|
||||
if (_smtpSession == null) {
|
||||
throw new CloudRuntimeException("Unable to create smtp session.");
|
||||
}
|
||||
SMTPMessage msg = new SMTPMessage(_smtpSession);
|
||||
msg.setSender(new InternetAddress(_emailSender, _emailSender));
|
||||
msg.setFrom(new InternetAddress(_emailSender, _emailSender));
|
||||
|
||||
for (String email : emails) {
|
||||
if (email != null && !email.isEmpty()) {
|
||||
try {
|
||||
InternetAddress address = new InternetAddress(email, email);
|
||||
msg.addRecipient(Message.RecipientType.TO, address);
|
||||
} catch (Exception pokemon) {
|
||||
s_logger.error("Exception in creating address for:" + email, pokemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg.setSubject(subject);
|
||||
msg.setSentDate(new Date());
|
||||
msg.setContent(body, "text/html; charset=utf-8");
|
||||
msg.saveChanges();
|
||||
|
||||
SMTPTransport smtpTrans = null;
|
||||
if (_smtpUseAuth) {
|
||||
smtpTrans = new SMTPSSLTransport(_smtpSession, new URLName("smtp", _smtpHost, _smtpPort, null, _smtpUsername, _smtpPassword));
|
||||
} else {
|
||||
smtpTrans = new SMTPTransport(_smtpSession, new URLName("smtp", _smtpHost, _smtpPort, null, _smtpUsername, _smtpPassword));
|
||||
}
|
||||
smtpTrans.connect();
|
||||
smtpTrans.sendMessage(msg, msg.getAllRecipients());
|
||||
smtpTrans.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//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
|
||||
//the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import com.cloud.utils.component.Manager;
|
||||
|
||||
public interface QuotaManager extends Manager {
|
||||
|
||||
boolean calculateQuotaUsage();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,464 @@
|
|||
//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.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
|
||||
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.utils.usage.UsageUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@Component
|
||||
@Local(value = QuotaManager.class)
|
||||
public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaManagerImpl.class.getName());
|
||||
|
||||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private QuotaAccountDao _quotaAcc;
|
||||
@Inject
|
||||
private UsageDao _usageDao;
|
||||
@Inject
|
||||
private QuotaTariffDao _quotaTariffDao;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsageDao;
|
||||
@Inject
|
||||
private ServiceOfferingDao _serviceOfferingDao;
|
||||
@Inject
|
||||
private QuotaBalanceDao _quotaBalanceDao;
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
|
||||
private TimeZone _usageTimezone;
|
||||
private int _aggregationDuration = 0;
|
||||
|
||||
final static BigDecimal s_hoursInMonth = new BigDecimal(30 * 24);
|
||||
final static BigDecimal s_minutesInMonth = new BigDecimal(30 * 24 * 60);
|
||||
final static BigDecimal s_gb = new BigDecimal(1024 * 1024 * 1024);
|
||||
|
||||
public QuotaManagerImpl() {
|
||||
super();
|
||||
}
|
||||
|
||||
private void mergeConfigs(Map<String, String> dbParams, Map<String, Object> xmlParams) {
|
||||
for (Map.Entry<String, Object> param : xmlParams.entrySet()) {
|
||||
dbParams.put(param.getKey(), (String)param.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
|
||||
Map<String, String> configs = _configDao.getConfiguration(params);
|
||||
|
||||
if (params != null) {
|
||||
mergeConfigs(configs, params);
|
||||
}
|
||||
|
||||
String aggregationRange = configs.get("usage.stats.job.aggregation.range");
|
||||
String timeZoneStr = configs.get("usage.aggregation.timezone");
|
||||
|
||||
if (timeZoneStr == null) {
|
||||
timeZoneStr = "GMT";
|
||||
}
|
||||
_usageTimezone = TimeZone.getTimeZone(timeZoneStr);
|
||||
|
||||
_aggregationDuration = Integer.parseInt(aggregationRange);
|
||||
if (_aggregationDuration < UsageUtils.USAGE_AGGREGATION_RANGE_MIN) {
|
||||
s_logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + UsageUtils.USAGE_AGGREGATION_RANGE_MIN);
|
||||
_aggregationDuration = UsageUtils.USAGE_AGGREGATION_RANGE_MIN;
|
||||
}
|
||||
s_logger.info("Usage timezone = " + _usageTimezone + " AggregationDuration=" + _aggregationDuration);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Starting Quota Manager");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Stopping Quota Manager");
|
||||
}
|
||||
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:
|
||||
List<QuotaUsageVO> lq = updateQuotaRunningVMUsage(usageRecord, aggregationRatio);
|
||||
if (!lq.isEmpty()) {
|
||||
quotaListForAccount.addAll(lq);
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.ALLOCATED_VM:
|
||||
QuotaUsageVO qu = updateQuotaAllocatedVMUsage(usageRecord, aggregationRatio);
|
||||
if (qu != null) {
|
||||
quotaListForAccount.add(qu);
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.SNAPSHOT:
|
||||
case QuotaTypes.TEMPLATE:
|
||||
case QuotaTypes.ISO:
|
||||
case QuotaTypes.VOLUME:
|
||||
case QuotaTypes.VM_SNAPSHOT:
|
||||
qu = updateQuotaDiskUsage(usageRecord, aggregationRatio, usageRecord.getUsageType());
|
||||
if (qu != null) {
|
||||
quotaListForAccount.add(qu);
|
||||
}
|
||||
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:
|
||||
qu = updateQuotaRaw(usageRecord, aggregationRatio, usageRecord.getUsageType());
|
||||
if (qu != null) {
|
||||
quotaListForAccount.add(qu);
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.NETWORK_BYTES_RECEIVED:
|
||||
case QuotaTypes.NETWORK_BYTES_SENT:
|
||||
qu = updateQuotaNetwork(usageRecord, usageRecord.getUsageType());
|
||||
if (qu != null) {
|
||||
quotaListForAccount.add(qu);
|
||||
}
|
||||
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.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(quotaListForAccount.get(0));
|
||||
}
|
||||
Date startDate = quotaListForAccount.get(0).getStartDate();
|
||||
Date endDate = quotaListForAccount.get(0).getEndDate();
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("processQuotaBalanceForAccount startDate " + startDate + " endDate=" + endDate);
|
||||
s_logger.debug("processQuotaBalanceForAccount last items startDate " + quotaListForAccount.get(quotaListForAccount.size() - 1).getStartDate() + " items endDate="
|
||||
+ quotaListForAccount.get(quotaListForAccount.size() - 1).getEndDate());
|
||||
}
|
||||
quotaListForAccount.add(new QuotaUsageVO());
|
||||
BigDecimal aggrUsage = new BigDecimal(0);
|
||||
List<QuotaBalanceVO> creditsReceived = null;
|
||||
|
||||
//bootstrapping
|
||||
QuotaUsageVO lastQuotaUsage = _quotaUsageDao.findLastQuotaUsageEntry(account.getAccountId(), account.getDomainId(), startDate);
|
||||
if (lastQuotaUsage == null) {
|
||||
creditsReceived = _quotaBalanceDao.findCreditBalance(account.getAccountId(), account.getDomainId(), new Date(0), startDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Credit entries count " + creditsReceived.size() + " on Before Date=" + startDate);
|
||||
}
|
||||
if (creditsReceived != null) {
|
||||
for (QuotaBalanceVO credit : creditsReceived) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Credit entry found " + credit);
|
||||
s_logger.debug("Total = " + aggrUsage);
|
||||
}
|
||||
aggrUsage = aggrUsage.add(credit.getCreditBalance());
|
||||
}
|
||||
}
|
||||
// create a balance entry for these accumulated credits
|
||||
QuotaBalanceVO firstBalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, startDate);
|
||||
_quotaBalanceDao.saveQuotaBalance(firstBalance);
|
||||
}
|
||||
else {
|
||||
QuotaBalanceVO lastRealBalanceEntry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), endDate);
|
||||
aggrUsage = aggrUsage.add(lastRealBalanceEntry.getCreditBalance());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Last balance entry " + lastRealBalanceEntry + " AggrUsage=" + aggrUsage);
|
||||
}
|
||||
}
|
||||
|
||||
for (QuotaUsageVO entry : quotaListForAccount) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Usage entry found " + entry);
|
||||
}
|
||||
if (entry.getQuotaUsed().compareTo(BigDecimal.ZERO) == 0) {
|
||||
// check if there were credits
|
||||
creditsReceived = _quotaBalanceDao.findCreditBalance(account.getAccountId(), account.getDomainId(), entry.getStartDate(), entry.getEndDate());
|
||||
if (creditsReceived != null) {
|
||||
for (QuotaBalanceVO credit : creditsReceived) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Credit entry found " + credit);
|
||||
s_logger.debug("Total = " + aggrUsage);
|
||||
}
|
||||
aggrUsage = aggrUsage.add(credit.getCreditBalance());
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (startDate.compareTo(entry.getStartDate()) != 0) {
|
||||
QuotaBalanceVO newBalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, endDate);
|
||||
_quotaBalanceDao.saveQuotaBalance(newBalance);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Saving Balance" + newBalance);
|
||||
}
|
||||
|
||||
//New balance entry
|
||||
aggrUsage = new BigDecimal(0);
|
||||
startDate = entry.getStartDate();
|
||||
endDate = entry.getEndDate();
|
||||
|
||||
QuotaBalanceVO lastRealBalanceEntry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), endDate);
|
||||
Date lastBalanceDate = new Date(0);
|
||||
if (lastRealBalanceEntry != null) {
|
||||
lastBalanceDate = lastRealBalanceEntry.getUpdatedOn();
|
||||
aggrUsage = aggrUsage.add(lastRealBalanceEntry.getCreditBalance());
|
||||
}
|
||||
creditsReceived = _quotaBalanceDao.findCreditBalance(account.getAccountId(), account.getDomainId(), lastBalanceDate, endDate);
|
||||
if (creditsReceived != null) {
|
||||
for (QuotaBalanceVO credit : creditsReceived) {
|
||||
aggrUsage = aggrUsage.add(credit.getCreditBalance());
|
||||
}
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Getting Balance" + account.getAccountName() + ",Balance entry=" + aggrUsage + " on Date=" + endDate);
|
||||
}
|
||||
}
|
||||
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
|
||||
}
|
||||
QuotaBalanceVO newBalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, endDate);
|
||||
_quotaBalanceDao.saveQuotaBalance(newBalance);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Saving Balance" + newBalance);
|
||||
}
|
||||
|
||||
// update quota_accounts
|
||||
QuotaAccountVO quota_account = _quotaAcc.findByIdQuotaAccount(account.getAccountId());
|
||||
|
||||
if (quota_account == null) {
|
||||
quota_account = new QuotaAccountVO(account.getAccountId());
|
||||
quota_account.setQuotaBalance(aggrUsage);
|
||||
quota_account.setQuotaBalanceDate(endDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(quota_account);
|
||||
}
|
||||
_quotaAcc.persistQuotaAccount(quota_account);
|
||||
} else {
|
||||
quota_account.setQuotaBalance(aggrUsage);
|
||||
quota_account.setQuotaBalanceDate(endDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(quota_account);
|
||||
}
|
||||
_quotaAcc.updateQuotaAccount(account.getAccountId(), quota_account);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean calculateQuotaUsage() {
|
||||
List<AccountVO> accounts = _accountDao.listAll();
|
||||
for (AccountVO account : accounts) {
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = _usageDao.getUsageRecordsPendingQuotaAggregation(account.getAccountId(), account.getDomainId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Usage entries size = " + usageRecords.second().intValue() + ", accId" + account.getAccountId() + ", domId" + 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());
|
||||
}
|
||||
processQuotaBalanceForAccount(account, quotaListForAccount);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal quotaUsgage;
|
||||
BigDecimal onehourcostpergb;
|
||||
BigDecimal noofgbinuse;
|
||||
onehourcostpergb = tariff.getCurrencyValue().multiply(aggregationRatio);
|
||||
noofgbinuse = new BigDecimal(usageRecord.getSize()).divide(s_gb, 8, RoundingMode.HALF_EVEN);
|
||||
quotaUsgage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcostpergb).multiply(noofgbinuse);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), usageRecord.getUsageType(),
|
||||
quotaUsgage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
}
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quota_usage;
|
||||
}
|
||||
|
||||
public List<QuotaUsageVO> updateQuotaRunningVMUsage(UsageVO usageRecord, final BigDecimal aggregationRatio) {
|
||||
List<QuotaUsageVO> quotalist = new ArrayList<QuotaUsageVO>();
|
||||
QuotaUsageVO quota_usage;
|
||||
BigDecimal cpuquotausgage, speedquotausage, memoryquotausage, vmusage;
|
||||
BigDecimal onehourcostpercpu, onehourcostper100mhz, onehourcostper1mb, onehourcostforvmusage;
|
||||
BigDecimal rawusage;
|
||||
// get service offering details
|
||||
ServiceOfferingVO serviceoffering = _serviceOfferingDao.findServiceOffering(usageRecord.getVmInstanceId(), usageRecord.getOfferingId());
|
||||
rawusage = new BigDecimal(usageRecord.getRawUsage());
|
||||
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_NUMBER, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal cpu = new BigDecimal(serviceoffering.getCpu());
|
||||
onehourcostpercpu = tariff.getCurrencyValue().multiply(aggregationRatio);
|
||||
cpuquotausgage = rawusage.multiply(onehourcostpercpu).multiply(cpu);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.CPU_NUMBER,
|
||||
cpuquotausgage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
quotalist.add(quota_usage);
|
||||
}
|
||||
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_CLOCK_RATE, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal speed = new BigDecimal(serviceoffering.getSpeed() / 100.00);
|
||||
onehourcostper100mhz = tariff.getCurrencyValue().multiply(aggregationRatio);
|
||||
speedquotausage = rawusage.multiply(onehourcostper100mhz).multiply(speed);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.CPU_CLOCK_RATE,
|
||||
speedquotausage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
quotalist.add(quota_usage);
|
||||
}
|
||||
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.MEMORY, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal memory = new BigDecimal(serviceoffering.getRamSize());
|
||||
onehourcostper1mb = tariff.getCurrencyValue().multiply(aggregationRatio);
|
||||
memoryquotausage = rawusage.multiply(onehourcostper1mb).multiply(memory);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.MEMORY, memoryquotausage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
quotalist.add(quota_usage);
|
||||
}
|
||||
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.RUNNING_VM, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
onehourcostforvmusage = tariff.getCurrencyValue().multiply(aggregationRatio);
|
||||
vmusage = rawusage.multiply(onehourcostforvmusage);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.RUNNING_VM, vmusage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
quotalist.add(quota_usage);
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quotalist;
|
||||
}
|
||||
|
||||
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().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal vmusage;
|
||||
BigDecimal onehourcostforvmusage;
|
||||
onehourcostforvmusage = tariff.getCurrencyValue().multiply(aggregationRatio);
|
||||
vmusage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcostforvmusage);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.ALLOCATED_VM, vmusage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quota_usage;
|
||||
}
|
||||
|
||||
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().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal ruleusage;
|
||||
BigDecimal onehourcost;
|
||||
onehourcost = tariff.getCurrencyValue().multiply(aggregationRatio);
|
||||
ruleusage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcost);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), ruleType, ruleusage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quota_usage;
|
||||
}
|
||||
|
||||
public QuotaUsageVO updateQuotaNetwork(UsageVO usageRecord, final int transferType) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(transferType, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal onegbcost;
|
||||
BigDecimal rawusageingb;
|
||||
BigDecimal networkusage;
|
||||
onegbcost = tariff.getCurrencyValue();
|
||||
rawusageingb = new BigDecimal(usageRecord.getRawUsage()).divide(s_gb, 8, RoundingMode.HALF_EVEN);
|
||||
networkusage = rawusageingb.multiply(onegbcost);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), transferType, networkusage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quota_usage;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
//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
|
||||
//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 java.util.Calendar;
|
||||
|
||||
import com.cloud.utils.component.Manager;
|
||||
|
||||
public interface QuotaStatement extends Manager {
|
||||
void sendStatement();
|
||||
Calendar[] getCurrentStatementTime();
|
||||
}
|
||||
|
|
@ -0,0 +1,376 @@
|
|||
//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 java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.QuotaAlertManagerImpl.DeferredQuotaEmail;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
|
||||
@Component
|
||||
@Local(value = QuotaStatement.class)
|
||||
public class QuotaStatementImpl extends ManagerBase implements QuotaStatement {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaStatementImpl.class);
|
||||
|
||||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private QuotaAccountDao _quotaAcc;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsage;
|
||||
@Inject
|
||||
private QuotaAlertManager _quotaAlert;
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
|
||||
final public static int s_LAST_STATEMENT_SENT_DAYS = 6; //ideally should be less than 7 days
|
||||
|
||||
public enum STATEMENT_PERIODS {
|
||||
BIMONTHLY, MONTHLY, QUATERLY, HALFYEARLY, YEARLY
|
||||
};
|
||||
|
||||
private STATEMENT_PERIODS _period = STATEMENT_PERIODS.MONTHLY;
|
||||
|
||||
public QuotaStatementImpl() {
|
||||
super();
|
||||
}
|
||||
|
||||
private void mergeConfigs(Map<String, String> dbParams, Map<String, Object> xmlParams) {
|
||||
for (Map.Entry<String, Object> param : xmlParams.entrySet()) {
|
||||
dbParams.put(param.getKey(), (String)param.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
|
||||
Map<String, String> configs = _configDao.getConfiguration(params);
|
||||
|
||||
if (params != null) {
|
||||
mergeConfigs(configs, params);
|
||||
}
|
||||
String period_str = configs.get(QuotaConfig.QuotaStatementPeriod.key());
|
||||
int period = period_str == null ? 1 : Integer.valueOf(period_str);
|
||||
|
||||
STATEMENT_PERIODS _period = STATEMENT_PERIODS.values()[period];
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Starting Statement Manager");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Stopping Statement Manager");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendStatement() {
|
||||
|
||||
List<DeferredQuotaEmail> deferredQuotaEmailList = new ArrayList<DeferredQuotaEmail>();
|
||||
for (final QuotaAccountVO quotaAccount : _quotaAcc.listAllQuotaAccount()) {
|
||||
if (quotaAccount.getQuotaBalance() == null) {
|
||||
continue; // no quota usage for this account ever, ignore
|
||||
}
|
||||
|
||||
//check if it is statement time
|
||||
Calendar interval[] = statementTime(Calendar.getInstance(), _period);
|
||||
|
||||
Date lastStatementDate = quotaAccount.getLastStatementDate();
|
||||
if (interval != null) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (lastStatementDate == null || getDifferenceDays(lastStatementDate, new Date()) >= s_LAST_STATEMENT_SENT_DAYS + 1) {
|
||||
BigDecimal quotaUsage = _quotaUsage.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, interval[0].getTime(), interval[1].getTime());
|
||||
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 (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("For " + quotaAccount.getId() + " the statement has been sent recently");
|
||||
|
||||
}
|
||||
}
|
||||
} else if (lastStatementDate != null) {
|
||||
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) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Attempting to send quota STATEMENT email to users of account: " + emailToBeSent.getAccount().getAccountName());
|
||||
}
|
||||
_quotaAlert.sendQuotaAlert(emailToBeSent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar[] getCurrentStatementTime() {
|
||||
final Calendar today = Calendar.getInstance();
|
||||
int day_of_month = today.get(Calendar.DAY_OF_MONTH);
|
||||
int month_of_year = today.get(Calendar.MONTH);
|
||||
|
||||
Calendar firstDateOfCurrentPeriod, lastDateOfCurrentPeriod;
|
||||
Calendar aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
lastDateOfCurrentPeriod = aCalendar;
|
||||
|
||||
switch (_period) {
|
||||
case BIMONTHLY:
|
||||
if (day_of_month < 16) {
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.MONTH, 0);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
} else {
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.set(Calendar.DATE, 16);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
}
|
||||
case MONTHLY:
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
case QUATERLY:
|
||||
if (month_of_year < Calendar.APRIL) {
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.JANUARY);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
} else if (month_of_year < Calendar.JULY) {
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.APRIL);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
} else if (month_of_year < Calendar.OCTOBER) {
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.JULY);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
} else {
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.OCTOBER);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
}
|
||||
case HALFYEARLY:
|
||||
// statements are sent in Jan=1, Jul 7,
|
||||
if (month_of_year < Calendar.JULY) {
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.JANUARY);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
} else {
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.JULY);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
}
|
||||
case YEARLY:
|
||||
aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.MONTH, Calendar.JANUARY);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfCurrentPeriod = aCalendar;
|
||||
return new Calendar[] {firstDateOfCurrentPeriod, lastDateOfCurrentPeriod};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Calendar[] statementTime(final Calendar today, final STATEMENT_PERIODS period) {
|
||||
//check if it is statement time
|
||||
int day_of_month = today.get(Calendar.DAY_OF_MONTH);
|
||||
int month_of_year = today.get(Calendar.MONTH);
|
||||
Calendar firstDateOfPreviousPeriod, lastDateOfPreviousPeriod;
|
||||
switch (period) {
|
||||
case BIMONTHLY:
|
||||
if (day_of_month < s_LAST_STATEMENT_SENT_DAYS) {
|
||||
Calendar aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.MONTH, 0);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
aCalendar.set(Calendar.DATE, 15);
|
||||
lastDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
return new Calendar[] {firstDateOfPreviousPeriod, lastDateOfPreviousPeriod};
|
||||
} else if (day_of_month > 15 && (day_of_month - 15) < s_LAST_STATEMENT_SENT_DAYS) {
|
||||
Calendar aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.MONTH, -1);
|
||||
aCalendar.set(Calendar.DATE, 16);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
lastDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
return new Calendar[] {firstDateOfPreviousPeriod, lastDateOfPreviousPeriod};
|
||||
}
|
||||
return null;
|
||||
case MONTHLY:
|
||||
if (day_of_month < s_LAST_STATEMENT_SENT_DAYS) {
|
||||
Calendar aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.MONTH, -1);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
lastDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
return new Calendar[] {firstDateOfPreviousPeriod, lastDateOfPreviousPeriod};
|
||||
}
|
||||
return null;
|
||||
case QUATERLY:
|
||||
// statements are sent in Jan=1, Apr 4, Jul 7, Oct 10
|
||||
if (month_of_year == Calendar.JANUARY || month_of_year == Calendar.APRIL || month_of_year == Calendar.JULY || month_of_year == Calendar.OCTOBER) {
|
||||
if (day_of_month < s_LAST_STATEMENT_SENT_DAYS) {
|
||||
Calendar aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.MONTH, -3);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
aCalendar.add(Calendar.MONTH, 2);
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
lastDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
return new Calendar[] {firstDateOfPreviousPeriod, lastDateOfPreviousPeriod};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
case HALFYEARLY:
|
||||
// statements are sent in Jan=1, Jul 7,
|
||||
if (month_of_year == Calendar.JANUARY || month_of_year == Calendar.JULY) {
|
||||
if (day_of_month < s_LAST_STATEMENT_SENT_DAYS) {
|
||||
Calendar aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.MONTH, -6);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
aCalendar.add(Calendar.MONTH, 5);
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
lastDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
return new Calendar[] {firstDateOfPreviousPeriod, lastDateOfPreviousPeriod};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
case YEARLY:
|
||||
// statements are sent in Jan=1
|
||||
if (month_of_year == Calendar.JANUARY) {
|
||||
if (day_of_month < s_LAST_STATEMENT_SENT_DAYS) {
|
||||
Calendar aCalendar = (Calendar)today.clone();
|
||||
aCalendar.add(Calendar.MONTH, -12);
|
||||
aCalendar.set(Calendar.DATE, 1);
|
||||
aCalendar.set(Calendar.HOUR, 0);
|
||||
aCalendar.set(Calendar.MINUTE, 0);
|
||||
aCalendar.set(Calendar.SECOND, 0);
|
||||
firstDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
aCalendar.add(Calendar.MONTH, 11);
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
lastDateOfPreviousPeriod = (Calendar)aCalendar.clone();
|
||||
return new Calendar[] {firstDateOfPreviousPeriod, lastDateOfPreviousPeriod};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static long getDifferenceDays(Date d1, Date d2) {
|
||||
long diff = d2.getTime() - d1.getTime();
|
||||
return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
//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 org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
||||
public interface QuotaConfig {
|
||||
|
||||
public static final ConfigKey<Boolean> QuotaPluginEnabled = new ConfigKey<Boolean>("Advanced", Boolean.class, "quota.enable.service", "false",
|
||||
"Indicates whether Quota plugin is enabled or not", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaEnableEnforcement = new ConfigKey<String>("Advanced", String.class, "quota.enable.enforcement", "false",
|
||||
"Enable the usage quota enforcement, i.e. on true when exceeding quota the respective account will be locked.", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaCurrencySymbol = new ConfigKey<String>("Advanced", String.class, "quota.currency.symbol", "$",
|
||||
"The symbol for the currency in use to measure usage.", true);
|
||||
|
||||
public static final ConfigKey<Integer> QuotaStatementPeriod = new ConfigKey<Integer>("Advanced", Integer.class, "quota.statement.period", "1",
|
||||
"This variables define the statement generation interval. Values correspond to bimonthly=0, monthly=1, quarterly=2, half-yearly=3 and yearly=4.", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaSmtpHost = new ConfigKey<String>("Advanced", String.class, "quota.usage.smtp.host", "", "Quota SMTP host for quota related emails",
|
||||
true);
|
||||
|
||||
public static final ConfigKey<String> QuotaSmtpTimeout = new ConfigKey<String>("Advanced", String.class, "quota.usage.smtp.connection.timeout", "60",
|
||||
"Quota SMTP server connection timeout duration", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaSmtpUser = new ConfigKey<String>("Advanced", String.class, "quota.usage.smtp.user", "", "Quota SMTP server username", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaSmtpPassword = new ConfigKey<String>("Advanced", String.class, "quota.usage.smtp.password", "", "Quota SMTP server password", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaSmtpPort = new ConfigKey<String>("Advanced", String.class, "quota.usage.smtp.port", "", "Quota SMTP port", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaSmtpAuthType = new ConfigKey<String>("Advanced", String.class, "quota.usage.smtp.useAuth", "",
|
||||
"If true, use secure SMTP authentication when sending emails.", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaSmtpSender = new ConfigKey<String>("Advanced", String.class, "quota.usage.smtp.sender", "",
|
||||
"Sender of quota alert email (will be in the From header of the email)", true);
|
||||
|
||||
enum QuotaEmailTemplateTypes {
|
||||
QUOTA_LOW, QUOTA_EMPTY, QUOTA_UNLOCK_ACCOUNT, QUOTA_STATEMENT
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
// 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 org.apache.cloudstack.usage.UsageTypes;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class QuotaTypes extends UsageTypes {
|
||||
public static final int CPU_CLOCK_RATE = 15;
|
||||
public static final int CPU_NUMBER = 16;
|
||||
public static final int MEMORY = 17;
|
||||
|
||||
private final Integer quotaType;
|
||||
private final String quotaName;
|
||||
private final String quotaUnit;
|
||||
private final String description;
|
||||
private final String discriminator;
|
||||
private final static Map<Integer, QuotaTypes> quotaTypeMap;
|
||||
|
||||
static {
|
||||
final HashMap<Integer, QuotaTypes> quotaTypeList = new HashMap<Integer, QuotaTypes>();
|
||||
quotaTypeList.put(RUNNING_VM, new QuotaTypes(RUNNING_VM, "RUNNING_VM", "Compute-Month", "Running Vm Usage"));
|
||||
quotaTypeList.put(ALLOCATED_VM, new QuotaTypes(ALLOCATED_VM, "ALLOCATED_VM", "Compute-Month", "Allocated Vm Usage"));
|
||||
quotaTypeList.put(IP_ADDRESS, new QuotaTypes(IP_ADDRESS, "IP_ADDRESS", "IP-Month", "IP Address Usage"));
|
||||
quotaTypeList.put(NETWORK_BYTES_SENT, new QuotaTypes(NETWORK_BYTES_SENT, "NETWORK_BYTES_SENT", "GB", "Network Usage (Bytes Sent)"));
|
||||
quotaTypeList.put(NETWORK_BYTES_RECEIVED, new QuotaTypes(NETWORK_BYTES_RECEIVED, "NETWORK_BYTES_RECEIVED", "GB", "Network Usage (Bytes Received)"));
|
||||
quotaTypeList.put(VOLUME, new QuotaTypes(VOLUME, "VOLUME", "GB-Month", "Volume Usage"));
|
||||
quotaTypeList.put(TEMPLATE, new QuotaTypes(TEMPLATE, "TEMPLATE", "GB-Month", "Template Usage"));
|
||||
quotaTypeList.put(ISO, new QuotaTypes(ISO, "ISO", "GB-Month", "ISO Usage"));
|
||||
quotaTypeList.put(SNAPSHOT, new QuotaTypes(SNAPSHOT, "SNAPSHOT", "GB-Month", "Snapshot Usage"));
|
||||
quotaTypeList.put(SECURITY_GROUP, new QuotaTypes(SECURITY_GROUP, "SECURITY_GROUP", "Policy-Month", "Security Group Usage"));
|
||||
quotaTypeList.put(LOAD_BALANCER_POLICY, new QuotaTypes(LOAD_BALANCER_POLICY, "LOAD_BALANCER_POLICY", "Policy-Month", "Load Balancer Usage"));
|
||||
quotaTypeList.put(PORT_FORWARDING_RULE, new QuotaTypes(PORT_FORWARDING_RULE, "PORT_FORWARDING_RULE", "Policy-Month", "Port Forwarding Usage"));
|
||||
quotaTypeList.put(NETWORK_OFFERING, new QuotaTypes(NETWORK_OFFERING, "NETWORK_OFFERING", "Policy-Month", "Network Offering Usage"));
|
||||
quotaTypeList.put(VPN_USERS, new QuotaTypes(VPN_USERS, "VPN_USERS", "Policy-Month", "VPN users usage"));
|
||||
quotaTypeList.put(VM_DISK_IO_READ, new QuotaTypes(VM_DISK_IO_READ, "VM_DISK_IO_READ", "GB", "VM Disk usage(I/O Read)"));
|
||||
quotaTypeList.put(VM_DISK_IO_WRITE, new QuotaTypes(VM_DISK_IO_WRITE, "VM_DISK_IO_WRITE", "GB", "VM Disk usage(I/O Write)"));
|
||||
quotaTypeList.put(VM_DISK_BYTES_READ, new QuotaTypes(VM_DISK_BYTES_READ, "VM_DISK_BYTES_READ", "GB", "VM Disk usage(Bytes Read)"));
|
||||
quotaTypeList.put(VM_DISK_BYTES_WRITE, new QuotaTypes(VM_DISK_BYTES_WRITE, "VPN_USERS", "GB", "VM Disk usage(Bytes Write)"));
|
||||
quotaTypeList.put(VM_SNAPSHOT, new QuotaTypes(VM_SNAPSHOT, "VM_SNAPSHOT", "GB-Month", "VM Snapshot storage usage"));
|
||||
quotaTypeList.put(CPU_CLOCK_RATE, new QuotaTypes(CPU_CLOCK_RATE, "CPU_CLOCK_RATE", "Compute-Month", "Quota tariff for using 1 CPU of clock rate 100MHz"));
|
||||
quotaTypeList.put(CPU_NUMBER, new QuotaTypes(CPU_NUMBER, "CPU_NUMBER", "Compute-Month", "Quota tariff for running VM that has 1vCPU"));
|
||||
quotaTypeList.put(MEMORY, new QuotaTypes(MEMORY, "MEMORY", "Compute-Month", "Quota tariff for using 1MB or RAM for 1 hour"));
|
||||
quotaTypeMap = Collections.unmodifiableMap(quotaTypeList);
|
||||
}
|
||||
|
||||
private QuotaTypes(Integer quotaType, String name, String unit, String description) {
|
||||
this.quotaType = quotaType;
|
||||
this.description = description;
|
||||
this.quotaName = name;
|
||||
this.quotaUnit = unit;
|
||||
this.discriminator = "None";
|
||||
}
|
||||
|
||||
public static Map<Integer, QuotaTypes> listQuotaTypes() {
|
||||
return quotaTypeMap;
|
||||
}
|
||||
|
||||
public String getDiscriminator() {
|
||||
return discriminator;
|
||||
}
|
||||
|
||||
public String getQuotaName() {
|
||||
return quotaName;
|
||||
}
|
||||
|
||||
public String getQuotaUnit() {
|
||||
return quotaUnit;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Integer getQuotaType() {
|
||||
return quotaType;
|
||||
}
|
||||
|
||||
static public String getDescription(int quotaType) {
|
||||
QuotaTypes t = quotaTypeMap.get(quotaType);
|
||||
if (t != null) {
|
||||
return t.getDescription();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
//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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface QuotaAccountDao extends GenericDao<QuotaAccountVO, Long> {
|
||||
|
||||
List<QuotaAccountVO> listAllQuotaAccount();
|
||||
|
||||
QuotaAccountVO findByIdQuotaAccount(Long id);
|
||||
|
||||
QuotaAccountVO persistQuotaAccount(QuotaAccountVO entity);
|
||||
|
||||
boolean updateQuotaAccount(Long id, QuotaAccountVO entity);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
//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.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
|
||||
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);
|
||||
|
||||
public List<QuotaAccountVO> listAllQuotaAccount() {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaAccountVO>>() {
|
||||
@Override
|
||||
public List<QuotaAccountVO> doInTransaction(final TransactionStatus status) {
|
||||
return listAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public QuotaAccountVO findByIdQuotaAccount(final Long id) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaAccountVO>() {
|
||||
@Override
|
||||
public QuotaAccountVO doInTransaction(final TransactionStatus status) {
|
||||
return findById(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public QuotaAccountVO persistQuotaAccount(final QuotaAccountVO entity) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaAccountVO>() {
|
||||
@Override
|
||||
public QuotaAccountVO doInTransaction(final TransactionStatus status) {
|
||||
return persist(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean updateQuotaAccount(final Long id, final QuotaAccountVO entity) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(final TransactionStatus status) {
|
||||
return update(id, entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//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.dao;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface QuotaBalanceDao extends GenericDao<QuotaBalanceVO, Long> {
|
||||
|
||||
QuotaBalanceVO saveQuotaBalance(QuotaBalanceVO qb);
|
||||
|
||||
List<QuotaBalanceVO> findCreditBalance(Long accountId, Long domainId, Date startDate, Date endDate);
|
||||
|
||||
QuotaBalanceVO findLastBalanceEntry(Long accountId, Long domainId, Date beforeThis);
|
||||
|
||||
QuotaBalanceVO findLaterBalanceEntry(Long accountId, Long domainId, Date afterThis);
|
||||
|
||||
List<QuotaBalanceVO> findQuotaBalance(Long accountId, Long domainId, Date startDate, Date endDate);
|
||||
|
||||
List<QuotaBalanceVO> lastQuotaBalanceVO(Long accountId, Long domainId, Date startDate);
|
||||
|
||||
BigDecimal lastQuotaBalance(Long accountId, Long domainId, Date startDate);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
//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.dao;
|
||||
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.QueryBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
|
||||
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.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Local(value = {QuotaBalanceDao.class})
|
||||
public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> implements QuotaBalanceDao {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaBalanceDaoImpl.class.getName());
|
||||
|
||||
public QuotaBalanceVO findLastBalanceEntry(final Long accountId, final Long domainId, final Date beforeThis) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaBalanceVO>() {
|
||||
@Override
|
||||
public QuotaBalanceVO doInTransaction(final TransactionStatus status) {
|
||||
List<QuotaBalanceVO> quotaBalanceEntries = new ArrayList<>();
|
||||
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 1L);
|
||||
QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class);
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.EQ, 0);
|
||||
qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.LT, beforeThis);
|
||||
quotaBalanceEntries = search(qb.create(), filter);
|
||||
return !quotaBalanceEntries.isEmpty() ? quotaBalanceEntries.get(0) : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public QuotaBalanceVO findLaterBalanceEntry(final Long accountId, final Long domainId, final Date afterThis) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaBalanceVO>() {
|
||||
@Override
|
||||
public QuotaBalanceVO doInTransaction(final TransactionStatus status) {
|
||||
List<QuotaBalanceVO> quotaBalanceEntries = new ArrayList<>();
|
||||
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, 1L);
|
||||
QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class);
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.EQ, 0);
|
||||
qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.GT, afterThis);
|
||||
quotaBalanceEntries = search(qb.create(), filter);
|
||||
return quotaBalanceEntries.size() > 0 ? quotaBalanceEntries.get(0) : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public QuotaBalanceVO saveQuotaBalance(final QuotaBalanceVO qb) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaBalanceVO>() {
|
||||
@Override
|
||||
public QuotaBalanceVO doInTransaction(final TransactionStatus status) {
|
||||
return persist(qb);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<QuotaBalanceVO> findCreditBalance(final Long accountId, final Long domainId, final Date lastbalancedate, final Date beforeThis) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaBalanceVO>>() {
|
||||
@Override
|
||||
public List<QuotaBalanceVO> doInTransaction(final TransactionStatus status) {
|
||||
if ((lastbalancedate != null) && (beforeThis != null) && lastbalancedate.before(beforeThis)) {
|
||||
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, Long.MAX_VALUE);
|
||||
QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class);
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.GT, 0);
|
||||
qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.BETWEEN, lastbalancedate, beforeThis);
|
||||
return search(qb.create(), filter);
|
||||
} else {
|
||||
return new ArrayList<QuotaBalanceVO>();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<QuotaBalanceVO> findQuotaBalance(final Long accountId, final Long domainId, final Date startDate, final Date endDate) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaBalanceVO>>() {
|
||||
@Override
|
||||
public List<QuotaBalanceVO> doInTransaction(final TransactionStatus status) {
|
||||
List<QuotaBalanceVO> quotaUsageRecords = null;
|
||||
QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class);
|
||||
if (accountId != null) {
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
}
|
||||
if (domainId != null) {
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
}
|
||||
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
|
||||
qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.BETWEEN, startDate, endDate);
|
||||
} else {
|
||||
return Collections.<QuotaBalanceVO> emptyList();
|
||||
}
|
||||
quotaUsageRecords = listBy(qb.create());
|
||||
if (quotaUsageRecords.size() == 0) {
|
||||
quotaUsageRecords.addAll(lastQuotaBalanceVO(accountId, domainId, startDate));
|
||||
}
|
||||
return quotaUsageRecords;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public List<QuotaBalanceVO> lastQuotaBalanceVO(final Long accountId, final Long domainId, final Date pivotDate) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaBalanceVO>>() {
|
||||
@Override
|
||||
public List<QuotaBalanceVO> doInTransaction(final TransactionStatus status) {
|
||||
List<QuotaBalanceVO> quotaUsageRecords = null;
|
||||
List<QuotaBalanceVO> trimmedRecords = new ArrayList<QuotaBalanceVO>();
|
||||
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 100L);
|
||||
// ASSUMPTION there will be less than 100 continuous credit
|
||||
// transactions
|
||||
QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class);
|
||||
if (accountId != null) {
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
}
|
||||
if (domainId != null) {
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
}
|
||||
if ((pivotDate != null)) {
|
||||
qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.LTEQ, pivotDate);
|
||||
}
|
||||
quotaUsageRecords = search(qb.create(), filter);
|
||||
|
||||
// get records before startDate to find start balance
|
||||
for (QuotaBalanceVO entry : quotaUsageRecords) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("FindQuotaBalIance Entry=" + entry);
|
||||
}
|
||||
if (entry.getCreditsId() > 0) {
|
||||
trimmedRecords.add(entry);
|
||||
} else {
|
||||
trimmedRecords.add(entry);
|
||||
break; // add only consecutive credit entries and last balance entry
|
||||
}
|
||||
}
|
||||
return trimmedRecords;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public BigDecimal lastQuotaBalance(final Long accountId, final Long domainId, Date startDate) {
|
||||
List<QuotaBalanceVO> quotaBalance = lastQuotaBalanceVO(accountId, domainId, startDate);
|
||||
BigDecimal finalBalance = new BigDecimal(0);
|
||||
if (quotaBalance.isEmpty()) {
|
||||
s_logger.info("There are no balance entries on or before the requested date.");
|
||||
return finalBalance;
|
||||
}
|
||||
for (QuotaBalanceVO entry : quotaBalance) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("lastQuotaBalance Entry=" + entry);
|
||||
}
|
||||
finalBalance = finalBalance.add(entry.getCreditBalance());
|
||||
}
|
||||
return finalBalance;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.quota.dao;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface QuotaCreditsDao extends GenericDao<QuotaCreditsVO, Long> {
|
||||
|
||||
List<QuotaCreditsVO> findCredits(long accountId, long domainId, Date startDate, Date endDate);
|
||||
|
||||
QuotaCreditsVO saveCredits(QuotaCreditsVO credits);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
//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.dao;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
||||
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.QueryBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
|
||||
@Component
|
||||
@Local(value = { QuotaCreditsDao.class })
|
||||
public class QuotaCreditsDaoImpl extends GenericDaoBase<QuotaCreditsVO, Long> implements QuotaCreditsDao {
|
||||
|
||||
@Inject
|
||||
QuotaBalanceDao _quotaBalanceDao;
|
||||
|
||||
@Override
|
||||
public List<QuotaCreditsVO> findCredits(final long accountId, final long domainId, final Date startDate, final Date endDate) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaCreditsVO>>() {
|
||||
@Override
|
||||
public List<QuotaCreditsVO> doInTransaction(final TransactionStatus status) {
|
||||
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
|
||||
Filter filter = new Filter(QuotaCreditsVO.class, "updatedOn", true, 0L, Long.MAX_VALUE);
|
||||
QueryBuilder<QuotaCreditsVO> qb = QueryBuilder.create(QuotaCreditsVO.class);
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.BETWEEN, startDate, endDate);
|
||||
return search(qb.create(), filter);
|
||||
} else {
|
||||
return Collections.<QuotaCreditsVO> emptyList();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaCreditsVO saveCredits(final QuotaCreditsVO credits) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaCreditsVO>() {
|
||||
@Override
|
||||
public QuotaCreditsVO doInTransaction(final TransactionStatus status) {
|
||||
persist(credits);
|
||||
// make an entry in the balance table
|
||||
QuotaBalanceVO bal = new QuotaBalanceVO(credits);
|
||||
_quotaBalanceDao.persist(bal);
|
||||
return credits;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//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.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface QuotaEmailTemplatesDao extends GenericDao<QuotaEmailTemplatesVO, Long> {
|
||||
List<QuotaEmailTemplatesVO> listAllQuotaEmailTemplates(String templateName);
|
||||
boolean updateQuotaEmailTemplate(QuotaEmailTemplatesVO template);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
//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.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
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);
|
||||
|
||||
protected SearchBuilder<QuotaEmailTemplatesVO> QuotaEmailTemplateSearch;
|
||||
|
||||
public QuotaEmailTemplatesDaoImpl() {
|
||||
super();
|
||||
|
||||
QuotaEmailTemplateSearch = createSearchBuilder();
|
||||
QuotaEmailTemplateSearch.and("template_name", QuotaEmailTemplateSearch.entity().getTemplateName(), SearchCriteria.Op.EQ);
|
||||
QuotaEmailTemplateSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaEmailTemplatesVO> listAllQuotaEmailTemplates(final String templateName) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaEmailTemplatesVO>>() {
|
||||
@Override
|
||||
public List<QuotaEmailTemplatesVO> doInTransaction(final TransactionStatus status) {
|
||||
SearchCriteria<QuotaEmailTemplatesVO> sc = QuotaEmailTemplateSearch.create();
|
||||
if (!Strings.isNullOrEmpty(templateName)) {
|
||||
sc.setParameters("template_name", templateName);
|
||||
}
|
||||
return listBy(sc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateQuotaEmailTemplate(final QuotaEmailTemplatesVO template) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(final TransactionStatus status) {
|
||||
return update(template.getId(), template);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
//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.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface QuotaTariffDao extends GenericDao<QuotaTariffVO, Long> {
|
||||
|
||||
QuotaTariffVO findTariffPlanByUsageType(int quotaType, Date onOrBefore);
|
||||
|
||||
List<QuotaTariffVO> listAllTariffPlans();
|
||||
|
||||
List<QuotaTariffVO> listAllTariffPlans(Date onOrBefore);
|
||||
|
||||
Boolean updateQuotaTariff(QuotaTariffVO plan);
|
||||
|
||||
QuotaTariffVO addQuotaTariff(QuotaTariffVO plan);
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
//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.dao;
|
||||
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Local(value = {QuotaTariffDao.class})
|
||||
public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> implements QuotaTariffDao {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaTariffDaoImpl.class.getName());
|
||||
|
||||
private final SearchBuilder<QuotaTariffVO> searchUsageType;
|
||||
private final SearchBuilder<QuotaTariffVO> listAllIncludedUsageType;
|
||||
|
||||
public QuotaTariffDaoImpl() {
|
||||
super();
|
||||
searchUsageType = createSearchBuilder();
|
||||
searchUsageType.and("usage_type", searchUsageType.entity().getUsageType(), SearchCriteria.Op.EQ);
|
||||
searchUsageType.done();
|
||||
|
||||
listAllIncludedUsageType = createSearchBuilder();
|
||||
listAllIncludedUsageType.and("onorbefore", listAllIncludedUsageType.entity().getEffectiveOn(), SearchCriteria.Op.LTEQ);
|
||||
listAllIncludedUsageType.and("quotatype", listAllIncludedUsageType.entity().getUsageType(), SearchCriteria.Op.EQ);
|
||||
listAllIncludedUsageType.done();
|
||||
}
|
||||
|
||||
public QuotaTariffVO findTariffPlanByUsageType(final int quotaType, final Date effectiveDate) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaTariffVO>() {
|
||||
@Override
|
||||
public QuotaTariffVO doInTransaction(final TransactionStatus status) {
|
||||
List<QuotaTariffVO> result = new ArrayList<>();
|
||||
final Filter filter = new Filter(QuotaTariffVO.class, "updatedOn", false, 0L, 1L);
|
||||
final SearchCriteria<QuotaTariffVO> sc = listAllIncludedUsageType.create();
|
||||
sc.setParameters("onorbefore", effectiveDate);
|
||||
sc.setParameters("quotatype", quotaType);
|
||||
result = search(sc, filter);
|
||||
if (result != null && !result.isEmpty()) {
|
||||
return result.get(0);
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("QuotaTariffDaoImpl::findTariffPlanByUsageType: Missing quota type " + quotaType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<QuotaTariffVO> listAllTariffPlans() {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaTariffVO>>() {
|
||||
@Override
|
||||
public List<QuotaTariffVO> doInTransaction(final TransactionStatus status) {
|
||||
return listAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<QuotaTariffVO> listAllTariffPlans(final Date effectiveDate) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaTariffVO>>() {
|
||||
@Override
|
||||
public List<QuotaTariffVO> doInTransaction(final TransactionStatus status) {
|
||||
List<QuotaTariffVO> tariffs = new ArrayList<QuotaTariffVO>();
|
||||
final Filter filter = new Filter(QuotaTariffVO.class, "updatedOn", false, 0L, 1L);
|
||||
final SearchCriteria<QuotaTariffVO> sc = listAllIncludedUsageType.create();
|
||||
sc.setParameters("onorbefore", effectiveDate);
|
||||
for (Integer quotaType : QuotaTypes.listQuotaTypes().keySet()) {
|
||||
sc.setParameters("quotatype", quotaType);
|
||||
List<QuotaTariffVO> result = search(sc, filter);
|
||||
if (result != null && !result.isEmpty()) {
|
||||
tariffs.add(result.get(0));
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("ListAllTariffPlans on or before " + effectiveDate + " quota type " + result.get(0).getDescription() + " , effective Date="
|
||||
+ result.get(0).getEffectiveOn() + " val=" + result.get(0).getCurrencyValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return tariffs;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Boolean updateQuotaTariff(final QuotaTariffVO plan) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInTransaction(final TransactionStatus status) {
|
||||
return update(plan.getId(), plan);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public QuotaTariffVO addQuotaTariff(final QuotaTariffVO plan) {
|
||||
if (plan.getIdObj() != null) {
|
||||
throw new IllegalStateException("The QuotaTariffVO being added should not have an Id set ");
|
||||
}
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaTariffVO>() {
|
||||
@Override
|
||||
public QuotaTariffVO doInTransaction(final TransactionStatus status) {
|
||||
return persist(plan);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
//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.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;
|
||||
|
||||
public interface QuotaUsageDao extends GenericDao<QuotaUsageVO, Long> {
|
||||
|
||||
QuotaUsageVO persistQuotaUsage(QuotaUsageVO quotaUsage);
|
||||
|
||||
List<QuotaUsageVO> findQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate);
|
||||
|
||||
BigDecimal findTotalQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate);
|
||||
|
||||
QuotaUsageVO findLastQuotaUsageEntry(Long accountId, Long domainId, Date beforeThis);
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
//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.dao;
|
||||
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.QueryBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
|
||||
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;
|
||||
|
||||
@Component
|
||||
@Local(value = {QuotaUsageDao.class})
|
||||
public class QuotaUsageDaoImpl extends GenericDaoBase<QuotaUsageVO, Long> implements QuotaUsageDao {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaUsageDaoImpl.class);
|
||||
|
||||
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 (QuotaUsageVO quotaRecord : quotaUsage) {
|
||||
total = total.add(quotaRecord.getQuotaUsed());
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public List<QuotaUsageVO> findQuotaUsage(final Long accountId, final Long domainId, final Integer usageType, final Date startDate, final Date endDate) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaUsageVO>>() {
|
||||
@Override
|
||||
public List<QuotaUsageVO> doInTransaction(final TransactionStatus status) {
|
||||
List<QuotaUsageVO> quv;
|
||||
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
|
||||
QueryBuilder<QuotaUsageVO> qb = QueryBuilder.create(QuotaUsageVO.class);
|
||||
if (accountId != null) {
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
}
|
||||
if (domainId != null) {
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
}
|
||||
if (usageType != null) {
|
||||
qb.and(qb.entity().getUsageType(), SearchCriteria.Op.EQ, usageType);
|
||||
}
|
||||
qb.and(qb.entity().getStartDate(), SearchCriteria.Op.BETWEEN, startDate, endDate);
|
||||
qb.and(qb.entity().getEndDate(), SearchCriteria.Op.BETWEEN, startDate, endDate);
|
||||
quv = listBy(qb.create());
|
||||
} else {
|
||||
quv = new ArrayList<QuotaUsageVO>();
|
||||
}
|
||||
if (quv.isEmpty()){
|
||||
//add a dummy entry
|
||||
QuotaUsageVO qu = new QuotaUsageVO();
|
||||
qu.setAccountId(accountId);
|
||||
qu.setDomainId(domainId);
|
||||
qu.setStartDate(startDate);
|
||||
qu.setEndDate(endDate);
|
||||
qu.setQuotaUsed(new BigDecimal(0));
|
||||
qu.setUsageType(-1);
|
||||
quv.add(qu);
|
||||
}
|
||||
return quv;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public QuotaUsageVO findLastQuotaUsageEntry(final Long accountId, final Long domainId, final Date beforeThis) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaUsageVO>() {
|
||||
@Override
|
||||
public QuotaUsageVO doInTransaction(final TransactionStatus status) {
|
||||
List<QuotaUsageVO> quotaUsageEntries = new ArrayList<>();
|
||||
Filter filter = new Filter(QuotaUsageVO.class, "startDate", false, 0L, 1L);
|
||||
QueryBuilder<QuotaUsageVO> qb = QueryBuilder.create(QuotaUsageVO.class);
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
qb.and(qb.entity().getStartDate(), SearchCriteria.Op.LT, beforeThis);
|
||||
quotaUsageEntries = search(qb.create(), filter);
|
||||
return !quotaUsageEntries.isEmpty() ? quotaUsageEntries.get(0) : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public QuotaUsageVO persistQuotaUsage(final QuotaUsageVO quotaUsage) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaUsageVO>() {
|
||||
@Override
|
||||
public QuotaUsageVO doInTransaction(final TransactionStatus status) {
|
||||
return persist(quotaUsage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 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.dao;
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -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.quota.dao;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.cloudstack.quota.vo.ServiceOfferingVO;
|
||||
|
||||
import com.cloud.event.UsageEventVO;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Component
|
||||
@Local(value = {ServiceOfferingDao.class})
|
||||
@DB()
|
||||
public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Long> implements ServiceOfferingDao {
|
||||
protected static final Logger s_logger = Logger.getLogger(ServiceOfferingDaoImpl.class);
|
||||
|
||||
@Inject
|
||||
UserVmDetailsDao userVmDetailsDao;
|
||||
|
||||
public ServiceOfferingVO findServiceOffering(final Long vmId, final long serviceOfferingId) {
|
||||
return Transaction.execute(TransactionLegacy.CLOUD_DB, new TransactionCallback<ServiceOfferingVO>() {
|
||||
@Override
|
||||
public ServiceOfferingVO doInTransaction(final TransactionStatus status) {
|
||||
ServiceOfferingVO offering = findById(serviceOfferingId);
|
||||
if (offering.isDynamic()) {
|
||||
if (vmId == null) {
|
||||
throw new CloudRuntimeException("missing argument vmId");
|
||||
}
|
||||
offering.setDynamicFlag(true);
|
||||
Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId);
|
||||
return getcomputeOffering(offering, dynamicOffering);
|
||||
}
|
||||
return offering;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private ServiceOfferingVO getcomputeOffering(final ServiceOfferingVO serviceOffering, final Map<String, String> customParameters) {
|
||||
return Transaction.execute(TransactionLegacy.CLOUD_DB, new TransactionCallback<ServiceOfferingVO>() {
|
||||
@Override
|
||||
public ServiceOfferingVO doInTransaction(final TransactionStatus status) {
|
||||
ServiceOfferingVO dummyoffering = new ServiceOfferingVO(serviceOffering);
|
||||
dummyoffering.setDynamicFlag(true);
|
||||
if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) {
|
||||
dummyoffering.setCpu(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuNumber.name())));
|
||||
}
|
||||
if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuSpeed.name())) {
|
||||
dummyoffering.setSpeed(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.cpuSpeed.name())));
|
||||
}
|
||||
if (customParameters.containsKey(UsageEventVO.DynamicParameters.memory.name())) {
|
||||
dummyoffering.setRamSize(Integer.parseInt(customParameters.get(UsageEventVO.DynamicParameters.memory.name())));
|
||||
}
|
||||
return dummyoffering;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.dao;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// 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.dao;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.cloudstack.quota.vo.UserVmDetailVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@Component
|
||||
@Local(value = UserVmDetailsDao.class)
|
||||
public class UserVmDetailsDaoImpl extends GenericDaoBase<UserVmDetailVO, Long> implements UserVmDetailsDao {
|
||||
private SearchBuilder<UserVmDetailVO> AllFieldsSearch;
|
||||
|
||||
public UserVmDetailsDaoImpl() {
|
||||
AllFieldsSearch = createSearchBuilder();
|
||||
AllFieldsSearch.and("resourceId", AllFieldsSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and("value", AllFieldsSearch.entity().getValue(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and("display", AllFieldsSearch.entity().isDisplay(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.done();
|
||||
}
|
||||
|
||||
@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);
|
||||
for (UserVmDetailVO result : results) {
|
||||
details.put(result.getName(), result.getValue());
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
//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.vo;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_account")
|
||||
public class QuotaAccountVO implements InternalIdentity {
|
||||
|
||||
private static final long serialVersionUID = -7112846845287653210L;
|
||||
|
||||
@Id
|
||||
@Column(name = "account_id")
|
||||
private Long accountId = null;
|
||||
|
||||
@Column(name = "quota_enforce")
|
||||
private Integer quotaEnforce = 0;
|
||||
|
||||
@Column(name = "quota_balance")
|
||||
private BigDecimal quotaBalance;
|
||||
|
||||
@Column(name = "quota_balance_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date quotaBalanceDate = null;
|
||||
|
||||
@Column(name = "quota_min_balance")
|
||||
private BigDecimal quotaMinBalance;
|
||||
|
||||
@Column(name = "quota_alert_type")
|
||||
private Integer quotaAlertType = null;
|
||||
|
||||
@Column(name = "quota_alert_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date quotaAlertDate = null;
|
||||
|
||||
@Column(name = "last_statement_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date lastStatementDate = null;
|
||||
|
||||
public QuotaAccountVO() {
|
||||
}
|
||||
|
||||
public QuotaAccountVO(Long accountId) {
|
||||
super();
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public Integer getQuotaEnforce() {
|
||||
return quotaEnforce == null ? 0 : quotaEnforce;
|
||||
}
|
||||
|
||||
public void setQuotaEnforce(Integer quotaEnforce) {
|
||||
this.quotaEnforce = quotaEnforce;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaBalance() {
|
||||
return quotaBalance;
|
||||
}
|
||||
|
||||
public void setQuotaBalance(BigDecimal quotaBalance) {
|
||||
this.quotaBalance = quotaBalance;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaMinBalance() {
|
||||
return quotaMinBalance == null ? new BigDecimal(0) : quotaMinBalance;
|
||||
}
|
||||
|
||||
public void setQuotaMinBalance(BigDecimal quotaMinBalance) {
|
||||
this.quotaMinBalance = quotaMinBalance;
|
||||
}
|
||||
|
||||
public Integer getQuotaAlertType() {
|
||||
return quotaAlertType;
|
||||
}
|
||||
|
||||
public void setQuotaAlertType(Integer quotaAlertType) {
|
||||
this.quotaAlertType = quotaAlertType;
|
||||
}
|
||||
|
||||
public Date getQuotaAlertDate() {
|
||||
return quotaAlertDate == null ? null : new Date(quotaAlertDate.getTime());
|
||||
}
|
||||
|
||||
public void setQuotaAlertDate(Date quotaAlertDate) {
|
||||
this.quotaAlertDate = quotaAlertDate == null ? null : new Date(quotaAlertDate.getTime());
|
||||
}
|
||||
|
||||
public Date getQuotaBalanceDate() {
|
||||
return quotaBalanceDate == null ? null : new Date(quotaBalanceDate.getTime());
|
||||
}
|
||||
|
||||
public void setQuotaBalanceDate(Date quotaBalanceDate) {
|
||||
this.quotaBalanceDate = quotaBalanceDate == null ? null : new Date(quotaBalanceDate.getTime());
|
||||
}
|
||||
|
||||
public Date getLastStatementDate() {
|
||||
return lastStatementDate == null ? null : new Date(lastStatementDate.getTime());
|
||||
}
|
||||
|
||||
public void setLastStatementDate(Date lastStatementDate) {
|
||||
this.lastStatementDate = lastStatementDate == null ? null : new Date(lastStatementDate.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QuotaAccountVO [accountId=" + accountId + ", quotaEnforce=" + quotaEnforce + ", quotaBalance=" + quotaBalance + ", quotaBalanceDate=" + quotaBalanceDate
|
||||
+ ", quotaMinBalance=" + quotaMinBalance + ", quotaAlertType=" + quotaAlertType + ", quotaAlertDate=" + quotaAlertDate + ", lastStatementDate=" + lastStatementDate
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
//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.vo;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_balance")
|
||||
public class QuotaBalanceVO implements InternalIdentity {
|
||||
|
||||
private static final long serialVersionUID = -7112846845287653210L;
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "account_id")
|
||||
private Long accountId = null;
|
||||
|
||||
@Column(name = "domain_id")
|
||||
private Long domainId = null;
|
||||
|
||||
@Column(name = "credit_balance")
|
||||
private BigDecimal creditBalance;
|
||||
|
||||
@Column(name = "credits_id")
|
||||
private Long creditsId;
|
||||
|
||||
@Column(name = "updated_on")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date updatedOn = null;
|
||||
|
||||
public QuotaBalanceVO() {
|
||||
}
|
||||
|
||||
public QuotaBalanceVO(final QuotaCreditsVO credit) {
|
||||
super();
|
||||
this.accountId = credit.getAccountId();
|
||||
this.domainId = credit.getDomainId();
|
||||
this.creditBalance = credit.getCredit();
|
||||
this.updatedOn = credit.getUpdatedOn() == null ? null : new Date(credit.getUpdatedOn().getTime());
|
||||
this.creditsId = credit.getId();
|
||||
}
|
||||
|
||||
public QuotaBalanceVO(final Long accountId, final Long domainId, final BigDecimal creditBalance, final Date updatedOn) {
|
||||
super();
|
||||
this.accountId = accountId;
|
||||
this.domainId = domainId;
|
||||
this.creditBalance = creditBalance;
|
||||
this.creditsId = 0L;
|
||||
this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public Long getCreditsId() {
|
||||
return creditsId;
|
||||
}
|
||||
|
||||
public void setCreditsId(Long creditsId) {
|
||||
this.creditsId = creditsId;
|
||||
}
|
||||
|
||||
public BigDecimal getCreditBalance() {
|
||||
return creditBalance;
|
||||
}
|
||||
|
||||
public void setCreditBalance(BigDecimal creditBalance) {
|
||||
this.creditBalance = creditBalance;
|
||||
}
|
||||
|
||||
public Date getUpdatedOn() {
|
||||
return updatedOn == null ? null : new Date(updatedOn.getTime());
|
||||
}
|
||||
|
||||
public void setUpdatedOn(Date updatedOn) {
|
||||
this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QuotaBalanceVO [id=" + id + ", accountId=" + accountId + ", domainId=" + domainId + ", creditBalance=" + creditBalance + ", creditsId=" + creditsId + ", updatedOn="
|
||||
+ updatedOn + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
//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.vo;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_credits")
|
||||
public class QuotaCreditsVO implements InternalIdentity {
|
||||
|
||||
private static final long serialVersionUID = -3576833845287653210L;
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "account_id")
|
||||
private Long accountId = null;
|
||||
|
||||
@Column(name = "domain_id")
|
||||
private Long domainId = null;
|
||||
|
||||
@Column(name = "credit")
|
||||
private BigDecimal credit;
|
||||
|
||||
@Column(name = "updated_on")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date updatedOn = null;
|
||||
|
||||
public QuotaCreditsVO() {
|
||||
}
|
||||
|
||||
public QuotaCreditsVO(long accountId, long domainId, BigDecimal credit, long updatedBy) {
|
||||
super();
|
||||
this.accountId = accountId;
|
||||
this.domainId = domainId;
|
||||
this.credit = credit;
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public BigDecimal getCredit() {
|
||||
return credit;
|
||||
}
|
||||
|
||||
public void setCredit(BigDecimal credit) {
|
||||
this.credit = credit;
|
||||
}
|
||||
|
||||
public Date getUpdatedOn() {
|
||||
return updatedOn == null ? null : new Date(updatedOn.getTime());
|
||||
}
|
||||
|
||||
public void setUpdatedOn(Date updatedOn) {
|
||||
this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime());
|
||||
}
|
||||
|
||||
public Long getUpdatedBy() {
|
||||
return updatedBy;
|
||||
}
|
||||
|
||||
public void setUpdatedBy(Long updatedBy) {
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
// User ID of the creditor
|
||||
@Column(name = "updated_by")
|
||||
private Long updatedBy = null;
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
//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.vo;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_email_templates")
|
||||
public class QuotaEmailTemplatesVO implements InternalIdentity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "template_name")
|
||||
private String templateName;
|
||||
|
||||
@Column(name = "template_subject")
|
||||
private String templateSubject;
|
||||
|
||||
@Column(name = "template_body")
|
||||
private String templateBody;
|
||||
|
||||
@Column(name = "locale")
|
||||
private String locale;
|
||||
|
||||
@Column(name = "updated")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date lastUpdated = null;
|
||||
|
||||
public QuotaEmailTemplatesVO() {
|
||||
}
|
||||
|
||||
public QuotaEmailTemplatesVO(String templateName, String templateSubject, String templateBody) {
|
||||
super();
|
||||
this.templateName = templateName;
|
||||
this.templateSubject = templateSubject;
|
||||
this.templateBody = templateBody;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
}
|
||||
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
public String getTemplateSubject() {
|
||||
return templateSubject;
|
||||
}
|
||||
|
||||
public void setTemplateSubject(String templateSubject) {
|
||||
this.templateSubject = templateSubject;
|
||||
}
|
||||
|
||||
public String getTemplateBody() {
|
||||
return templateBody;
|
||||
}
|
||||
|
||||
public void setTemplateBody(String templateBody) {
|
||||
this.templateBody = templateBody;
|
||||
}
|
||||
|
||||
public Date getLastUpdated() {
|
||||
return lastUpdated == null ? null : new Date(lastUpdated.getTime());
|
||||
}
|
||||
|
||||
public void setLastUpdated(Date lastUpdated) {
|
||||
this.lastUpdated = lastUpdated == null ? null : new Date(lastUpdated.getTime());
|
||||
}
|
||||
|
||||
public String getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public void setLocale(String locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
//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.vo;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_tariff")
|
||||
public class QuotaTariffVO implements InternalIdentity {
|
||||
private static final long serialVersionUID = -7117933766387653203L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "usage_type")
|
||||
private int usageType;
|
||||
|
||||
@Column(name = "usage_name")
|
||||
private String usageName;
|
||||
|
||||
@Column(name = "usage_unit")
|
||||
private String usageUnit;
|
||||
|
||||
@Column(name = "usage_discriminator")
|
||||
private String usageDiscriminator;
|
||||
|
||||
@Column(name = "currency_value")
|
||||
private BigDecimal currencyValue;
|
||||
|
||||
@Column(name = "effective_on")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date effectiveOn = null;
|
||||
|
||||
@Column(name = "updated_on")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date updatedOn = null;
|
||||
|
||||
@Column(name = "updated_by")
|
||||
private Long updatedBy = null;
|
||||
|
||||
public QuotaTariffVO() {
|
||||
}
|
||||
|
||||
public QuotaTariffVO(final int usagetype) {
|
||||
this.usageType = usagetype;
|
||||
}
|
||||
|
||||
public QuotaTariffVO(final int usagetype, final String usagename, final String usageunit, final String usagediscriminator, final BigDecimal currencyvalue,
|
||||
final Date effectiveOn, final Date updatedOn, final long updatedBy) {
|
||||
this.usageType = usagetype;
|
||||
this.usageName = usagename;
|
||||
this.usageUnit = usageunit;
|
||||
this.usageDiscriminator = usagediscriminator;
|
||||
this.currencyValue = currencyvalue;
|
||||
this.effectiveOn = effectiveOn;
|
||||
this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime());
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Date getEffectiveOn() {
|
||||
return effectiveOn == null ? null : new Date(effectiveOn.getTime());
|
||||
}
|
||||
|
||||
public void setEffectiveOn(Date effectiveOn) {
|
||||
this.effectiveOn = effectiveOn == null ? null : new Date(effectiveOn.getTime());
|
||||
}
|
||||
|
||||
public Date getUpdatedOn() {
|
||||
return updatedOn == null ? null : new Date(updatedOn.getTime());
|
||||
}
|
||||
|
||||
public void setUpdatedOn(Date updatedOn) {
|
||||
this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime());
|
||||
}
|
||||
|
||||
public Long getUpdatedBy() {
|
||||
return updatedBy;
|
||||
}
|
||||
|
||||
public void setUpdatedBy(Long updatedBy) {
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public String getUsageName() {
|
||||
return usageName;
|
||||
}
|
||||
|
||||
public void setUsageName(String usageName) {
|
||||
this.usageName = usageName;
|
||||
}
|
||||
|
||||
public String getUsageUnit() {
|
||||
return usageUnit;
|
||||
}
|
||||
|
||||
public void setUsageUnit(String usageUnit) {
|
||||
this.usageUnit = usageUnit;
|
||||
}
|
||||
|
||||
public String getUsageDiscriminator() {
|
||||
return usageDiscriminator;
|
||||
}
|
||||
|
||||
public void setUsageDiscriminator(String usageDiscriminator) {
|
||||
this.usageDiscriminator = usageDiscriminator;
|
||||
}
|
||||
|
||||
public BigDecimal getCurrencyValue() {
|
||||
return currencyValue;
|
||||
}
|
||||
|
||||
public void setCurrencyValue(BigDecimal currencyValue) {
|
||||
this.currencyValue = currencyValue;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return QuotaTypes.getDescription(usageType);
|
||||
}
|
||||
|
||||
public Long getIdObj(){
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
//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.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_usage")
|
||||
public class QuotaUsageVO implements InternalIdentity {
|
||||
|
||||
private static final long serialVersionUID = -7117933845287204781L;
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "zone_id")
|
||||
private Long zoneId = null;
|
||||
|
||||
@Column(name = "account_id")
|
||||
private Long accountId = null;
|
||||
|
||||
@Column(name = "domain_id")
|
||||
private Long domainId = null;
|
||||
|
||||
@Column(name = "usage_item_id")
|
||||
private Long usageItemId;
|
||||
|
||||
@Column(name = "usage_type")
|
||||
private int usageType;
|
||||
|
||||
@Column(name = "quota_used")
|
||||
private BigDecimal quotaUsed;
|
||||
|
||||
@Column(name = "start_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date startDate = null;
|
||||
|
||||
@Column(name = "end_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date endDate = null;
|
||||
|
||||
public QuotaUsageVO() {
|
||||
usageType = -1;
|
||||
quotaUsed = new BigDecimal(0);
|
||||
endDate = new Date();
|
||||
startDate = new Date();
|
||||
}
|
||||
|
||||
public QuotaUsageVO(Long usageItemId, Long zoneId, Long accountId, Long domainId, int usageType, BigDecimal quotaUsed, Date startDate, Date endDate) {
|
||||
super();
|
||||
this.usageItemId = usageItemId;
|
||||
this.zoneId = zoneId;
|
||||
this.accountId = accountId;
|
||||
this.domainId = domainId;
|
||||
this.usageType = usageType;
|
||||
this.quotaUsed = quotaUsed;
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public QuotaUsageVO(QuotaUsageVO toclone) {
|
||||
super();
|
||||
this.usageItemId = toclone.usageItemId;
|
||||
this.zoneId = toclone.zoneId;
|
||||
this.accountId = toclone.accountId;
|
||||
this.domainId = toclone.domainId;
|
||||
this.usageType = toclone.usageType;
|
||||
this.quotaUsed = toclone.quotaUsed;
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public Long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public void setZoneId(Long zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Long getUsageItemId() {
|
||||
return usageItemId;
|
||||
}
|
||||
|
||||
public void setUsageItemId(Long usageItemId) {
|
||||
this.usageItemId = usageItemId;
|
||||
}
|
||||
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaUsed() {
|
||||
return quotaUsed;
|
||||
}
|
||||
|
||||
public void setQuotaUsed(BigDecimal quotaUsed) {
|
||||
this.quotaUsed = quotaUsed;
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QuotaUsageVO [id=" + id + ", zoneId=" + zoneId + ", accountId=" + accountId + ", domainId=" + domainId + ", usageItemId=" + usageItemId + ", usageType=" + usageType
|
||||
+ ", quotaUsed=" + quotaUsed + ", startDate=" + startDate + ", endDate=" + endDate + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
//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.vo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.PrimaryKeyJoinColumn;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.Storage.ProvisioningType;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
@Entity
|
||||
@Table(name = "service_offering")
|
||||
@DiscriminatorValue(value = "Service")
|
||||
@PrimaryKeyJoinColumn(name = "id")
|
||||
public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering {
|
||||
@Column(name = "cpu")
|
||||
private Integer cpu;
|
||||
|
||||
@Column(name = "speed")
|
||||
private Integer speed;
|
||||
|
||||
@Column(name = "ram_size")
|
||||
private Integer ramSize;
|
||||
|
||||
@Column(name = "nw_rate")
|
||||
private Integer rateMbps;
|
||||
|
||||
@Column(name = "mc_rate")
|
||||
private Integer multicastRateMbps;
|
||||
|
||||
@Column(name = "ha_enabled")
|
||||
private boolean offerHA;
|
||||
|
||||
@Column(name = "limit_cpu_use")
|
||||
private boolean limitCpuUse;
|
||||
|
||||
@Column(name = "is_volatile")
|
||||
private boolean volatileVm;
|
||||
|
||||
@Column(name = "host_tag")
|
||||
private String hostTag;
|
||||
|
||||
@Column(name = "default_use")
|
||||
private boolean defaultUse;
|
||||
|
||||
@Column(name = "vm_type")
|
||||
private String vmType;
|
||||
|
||||
@Column(name = "sort_key")
|
||||
int sortKey;
|
||||
|
||||
@Column(name = "deployment_planner")
|
||||
private String deploymentPlanner = null;
|
||||
|
||||
// This is a delayed load value. If the value is null,
|
||||
// then this field has not been loaded yet.
|
||||
// Call service offering dao to load it.
|
||||
@Transient
|
||||
Map<String, String> details;
|
||||
|
||||
// This flag is required to tell if the offering is dynamic once the cpu, memory and speed are set.
|
||||
// In some cases cpu, memory and speed are set to non-null values even if the offering is dynamic.
|
||||
@Transient
|
||||
boolean isDynamic;
|
||||
|
||||
protected ServiceOfferingVO() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, String displayText,
|
||||
ProvisioningType provisioningType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vmType, boolean defaultUse) {
|
||||
super(name, displayText, provisioningType, false, tags, recreatable, useLocalStorage, systemUse, true);
|
||||
this.cpu = cpu;
|
||||
this.ramSize = ramSize;
|
||||
this.speed = speed;
|
||||
this.rateMbps = rateMbps;
|
||||
this.multicastRateMbps = multicastRateMbps;
|
||||
this.offerHA = offerHA;
|
||||
limitCpuUse = false;
|
||||
volatileVm = false;
|
||||
this.defaultUse = defaultUse;
|
||||
this.vmType = vmType == null ? null : vmType.toString().toLowerCase();
|
||||
}
|
||||
|
||||
public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitCpuUse,
|
||||
boolean volatileVm, String displayText, ProvisioningType provisioningType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vmType, Long domainId) {
|
||||
super(name, displayText, provisioningType, false, tags, recreatable, useLocalStorage, systemUse, true, domainId);
|
||||
this.cpu = cpu;
|
||||
this.ramSize = ramSize;
|
||||
this.speed = speed;
|
||||
this.rateMbps = rateMbps;
|
||||
this.multicastRateMbps = multicastRateMbps;
|
||||
this.offerHA = offerHA;
|
||||
this.limitCpuUse = limitCpuUse;
|
||||
this.volatileVm = volatileVm;
|
||||
this.vmType = vmType == null ? null : vmType.toString().toLowerCase();
|
||||
}
|
||||
|
||||
public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA,
|
||||
boolean limitResourceUse, boolean volatileVm, String displayText, ProvisioningType provisioningType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse,
|
||||
VirtualMachine.Type vmType, Long domainId, String hostTag) {
|
||||
this(name,
|
||||
cpu,
|
||||
ramSize,
|
||||
speed,
|
||||
rateMbps,
|
||||
multicastRateMbps,
|
||||
offerHA,
|
||||
limitResourceUse,
|
||||
volatileVm,
|
||||
displayText,
|
||||
provisioningType,
|
||||
useLocalStorage,
|
||||
recreatable,
|
||||
tags,
|
||||
systemUse,
|
||||
vmType,
|
||||
domainId);
|
||||
this.hostTag = hostTag;
|
||||
}
|
||||
|
||||
public ServiceOfferingVO(String name, Integer cpu, Integer ramSize, Integer speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA,
|
||||
boolean limitResourceUse, boolean volatileVm, String displayText, ProvisioningType provisioningType, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse,
|
||||
VirtualMachine.Type vmType, Long domainId, String hostTag, String deploymentPlanner) {
|
||||
this(name,
|
||||
cpu,
|
||||
ramSize,
|
||||
speed,
|
||||
rateMbps,
|
||||
multicastRateMbps,
|
||||
offerHA,
|
||||
limitResourceUse,
|
||||
volatileVm,
|
||||
displayText,
|
||||
provisioningType,
|
||||
useLocalStorage,
|
||||
recreatable,
|
||||
tags,
|
||||
systemUse,
|
||||
vmType,
|
||||
domainId,
|
||||
hostTag);
|
||||
this.deploymentPlanner = deploymentPlanner;
|
||||
}
|
||||
|
||||
public ServiceOfferingVO(ServiceOfferingVO offering) {
|
||||
super(offering.getId(),
|
||||
offering.getName(),
|
||||
offering.getDisplayText(),
|
||||
offering.getProvisioningType(),
|
||||
false,
|
||||
offering.getTags(),
|
||||
offering.isRecreatable(),
|
||||
offering.getUseLocalStorage(),
|
||||
offering.getSystemUse(),
|
||||
true,
|
||||
offering.isCustomizedIops()== null ? false:offering.isCustomizedIops(),
|
||||
offering.getDomainId(),
|
||||
offering.getMinIops(),
|
||||
offering.getMaxIops());
|
||||
cpu = offering.getCpu();
|
||||
ramSize = offering.getRamSize();
|
||||
speed = offering.getSpeed();
|
||||
rateMbps = offering.getRateMbps();
|
||||
multicastRateMbps = offering.getMulticastRateMbps();
|
||||
offerHA = offering.getOfferHA();
|
||||
limitCpuUse = offering.getLimitCpuUse();
|
||||
volatileVm = offering.getVolatileVm();
|
||||
hostTag = offering.getHostTag();
|
||||
vmType = offering.getSystemVmType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOfferHA() {
|
||||
return offerHA;
|
||||
}
|
||||
|
||||
public void setOfferHA(boolean offerHA) {
|
||||
this.offerHA = offerHA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getLimitCpuUse() {
|
||||
return limitCpuUse;
|
||||
}
|
||||
|
||||
public void setLimitResourceUse(boolean limitCpuUse) {
|
||||
this.limitCpuUse = limitCpuUse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDefaultUse() {
|
||||
return defaultUse;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transient
|
||||
public String[] getTagsArray() {
|
||||
String tags = getTags();
|
||||
if (tags == null || tags.length() == 0) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
return tags.split(",");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getCpu() {
|
||||
return cpu;
|
||||
}
|
||||
|
||||
public void setCpu(int cpu) {
|
||||
this.cpu = cpu;
|
||||
}
|
||||
|
||||
public void setSpeed(int speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public void setRamSize(int ramSize) {
|
||||
this.ramSize = ramSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getRamSize() {
|
||||
return ramSize;
|
||||
}
|
||||
|
||||
public void setRateMbps(Integer rateMbps) {
|
||||
this.rateMbps = rateMbps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getRateMbps() {
|
||||
return rateMbps;
|
||||
}
|
||||
|
||||
public void setMulticastRateMbps(Integer multicastRateMbps) {
|
||||
this.multicastRateMbps = multicastRateMbps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getMulticastRateMbps() {
|
||||
return multicastRateMbps;
|
||||
}
|
||||
|
||||
public void setHostTag(String hostTag) {
|
||||
this.hostTag = hostTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostTag() {
|
||||
return hostTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSystemVmType() {
|
||||
return vmType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSortKey(int key) {
|
||||
sortKey = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSortKey() {
|
||||
return sortKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVolatileVm() {
|
||||
return volatileVm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeploymentPlanner() {
|
||||
return deploymentPlanner;
|
||||
}
|
||||
|
||||
public Map<String, String> getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
public String getDetail(String name) {
|
||||
assert (details != null) : "Did you forget to load the details?";
|
||||
|
||||
return details != null ? details.get(name) : null;
|
||||
}
|
||||
|
||||
public void setDetail(String name, String value) {
|
||||
assert (details != null) : "Did you forget to load the details?";
|
||||
|
||||
details.put(name, value);
|
||||
}
|
||||
|
||||
public void setDetails(Map<String, String> details) {
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamic() {
|
||||
return cpu == null || speed == null || ramSize == null || isDynamic;
|
||||
}
|
||||
|
||||
public void setDynamicFlag(boolean isdynamic) {
|
||||
isDynamic = isdynamic;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
//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.vo;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.api.ResourceDetail;
|
||||
|
||||
@Entity
|
||||
@Table(name = "user_vm_details")
|
||||
public class UserVmDetailVO implements ResourceDetail {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "vm_id")
|
||||
private long resourceId;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "value", length = 5120)
|
||||
private String value;
|
||||
|
||||
@Column(name = "display")
|
||||
private boolean display = true;
|
||||
|
||||
public UserVmDetailVO() {
|
||||
}
|
||||
|
||||
public UserVmDetailVO(long vmId, String name, String value, boolean display) {
|
||||
this.resourceId = vmId;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
// 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.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 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.listAllQuotaAccount()).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);
|
||||
assertTrue(email.getSendDate()!= null);
|
||||
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,200 @@
|
|||
// 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 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 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);
|
||||
|
||||
QuotaUsageVO qu = quotaManager.updateQuotaNetwork(usageVO, UsageTypes.NETWORK_BYTES_SENT);
|
||||
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
|
||||
qu = quotaManager.updateQuotaAllocatedVMUsage(usageVO, new BigDecimal(0.5));
|
||||
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
|
||||
qu = quotaManager.updateQuotaDiskUsage(usageVO, new BigDecimal(0.5), UsageTypes.VOLUME);
|
||||
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
|
||||
qu = quotaManager.updateQuotaRaw(usageVO, new BigDecimal(0.5), UsageTypes.VPN_USERS);
|
||||
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
|
||||
|
||||
Mockito.verify(quotaUsageDao, Mockito.times(4)).persistQuotaUsage(Mockito.any(QuotaUsageVO.class));
|
||||
Mockito.verify(usageDao, Mockito.times(4)).persistUsage(Mockito.any(UsageVO.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessQuotaBalanceForAccount() {
|
||||
Date now = new Date();
|
||||
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(now.getTime()));
|
||||
quotaUsageVO.setEndDate(new Date(now.getTime()));
|
||||
List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
|
||||
quotaListForAccount.add(quotaUsageVO);
|
||||
|
||||
quotaManager.processQuotaBalanceForAccount(accountVO, quotaListForAccount);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
// 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.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.QuotaStatementImpl.STATEMENT_PERIODS;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
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 QuotaStatementTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
AccountDao accountDao;
|
||||
@Mock
|
||||
QuotaAccountDao quotaAcc;
|
||||
@Mock
|
||||
ConfigurationDao configDao;
|
||||
@Mock
|
||||
QuotaUsageDao quotaUsage;
|
||||
@Mock
|
||||
QuotaAlertManager alertManager;
|
||||
|
||||
@Spy
|
||||
QuotaStatementImpl quotaStatement = new QuotaStatementImpl();
|
||||
|
||||
private void injectMockToField(Object mock, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field f = QuotaStatementImpl.class.getDeclaredField(fieldName);
|
||||
f.setAccessible(true);
|
||||
f.set(quotaStatement, mock);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
|
||||
// Dummy transaction stack setup
|
||||
TransactionLegacy.open("QuotaStatementImplTest");
|
||||
|
||||
injectMockToField(accountDao, "_accountDao");
|
||||
injectMockToField(quotaAcc, "_quotaAcc");
|
||||
injectMockToField(configDao, "_configDao");
|
||||
injectMockToField(quotaUsage, "_quotaUsage");
|
||||
injectMockToField(alertManager, "_quotaAlert");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatementPeriodBIMONTHLY() {
|
||||
Calendar date = Calendar.getInstance();
|
||||
|
||||
//BIMONTHLY - first statement of month
|
||||
date.set(Calendar.DATE, QuotaStatementImpl.s_LAST_STATEMENT_SENT_DAYS + 1);
|
||||
Calendar period[] = quotaStatement.statementTime(date, STATEMENT_PERIODS.BIMONTHLY);
|
||||
assertTrue(period == null);
|
||||
|
||||
//1 of this month
|
||||
date.set(Calendar.DATE, 1);
|
||||
period = quotaStatement.statementTime(date, STATEMENT_PERIODS.BIMONTHLY);
|
||||
assertTrue(period != null);
|
||||
assertTrue(period.length == 2);
|
||||
assertTrue(period[0].toString(), period[0].before(period[1]));
|
||||
assertTrue(period[0].toString(), period[0].get(Calendar.DATE) == 1);
|
||||
assertTrue(period[1].toString(), period[1].get(Calendar.DATE) == 15);
|
||||
|
||||
//BIMONTHLY - second statement of month
|
||||
date = Calendar.getInstance();
|
||||
date.set(Calendar.DATE, QuotaStatementImpl.s_LAST_STATEMENT_SENT_DAYS + 16);
|
||||
period = quotaStatement.statementTime(date, STATEMENT_PERIODS.BIMONTHLY);
|
||||
assertTrue(period == null);
|
||||
|
||||
//17 of this month
|
||||
date.set(Calendar.DATE, 17);
|
||||
period = quotaStatement.statementTime(date, STATEMENT_PERIODS.BIMONTHLY);
|
||||
assertTrue(period != null);
|
||||
assertTrue(period.length == 2);
|
||||
assertTrue(period[0].toString(), period[0].before(period[1]));
|
||||
assertTrue(period[0].toString(), period[0].get(Calendar.DATE) == 16);
|
||||
|
||||
//get last day of the previous month
|
||||
Calendar aCalendar = Calendar.getInstance();
|
||||
aCalendar.add(Calendar.MONTH, -1);
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
|
||||
assertTrue(period[1].toString(), period[1].get(Calendar.DATE) == aCalendar.get(Calendar.DATE));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatementPeriodMONTHLY() {
|
||||
Calendar date = Calendar.getInstance();
|
||||
Calendar aCalendar = Calendar.getInstance();
|
||||
|
||||
//MONTHLY
|
||||
date = Calendar.getInstance();
|
||||
date.set(Calendar.DATE, QuotaStatementImpl.s_LAST_STATEMENT_SENT_DAYS + 1);
|
||||
Calendar period[] = quotaStatement.statementTime(date, STATEMENT_PERIODS.MONTHLY);
|
||||
assertTrue(period == null);
|
||||
|
||||
//1 of this month
|
||||
date.set(Calendar.DATE, QuotaStatementImpl.s_LAST_STATEMENT_SENT_DAYS - 1);
|
||||
period = quotaStatement.statementTime(date, STATEMENT_PERIODS.MONTHLY);
|
||||
assertTrue(period != null);
|
||||
assertTrue(period.length == 2);
|
||||
assertTrue(period[0].toString(), period[0].before(period[1]));
|
||||
assertTrue(period[0].toString(), period[0].get(Calendar.DATE) == 1);
|
||||
|
||||
//get last day of the previous month
|
||||
aCalendar = Calendar.getInstance();
|
||||
aCalendar.add(Calendar.MONTH, -1);
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
|
||||
assertTrue(period[1].toString(), period[1].get(Calendar.DATE) == aCalendar.get(Calendar.DATE));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatementPeriodQUATERLY() {
|
||||
Calendar date = Calendar.getInstance();
|
||||
Calendar aCalendar = Calendar.getInstance();
|
||||
|
||||
//QUATERLY
|
||||
date = Calendar.getInstance();
|
||||
date.set(Calendar.MONTH, Calendar.JANUARY); // 1 Jan
|
||||
date.set(Calendar.DATE, 1);
|
||||
Calendar period[] = quotaStatement.statementTime(date, STATEMENT_PERIODS.QUATERLY);
|
||||
assertTrue(period != null);
|
||||
assertTrue(period.length == 2);
|
||||
assertTrue("period[0].before(period[1])" + period[0].toString(), period[0].before(period[1]));
|
||||
assertTrue("period[0].get(Calendar.DATE) == 1" + period[0].toString(), period[0].get(Calendar.DATE) == 1);
|
||||
assertTrue("period[0].get(Calendar.MONTH) == Calendar.OCTOBER" + period[0].toString(), period[0].get(Calendar.MONTH) == Calendar.OCTOBER); //october
|
||||
|
||||
//get last day of the previous month
|
||||
aCalendar = Calendar.getInstance();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.DECEMBER);
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
assertTrue(" period[1].get(Calendar.DATE) == aCalendar.get(Calendar.DATE)" + period[1].toString(), period[1].get(Calendar.DATE) == aCalendar.get(Calendar.DATE));
|
||||
assertTrue("period[1].get(Calendar.MONTH) == aCalendar.get(Calendar.MONTH)" + period[1].toString(), period[1].get(Calendar.MONTH) == aCalendar.get(Calendar.MONTH));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatementPeriodHALFYEARLY() {
|
||||
Calendar date = Calendar.getInstance();
|
||||
Calendar aCalendar = Calendar.getInstance();
|
||||
|
||||
//QUATERLY
|
||||
date = Calendar.getInstance();
|
||||
date.set(Calendar.MONTH, Calendar.JANUARY); // 1 Jan
|
||||
date.set(Calendar.DATE, 1);
|
||||
Calendar period[] = quotaStatement.statementTime(date, STATEMENT_PERIODS.HALFYEARLY);
|
||||
assertTrue(period != null);
|
||||
assertTrue(period.length == 2);
|
||||
assertTrue("period[0].before(period[1])" + period[0].toString(), period[0].before(period[1]));
|
||||
assertTrue("period[0].get(Calendar.DATE) == 1" + period[0].toString(), period[0].get(Calendar.DATE) == 1);
|
||||
assertTrue("period[0].get(Calendar.MONTH) == Calendar.JULY" + period[0].toString(), period[0].get(Calendar.MONTH) == Calendar.JULY); //july
|
||||
|
||||
//get last day of the previous month
|
||||
aCalendar = Calendar.getInstance();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.DECEMBER);
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
assertTrue(" period[1].get(Calendar.DATE) == aCalendar.get(Calendar.DATE)" + period[1].toString(), period[1].get(Calendar.DATE) == aCalendar.get(Calendar.DATE));
|
||||
assertTrue("period[1].get(Calendar.MONTH) == aCalendar.get(Calendar.MONTH)" + period[1].toString(), period[1].get(Calendar.MONTH) == aCalendar.get(Calendar.MONTH));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatementPeriodYEARLY() {
|
||||
Calendar date = Calendar.getInstance();
|
||||
Calendar aCalendar = Calendar.getInstance();
|
||||
|
||||
//QUATERLY
|
||||
date = Calendar.getInstance();
|
||||
date.set(Calendar.MONTH, Calendar.JANUARY); // 1 Jan
|
||||
date.set(Calendar.DATE, 1);
|
||||
Calendar period[] = quotaStatement.statementTime(date, STATEMENT_PERIODS.YEARLY);
|
||||
assertTrue("period != null", period != null);
|
||||
assertTrue(period.length == 2);
|
||||
assertTrue("period[0].before(period[1])" + period[0].toString(), period[0].before(period[1]));
|
||||
assertTrue("period[0].get(Calendar.DATE) == 1" + period[0].toString(), period[0].get(Calendar.DATE) == 1);
|
||||
assertTrue("period[0].get(Calendar.MONTH) == Calendar.JANUARY" + period[0].toString(), period[0].get(Calendar.MONTH) == Calendar.JANUARY); //january
|
||||
|
||||
//get last day of the previous month
|
||||
aCalendar = Calendar.getInstance();
|
||||
aCalendar.set(Calendar.MONTH, Calendar.DECEMBER);
|
||||
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
|
||||
assertTrue(" period[1].get(Calendar.DATE) == aCalendar.get(Calendar.DATE)" + period[1].toString(), period[1].get(Calendar.DATE) == aCalendar.get(Calendar.DATE));
|
||||
assertTrue("period[1].get(Calendar.MONTH) == aCalendar.get(Calendar.MONTH)" + period[1].toString(), period[1].get(Calendar.MONTH) == aCalendar.get(Calendar.MONTH));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendStatement() throws UnsupportedEncodingException, MessagingException {
|
||||
Calendar date = Calendar.getInstance();
|
||||
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.listAllQuotaAccount()).thenReturn(accounts);
|
||||
|
||||
Mockito.when(quotaUsage.findTotalQuotaUsage(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyInt(), Mockito.any(Date.class), Mockito.any(Date.class)))
|
||||
.thenReturn(new BigDecimal(100));
|
||||
|
||||
QuotaAlertManagerImpl.DeferredQuotaEmail email = new QuotaAlertManagerImpl.DeferredQuotaEmail(accountVO, acc, new BigDecimal(100),
|
||||
QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW);
|
||||
// call real method on send monthly statement
|
||||
Mockito.doCallRealMethod().when(quotaStatement).sendStatement();
|
||||
Calendar period[] = quotaStatement.statementTime(date, STATEMENT_PERIODS.MONTHLY);
|
||||
if (period != null){
|
||||
Mockito.verify(alertManager, Mockito.times(1)).sendQuotaAlert(email);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// 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.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaTypesTest extends TestCase {
|
||||
|
||||
@Test
|
||||
public void testQuotaTypesList() {
|
||||
Map<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));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +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. -->
|
||||
<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.7.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>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# 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.
|
||||
name=quota
|
||||
parent=api
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<bean id="QuotaService" class="org.apache.cloudstack.quota.QuotaServiceImpl" />
|
||||
<bean id="QuotaResponseBuilder" class="org.apache.cloudstack.api.response.QuotaResponseBuilderImpl"/>
|
||||
|
||||
</beans>
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
//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 java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaBalanceResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.api.response.QuotaStatementItemResponse;
|
||||
|
||||
@APICommand(name = "quotaBalance", responseObject = QuotaStatementItemResponse.class, description = "Create a quota balance statement", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaBalanceCmd extends BaseCmd {
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaBalanceCmd.class);
|
||||
|
||||
private static final String s_name = "quotabalanceresponse";
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "Account Id for which statement needs to be generated")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "If domain Id is given and the caller is domain admin then the statement is generated for domain.")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "End date range for quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.")
|
||||
private Date endDate;
|
||||
|
||||
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "Start date range quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.")
|
||||
private Date startDate;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "List usage records for the specified account")
|
||||
private Long accountId;
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _responseBuilder;
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate == null ? null : _responseBuilder.startOfNextDay(endDate == null ? null : new Date(endDate.getTime()));
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return _accountService.getActiveAccountByName(accountName, domainId).getAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
List<QuotaBalanceVO> quotaUsage = _responseBuilder.getQuotaBalance(this);
|
||||
|
||||
QuotaBalanceResponse response;
|
||||
if (getEndDate() == null) {
|
||||
response = _responseBuilder.createQuotaLastBalanceResponse(quotaUsage, getStartDate());
|
||||
} else {
|
||||
response = _responseBuilder.createQuotaBalanceResponse(quotaUsage, getStartDate(), endDate == null ? null : new Date(endDate.getTime()));
|
||||
}
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
//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.Account;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaCreditsResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = "quotaCredits", responseObject = QuotaCreditsResponse.class, description = "Add +-credits to an account", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaCreditsCmd extends BaseCmd {
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _responseBuilder;
|
||||
|
||||
@Inject
|
||||
QuotaService _quotaService;
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaStatementCmd.class);
|
||||
|
||||
private static final String s_name = "quotacreditsresponse";
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "Account Id for which quota credits need to be added")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "Domain for which quota credits need to be added")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.VALUE, type = CommandType.DOUBLE, required = true, description = "Value of the credits to be added+, subtracted-")
|
||||
private Double value;
|
||||
|
||||
@Parameter(name = "min_balance", type = CommandType.DOUBLE, required = false, description = "Minimum balance threshold of the account")
|
||||
private Double minBalance;
|
||||
|
||||
@Parameter(name = "quota_enforce", type = CommandType.BOOLEAN, required = false, description = "Account for which quota enforce is set to false will not be locked when there is no credit balance")
|
||||
private Boolean quotaEnforce;
|
||||
|
||||
public Double getMinBalance() {
|
||||
return minBalance;
|
||||
}
|
||||
|
||||
public void setMinBalance(Double minBalance) {
|
||||
this.minBalance = minBalance;
|
||||
}
|
||||
|
||||
public Boolean getQuotaEnforce() {
|
||||
return quotaEnforce;
|
||||
}
|
||||
|
||||
public void setQuotaEnforce(Boolean quotaEnforce) {
|
||||
this.quotaEnforce = quotaEnforce;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public QuotaCreditsCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
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 (getValue() == null) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please send a valid non-empty quota value");
|
||||
}
|
||||
if (getQuotaEnforce() != null && getQuotaEnforce()) {
|
||||
_quotaService.setLockAccount(accountId, getQuotaEnforce());
|
||||
}
|
||||
if (getMinBalance() != null) {
|
||||
_quotaService.setMinBalance(accountId, getMinBalance());
|
||||
}
|
||||
else {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please set a value for min balance");
|
||||
}
|
||||
|
||||
final QuotaCreditsResponse response = _responseBuilder.addQuotaCredits(accountId, getDomainId(), getValue(), CallContext.current().getCallingUserId());
|
||||
response.setResponseName(getCommandName());
|
||||
response.setObjectName("quotacredits");
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
//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 org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaEmailTemplateResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = "quotaEmailTemplateList", responseObject = QuotaEmailTemplateResponse.class, description = "Lists all quota email templates", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaEmailTemplateListCmd extends BaseListCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaEmailTemplateListCmd.class);
|
||||
private static final String s_name = "quotaemailtemplatelistresponse";
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _quotaResponseBuilder;
|
||||
|
||||
@Parameter(name = "templatetype", type = CommandType.STRING, description = "List by type of the quota email template, allowed types: QUOTA_LOW, QUOTA_EMPTY")
|
||||
private String templateName;
|
||||
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
}
|
||||
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final ListResponse<QuotaEmailTemplateResponse> response = new ListResponse<QuotaEmailTemplateResponse>();
|
||||
response.setResponses(_quotaResponseBuilder.listQuotaEmailTemplates(this));
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
//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.Account;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
|
||||
@APICommand(name = "quotaEmailTemplateUpdate", responseObject = SuccessResponse.class, description = "Updates existing email templates for quota alerts", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaEmailTemplateUpdateCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaEmailTemplateUpdateCmd.class);
|
||||
private static final String s_name = "quotaemailtemplateupdateresponse";
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _quotaResponseBuilder;
|
||||
|
||||
@Parameter(name = "templatetype", type = CommandType.STRING, required=true, description = "Type of the quota email template, allowed types: QUOTA_LOW, QUOTA_EMPTY")
|
||||
private String templateName;
|
||||
|
||||
@Parameter(name = "templatesubject", type = CommandType.STRING, required=true, description = "The quota email template subject, max: 77 characters", length = 77)
|
||||
private String templateSubject;
|
||||
|
||||
@Parameter(name = "templatebody", type = CommandType.STRING, required=true, description = "The quota email template body, max: 500k characters", length = 512000)
|
||||
private String templateBody;
|
||||
|
||||
@Parameter(name = "locale", type = CommandType.STRING, description = "The locale of the email text")
|
||||
private String locale;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final String templateName = getTemplateName();
|
||||
if (templateName == null || getTemplateSubject() == null || getTemplateBody() == null) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Failed to update quota email template due to empty or invalid template name or text");
|
||||
}
|
||||
|
||||
boolean isValidTemplateName = false;
|
||||
for (QuotaConfig.QuotaEmailTemplateTypes e: QuotaConfig.QuotaEmailTemplateTypes.values()) {
|
||||
if (e.toString().equalsIgnoreCase(templateName)) {
|
||||
isValidTemplateName = true;
|
||||
setTemplateName(e.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isValidTemplateName) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid quota email template type, allowed values are: " + Arrays.toString(QuotaConfig.QuotaEmailTemplateTypes.values()));
|
||||
}
|
||||
|
||||
if (!_quotaResponseBuilder.updateQuotaEmailTemplate(this)) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Unable to update quota email template due to an internal error");
|
||||
}
|
||||
final SuccessResponse response = new SuccessResponse();
|
||||
response.setResponseName(getCommandName());
|
||||
response.setSuccess(true);
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
}
|
||||
|
||||
public String getTemplateSubject() {
|
||||
return templateSubject;
|
||||
}
|
||||
|
||||
public String getTemplateBody() {
|
||||
return templateBody;
|
||||
}
|
||||
|
||||
public String getLocale() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
//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 java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaStatementResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.api.response.QuotaStatementItemResponse;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "quotaStatement", responseObject = QuotaStatementItemResponse.class, description = "Create a quota statement", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaStatementCmd extends BaseCmd {
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaStatementCmd.class);
|
||||
|
||||
private static final String s_name = "quotastatementresponse";
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "Optional, Account Id for which statement needs to be generated")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = true, description = "End date range for quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.")
|
||||
private Date endDate;
|
||||
|
||||
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = true, description = "Start date range quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.")
|
||||
private Date startDate;
|
||||
|
||||
@Parameter(name = ApiConstants.TYPE, type = CommandType.INTEGER, description = "List quota usage records for the specified usage type")
|
||||
private Integer usageType;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "List usage records for the specified account")
|
||||
private Long accountId;
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _responseBuilder;
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public Integer getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(Integer usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return _responseBuilder.startOfNextDay(endDate == null ? new Date() : new Date(endDate.getTime()));
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Long accountId = _accountService.getActiveAccountByName(accountName, domainId).getAccountId();
|
||||
if (accountId == null) {
|
||||
return CallContext.current().getCallingAccount().getId();
|
||||
}
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
List<QuotaUsageVO> quotaUsage = _responseBuilder.getQuotaUsage(this);
|
||||
|
||||
QuotaStatementResponse response = _responseBuilder.createQuotaStatementResponse(quotaUsage);
|
||||
response.setStartDate(startDate == null ? null : new Date(startDate.getTime()));
|
||||
response.setEndDate(endDate == null ? null : new Date(endDate.getTime()));
|
||||
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
//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.Account;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.BaseCmd.CommandType;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaSummaryResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = "quotaSummary", responseObject = QuotaSummaryResponse.class, description = "Lists balance and quota usage for all accounts", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaSummaryCmd extends BaseListCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaSummaryCmd.class);
|
||||
private static final String s_name = "quotasummaryresponse";
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = false, description = "Optional, Account Id for which statement needs to be generated")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = false, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, required = false, description = "Optional, to list all accounts irrespective of the quota activity")
|
||||
private Boolean listAll;
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _responseBuilder;
|
||||
|
||||
public QuotaSummaryCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<QuotaSummaryResponse> responses;
|
||||
if (caller.getAccountId() <= 2) { //non root admin or system
|
||||
if (getAccountName() != null && getDomainId() != null)
|
||||
responses = _responseBuilder.createQuotaSummaryResponse(caller.getAccountName(), caller.getDomainId());
|
||||
else
|
||||
responses = _responseBuilder.createQuotaSummaryResponse(getListAll());
|
||||
} else {
|
||||
responses = _responseBuilder.createQuotaSummaryResponse(caller.getAccountName(), caller.getDomainId());
|
||||
}
|
||||
final ListResponse<QuotaSummaryResponse> response = new ListResponse<QuotaSummaryResponse>();
|
||||
response.setResponses(responses);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
public Boolean getListAll() {
|
||||
return listAll == null ? false: listAll;
|
||||
}
|
||||
|
||||
public void setListAll(Boolean listAll) {
|
||||
this.listAll = listAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
//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.Account;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaTariffResponse;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@APICommand(name = "quotaTariffList", responseObject = QuotaTariffResponse.class, description = "Lists all quota tariff plans", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaTariffListCmd extends BaseListCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaTariffListCmd.class);
|
||||
private static final String s_name = "quotatarifflistresponse";
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _responseBuilder;
|
||||
|
||||
@Parameter(name = ApiConstants.USAGE_TYPE, type = CommandType.INTEGER, required = false, description = "Usage type of the resource")
|
||||
private Integer usageType;
|
||||
|
||||
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = false, description = "The effective start date on/after which the quota tariff is effective and older tariffs are no longer used for the usage type. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.")
|
||||
private Date effectiveDate;
|
||||
|
||||
public QuotaTariffListCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final List<QuotaTariffVO> result = _responseBuilder.listQuotaTariffPlans(this);
|
||||
|
||||
final List<QuotaTariffResponse> responses = new ArrayList<QuotaTariffResponse>();
|
||||
for (final QuotaTariffVO resource : result) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Result desc=" + resource.getDescription() + " date=" + resource.getEffectiveOn() + " val=" + resource.getCurrencyValue());
|
||||
}
|
||||
responses.add(_responseBuilder.createQuotaTariffResponse(resource));
|
||||
}
|
||||
|
||||
final ListResponse<QuotaTariffResponse> response = new ListResponse<QuotaTariffResponse>();
|
||||
response.setResponses(responses);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public Date getEffectiveDate() {
|
||||
return effectiveDate ==null ? null : new Date(effectiveDate.getTime());
|
||||
}
|
||||
|
||||
public Integer getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(Integer usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
//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.Account;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
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.vo.QuotaTariffVO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@APICommand(name = "quotaTariffUpdate", responseObject = QuotaTariffResponse.class, description = "Update the tariff plan for a resource", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaTariffUpdateCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaTariffUpdateCmd.class);
|
||||
private static final String s_name = "quotatariffupdateresponse";
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder _responseBuilder;
|
||||
|
||||
@Parameter(name = ApiConstants.USAGE_TYPE, type = CommandType.INTEGER, required = true, description = "Integer value for the usage type of the resource")
|
||||
private Integer usageType;
|
||||
|
||||
@Parameter(name = "value", type = CommandType.DOUBLE, required = true, description = "The quota tariff value of the resource as per the default unit")
|
||||
private Double value;
|
||||
|
||||
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = true, description = "The effective start date on/after which the quota tariff is effective and older tariffs are no longer used for the usage type. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.")
|
||||
private Date startDate;
|
||||
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public QuotaTariffUpdateCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final QuotaTariffVO result = _responseBuilder.updateQuotaTariffPlan(this);
|
||||
if (result == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update quota tariff plan");
|
||||
}
|
||||
final QuotaTariffResponse response = _responseBuilder.createQuotaTariffResponse(result);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
//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.Account;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.response.QuotaUpdateResponse;
|
||||
import org.apache.cloudstack.quota.QuotaAlertManager;
|
||||
import org.apache.cloudstack.quota.QuotaManager;
|
||||
import org.apache.cloudstack.quota.QuotaStatement;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = "quotaUpdate", responseObject = QuotaUpdateResponse.class, description = "Update quota calculations, alerts and statements", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaUpdateCmd extends BaseCmd {
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaUpdateCmd.class);
|
||||
|
||||
private static final String s_name = "quotaupdateresponse";
|
||||
|
||||
@Inject
|
||||
QuotaManager _manager;
|
||||
@Inject
|
||||
QuotaStatement _statement;
|
||||
@Inject
|
||||
QuotaAlertManager _alert;
|
||||
|
||||
public QuotaUpdateCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
_manager.calculateQuotaUsage();
|
||||
_statement.sendStatement();
|
||||
_alert.checkAndSendQuotaAlertEmails();
|
||||
QuotaUpdateResponse response = new QuotaUpdateResponse(Calendar.getInstance());
|
||||
response.setResponseName(getCommandName());
|
||||
response.setObjectName("quotacredits");
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
//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 java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class QuotaBalanceResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("accountid")
|
||||
@Param(description = "account id")
|
||||
private Long accountId;
|
||||
|
||||
@SerializedName("account")
|
||||
@Param(description = "account name")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName("domain")
|
||||
@Param(description = "domain id")
|
||||
private Long domainId;
|
||||
|
||||
@SerializedName("startquota")
|
||||
@Param(description = "quota started with")
|
||||
private BigDecimal startQuota;
|
||||
|
||||
@SerializedName("endquota")
|
||||
@Param(description = "quota by end of this period")
|
||||
private BigDecimal endQuota;
|
||||
|
||||
@SerializedName("credits")
|
||||
@Param(description = "list of credits made during this period")
|
||||
private List<QuotaCreditsResponse> credits = null;
|
||||
|
||||
@SerializedName("startdate")
|
||||
@Param(description = "start date")
|
||||
private Date startDate = null;
|
||||
|
||||
@SerializedName("enddate")
|
||||
@Param(description = "end date")
|
||||
private Date endDate = null;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "currency")
|
||||
private String currency;
|
||||
|
||||
public QuotaBalanceResponse() {
|
||||
super();
|
||||
credits = new ArrayList<QuotaCreditsResponse>();
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public BigDecimal getStartQuota() {
|
||||
return startQuota;
|
||||
}
|
||||
|
||||
public void setStartQuota(BigDecimal startQuota) {
|
||||
this.startQuota = startQuota.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
public BigDecimal getEndQuota() {
|
||||
return endQuota;
|
||||
}
|
||||
|
||||
public void setEndQuota(BigDecimal endQuota) {
|
||||
this.endQuota = endQuota.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
public List<QuotaCreditsResponse> getCredits() {
|
||||
return credits;
|
||||
}
|
||||
|
||||
public void setCredits(List<QuotaCreditsResponse> credits) {
|
||||
this.credits = credits;
|
||||
}
|
||||
|
||||
public void addCredits(QuotaBalanceVO credit) {
|
||||
QuotaCreditsResponse cr = new QuotaCreditsResponse();
|
||||
cr.setCredits(credit.getCreditBalance());
|
||||
cr.setUpdatedOn(credit.getUpdatedOn() == null ? null : new Date(credit.getUpdatedOn().getTime()));
|
||||
credits.add(0, cr);
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
//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.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Date;
|
||||
|
||||
public class QuotaCreditsResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("credits")
|
||||
@Param(description = "the credit deposited")
|
||||
private BigDecimal credits;
|
||||
|
||||
@SerializedName("updated_by")
|
||||
@Param(description = "the user name of the admin who updated the credits")
|
||||
private String updatedBy;
|
||||
|
||||
@SerializedName("updated_on")
|
||||
@Param(description = "the account name of the admin who updated the credits")
|
||||
private Date updatedOn;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "currency")
|
||||
private String currency;
|
||||
|
||||
public QuotaCreditsResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public QuotaCreditsResponse(QuotaCreditsVO result, String updatedBy) {
|
||||
super();
|
||||
if (result != null) {
|
||||
setCredits(result.getCredit());
|
||||
setUpdatedBy(updatedBy);
|
||||
setUpdatedOn(new Date());
|
||||
}
|
||||
}
|
||||
|
||||
public BigDecimal getCredits() {
|
||||
return credits;
|
||||
}
|
||||
|
||||
public void setCredits(BigDecimal credits) {
|
||||
this.credits = credits.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
public String getUpdatedBy() {
|
||||
return updatedBy;
|
||||
}
|
||||
|
||||
public void setUpdatedBy(String updatedBy) {
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
|
||||
public Date getUpdatedOn() {
|
||||
return updatedOn;
|
||||
}
|
||||
|
||||
public void setUpdatedOn(Date updatedOn) {
|
||||
this.updatedOn = updatedOn;
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
//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.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class QuotaEmailTemplateResponse extends BaseResponse {
|
||||
@SerializedName("templatetype")
|
||||
@Param(description = "Template type")
|
||||
private String templateType;
|
||||
|
||||
@SerializedName("templatesubject")
|
||||
@Param(description = "The quota email template subject")
|
||||
private String templateSubject;
|
||||
|
||||
@SerializedName("templatebody")
|
||||
@Param(description = "The quota email template content")
|
||||
private String templateText;
|
||||
|
||||
@SerializedName("locale")
|
||||
@Param(description = "The quota email template locale")
|
||||
private String locale;
|
||||
|
||||
@SerializedName("last_updated")
|
||||
@Param(description = "Last date/time when template was updated")
|
||||
private Date lastUpdatedOn;
|
||||
|
||||
public QuotaEmailTemplateResponse() {
|
||||
super();
|
||||
this.setObjectName("quotaemailtemplate");
|
||||
}
|
||||
|
||||
public String getTemplateType() {
|
||||
return templateType;
|
||||
}
|
||||
|
||||
public void setTemplateType(String templateType) {
|
||||
this.templateType = templateType;
|
||||
}
|
||||
|
||||
public String getTemplateSubject() {
|
||||
return templateSubject;
|
||||
}
|
||||
|
||||
public void setTemplateSubject(String templateSubject) {
|
||||
this.templateSubject = templateSubject;
|
||||
}
|
||||
|
||||
public String getTemplateText() {
|
||||
return templateText;
|
||||
}
|
||||
|
||||
public void setTemplateText(String templateText) {
|
||||
this.templateText = templateText;
|
||||
}
|
||||
|
||||
public String getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public void setLocale(String locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public Date getLastUpdatedOn() {
|
||||
return lastUpdatedOn;
|
||||
}
|
||||
|
||||
public void setLastUpdatedOn(Date lastUpdatedOn) {
|
||||
this.lastUpdatedOn = lastUpdatedOn;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.response;
|
||||
|
||||
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface QuotaResponseBuilder {
|
||||
|
||||
QuotaTariffVO updateQuotaTariffPlan(QuotaTariffUpdateCmd cmd);
|
||||
|
||||
List<QuotaTariffVO> listQuotaTariffPlans(QuotaTariffListCmd cmd);
|
||||
|
||||
QuotaTariffResponse createQuotaTariffResponse(QuotaTariffVO configuration);
|
||||
|
||||
QuotaStatementResponse createQuotaStatementResponse(List<QuotaUsageVO> quotaUsage);
|
||||
|
||||
QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaUsage, Date startDate, Date endDate);
|
||||
|
||||
List<QuotaSummaryResponse> createQuotaSummaryResponse(Boolean listAll);
|
||||
|
||||
List<QuotaSummaryResponse> createQuotaSummaryResponse(String accountName, Long domainId);
|
||||
|
||||
QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate);
|
||||
|
||||
QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy, Date despositedOn);
|
||||
|
||||
List<QuotaUsageVO> getQuotaUsage(QuotaStatementCmd cmd);
|
||||
|
||||
List<QuotaBalanceVO> getQuotaBalance(QuotaBalanceCmd cmd);
|
||||
|
||||
QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy);
|
||||
|
||||
List<QuotaEmailTemplateResponse> listQuotaEmailTemplates(QuotaEmailTemplateListCmd cmd);
|
||||
|
||||
boolean updateQuotaEmailTemplate(QuotaEmailTemplateUpdateCmd cmd);
|
||||
|
||||
Date startOfNextDay(Date dt);
|
||||
|
||||
Date startOfNextDay();
|
||||
}
|
||||
|
|
@ -0,0 +1,516 @@
|
|||
//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.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
|
||||
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.apache.cloudstack.quota.QuotaStatement;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
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.QuotaCreditsDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
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.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.region.RegionManager;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
@Component
|
||||
@Local(value = QuotaResponseBuilderImpl.class)
|
||||
public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaResponseBuilderImpl.class);
|
||||
|
||||
@Inject
|
||||
private QuotaTariffDao _quotaTariffDao;
|
||||
@Inject
|
||||
private QuotaBalanceDao _quotaBalanceDao;
|
||||
@Inject
|
||||
private QuotaCreditsDao _quotaCreditsDao;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsageDao;
|
||||
@Inject
|
||||
private QuotaEmailTemplatesDao _quotaEmailTemplateDao;
|
||||
|
||||
@Inject
|
||||
private UserDao _userDao;
|
||||
@Inject
|
||||
private QuotaService _quotaService;
|
||||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private QuotaAccountDao _quotaAccountDao;
|
||||
@Inject
|
||||
private DomainDao _domainDao;
|
||||
@Inject
|
||||
private RegionManager _regionMgr;
|
||||
@Inject
|
||||
private QuotaStatement _statement;
|
||||
|
||||
@Override
|
||||
public QuotaTariffResponse createQuotaTariffResponse(QuotaTariffVO tariff) {
|
||||
final QuotaTariffResponse response = new QuotaTariffResponse();
|
||||
response.setUsageType(tariff.getUsageType());
|
||||
response.setUsageName(tariff.getUsageName());
|
||||
response.setUsageUnit(tariff.getUsageUnit());
|
||||
response.setUsageDiscriminator(tariff.getUsageDiscriminator());
|
||||
response.setTariffValue(tariff.getCurrencyValue());
|
||||
response.setEffectiveOn(tariff.getEffectiveOn());
|
||||
response.setDescription(tariff.getDescription());
|
||||
response.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaSummaryResponse> createQuotaSummaryResponse(final String accountName, final Long domainId) {
|
||||
List<QuotaSummaryResponse> result = new ArrayList<QuotaSummaryResponse>();
|
||||
|
||||
if (accountName != null && domainId != null) {
|
||||
Account account = _accountDao.findActiveAccount(accountName, domainId);
|
||||
QuotaSummaryResponse qr = getQuotaSummaryResponse(account);
|
||||
result.add(qr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaSummaryResponse> createQuotaSummaryResponse(Boolean listAll) {
|
||||
List<QuotaSummaryResponse> result = new ArrayList<QuotaSummaryResponse>();
|
||||
|
||||
if (listAll) {
|
||||
for (final AccountVO account : _accountDao.listAll()) {
|
||||
QuotaSummaryResponse qr = getQuotaSummaryResponse(account);
|
||||
result.add(qr);
|
||||
}
|
||||
} else {
|
||||
for (final QuotaAccountVO quotaAccount : _quotaAccountDao.listAllQuotaAccount()) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
QuotaSummaryResponse qr = getQuotaSummaryResponse(account);
|
||||
result.add(qr);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private QuotaSummaryResponse getQuotaSummaryResponse(final Account account) {
|
||||
Calendar[] period = _statement.getCurrentStatementTime();
|
||||
|
||||
if (account != null) {
|
||||
QuotaSummaryResponse qr = new QuotaSummaryResponse();
|
||||
DomainVO domain = _domainDao.findById(account.getDomainId());
|
||||
BigDecimal curBalance = _quotaBalanceDao.lastQuotaBalance(account.getAccountId(), account.getDomainId(), period[1].getTime());
|
||||
BigDecimal quotaUsage = _quotaUsageDao.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, period[0].getTime(), period[1].getTime());
|
||||
|
||||
qr.setAccountId(account.getAccountId());
|
||||
qr.setAccountName(account.getAccountName());
|
||||
qr.setDomainId(account.getDomainId());
|
||||
qr.setDomainName(domain.getName());
|
||||
qr.setBalance(curBalance);
|
||||
qr.setQuotaUsage(quotaUsage);
|
||||
qr.setState(account.getState());
|
||||
qr.setStartDate(period[0].getTime());
|
||||
qr.setEndDate(period[1].getTime());
|
||||
qr.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
qr.setObjectName("summary");
|
||||
return qr;
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Quota summary response for an account requires a valid account.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate, Date endDate) {
|
||||
if (quotaBalance == null || quotaBalance.isEmpty()) {
|
||||
new InvalidParameterValueException("The request period does not contain balance entries.");
|
||||
}
|
||||
Collections.sort(quotaBalance, new Comparator<QuotaBalanceVO>() {
|
||||
public int compare(QuotaBalanceVO o1, QuotaBalanceVO o2) {
|
||||
return o2.getUpdatedOn().compareTo(o1.getUpdatedOn()); // desc
|
||||
}
|
||||
});
|
||||
|
||||
boolean have_balance_entries = false;
|
||||
//check that there is at least one balance entry
|
||||
for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) {
|
||||
QuotaBalanceVO entry = it.next();
|
||||
if (entry.getCreditsId() > 0) {
|
||||
have_balance_entries = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//if last entry is a credit deposit then remove that as that is already
|
||||
//accounted for in the starting balance after that entry, note the sort is desc
|
||||
if (have_balance_entries) {
|
||||
ListIterator<QuotaBalanceVO> li = quotaBalance.listIterator(quotaBalance.size());
|
||||
// Iterate in reverse.
|
||||
while (li.hasPrevious()) {
|
||||
QuotaBalanceVO entry = li.previous();
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("createQuotaBalanceResponse: Entry=" + entry);
|
||||
}
|
||||
if (entry.getCreditsId() > 0) {
|
||||
li.remove();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int quota_activity = quotaBalance.size();
|
||||
QuotaBalanceResponse resp = new QuotaBalanceResponse();
|
||||
BigDecimal lastCredits = new BigDecimal(0);
|
||||
boolean consecutive = true;
|
||||
for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) {
|
||||
QuotaBalanceVO entry = it.next();
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("createQuotaBalanceResponse: All Credit Entry=" + entry);
|
||||
}
|
||||
if (entry.getCreditsId() > 0) {
|
||||
if (consecutive) {
|
||||
lastCredits = lastCredits.add(entry.getCreditBalance());
|
||||
}
|
||||
resp.addCredits(entry);
|
||||
it.remove();
|
||||
} else {
|
||||
consecutive = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (quota_activity > 0 && quotaBalance.size() > 0) {
|
||||
// order is desc last item is the start item
|
||||
QuotaBalanceVO startItem = quotaBalance.get(quotaBalance.size() - 1);
|
||||
QuotaBalanceVO endItem = quotaBalance.get(0);
|
||||
resp.setStartDate(startItem.getUpdatedOn());
|
||||
resp.setStartQuota(startItem.getCreditBalance());
|
||||
resp.setEndDate(endItem.getUpdatedOn());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("createQuotaBalanceResponse: Start Entry=" + startItem);
|
||||
s_logger.debug("createQuotaBalanceResponse: End Entry=" + endItem);
|
||||
}
|
||||
resp.setEndQuota(endItem.getCreditBalance().add(lastCredits));
|
||||
} else if (quota_activity > 0) {
|
||||
// order is desc last item is the start item
|
||||
resp.setStartDate(startDate);
|
||||
resp.setStartQuota(new BigDecimal(0));
|
||||
resp.setEndDate(endDate);
|
||||
resp.setEndQuota(new BigDecimal(0).add(lastCredits));
|
||||
} else {
|
||||
resp.setStartDate(startDate);
|
||||
resp.setEndDate(endDate);
|
||||
resp.setStartQuota(new BigDecimal(0));
|
||||
resp.setEndQuota(new BigDecimal(0));
|
||||
}
|
||||
resp.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
resp.setObjectName("balance");
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaStatementResponse createQuotaStatementResponse(final List<QuotaUsageVO> quotaUsage) {
|
||||
if (quotaUsage == null || quotaUsage.isEmpty()) {
|
||||
throw new InvalidParameterValueException("There is no usage data found for period mentioned.");
|
||||
}
|
||||
|
||||
QuotaStatementResponse statement = new QuotaStatementResponse();
|
||||
|
||||
HashMap<Integer, QuotaTypes> quotaTariffMap = new HashMap<Integer, QuotaTypes>();
|
||||
Collection<QuotaTypes> result = QuotaTypes.listQuotaTypes().values();
|
||||
|
||||
for (QuotaTypes quotaTariff : result) {
|
||||
quotaTariffMap.put(quotaTariff.getQuotaType(), quotaTariff);
|
||||
// add dummy record for each usage type
|
||||
QuotaUsageVO dummy = new QuotaUsageVO(quotaUsage.get(0));
|
||||
dummy.setUsageType(quotaTariff.getQuotaType());
|
||||
dummy.setQuotaUsed(new BigDecimal(0));
|
||||
quotaUsage.add(dummy);
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(
|
||||
"createQuotaStatementResponse Type=" + quotaUsage.get(0).getUsageType() + " usage=" + quotaUsage.get(0).getQuotaUsed().setScale(2, RoundingMode.HALF_EVEN)
|
||||
+ " rec.id=" + quotaUsage.get(0).getUsageItemId() + " SD=" + quotaUsage.get(0).getStartDate() + " ED=" + quotaUsage.get(0).getEndDate());
|
||||
}
|
||||
|
||||
Collections.sort(quotaUsage, new Comparator<QuotaUsageVO>() {
|
||||
public int compare(QuotaUsageVO o1, QuotaUsageVO o2) {
|
||||
if (o1.getUsageType() == o2.getUsageType())
|
||||
return 0;
|
||||
return o1.getUsageType() < o2.getUsageType() ? -1 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
List<QuotaStatementItemResponse> items = new ArrayList<QuotaStatementItemResponse>();
|
||||
QuotaStatementItemResponse lineitem;
|
||||
int type = -1;
|
||||
BigDecimal usage = new BigDecimal(0);
|
||||
BigDecimal totalUsage = new BigDecimal(0);
|
||||
quotaUsage.add(new QuotaUsageVO());// boundary
|
||||
QuotaUsageVO prev = quotaUsage.get(0);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("createQuotaStatementResponse record count=" + quotaUsage.size());
|
||||
}
|
||||
for (final QuotaUsageVO quotaRecord : quotaUsage) {
|
||||
if (type != quotaRecord.getUsageType()) {
|
||||
if (type != -1) {
|
||||
lineitem = new QuotaStatementItemResponse(type);
|
||||
lineitem.setQuotaUsed(usage);
|
||||
lineitem.setAccountId(prev.getAccountId());
|
||||
lineitem.setDomainId(prev.getDomainId());
|
||||
lineitem.setUsageUnit(quotaTariffMap.get(type).getQuotaUnit());
|
||||
lineitem.setUsageName(quotaTariffMap.get(type).getQuotaName());
|
||||
lineitem.setObjectName("quotausage");
|
||||
items.add(lineitem);
|
||||
totalUsage = totalUsage.add(usage);
|
||||
usage = new BigDecimal(0);
|
||||
}
|
||||
type = quotaRecord.getUsageType();
|
||||
}
|
||||
prev = quotaRecord;
|
||||
usage = usage.add(quotaRecord.getQuotaUsed());
|
||||
}
|
||||
|
||||
statement.setLineItem(items);
|
||||
statement.setTotalQuota(totalUsage);
|
||||
statement.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
statement.setObjectName("statement");
|
||||
return statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaTariffVO> listQuotaTariffPlans(final QuotaTariffListCmd cmd) {
|
||||
List<QuotaTariffVO> result = new ArrayList<QuotaTariffVO>();
|
||||
Date effectiveDate = cmd.getEffectiveDate() == null ? new Date() : cmd.getEffectiveDate();
|
||||
Date adjustedEffectiveDate = _quotaService.computeAdjustedTime(effectiveDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Effective datec=" + effectiveDate + " quotatype=" + cmd.getUsageType() + " Adjusted date=" + adjustedEffectiveDate);
|
||||
}
|
||||
if (cmd.getUsageType() != null) {
|
||||
QuotaTariffVO tariffPlan = _quotaTariffDao.findTariffPlanByUsageType(cmd.getUsageType(), adjustedEffectiveDate);
|
||||
if (tariffPlan != null) {
|
||||
result.add(tariffPlan);
|
||||
}
|
||||
} else {
|
||||
result = _quotaTariffDao.listAllTariffPlans(adjustedEffectiveDate);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaTariffVO updateQuotaTariffPlan(QuotaTariffUpdateCmd cmd) {
|
||||
final int quotaType = cmd.getUsageType();
|
||||
final BigDecimal quotaCost = new BigDecimal(cmd.getValue());
|
||||
final Date effectiveDate = _quotaService.computeAdjustedTime(cmd.getStartDate());
|
||||
final Date now = _quotaService.computeAdjustedTime(new Date());
|
||||
// if effective date is in the past return error
|
||||
if (effectiveDate.compareTo(now) < 0) {
|
||||
throw new InvalidParameterValueException("Incorrect effective date for tariff " + effectiveDate + " is less than now " + now);
|
||||
}
|
||||
QuotaTypes quotaConstant = QuotaTypes.listQuotaTypes().get(quotaType);
|
||||
if (quotaConstant == null) {
|
||||
throw new InvalidParameterValueException("Quota type does not exists " + quotaType);
|
||||
}
|
||||
|
||||
QuotaTariffVO result = null;
|
||||
result = new QuotaTariffVO(quotaType);
|
||||
result.setUsageName(quotaConstant.getQuotaName());
|
||||
result.setUsageUnit(quotaConstant.getQuotaUnit());
|
||||
result.setUsageDiscriminator(quotaConstant.getDiscriminator());
|
||||
result.setCurrencyValue(quotaCost);
|
||||
result.setEffectiveOn(effectiveDate);
|
||||
result.setUpdatedOn(now);
|
||||
result.setUpdatedBy(cmd.getEntityOwnerId());
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(String.format("Updating Quota Tariff Plan: New value=%s for resource type=%d effective on date=%s", quotaCost, quotaType, effectiveDate));
|
||||
}
|
||||
_quotaTariffDao.addQuotaTariff(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy) {
|
||||
Date depositDate = new Date();
|
||||
Date adjustedStartDate = _quotaService.computeAdjustedTime(depositDate);
|
||||
QuotaBalanceVO qb = _quotaBalanceDao.findLaterBalanceEntry(accountId, domainId, adjustedStartDate);
|
||||
|
||||
if (qb != null) {
|
||||
throw new InvalidParameterValueException("Incorrect deposit date: " + adjustedStartDate + " there are balance entries after this date");
|
||||
}
|
||||
|
||||
return addQuotaCredits(accountId, domainId, amount, updatedBy, adjustedStartDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaCreditsResponse addQuotaCredits(final Long accountId, final Long domainId, final Double amount, final Long updatedBy, final Date despositedOn) {
|
||||
|
||||
QuotaCreditsVO credits = new QuotaCreditsVO(accountId, domainId, new BigDecimal(amount), updatedBy);
|
||||
s_logger.debug("AddQuotaCredits: Depositing " + amount + " on adjusted date " + despositedOn);
|
||||
credits.setUpdatedOn(despositedOn);
|
||||
QuotaCreditsVO result = _quotaCreditsDao.saveCredits(credits);
|
||||
|
||||
final AccountVO account = _accountDao.findById(accountId);
|
||||
final boolean lockAccountEnforcement = "true".equalsIgnoreCase(QuotaConfig.QuotaEnableEnforcement.value());
|
||||
final BigDecimal currentAccountBalance = _quotaBalanceDao.lastQuotaBalance(accountId, domainId, startOfNextDay(despositedOn));
|
||||
if (lockAccountEnforcement && (currentAccountBalance.compareTo(new BigDecimal(0)) >= 0)) {
|
||||
if (account.getState() == Account.State.locked) {
|
||||
_regionMgr.enableAccount(account.getAccountName(), domainId, accountId);
|
||||
}
|
||||
}
|
||||
|
||||
String creditor = String.valueOf(Account.ACCOUNT_ID_SYSTEM);
|
||||
User creditorUser = _userDao.getUser(updatedBy);
|
||||
if (creditorUser != null) {
|
||||
creditor = creditorUser.getUsername();
|
||||
}
|
||||
QuotaCreditsResponse response = new QuotaCreditsResponse(result, creditor);
|
||||
response.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
return response;
|
||||
}
|
||||
|
||||
private QuotaEmailTemplateResponse createQuotaEmailResponse(QuotaEmailTemplatesVO template) {
|
||||
QuotaEmailTemplateResponse response = new QuotaEmailTemplateResponse();
|
||||
response.setTemplateType(template.getTemplateName());
|
||||
response.setTemplateSubject(template.getTemplateSubject());
|
||||
response.setTemplateText(template.getTemplateBody());
|
||||
response.setLocale(template.getLocale());
|
||||
response.setLastUpdatedOn(template.getLastUpdated());
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaEmailTemplateResponse> listQuotaEmailTemplates(QuotaEmailTemplateListCmd cmd) {
|
||||
final String templateName = cmd.getTemplateName();
|
||||
List<QuotaEmailTemplatesVO> templates = _quotaEmailTemplateDao.listAllQuotaEmailTemplates(templateName);
|
||||
final List<QuotaEmailTemplateResponse> responses = new ArrayList<QuotaEmailTemplateResponse>();
|
||||
for (final QuotaEmailTemplatesVO template : templates) {
|
||||
responses.add(createQuotaEmailResponse(template));
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateQuotaEmailTemplate(QuotaEmailTemplateUpdateCmd cmd) {
|
||||
final String templateName = cmd.getTemplateName();
|
||||
final String templateSubject = StringEscapeUtils.escapeJavaScript(cmd.getTemplateSubject());
|
||||
final String templateBody = StringEscapeUtils.escapeJavaScript(cmd.getTemplateBody());
|
||||
final String locale = cmd.getLocale();
|
||||
|
||||
final List<QuotaEmailTemplatesVO> templates = _quotaEmailTemplateDao.listAllQuotaEmailTemplates(templateName);
|
||||
if (templates.size() == 1) {
|
||||
final QuotaEmailTemplatesVO template = templates.get(0);
|
||||
template.setTemplateSubject(templateSubject);
|
||||
template.setTemplateBody(templateBody);
|
||||
if (locale != null) {
|
||||
template.setLocale(locale);
|
||||
}
|
||||
return _quotaEmailTemplateDao.updateQuotaEmailTemplate(template);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate) {
|
||||
if (quotaBalance == null) {
|
||||
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 (QuotaBalanceVO entry : quotaBalance) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("createQuotaLastBalanceResponse Date=" + entry.getUpdatedOn() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
|
||||
}
|
||||
lastCredits = lastCredits.add(entry.getCreditBalance());
|
||||
}
|
||||
resp.setStartQuota(lastCredits);
|
||||
resp.setStartDate(_quotaService.computeAdjustedTime(startDate));
|
||||
resp.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
resp.setObjectName("balance");
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaUsageVO> getQuotaUsage(QuotaStatementCmd cmd) {
|
||||
return _quotaService.getQuotaUsage(cmd.getAccountId(), cmd.getAccountName(), cmd.getDomainId(), cmd.getUsageType(), cmd.getStartDate(), cmd.getEndDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaBalanceVO> getQuotaBalance(QuotaBalanceCmd cmd) {
|
||||
return _quotaService.findQuotaBalanceVO(cmd.getAccountId(), cmd.getAccountName(), cmd.getDomainId(), cmd.getStartDate(), cmd.getEndDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date startOfNextDay(Date dt) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(dt);
|
||||
c.add(Calendar.DATE, 1);
|
||||
dt = c.getTime();
|
||||
return dt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date startOfNextDay() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(new Date());
|
||||
c.add(Calendar.DATE, 1);
|
||||
Date dt = c.getTime();
|
||||
return dt;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
//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 java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class QuotaStatementItemResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("type")
|
||||
@Param(description = "usage type")
|
||||
private int usageType;
|
||||
|
||||
@SerializedName("accountid")
|
||||
@Param(description = "account id")
|
||||
private Long accountId;
|
||||
|
||||
@SerializedName("account")
|
||||
@Param(description = "account name")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName("domain")
|
||||
@Param(description = "domain id")
|
||||
private Long domainId;
|
||||
|
||||
@SerializedName("name")
|
||||
@Param(description = "usage type name")
|
||||
private String usageName;
|
||||
|
||||
@SerializedName("unit")
|
||||
@Param(description = "usage unit")
|
||||
private String usageUnit;
|
||||
|
||||
@SerializedName("quota")
|
||||
@Param(description = "quota consumed")
|
||||
private BigDecimal quotaUsed;
|
||||
|
||||
public QuotaStatementItemResponse(final int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public String getUsageName() {
|
||||
return usageName;
|
||||
}
|
||||
|
||||
public void setUsageName(String usageName) {
|
||||
this.usageName = usageName;
|
||||
}
|
||||
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public String getUsageUnit() {
|
||||
return usageUnit;
|
||||
}
|
||||
|
||||
public void setUsageUnit(String usageUnit) {
|
||||
this.usageUnit = usageUnit;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaUsed() {
|
||||
return quotaUsed;
|
||||
}
|
||||
|
||||
public void setQuotaUsed(BigDecimal quotaUsed) {
|
||||
this.quotaUsed = quotaUsed.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
//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.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class QuotaStatementResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("accountid")
|
||||
@Param(description = "account id")
|
||||
private Long accountId;
|
||||
|
||||
@SerializedName("account")
|
||||
@Param(description = "account name")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName("domain")
|
||||
@Param(description = "domain id")
|
||||
private Long domainId;
|
||||
|
||||
@SerializedName("quotausage")
|
||||
@Param(description = "list of quota usage under various types", responseObject = QuotaStatementItemResponse.class)
|
||||
private List<QuotaStatementItemResponse> lineItem;
|
||||
|
||||
@SerializedName("totalquota")
|
||||
@Param(description = "total quota used during this period")
|
||||
private BigDecimal totalQuota;
|
||||
|
||||
@SerializedName("startdate")
|
||||
@Param(description = "start date")
|
||||
private Date startDate = null;
|
||||
|
||||
@SerializedName("enddate")
|
||||
@Param(description = "end date")
|
||||
private Date endDate = null;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "currency")
|
||||
private String currency;
|
||||
|
||||
public QuotaStatementResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public List<QuotaStatementItemResponse> getLineItem() {
|
||||
return lineItem;
|
||||
}
|
||||
|
||||
public void setLineItem(List<QuotaStatementItemResponse> lineItem) {
|
||||
this.lineItem = lineItem;
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
|
||||
public BigDecimal getTotalQuota() {
|
||||
return totalQuota;
|
||||
}
|
||||
|
||||
public void setTotalQuota(BigDecimal totalQuota) {
|
||||
this.totalQuota = totalQuota.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
//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 java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Date;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.cloud.user.Account.State;
|
||||
|
||||
public class QuotaSummaryResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("accountid")
|
||||
@Param(description = "account id")
|
||||
private Long accountId;
|
||||
|
||||
@SerializedName("account")
|
||||
@Param(description = "account name")
|
||||
private String accountName;
|
||||
|
||||
@SerializedName("domainid")
|
||||
@Param(description = "domain id")
|
||||
private Long domainId;
|
||||
|
||||
@SerializedName("domain")
|
||||
@Param(description = "domain name")
|
||||
private String domainName;
|
||||
|
||||
@SerializedName("balance")
|
||||
@Param(description = "account balance")
|
||||
private BigDecimal balance;
|
||||
|
||||
@SerializedName("state")
|
||||
@Param(description = "account state")
|
||||
private State state;
|
||||
|
||||
@SerializedName("quota")
|
||||
@Param(description = "quota usage of this period")
|
||||
private BigDecimal quotaUsage;
|
||||
|
||||
@SerializedName("startdate")
|
||||
@Param(description = "start date")
|
||||
private Date startDate = null;
|
||||
|
||||
@SerializedName("enddate")
|
||||
@Param(description = "end date")
|
||||
private Date endDate = null;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "currency")
|
||||
private String currency;
|
||||
|
||||
public QuotaSummaryResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public String getDomainName() {
|
||||
return domainName;
|
||||
}
|
||||
|
||||
public void setDomainName(String domainName) {
|
||||
this.domainName = domainName;
|
||||
}
|
||||
|
||||
public BigDecimal getQuotaUsage() {
|
||||
return quotaUsage;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void setQuotaUsage(BigDecimal startQuota) {
|
||||
this.quotaUsage = startQuota.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
public BigDecimal getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
public void setBalance(BigDecimal balance) {
|
||||
this.balance = balance.setScale(2, RoundingMode.HALF_EVEN);
|
||||
}
|
||||
|
||||
public Date getStartDate() {
|
||||
return startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate == null ? null : new Date(endDate.getTime());
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
//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.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
public class QuotaTariffResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("usageType")
|
||||
@Param(description = "usageType")
|
||||
private int usageType;
|
||||
|
||||
@SerializedName("usageName")
|
||||
@Param(description = "usageName")
|
||||
private String usageName;
|
||||
|
||||
@SerializedName("usageUnit")
|
||||
@Param(description = "usageUnit")
|
||||
private String usageUnit;
|
||||
|
||||
@SerializedName("usageDiscriminator")
|
||||
@Param(description = "usageDiscriminator")
|
||||
private String usageDiscriminator;
|
||||
|
||||
@SerializedName("tariffValue")
|
||||
@Param(description = "tariffValue")
|
||||
private BigDecimal tariffValue;
|
||||
|
||||
@SerializedName("effectiveDate")
|
||||
@Param(description = "the date on/after which this quota value will be effective")
|
||||
private Date effectiveOn = null;
|
||||
|
||||
@SerializedName("description")
|
||||
@Param(description = "description")
|
||||
private String description;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "currency")
|
||||
private String currency;
|
||||
|
||||
public QuotaTariffResponse() {
|
||||
super();
|
||||
this.setObjectName("quotatariff");
|
||||
}
|
||||
|
||||
public QuotaTariffResponse(final int usageType) {
|
||||
super();
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public String getUsageName() {
|
||||
return usageName;
|
||||
}
|
||||
|
||||
public void setUsageName(String usageName) {
|
||||
this.usageName = usageName;
|
||||
}
|
||||
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public String getUsageUnit() {
|
||||
return usageUnit;
|
||||
}
|
||||
|
||||
public void setUsageUnit(String usageUnit) {
|
||||
this.usageUnit = usageUnit;
|
||||
}
|
||||
|
||||
public String getUsageDiscriminator() {
|
||||
return usageDiscriminator;
|
||||
}
|
||||
|
||||
public void setUsageDiscriminator(String usageDiscriminator) {
|
||||
this.usageDiscriminator = usageDiscriminator;
|
||||
}
|
||||
|
||||
public BigDecimal getTariffValue() {
|
||||
return tariffValue;
|
||||
}
|
||||
|
||||
public void setTariffValue(BigDecimal tariffValue) {
|
||||
this.tariffValue = tariffValue;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Date getEffectiveOn() {
|
||||
return effectiveOn;
|
||||
}
|
||||
|
||||
public void setEffectiveOn(Date effectiveOn) {
|
||||
this.effectiveOn = effectiveOn;
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// 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.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class QuotaTypeResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("quotatypeid")
|
||||
@Param(description = "quota type")
|
||||
private Integer quotaType;
|
||||
|
||||
@SerializedName(ApiConstants.DESCRIPTION)
|
||||
@Param(description = "description of usage type")
|
||||
private String description;
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Integer getQuotaType() {
|
||||
return quotaType;
|
||||
}
|
||||
|
||||
public void setQuotaType(Integer quotaType) {
|
||||
this.quotaType = quotaType;
|
||||
}
|
||||
|
||||
public QuotaTypeResponse(Integer quotaType, String description) {
|
||||
this.quotaType = quotaType;
|
||||
this.description = description;
|
||||
setObjectName(ApiConstants.USAGE_TYPE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
//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.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
public class QuotaUpdateResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("updated_on")
|
||||
@Param(description = "timestamp when the run got over")
|
||||
private Date updatedOn;
|
||||
|
||||
public QuotaUpdateResponse(Calendar now) {
|
||||
super();
|
||||
updatedOn=now.getTime();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import com.cloud.utils.component.PluggableService;
|
||||
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface QuotaService extends PluggableService {
|
||||
|
||||
List<QuotaUsageVO> getQuotaUsage(Long accountId, String accountName, Long domainId, Integer usageType, Date startDate, Date endDate);
|
||||
|
||||
List<QuotaBalanceVO> findQuotaBalanceVO(Long accountId, String accountName, Long domainId, Date startDate, Date endDate);
|
||||
|
||||
Date computeAdjustedTime(Date date);
|
||||
|
||||
void setLockAccount(Long accountId, Boolean state);
|
||||
|
||||
void setMinBalance(Long accountId, Double balance);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.db.Filter;
|
||||
|
||||
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaCreditsCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaSummaryCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaUpdateCmd;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
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.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.utils.usage.UsageUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@Component
|
||||
@Local(value = QuotaService.class)
|
||||
public class QuotaServiceImpl extends ManagerBase implements QuotaService, Configurable, QuotaConfig {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaServiceImpl.class);
|
||||
|
||||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private QuotaAccountDao _quotaAcc;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsageDao;
|
||||
@Inject
|
||||
private DomainDao _domainDao;
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
@Inject
|
||||
private QuotaBalanceDao _quotaBalanceDao;
|
||||
@Inject
|
||||
private QuotaResponseBuilder _respBldr;
|
||||
|
||||
private TimeZone _usageTimezone;
|
||||
private int _aggregationDuration = 0;
|
||||
|
||||
public QuotaServiceImpl() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
String timeZoneStr = _configDao.getValue(Config.UsageAggregationTimezone.toString());
|
||||
String aggregationRange = _configDao.getValue(Config.UsageStatsJobAggregationRange.toString());
|
||||
if (timeZoneStr == null) {
|
||||
timeZoneStr = "GMT";
|
||||
}
|
||||
_usageTimezone = TimeZone.getTimeZone(timeZoneStr);
|
||||
|
||||
_aggregationDuration = Integer.parseInt(aggregationRange);
|
||||
if (_aggregationDuration < UsageUtils.USAGE_AGGREGATION_RANGE_MIN) {
|
||||
s_logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + UsageUtils.USAGE_AGGREGATION_RANGE_MIN);
|
||||
_aggregationDuration = UsageUtils.USAGE_AGGREGATION_RANGE_MIN;
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Usage timezone = " + _usageTimezone + " AggregationDuration=" + _aggregationDuration);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<?>> getCommands() {
|
||||
final List<Class<?>> cmdList = new ArrayList<Class<?>>();
|
||||
if (!isQuotaServiceEnabled()) {
|
||||
return cmdList;
|
||||
}
|
||||
cmdList.add(QuotaStatementCmd.class);
|
||||
cmdList.add(QuotaBalanceCmd.class);
|
||||
cmdList.add(QuotaSummaryCmd.class);
|
||||
cmdList.add(QuotaUpdateCmd.class);
|
||||
cmdList.add(QuotaTariffListCmd.class);
|
||||
cmdList.add(QuotaTariffUpdateCmd.class);
|
||||
cmdList.add(QuotaCreditsCmd.class);
|
||||
cmdList.add(QuotaEmailTemplateListCmd.class);
|
||||
cmdList.add(QuotaEmailTemplateUpdateCmd.class);
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return "QUOTA-PLUGIN";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] { QuotaPluginEnabled, QuotaEnableEnforcement, QuotaCurrencySymbol, QuotaStatementPeriod, QuotaSmtpHost, QuotaSmtpPort, QuotaSmtpTimeout, QuotaSmtpUser, QuotaSmtpPassword,
|
||||
QuotaSmtpAuthType, QuotaSmtpSender };
|
||||
}
|
||||
|
||||
public Boolean isQuotaServiceEnabled() {
|
||||
return QuotaPluginEnabled.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaBalanceVO> findQuotaBalanceVO(Long accountId, String accountName, Long domainId, Date startDate, Date endDate) {
|
||||
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);
|
||||
if (!accounts.isEmpty()) {
|
||||
userAccount = accounts.get(0);
|
||||
}
|
||||
if (userAccount != null) {
|
||||
accountId = userAccount.getId();
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
|
||||
}
|
||||
} else {
|
||||
throw new PermissionDeniedException("Invalid Domain Id or Account");
|
||||
}
|
||||
}
|
||||
|
||||
startDate = startDate == null ? new Date() : startDate;
|
||||
|
||||
if (endDate == null) {
|
||||
// adjust start date to end of day as there is no end date
|
||||
Date adjustedStartDate = computeAdjustedTime(_respBldr.startOfNextDay(startDate));
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("getQuotaBalance1: Getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", on or before " + adjustedStartDate);
|
||||
}
|
||||
List<QuotaBalanceVO> qbrecords = _quotaBalanceDao.lastQuotaBalanceVO(accountId, domainId, adjustedStartDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Found records size=" + qbrecords.size());
|
||||
}
|
||||
if (qbrecords.isEmpty()) {
|
||||
s_logger.info("Incorrect Date there are no quota records before this date " + adjustedStartDate);
|
||||
return qbrecords;
|
||||
} else {
|
||||
return qbrecords;
|
||||
}
|
||||
} else {
|
||||
Date adjustedStartDate = computeAdjustedTime(startDate);
|
||||
if (endDate.after(_respBldr.startOfNextDay())) {
|
||||
throw new InvalidParameterValueException("Incorrect Date Range. End date:" + endDate + " should not be in future. ");
|
||||
} else if (startDate.before(endDate)) {
|
||||
Date adjustedEndDate = computeAdjustedTime(endDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("getQuotaBalance2: Getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and "
|
||||
+ adjustedEndDate);
|
||||
}
|
||||
List<QuotaBalanceVO> qbrecords = _quotaBalanceDao.findQuotaBalance(accountId, domainId, adjustedStartDate, adjustedEndDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("getQuotaBalance3: Found records size=" + qbrecords.size());
|
||||
}
|
||||
if (qbrecords.isEmpty()) {
|
||||
s_logger.info("There are no quota records between these dates start date " + adjustedStartDate + " and end date:" + endDate);
|
||||
return qbrecords;
|
||||
} else {
|
||||
return qbrecords;
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
// 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);
|
||||
if (!accounts.isEmpty()) {
|
||||
userAccount = accounts.get(0);
|
||||
}
|
||||
if (userAccount != null) {
|
||||
accountId = userAccount.getId();
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
|
||||
}
|
||||
} else {
|
||||
throw new PermissionDeniedException("Invalid Domain Id or Account");
|
||||
}
|
||||
}
|
||||
|
||||
if (startDate.after(endDate)) {
|
||||
throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate);
|
||||
}
|
||||
if (endDate.after(_respBldr.startOfNextDay())) {
|
||||
throw new InvalidParameterValueException("Incorrect Date Range. End date:" + endDate + " should not be in future. ");
|
||||
}
|
||||
Date adjustedEndDate = computeAdjustedTime(endDate);
|
||||
Date adjustedStartDate = computeAdjustedTime(startDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Getting quota records for account: " + accountId + ", domainId: " + domainId + ", between " + startDate + " and " + endDate);
|
||||
}
|
||||
return _quotaUsageDao.findQuotaUsage(accountId, domainId, usageType, adjustedStartDate, adjustedEndDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date computeAdjustedTime(final Date date) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
TimeZone localTZ = cal.getTimeZone();
|
||||
int timezoneOffset = cal.get(Calendar.ZONE_OFFSET);
|
||||
if (localTZ.inDaylightTime(date)) {
|
||||
timezoneOffset += (60 * 60 * 1000);
|
||||
}
|
||||
cal.add(Calendar.MILLISECOND, timezoneOffset);
|
||||
|
||||
Date newTime = cal.getTime();
|
||||
|
||||
Calendar calTS = Calendar.getInstance(_usageTimezone);
|
||||
calTS.setTime(newTime);
|
||||
timezoneOffset = calTS.get(Calendar.ZONE_OFFSET);
|
||||
if (_usageTimezone.inDaylightTime(date)) {
|
||||
timezoneOffset += (60 * 60 * 1000);
|
||||
}
|
||||
|
||||
calTS.add(Calendar.MILLISECOND, -1 * timezoneOffset);
|
||||
|
||||
return calTS.getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLockAccount(Long accountId, Boolean state) {
|
||||
QuotaAccountVO acc = _quotaAcc.findByIdQuotaAccount(accountId);
|
||||
if (acc == null) {
|
||||
acc = new QuotaAccountVO(accountId);
|
||||
acc.setQuotaEnforce(state ? 1 : 0);
|
||||
_quotaAcc.persistQuotaAccount(acc);
|
||||
} else {
|
||||
acc.setQuotaEnforce(state ? 1 : 0);
|
||||
_quotaAcc.updateQuotaAccount(accountId, acc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMinBalance(Long accountId, Double balance) {
|
||||
QuotaAccountVO acc = _quotaAcc.findByIdQuotaAccount(accountId);
|
||||
if (acc == null) {
|
||||
acc = new QuotaAccountVO(accountId);
|
||||
acc.setQuotaMinBalance(new BigDecimal(balance));
|
||||
_quotaAcc.persistQuotaAccount(acc);
|
||||
} else {
|
||||
acc.setQuotaMinBalance(new BigDecimal(balance));
|
||||
_quotaAcc.updateQuotaAccount(accountId, acc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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,87 @@
|
|||
// 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");
|
||||
cmd.setMinBalance(200.0);
|
||||
|
||||
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,183 @@
|
|||
// 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()));
|
||||
// FIXME: fix this test
|
||||
}
|
||||
|
||||
@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.findByIdQuotaAccount(Mockito.anyLong())).thenReturn(quotaAccountVO);
|
||||
quotaService.setLockAccount(2L, true);
|
||||
Mockito.verify(quotaAcc, Mockito.times(0)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).updateQuotaAccount(Mockito.anyLong(), Mockito.any(QuotaAccountVO.class));
|
||||
|
||||
// new account
|
||||
Mockito.when(quotaAcc.findByIdQuotaAccount(Mockito.anyLong())).thenReturn(null);
|
||||
quotaService.setLockAccount(2L, true);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persistQuotaAccount(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.findByIdQuotaAccount(Mockito.anyLong())).thenReturn(quotaAccountVO);
|
||||
quotaService.setMinBalance(accountId, balance);
|
||||
Mockito.verify(quotaAcc, Mockito.times(0)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).updateQuotaAccount(Mockito.anyLong(), Mockito.any(QuotaAccountVO.class));
|
||||
|
||||
// no account with limit set
|
||||
Mockito.when(quotaAcc.findByIdQuotaAccount(Mockito.anyLong())).thenReturn(null);
|
||||
quotaService.setMinBalance(accountId, balance);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${cs.lang3.version}</version>
|
||||
<version>${cs.commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${cs.lang3.version}</version>
|
||||
<version>${cs.commons-lang3.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@
|
|||
<module>network-elements/internal-loadbalancer</module>
|
||||
<module>network-elements/vxlan</module>
|
||||
<module>network-elements/globodns</module>
|
||||
<module>database/quota</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
|||
16
pom.xml
16
pom.xml
|
|
@ -99,7 +99,7 @@
|
|||
<cs.aws.sdk.version>1.10.34</cs.aws.sdk.version>
|
||||
<cs.jackson.version>2.6.3</cs.jackson.version>
|
||||
<cs.lang.version>2.6</cs.lang.version>
|
||||
<cs.lang3.version>3.4</cs.lang3.version>
|
||||
<cs.commons-lang3.version>3.4</cs.commons-lang3.version>
|
||||
<cs.commons-io.version>2.4</cs.commons-io.version>
|
||||
<cs.commons-validator.version>1.4.0</cs.commons-validator.version>
|
||||
<cs.reflections.version>0.9.9</cs.reflections.version>
|
||||
|
|
@ -116,6 +116,7 @@
|
|||
<cs.javadoc.version>2.10.1</cs.javadoc.version>
|
||||
<cs.opensaml.version>2.6.1</cs.opensaml.version>
|
||||
<cs.xml-apis.version>1.4.01</cs.xml-apis.version>
|
||||
<cs.joda-time.version>2.8.1</cs.joda-time.version>
|
||||
</properties>
|
||||
|
||||
<distributionManagement>
|
||||
|
|
@ -714,6 +715,19 @@
|
|||
<ignore></ignore>
|
||||
</action>
|
||||
</pluginExecution>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<versionRange>[2.11,)</versionRange>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore></ignore>
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
|
|
|
|||
|
|
@ -294,6 +294,14 @@ public class ParamProcessWorker implements DispatchWorker {
|
|||
field.set(cmdObj, Float.valueOf(paramObj.toString()));
|
||||
}
|
||||
break;
|
||||
case DOUBLE:
|
||||
// Assuming that the parameters have been checked for required before now,
|
||||
// we ignore blank or null values and defer to the command to set a default
|
||||
// value for optional parameters ...
|
||||
if (paramObj != null && isNotBlank(paramObj.toString())) {
|
||||
field.set(cmdObj, Double.valueOf(paramObj.toString()));
|
||||
}
|
||||
break;
|
||||
case INTEGER:
|
||||
// Assuming that the parameters have been checked for required before now,
|
||||
// we ignore blank or null values and defer to the command to set a default
|
||||
|
|
|
|||
|
|
@ -2184,8 +2184,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("User " + username + " in domain " + domainName + " is disabled/locked (or account is disabled/locked)");
|
||||
}
|
||||
throw new CloudAuthenticationException("User " + username + " in domain " + domainName + " is disabled/locked (or account is disabled/locked)");
|
||||
// return null;
|
||||
throw new CloudAuthenticationException("User " + username + " (or their account) in domain " + domainName + " is disabled/locked. Please contact the administrator.");
|
||||
}
|
||||
// Whenever the user is able to log in successfully, reset the login attempts to zero
|
||||
if (!isInternalAccount(userAccount.getId()))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,4 +19,3 @@
|
|||
-- Schema cleanup from 4.2.0 to 4.3.0;
|
||||
--;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,3 +30,113 @@ CREATE TABLE IF NOT EXISTS `cloud`.`domain_vlan_map` (
|
|||
INDEX `i_account_vlan_map__vlan_id`(`vlan_db_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Quota
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_account` (
|
||||
`account_id` int(11) NOT NULL,
|
||||
`quota_balance` decimal(15,2) NULL,
|
||||
`quota_balance_date` datetime NULL,
|
||||
`quota_enforce` int(1) DEFAULT NULL,
|
||||
`quota_min_balance` decimal(15,2) DEFAULT NULL,
|
||||
`quota_alert_date` datetime DEFAULT NULL,
|
||||
`quota_alert_type` int(11) DEFAULT NULL,
|
||||
`last_statement_date` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`account_id`),
|
||||
CONSTRAINT `account_id` FOREIGN KEY (`account_id`) REFERENCES `cloud_usage`.`account` (`quota_enforce`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_tariff` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||
`usage_type` int(2) unsigned DEFAULT NULL,
|
||||
`usage_name` varchar(255) NOT NULL COMMENT 'usage type',
|
||||
`usage_unit` varchar(255) NOT NULL COMMENT 'usage type',
|
||||
`usage_discriminator` varchar(255) NOT NULL COMMENT 'usage type',
|
||||
`currency_value` decimal(15,2) NOT NULL COMMENT 'usage type',
|
||||
`effective_on` datetime NOT NULL COMMENT 'date time on which this quota values will become effective',
|
||||
`updated_on` datetime NOT NULL COMMENT 'date this entry was updated on',
|
||||
`updated_by` bigint unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
LOCK TABLES `cloud_usage`.`quota_tariff` WRITE;
|
||||
INSERT IGNORE INTO `cloud_usage`.`quota_tariff` (`usage_type`, `usage_name`, `usage_unit`, `usage_discriminator`, `currency_value`, `effective_on`, `updated_on`, `updated_by`) VALUES
|
||||
(1,'RUNNING_VM','Compute-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(2,'ALLOCATED_VM','Compute-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(3,'IP_ADDRESS','IP-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(4,'NETWORK_BYTES_SENT','GB','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(5,'NETWORK_BYTES_RECEIVED','GB','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(6,'VOLUME','GB-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(7,'TEMPLATE','GB-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(8,'ISO','GB-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(9,'SNAPSHOT','GB-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(10,'SECURITY_GROUP','Policy-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(11,'LOAD_BALANCER_POLICY','Policy-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(12,'PORT_FORWARDING_RULE','Policy-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(13,'NETWORK_OFFERING','Policy-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(14,'VPN_USERS','Policy-Month','',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(15,'CPU_SPEED','Compute-Month','100MHz',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(16,'vCPU','Compute-Month','1VCPU',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(17,'MEMORY','Compute-Month','1MB',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(21,'VM_DISK_IO_READ','GB','1',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(22,'VM_DISK_IO_WRITE','GB','1',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(23,'VM_DISK_BYTES_READ','GB','1',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(24,'VM_DISK_BYTES_WRITE','GB','1',0.00,'2010-05-04', '2010-05-04',1),
|
||||
(25,'VM_SNAPSHOT','GB-Month','',0.00,'2010-05-04', '2010-05-04',1);
|
||||
UNLOCK TABLES;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_credits` (
|
||||
`id` bigint unsigned NOT NULL auto_increment COMMENT 'id',
|
||||
`account_id` bigint unsigned NOT NULL,
|
||||
`domain_id` bigint(20) unsigned NOT NULL,
|
||||
`credit` decimal(15,4) COMMENT 'amount credited',
|
||||
`updated_on` datetime NOT NULL COMMENT 'date created',
|
||||
`updated_by` bigint unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_usage` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`usage_item_id` bigint(20) unsigned NOT NULL,
|
||||
`zone_id` bigint(20) unsigned NOT NULL,
|
||||
`account_id` bigint(20) unsigned NOT NULL,
|
||||
`domain_id` bigint(20) unsigned NOT NULL,
|
||||
`usage_type` varchar(64) DEFAULT NULL,
|
||||
`quota_used` decimal(15,8) unsigned NOT NULL,
|
||||
`start_date` datetime NOT NULL COMMENT 'start time for this usage item',
|
||||
`end_date` datetime NOT NULL COMMENT 'end time for this usage item',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_balance` (
|
||||
`id` bigint unsigned NOT NULL auto_increment COMMENT 'id',
|
||||
`account_id` bigint unsigned NOT NULL,
|
||||
`domain_id` bigint(20) unsigned NOT NULL,
|
||||
`credit_balance` decimal(15,8) COMMENT 'amount of credits remaining',
|
||||
`credits_id` bigint unsigned COMMENT 'if not null then this entry corresponds to credit change quota_credits',
|
||||
`updated_on` datetime NOT NULL COMMENT 'date updated on',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_email_templates` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`template_name` varchar(64) NOT NULL UNIQUE,
|
||||
`template_subject` longtext,
|
||||
`template_body` longtext,
|
||||
`locale` varchar(25) DEFAULT 'en_US',
|
||||
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
LOCK TABLES `cloud_usage`.`quota_email_templates` WRITE;
|
||||
INSERT IGNORE INTO `cloud_usage`.`quota_email_templates` (`template_name`, `template_subject`, `template_body`) VALUES
|
||||
('QUOTA_LOW', 'Quota Usage Threshold crossed by your account ${accountName}', 'Your account ${accountName} in the domain ${domainName} has reached quota usage threshold, your current quota balance is ${quotaBalance}.'),
|
||||
('QUOTA_EMPTY', 'Quota Exhausted, account ${accountName} has no quota left.', 'Your account ${accountName} in the domain ${domainName} has exhausted allocated quota, please contact the administrator.'),
|
||||
('QUOTA_UNLOCK_ACCOUNT', 'Quota credits added, account ${accountName} is unlocked now, if it was locked', 'Your account ${accountName} in the domain ${domainName} has enough quota credits now with the current balance of ${quotaBalance}.'),
|
||||
('QUOTA_STATEMENT', 'Quota Statement for your account ${accountName}', 'Monthly quota statement of your account ${accountName} in the domain ${domainName}:<br>Balance = ${quotaBalance}<br>Total Usage = ${quotaUsage}.');
|
||||
UNLOCK TABLES;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,204 @@
|
|||
# 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.
|
||||
""" Test cases for checking quota API
|
||||
"""
|
||||
|
||||
#Import Local Modules
|
||||
import marvin
|
||||
from marvin.cloudstackTestCase import *
|
||||
from marvin.cloudstackAPI import *
|
||||
from marvin.lib.utils import *
|
||||
from marvin.lib.base import *
|
||||
from marvin.lib.common import *
|
||||
from marvin.lib.utils import (random_gen)
|
||||
from nose.plugins.attrib import attr
|
||||
|
||||
#Import System modules
|
||||
import time
|
||||
|
||||
#ENABLE THE QUOTA PLUGIN AND RESTART THE MANAGEMENT SERVER TO RUN QUOTA TESTS
|
||||
|
||||
class TestQuota(cloudstackTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.apiclient = self.testClient.getApiClient()
|
||||
self.hypervisor = self.testClient.getHypervisorInfo()
|
||||
self.dbclient = self.testClient.getDbConnection()
|
||||
self.services = self.testClient.getParsedTestDataConfig()
|
||||
self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
|
||||
self.pod = get_pod(self.apiclient, self.zone.id)
|
||||
self.cleanup = []
|
||||
return
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
#Clean up, terminate the created templates
|
||||
cleanup_resources(self.apiclient, self.cleanup)
|
||||
except Exception as e:
|
||||
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||
return
|
||||
|
||||
#Check quotaTariffList API returning 22 items
|
||||
@attr(tags=["smoke", "advanced"], required_hardware="false")
|
||||
def test_01_quota(self):
|
||||
cmd = quotaTariffList.quotaTariffListCmd()
|
||||
response = self.apiclient.quotaTariffList(cmd)
|
||||
|
||||
self.debug("Number of quota usage types: %s" % len(response))
|
||||
self.assertEqual(
|
||||
len(response), 22
|
||||
)
|
||||
for quota in response:
|
||||
self.debug("Usage Name: %s" % quota.usageName)
|
||||
self.assertEqual(
|
||||
hasattr(quota, 'usageName'),
|
||||
True,
|
||||
"Check whether usgaeName field is there"
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
#Check quota tariff on a particualr day
|
||||
@attr(tags=["smoke", "advanced"], required_hardware="false")
|
||||
def test_02_quota(self):
|
||||
cmd = quotaTariffList.quotaTariffListCmd()
|
||||
cmd.startdate='2015-07-06'
|
||||
response = self.apiclient.quotaTariffList(cmd)
|
||||
|
||||
self.debug("Number of quota usage types: %s" % len(response))
|
||||
self.assertEqual(
|
||||
len(response), 22
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
#check quota tariff of a particular item
|
||||
@attr(tags=["smoke", "advanced"], required_hardware="false")
|
||||
def test_03_quota(self):
|
||||
cmd = quotaTariffList.quotaTariffListCmd()
|
||||
cmd.startdate='2015-07-06'
|
||||
cmd.usagetype='10'
|
||||
response = self.apiclient.quotaTariffList(cmd)
|
||||
|
||||
self.debug("Number of quota usage types: %s" % len(response))
|
||||
self.assertEqual(
|
||||
len(response), 1
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
#check quota tariff
|
||||
#Change it
|
||||
#Check on affective date the new tariff should be applicable
|
||||
#check the old tariff it should be same
|
||||
@attr(tags=["smoke", "advanced"], required_hardware="false")
|
||||
def test_04_quota(self):
|
||||
cmd = quotaTariffList.quotaTariffListCmd()
|
||||
cmd.startdate='2015-07-06'
|
||||
cmd.usagetype='10'
|
||||
response = self.apiclient.quotaTariffList(cmd)
|
||||
|
||||
self.debug("Number of quota usage types: %s" % len(response))
|
||||
self.assertEqual(
|
||||
len(response), 1
|
||||
)
|
||||
quota = response[0]
|
||||
self.debug("Tariff Value for 10: %s" % quota.tariffValue)
|
||||
|
||||
cmd = quotaTariffUpdate.quotaTariffUpdateCmd()
|
||||
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
|
||||
cmd.startdate=tomorrow
|
||||
cmd.usagetype='10'
|
||||
cmd.value='2.9'
|
||||
response = self.apiclient.quotaTariffUpdate(cmd)
|
||||
|
||||
cmd = quotaTariffList.quotaTariffListCmd()
|
||||
cmd.startdate=tomorrow
|
||||
cmd.usagetype='10'
|
||||
response = self.apiclient.quotaTariffList(cmd)
|
||||
self.assertEqual(
|
||||
len(response), 1
|
||||
)
|
||||
quota = response[0]
|
||||
self.debug("Tariff Value for 10: %s" % quota.tariffValue)
|
||||
|
||||
self.assertEqual( quota.tariffValue, 2.9)
|
||||
|
||||
|
||||
cmd = quotaTariffList.quotaTariffListCmd()
|
||||
cmd.startdate='2015-07-07'
|
||||
cmd.usagetype='10'
|
||||
response = self.apiclient.quotaTariffList(cmd)
|
||||
self.assertEqual(
|
||||
len(response), 1
|
||||
)
|
||||
quota = response[0]
|
||||
self.debug("Tariff Value for 10: %s" % quota.tariffValue)
|
||||
|
||||
self.assertEqual( quota.tariffValue, 0)
|
||||
|
||||
return
|
||||
|
||||
|
||||
#Make credit deposit
|
||||
@attr(tags=["smoke", "advanced"], required_hardware="false")
|
||||
def test_05_quota(self):
|
||||
cmd = quotaCredits.quotaCreditsCmd()
|
||||
cmd.domainid = '1'
|
||||
cmd.account = 'admin'
|
||||
cmd.value = '10'
|
||||
cmd.quota_enforce = '1'
|
||||
cmd.min_balance = '9'
|
||||
response = self.apiclient.quotaCredits(cmd)
|
||||
|
||||
self.debug("Credit response update on: %s" % response.updated_on)
|
||||
|
||||
return
|
||||
|
||||
|
||||
#Make credit deposit and check today balance
|
||||
@attr(tags=["smoke", "advanced"], required_hardware="false")
|
||||
def test_06_quota(self):
|
||||
cmd = quotaBalance.quotaBalanceCmd()
|
||||
today = datetime.date.today()
|
||||
cmd.domainid = '1'
|
||||
cmd.account = 'admin'
|
||||
cmd.startdate = today
|
||||
response = self.apiclient.quotaBalance(cmd)
|
||||
|
||||
self.debug("Quota Balance on: %s" % response.startdate)
|
||||
self.debug("is: %s" % response.startquota)
|
||||
|
||||
self.assertGreater( response.startquota, 9)
|
||||
return
|
||||
|
||||
#make credit deposit and check start and end date balances
|
||||
@attr(tags=["smoke", "advanced"], required_hardware="false")
|
||||
def test_07_quota(self):
|
||||
cmd = quotaBalance.quotaBalanceCmd()
|
||||
today = datetime.date.today()
|
||||
cmd.domainid = '1'
|
||||
cmd.account = 'admin'
|
||||
cmd.startdate = today - datetime.timedelta(days=2)
|
||||
cmd.enddate = today
|
||||
response = self.apiclient.quotaBalance(cmd)
|
||||
|
||||
self.debug("Quota Balance on: %s" % response.startdate)
|
||||
self.debug("is: %s" % response.startquota)
|
||||
|
||||
self.assertGreater( response.endquota, 9)
|
||||
return
|
||||
|
|
@ -118,6 +118,8 @@ known_categories = {
|
|||
'listIdps': 'Authentication',
|
||||
'authorizeSamlSso': 'Authentication',
|
||||
'listSamlAuthorization': 'Authentication',
|
||||
'quota': 'Quota',
|
||||
'emailTemplate': 'Quota',
|
||||
'Capacity': 'System Capacity',
|
||||
'NetworkDevice': 'Network Device',
|
||||
'ExternalLoadBalancer': 'Ext Load Balancer',
|
||||
|
|
|
|||
|
|
@ -1024,6 +1024,50 @@ dictionary = {
|
|||
'label.purpose': '<fmt:message key="label.purpose" />',
|
||||
'label.Pxe.server.type': '<fmt:message key="label.Pxe.server.type" />',
|
||||
'label.quickview': '<fmt:message key="label.quickview" />',
|
||||
'label.usage.type': '<fmt:message key="label.usage.type" />',
|
||||
'label.usage.unit': '<fmt:message key="label.usage.unit" />',
|
||||
'label.quota.value': '<fmt:message key="label.quota.value" />',
|
||||
'label.quota.description': '<fmt:message key="label.quota.description" />',
|
||||
'label.quota.configuration': '<fmt:message key="label.quota.configuration" />',
|
||||
'label.quota.configure': '<fmt:message key="label.quota.configure" />',
|
||||
'label.quota.remove': '<fmt:message key="label.quota.remove" />',
|
||||
'label.quota.totalusage': '<fmt:message key="label.quota.totalusage" />',
|
||||
'label.quota.balance': '<fmt:message key="label.quota.balance" />',
|
||||
'label.quota.summary': '<fmt:message key="label.quota.summary" />',
|
||||
'label.quota.fullsummary': '<fmt:message key="label.quota.fullsummary" />',
|
||||
'label.quota.minbalance': '<fmt:message key="label.quota.minbalance" />',
|
||||
'label.quota.enforcequota': '<fmt:message key="label.quota.enforcequota" />',
|
||||
'label.quota.tariff': '<fmt:message key="label.quota.tariff" />',
|
||||
'label.quota.state': '<fmt:message key="label.quota.state" />',
|
||||
'label.quota.startdate': '<fmt:message key="label.quota.startdate" />',
|
||||
'label.quota.enddate': '<fmt:message key="label.quota.enddate" />',
|
||||
'label.quota.total': '<fmt:message key="label.quota.total" />',
|
||||
'label.quota.type.name': '<fmt:message key="label.quota.type.name" />',
|
||||
'label.quota.type.unit': '<fmt:message key="label.quota.type.unit" />',
|
||||
'label.quota.usage': '<fmt:message key="label.quota.usage" />',
|
||||
'label.quota.startquota': '<fmt:message key="label.quota.startquota" />',
|
||||
'label.quota.endquota': '<fmt:message key="label.quota.endquota" />',
|
||||
'label.quota.statement.quota': '<fmt:message key="label.quota.statement.quota" />',
|
||||
'label.quota.add.credits': '<fmt:message key="label.quota.add.credits" />',
|
||||
'label.quota.date': '<fmt:message key="label.quota.date" />',
|
||||
'label.quota.dates': '<fmt:message key="label.quota.dates" />',
|
||||
'label.quota.credit': '<fmt:message key="label.quota.credit" />',
|
||||
'label.quota.credits': '<fmt:message key="label.quota.credits" />',
|
||||
'label.quota.value': '<fmt:message key="label.quota.value" />',
|
||||
'label.quota.statement.bydates': '<fmt:message key="label.quota.statement.bydates" />',
|
||||
'label.quota.email.template': '<fmt:message key="label.quota.email.template" />',
|
||||
'label.quota.statement': '<fmt:message key="label.quota.statement" />',
|
||||
'label.quota.statement.balance': '<fmt:message key="label.quota.statement.balance" />',
|
||||
'label.quota.statement.tariff': '<fmt:message key="label.quota.statement.tariff" />',
|
||||
'label.quota.statement.balance': '<fmt:message key="label.quota.statement.balance" />',
|
||||
'label.quota.statement.tariff': '<fmt:message key="label.quota.statement.tariff" />',
|
||||
'label.quota.tariff.edit': '<fmt:message key="label.quota.tariff.edit" />',
|
||||
'label.quota.tariff.effectivedate': '<fmt:message key="label.quota.tariff.effectivedate" />',
|
||||
'label.quota.email.subject': '<fmt:message key="label.quota.email.subject" />',
|
||||
'label.quota.tariff.value': '<fmt:message key="label.quota.tariff.value" />',
|
||||
'label.quota.email.subject': '<fmt:message key="label.quota.email.subject" />',
|
||||
'label.quota.email.body': '<fmt:message key="label.quota.email.body" />',
|
||||
'label.quota.email.lastupdated': '<fmt:message key="label.quota.email.lastupdated" />',
|
||||
'label.rbd': '<fmt:message key="label.rbd" />',
|
||||
'label.rbd.monitor': '<fmt:message key="label.rbd.monitor" />',
|
||||
'label.rbd.pool': '<fmt:message key="label.rbd.pool" />',
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
// under the License.
|
||||
(function($, cloudStack) {
|
||||
cloudStack.plugins = [
|
||||
// 'testPlugin'
|
||||
'quota',
|
||||
//'testPlugin'
|
||||
];
|
||||
}(jQuery, cloudStack));
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue