mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-8592: Implement Quota service
Quota service while allowing for scalability will make sure that the cloud is not exploited by attacks, careless use and program errors. To address this problem, we propose to employ a quota-enforcement service that allows resource usage within certain bounds as defined by policies and available quotas for various entities. Quota service extends the functionality of usage server to provide a measurement for the resources used by the accounts and domains using a common unit referred to as cloud currency in this document. It can be configured to ensure that your usage won’t exceed the budget allocated to accounts/domain in cloud currency. It will let user know how much of the cloud resources he is using. It will help the cloud admins, if they want, to ensure that a user does not go beyond his allocated quota. Per usage cycle if a account is found to be exceeding its quota then it is locked. Locking an account means that it will not be able to initiat e a new resource allocation request, whether it is more storage or an additional ip. Needless to say quota service as well as any action on the account is configurable. Changes from Github code review: - Added marvin test for quota plugin API - removed unused commented code - debug messages in debug enabled check - checks for nulls, fixed access to member variables and feature - changes based on PR comments - unit tests for UsageTypes - unit tests for all Cmd classes - unit tests for all service and manager impls - try-catch-finally or try-with-resource in dao impls for failsafe db switching - remove dead code - add missing quota calculation case (regression fixed) - replace tabs with spaces in pom.xmls - quota: though default value for quota_calculated is 0, the usage server makes it null while entering usage entries. Flipping the condition so as to acocunt for that. - quotatypes: fix NPE in quota type - quota framework test fixes - made statement period configurable - changed default email templates to reflect the fact that exhausted quota may not result in a locked account - added quotaUpdateCmd that refreshes quota balances and sends alerts and statements - report quotaSummary command returns quota balance, quota usage and state for all account - made UI framework changes to allow for text area input in edit views - process usage entries that have greater than 0 usage - orocess quota entries only if tariff is non zero - if there are credit entries but no balance entry create a dummy balance entry - remove any credit entries that are before the last balance entry when displaying balance statement - on a rerun the last balance is now getting added FS: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Quota+Service+-+FS PR: https://github.com/apache/cloudstack/pull/768 Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
f30fbe9a5c
commit
987fcbd441
@ -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>
|
||||
|
||||
73
framework/quota/pom.xml
Normal file
73
framework/quota/pom.xml
Normal file
@ -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));
|
||||
}
|
||||
}
|
||||
99
plugins/database/quota/pom.xml
Normal file
99
plugins/database/quota/pom.xml
Normal file
@ -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;
|
||||
|
||||
204
test/integration/smoke/test_quota.py
Normal file
204
test/integration/smoke/test_quota.py
Normal file
@ -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…
x
Reference in New Issue
Block a user