quota service

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2015-08-06 18:04:00 +05:30
parent 873dba477b
commit d0852ef87c
82 changed files with 7197 additions and 59 deletions

View File

@ -269,6 +269,7 @@ public class ApiConstants {
public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids";
public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
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";

View File

@ -97,7 +97,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;

View File

@ -38,6 +38,7 @@ import com.cloud.utils.Pair;
@APICommand(name = "listUsageRecords", description = "Lists usage records for accounts", responseObject = UsageRecordResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class GetUsageRecordsCmd extends BaseListCmd {
public static final Logger s_logger = Logger.getLogger(GetUsageRecordsCmd.class.getName());
private static final String s_name = "listusagerecordsresponse";
@ -111,6 +112,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;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public void setUsageId(String usageId) {
this.usageId = usageId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////

View File

@ -22,6 +22,8 @@ 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;

View File

@ -1356,6 +1356,13 @@ 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.destroy.vm.graceperiod=Destroy VM Grace Period
label.SNMP.community=SNMP Community
label.SNMP.port=SNMP Port

View File

@ -246,6 +246,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>
@ -356,6 +361,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>

View File

@ -782,3 +782,14 @@ listOpenDaylightControllers=1
### GloboDNS commands
addGloboDnsHost=1
### Quota Service
quotaRefresh=1
quotaStatement=15
quotaBalance=15
quotaTariffList=15
quotaTariffUpdate=1
quotaCredits=1
quotaEmailTemplateList=1
quotaEmailTemplateUpdate=1

View File

@ -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 = null;
public Integer getQuotaCalculated() {
return quotaCalculated;
}
public void setQuotaCalculated(Integer quotaCalculated) {
this.quotaCalculated = quotaCalculated;
}
public UsageVO() {
}

View File

@ -53,4 +53,6 @@ public interface UsageDao extends GenericDao<UsageVO, Long> {
void saveVmDiskStats(List<VmDiskStatisticsVO> vmDiskStats);
void saveUsageRecords(List<UsageVO> usageRecords);
Pair<List<? extends UsageVO>, Integer> getUsageRecordsPendingQuotaAggregation(long accountId, long domainId);
}

View File

@ -42,35 +42,30 @@ import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
@Component
@Local(value = {UsageDao.class})
@Local(value = { UsageDao.class })
public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements UsageDao {
public static final Logger s_logger = Logger.getLogger(UsageDaoImpl.class.getName());
private static final String DELETE_ALL = "DELETE FROM cloud_usage";
private static final String DELETE_ALL_BY_ACCOUNTID = "DELETE FROM cloud_usage WHERE account_id = ?";
private static final String INSERT_ACCOUNT = "INSERT INTO cloud_usage.account (id, account_name, type, domain_id, removed, cleanup_needed) VALUES (?,?,?,?,?,?)";
private static final String INSERT_USER_STATS =
"INSERT INTO cloud_usage.user_statistics (id, data_center_id, account_id, public_ip_address, device_id, device_type, network_id, net_bytes_received,"
+ " net_bytes_sent, current_bytes_received, current_bytes_sent, agg_bytes_received, agg_bytes_sent) VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?)";
private static final String INSERT_USER_STATS = "INSERT INTO cloud_usage.user_statistics (id, data_center_id, account_id, public_ip_address, device_id, device_type, network_id, net_bytes_received,"
+ " net_bytes_sent, current_bytes_received, current_bytes_sent, agg_bytes_received, agg_bytes_sent) VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?)";
private static final String UPDATE_ACCOUNT = "UPDATE cloud_usage.account SET account_name=?, removed=? WHERE id=?";
private static final String UPDATE_USER_STATS =
"UPDATE cloud_usage.user_statistics SET net_bytes_received=?, net_bytes_sent=?, current_bytes_received=?, current_bytes_sent=?, agg_bytes_received=?, agg_bytes_sent=? WHERE id=?";
private static final String UPDATE_USER_STATS = "UPDATE cloud_usage.user_statistics SET net_bytes_received=?, net_bytes_sent=?, current_bytes_received=?, current_bytes_sent=?, agg_bytes_received=?, agg_bytes_sent=? WHERE id=?";
private static final String GET_LAST_ACCOUNT = "SELECT id FROM cloud_usage.account ORDER BY id DESC LIMIT 1";
private static final String GET_LAST_USER_STATS = "SELECT id FROM cloud_usage.user_statistics ORDER BY id DESC LIMIT 1";
private static final String GET_PUBLIC_TEMPLATES_BY_ACCOUNTID = "SELECT id FROM cloud.vm_template WHERE account_id = ? AND public = '1' AND removed IS NULL";
private static final String GET_LAST_VM_DISK_STATS = "SELECT id FROM cloud_usage.vm_disk_statistics ORDER BY id DESC LIMIT 1";
private static final String INSERT_VM_DISK_STATS =
"INSERT INTO cloud_usage.vm_disk_statistics (id, data_center_id, account_id, vm_id, volume_id, net_io_read, net_io_write, current_io_read, "
+ "current_io_write, agg_io_read, agg_io_write, net_bytes_read, net_bytes_write, current_bytes_read, current_bytes_write, agg_bytes_read, agg_bytes_write) "
+ " VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?, ?,?, ?, ?)";
private static final String UPDATE_VM_DISK_STATS =
"UPDATE cloud_usage.vm_disk_statistics SET net_io_read=?, net_io_write=?, current_io_read=?, current_io_write=?, agg_io_read=?, agg_io_write=?, "
+ "net_bytes_read=?, net_bytes_write=?, current_bytes_read=?, current_bytes_write=?, agg_bytes_read=?, agg_bytes_write=? WHERE id=?";
private static final String INSERT_VM_DISK_STATS = "INSERT INTO cloud_usage.vm_disk_statistics (id, data_center_id, account_id, vm_id, volume_id, net_io_read, net_io_write, current_io_read, "
+ "current_io_write, agg_io_read, agg_io_write, net_bytes_read, net_bytes_write, current_bytes_read, current_bytes_write, agg_bytes_read, agg_bytes_write) "
+ " VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?, ?,?, ?, ?)";
private static final String UPDATE_VM_DISK_STATS = "UPDATE cloud_usage.vm_disk_statistics SET net_io_read=?, net_io_write=?, current_io_read=?, current_io_write=?, agg_io_read=?, agg_io_write=?, "
+ "net_bytes_read=?, net_bytes_write=?, current_bytes_read=?, current_bytes_write=?, agg_bytes_read=?, agg_bytes_write=? WHERE id=?";
private static final String INSERT_USAGE_RECORDS = "INSERT INTO cloud_usage.cloud_usage (zone_id, account_id, domain_id, description, usage_display, "
+
"usage_type, raw_usage, vm_instance_id, vm_name, offering_id, template_id, "
+ "usage_type, raw_usage, vm_instance_id, vm_name, offering_id, template_id, "
+ "usage_id, type, size, network_id, start_date, end_date, virtual_size) VALUES (?,?,?,?,?,?,?,?,?, ?, ?, ?,?,?,?,?,?,?)";
protected final static TimeZone s_gmtTimeZone = TimeZone.getTimeZone("GMT");
@ -111,7 +106,9 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
txn.start();
String sql = INSERT_ACCOUNT;
PreparedStatement pstmt = null;
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
// want CLOUD_USAGE
// dataSource connection
for (AccountVO acct : accounts) {
pstmt.setLong(1, acct.getId());
pstmt.setString(2, acct.getAccountName());
@ -145,7 +142,9 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
txn.start();
String sql = UPDATE_ACCOUNT;
PreparedStatement pstmt = null;
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
// want CLOUD_USAGE
// dataSource connection
for (AccountVO acct : accounts) {
pstmt.setString(1, acct.getAccountName());
@ -175,7 +174,9 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
txn.start();
String sql = INSERT_USER_STATS;
PreparedStatement pstmt = null;
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
// want CLOUD_USAGE
// dataSource connection
for (UserStatisticsVO userStat : userStats) {
pstmt.setLong(1, userStat.getId());
pstmt.setLong(2, userStat.getDataCenterId());
@ -216,7 +217,9 @@ 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());
@ -313,7 +316,9 @@ 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());
@ -347,7 +352,9 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
txn.start();
String sql = INSERT_VM_DISK_STATS;
PreparedStatement pstmt = null;
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
// want CLOUD_USAGE
// dataSource connection
for (VmDiskStatisticsVO vmDiskStat : vmDiskStats) {
pstmt.setLong(1, vmDiskStat.getId());
pstmt.setLong(2, vmDiskStat.getDataCenterId());
@ -393,7 +400,9 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
txn.start();
String sql = INSERT_USAGE_RECORDS;
PreparedStatement pstmt = null;
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just
// want CLOUD_USAGE
// dataSource connection
for (UsageVO usageRecord : usageRecords) {
pstmt.setLong(1, usageRecord.getZoneId());
pstmt.setLong(2, usageRecord.getAccountId());
@ -451,4 +460,25 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
throw new CloudRuntimeException(ex.getMessage());
}
}
@Override
@SuppressWarnings("deprecation")
public Pair<List<? extends UsageVO>, Integer> getUsageRecordsPendingQuotaAggregation(final long accountId, final long domainId) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
s_logger.debug("getting usage records for account: " + accountId + ", domainId: " + domainId);
Filter usageFilter = new Filter(UsageVO.class, "startDate", true, 0L, 10000L);
SearchCriteria<UsageVO> sc = createSearchCriteria();
if (accountId != -1) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
if (domainId != -1) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
sc.addAnd("quotaCalculated", SearchCriteria.Op.EQ, 0);
s_logger.debug("Getting usage records" + usageFilter.getOrderBy());
Pair<List<UsageVO>, Integer> usageRecords = searchAndCountAllRecords(sc, usageFilter);
TransactionLegacy.open(opendb).close();
return new Pair<List<? extends UsageVO>, Integer>(usageRecords.first(), usageRecords.second());
}
}

View File

@ -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>

41
framework/quota/pom.xml Normal file
View File

@ -0,0 +1,41 @@
<!--
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.5.2</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>
</dependencies>
</project>

View File

@ -0,0 +1,30 @@
<!-- 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" />
</beans>

View File

@ -0,0 +1,56 @@
//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", "true",
"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", "R",
"The symbol for the currency in use to measure usage.", 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
}
}

View File

@ -0,0 +1,92 @@
// 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.HashMap;
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 Integer quotaType;
private String quotaName;
private String quotaUnit;
private String description;
private String discriminator;
public 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 HashMap<Integer, QuotaTypes> listQuotaTypes() {
final HashMap<Integer, QuotaTypes> quotaTypeList = new HashMap<Integer, QuotaTypes>();
quotaTypeList.put(new Integer(RUNNING_VM), new QuotaTypes(new Integer(RUNNING_VM), "RUNNING_VM", "Compute-Month", "Running Vm Usage"));
quotaTypeList.put(new Integer(ALLOCATED_VM), new QuotaTypes(new Integer(ALLOCATED_VM), "ALLOCATED_VM", "Compute-Month", "Allocated Vm Usage"));
quotaTypeList.put(new Integer(IP_ADDRESS), new QuotaTypes(new Integer(IP_ADDRESS), "IP_ADDRESS", "IP-Month", "IP Address Usage"));
quotaTypeList.put(new Integer(NETWORK_BYTES_SENT), new QuotaTypes(new Integer(NETWORK_BYTES_SENT), "NETWORK_BYTES_SENT", "GB", "Network Usage (Bytes Sent)"));
quotaTypeList.put(new Integer(NETWORK_BYTES_RECEIVED), new QuotaTypes(new Integer(NETWORK_BYTES_RECEIVED), "NETWORK_BYTES_RECEIVED", "GB", "Network Usage (Bytes Received)"));
quotaTypeList.put(new Integer(VOLUME), new QuotaTypes(new Integer(VOLUME), "VOLUME", "GB-Month", "Volume Usage"));
quotaTypeList.put(new Integer(TEMPLATE), new QuotaTypes(new Integer(TEMPLATE), "TEMPLATE", "GB-Month", "Template Usage"));
quotaTypeList.put(new Integer(ISO), new QuotaTypes(new Integer(ISO), "ISO", "GB-Month", "ISO Usage"));
quotaTypeList.put(new Integer(SNAPSHOT), new QuotaTypes(new Integer(SNAPSHOT), "SNAPSHOT", "GB-Month", "Snapshot Usage"));
quotaTypeList.put(new Integer(SECURITY_GROUP), new QuotaTypes(new Integer(SECURITY_GROUP), "SECURITY_GROUP", "Policy-Month", "Security Group Usage"));
quotaTypeList.put(new Integer(LOAD_BALANCER_POLICY), new QuotaTypes(new Integer(LOAD_BALANCER_POLICY), "LOAD_BALANCER_POLICY", "Policy-Month", "Load Balancer Usage"));
quotaTypeList.put(new Integer(PORT_FORWARDING_RULE), new QuotaTypes(new Integer(PORT_FORWARDING_RULE), "PORT_FORWARDING_RULE", "Policy-Month", "Port Forwarding Usage"));
quotaTypeList.put(new Integer(NETWORK_OFFERING), new QuotaTypes(new Integer(NETWORK_OFFERING), "NETWORK_OFFERING", "Policy-Month", "Network Offering Usage"));
quotaTypeList.put(new Integer(VPN_USERS), new QuotaTypes(new Integer(VPN_USERS), "VPN_USERS", "Policy-Month", "VPN users usage"));
quotaTypeList.put(new Integer(VM_DISK_IO_READ), new QuotaTypes(new Integer(VM_DISK_IO_READ), "VM_DISK_IO_READ", "GB", "VM Disk usage(I/O Read)"));
quotaTypeList.put(new Integer(VM_DISK_IO_WRITE), new QuotaTypes(new Integer(VM_DISK_IO_WRITE), "VM_DISK_IO_WRITE", "GB", "VM Disk usage(I/O Write)"));
quotaTypeList.put(new Integer(VM_DISK_BYTES_READ), new QuotaTypes(new Integer(VM_DISK_BYTES_READ), "VM_DISK_BYTES_READ", "GB", "VM Disk usage(Bytes Read)"));
quotaTypeList.put(new Integer(VM_DISK_BYTES_WRITE), new QuotaTypes(new Integer(VM_DISK_BYTES_WRITE), "VPN_USERS", "GB", "VM Disk usage(Bytes Write)"));
quotaTypeList.put(new Integer(VM_SNAPSHOT), new QuotaTypes(new Integer(VM_SNAPSHOT), "VM_SNAPSHOT", "GB-Month", "VM Snapshot storage usage"));
quotaTypeList.put(new Integer(CPU_CLOCK_RATE), new QuotaTypes(new Integer(CPU_CLOCK_RATE), "CPU_CLOCK_RATE", "Compute-Month", "Quota tariff for using 1 CPU of clock rate 100MHz"));
quotaTypeList.put(new Integer(CPU_NUMBER), new QuotaTypes(new Integer(CPU_NUMBER), "CPU_NUMBER", "Compute-Month", "Quota tariff for running VM that has 1vCPU"));
quotaTypeList.put(new Integer(MEMORY), new QuotaTypes(new Integer(MEMORY), "MEMORY", "Compute-Month", "Quota tariff for using 1MB or RAM for 1 hour"));
return quotaTypeList;
}
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) {
return listQuotaTypes().get(quotaType).getDescription();
}
}

View File

@ -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> listAll();
QuotaAccountVO findById(Long id);
QuotaAccountVO persist(QuotaAccountVO entity);
boolean update(Long id, QuotaAccountVO entity);
}

View 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.
package org.apache.cloudstack.quota.dao;
import java.util.List;
import javax.ejb.Local;
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
import org.springframework.stereotype.Component;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.TransactionLegacy;
@Component
@Local(value = { QuotaAccountDao.class })
public class QuotaAccountDaoImpl extends GenericDaoBase<QuotaAccountVO, Long> implements QuotaAccountDao {
@Override
public List<QuotaAccountVO> listAll() {
List<QuotaAccountVO> result = null;
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
result = super.listAll();
TransactionLegacy.open(opendb).close();
return result;
}
@Override
public QuotaAccountVO findById(Long id) {
QuotaAccountVO result = null;
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
result = super.findById(id);
TransactionLegacy.open(opendb).close();
return result;
}
@Override
public QuotaAccountVO persist(QuotaAccountVO entity) {
QuotaAccountVO result = null;
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
result = super.persist(entity);
TransactionLegacy.open(opendb).close();
return result;
}
@Override
public boolean update(Long id, QuotaAccountVO entity) {
boolean result = false;
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
result = super.update(id, entity);
TransactionLegacy.open(opendb).close();
return result;
}
}

View File

@ -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> {
void saveQuotaBalance(List<QuotaBalanceVO> credits);
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);
}

View File

@ -0,0 +1,201 @@
//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.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.ejb.Local;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
import org.apache.log4j.Logger;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
@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());
@SuppressWarnings("deprecation")
@Override
public QuotaBalanceVO findLastBalanceEntry(final long accountId, final long domainId, final Date beforeThis) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 1L);
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
sc.addAnd("creditsId", SearchCriteria.Op.EQ, 0);
sc.addAnd("updatedOn", SearchCriteria.Op.LT, beforeThis);
List<QuotaBalanceVO> quotab = this.search(sc, filter);
TransactionLegacy.open(opendb).close();
return quotab.size() > 0 ? quotab.get(0) : null;
}
@SuppressWarnings("deprecation")
@Override
public QuotaBalanceVO findLaterBalanceEntry(final long accountId, final long domainId, final Date afterThis) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, 1L);
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
sc.addAnd("creditsId", SearchCriteria.Op.EQ, 0);
sc.addAnd("updatedOn", SearchCriteria.Op.GT, afterThis);
List<QuotaBalanceVO> quotab = this.search(sc, filter);
TransactionLegacy.open(opendb).close();
return quotab.size() > 0 ? quotab.get(0) : null;
}
@Override
public void saveQuotaBalance(final List<QuotaBalanceVO> credits) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
for (QuotaBalanceVO credit : credits) {
persist(credit);
}
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close();
}
@SuppressWarnings("deprecation")
@Override
public List<QuotaBalanceVO> findCreditBalance(final long accountId, final long domainId, final Date lastbalancedate, final Date beforeThis) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, Long.MAX_VALUE);
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
sc.addAnd("creditsId", SearchCriteria.Op.GT, 0);
if ((lastbalancedate != null) && (beforeThis != null) && lastbalancedate.before(beforeThis)) {
sc.addAnd("updatedOn", SearchCriteria.Op.BETWEEN, lastbalancedate, beforeThis);
} else {
return new ArrayList<QuotaBalanceVO>();
}
List<QuotaBalanceVO> qb = search(sc, filter);
TransactionLegacy.open(opendb).close();
return qb;
}
@SuppressWarnings("deprecation")
@Override
public List<QuotaBalanceVO> findQuotaBalance(final Long accountId, final Long domainId, final Date startDate, final Date endDate) {
// TODO account for series of credits around boundaries
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
List<QuotaBalanceVO> quotaUsageRecords = null;
try {
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
sc.addAnd("updatedOn", SearchCriteria.Op.BETWEEN, startDate, endDate);
} else {
return new ArrayList<QuotaBalanceVO>();
}
quotaUsageRecords = listBy(sc);
if (quotaUsageRecords.size() == 0) {
quotaUsageRecords.addAll(lastQuotaBalanceVO(accountId, domainId, startDate));
}
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close();
return quotaUsageRecords;
}
@SuppressWarnings("deprecation")
@Override
public List<QuotaBalanceVO> lastQuotaBalanceVO(final Long accountId, final Long domainId, final Date pivotDate) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
List<QuotaBalanceVO> quotaUsageRecords = null;
List<QuotaBalanceVO> trimmedRecords = new ArrayList<QuotaBalanceVO>();
try {
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 100L);
// ASSUMPTION there will be less than 100 continuous credit
// transactions
SearchCriteria<QuotaBalanceVO> sc = createSearchCriteria();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if ((pivotDate != null)) {
sc.addAnd("updatedOn", SearchCriteria.Op.LTEQ, pivotDate);
}
quotaUsageRecords = search(sc, filter);
// get records before startDate to find start balance
for (Iterator<QuotaBalanceVO> it = quotaUsageRecords.iterator(); it.hasNext();) {
QuotaBalanceVO entry = it.next();
s_logger.info("findQuotaBalance Date=" + entry.getUpdatedOn().toGMTString() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
if (entry.getCreditsId() > 0) {
trimmedRecords.add(entry);
} else {
trimmedRecords.add(entry);
break; // add only consecutive credit entries and last balance entry
}
}
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close();
return trimmedRecords;
}
@Override
public BigDecimal lastQuotaBalance(final Long accountId, final Long domainId, Date startDate) {
List<QuotaBalanceVO> quotaBalance = lastQuotaBalanceVO(accountId, domainId, startDate);
if (quotaBalance.size() == 0) {
new InvalidParameterValueException("There are no balance entries on or before the requested date.");
}
BigDecimal finalBalance = new BigDecimal(0);
for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) {
QuotaBalanceVO entry = it.next();
s_logger.info("lastQuotaBalance Date=" + entry.getUpdatedOn().toGMTString() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
finalBalance.add(entry.getCreditBalance());
}
return finalBalance;
}
}

View File

@ -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);
}

View File

@ -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.quota.dao;
import java.util.ArrayList;
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.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
@Component
@Local(value = { QuotaCreditsDao.class })
public class QuotaCreditsDaoImpl extends GenericDaoBase<QuotaCreditsVO, Long> implements QuotaCreditsDao {
@Inject
QuotaBalanceDao _quotaBalanceDao;
@SuppressWarnings("deprecation")
@Override
public List<QuotaCreditsVO> findCredits(final long accountId, final long domainId, final Date startDate, final Date endDate) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
Filter filter = new Filter(QuotaCreditsVO.class, "updatedOn", true, 0L, Long.MAX_VALUE);
SearchCriteria<QuotaCreditsVO> sc = createSearchCriteria();
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
sc.addAnd("updatedOn", SearchCriteria.Op.BETWEEN, startDate, endDate);
} else {
return new ArrayList<QuotaCreditsVO>();
}
List<QuotaCreditsVO> qc = search(sc, filter);
TransactionLegacy.open(opendb).close();
return qc;
}
@Override
public QuotaCreditsVO saveCredits(final QuotaCreditsVO credits) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
persist(credits);
// make an entry in the balance table
QuotaBalanceVO bal = new QuotaBalanceVO(credits);
_quotaBalanceDao.persist(bal);
TransactionLegacy.open(opendb).close();
return credits;
}
}

View File

@ -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);
}

View File

@ -0,0 +1,64 @@
//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.TransactionLegacy;
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
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 {
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(String templateName) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
SearchCriteria<QuotaEmailTemplatesVO> sc = QuotaEmailTemplateSearch.create();
if (templateName != null) {
sc.setParameters("template_name", templateName);
}
List<QuotaEmailTemplatesVO> result = this.listBy(sc);
TransactionLegacy.open(opendb).close();
return result;
}
@Override
public boolean updateQuotaEmailTemplate(QuotaEmailTemplatesVO template) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
final boolean result = this.update(template.getId(), template);
TransactionLegacy.open(opendb).close();
return result;
}
}

View File

@ -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.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(Date onOrBefore);
boolean updateQuotaTariff(QuotaTariffVO plan);
QuotaTariffVO addQuotaTariff(QuotaTariffVO plan);
}

View File

@ -0,0 +1,138 @@
//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.TransactionLegacy;
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();
}
@Override
public QuotaTariffVO findTariffPlanByUsageType(final int quotaType, final Date effectiveDate) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
List<QuotaTariffVO> result = null;
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
final Filter filter = new Filter(QuotaTariffVO.class, "effectiveOn", false, 0L, 1L);
final SearchCriteria<QuotaTariffVO> sc = listAllIncludedUsageType.create();
sc.setParameters("onorbefore", effectiveDate);
sc.setParameters("quotatype", quotaType);
result = search(sc, filter);
} finally {
txn.close();
}
// Switch back
TransactionLegacy.open(opendb).close();
if (result.size() > 0) {
//s_logger.info("findTariffPlanByUsageType: " + effectiveDate + "quota type " + quotaType + " val=" + result.get(0).getCurrencyValue());
return result.get(0);
} else {
//s_logger.info("Missing quota type " + quotaType);
return null;
}
}
@Override
public List<QuotaTariffVO> listAllTariffPlans(final Date effectiveDate) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
List<QuotaTariffVO> tariffs = new ArrayList<QuotaTariffVO>();
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
final Filter filter = new Filter(QuotaTariffVO.class, "effectiveOn", 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.size() > 0) {
tariffs.add(result.get(0));
s_logger.info("listAllTariffPlans onorbefore" + effectiveDate + "quota type " + result.get(0).getDescription() + " , effective Date=" + result.get(0).getEffectiveOn() + " val=" + result.get(0).getCurrencyValue());
}
}
} finally {
txn.close();
}
// Switch back
TransactionLegacy.open(opendb).close();
return tariffs;
}
@Override
public boolean updateQuotaTariff(QuotaTariffVO plan) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); // Switch
// to
boolean result = false;
try {
// Usage DB
result = this.update(plan.getId(), plan);
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close(); // Switch back
return result;
}
@Override
public QuotaTariffVO addQuotaTariff(QuotaTariffVO plan) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); // Switch
// to
QuotaTariffVO result = null;
try {
// Usage DB
plan.setId(null);
result = this.persist(plan);
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close(); // Switch back
return result;
}
}

View File

@ -0,0 +1,40 @@
//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.QuotaUsageVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.SearchCriteria;
public interface QuotaUsageDao extends GenericDao<QuotaUsageVO, Long> {
List<QuotaUsageVO> findQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate);
Pair<List<QuotaUsageVO>, Integer> searchAndCountAllRecords(SearchCriteria<QuotaUsageVO> sc, Filter filter);
void saveQuotaUsage(List<QuotaUsageVO> credits);
BigDecimal findTotalQuotaUsage(Long accountId, Long domainId, Integer usageType, Date startDate, Date endDate);
}

View File

@ -0,0 +1,106 @@
//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.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Local;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
@Component
@Local(value = { QuotaUsageDao.class })
public class QuotaUsageDaoImpl extends GenericDaoBase<QuotaUsageVO, Long> implements QuotaUsageDao {
@Override
public Pair<List<QuotaUsageVO>, Integer> searchAndCountAllRecords(SearchCriteria<QuotaUsageVO> sc, Filter filter) {
return listAndCountIncludingRemovedBy(sc, filter);
}
@Override
public void saveQuotaUsage(List<QuotaUsageVO> records) {
for (QuotaUsageVO usageRecord : records) {
persist(usageRecord);
}
}
@Override
public BigDecimal findTotalQuotaUsage(final Long accountId, final Long domainId, final Integer usageType, final Date startDate, final Date endDate) {
List<QuotaUsageVO> quotaUsage = findQuotaUsage(accountId, domainId, null, startDate, endDate);
BigDecimal total = new BigDecimal(0);
for (final QuotaUsageVO quotaRecord : quotaUsage) {
total = total.add(quotaRecord.getQuotaUsed());
}
return total;
}
@SuppressWarnings("deprecation")
@Override
public List<QuotaUsageVO> findQuotaUsage(final Long accountId, final Long domainId, final Integer usageType, final Date startDate, final Date endDate) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
List<QuotaUsageVO> quotaUsageRecords = null;
try {
// TODO instead of max value query with reasonable number and
// iterate
SearchCriteria<QuotaUsageVO> sc = createSearchCriteria();
if (accountId != null) {
sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
}
/*
* if (isDomainAdmin) { SearchCriteria<DomainVO> sdc =
* _domainDao.createSearchCriteria(); sdc.addOr("path",
* SearchCriteria.Op.LIKE,
* _domainDao.findById(caller.getDomainId()).getPath() + "%");
* List<DomainVO> domains = _domainDao.search(sdc, null); List<Long>
* domainIds = new ArrayList<Long>(); for (DomainVO domain :
* domains) domainIds.add(domain.getId()); sc.addAnd("domainId",
* SearchCriteria.Op.IN, domainIds.toArray());
* s_logger.debug("Account ID=" + accountId); }
*/
if (domainId != null) {
sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
}
if (usageType != null) {
sc.addAnd("usageType", SearchCriteria.Op.EQ, usageType);
}
if ((startDate != null) && (endDate != null) && startDate.before(endDate)) {
sc.addAnd("startDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
sc.addAnd("endDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
} else {
return new ArrayList<QuotaUsageVO>();
}
quotaUsageRecords = listBy(sc);
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close();
return quotaUsageRecords;
}
}

View File

@ -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 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);
}

View File

@ -0,0 +1,85 @@
// 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.TransactionLegacy;
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;
@Override
public ServiceOfferingVO findServiceOffering(final Long vmId, final long serviceOfferingId) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
ServiceOfferingVO result;
try {
result = findById(vmId, serviceOfferingId);
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close();
return result;
}
public ServiceOfferingVO findById(Long vmId, long serviceOfferingId) {
ServiceOfferingVO offering = super.findById(serviceOfferingId);
if (offering.isDynamic()) {
offering.setDynamicFlag(true);
if (vmId == null) {
throw new CloudRuntimeException("missing argument vmId");
}
Map<String, String> dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId);
return getcomputeOffering(offering, dynamicOffering);
}
return offering;
}
public ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map<String, String> customParameters) {
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;
}
}

View File

@ -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.
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);
}

View File

@ -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.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);
// FIXME SnapshotDetailsVO doesn't have a display field
if (_allAttributes.containsKey("display")) {
AllFieldsSearch.and("display", AllFieldsSearch.entity().isDisplay(), SearchCriteria.Op.EQ);
}
AllFieldsSearch.done();
}
@Override
public Map<String, String> listDetailsKeyPairs(long resourceId) {
SearchCriteria<UserVmDetailVO> sc = AllFieldsSearch.create();
sc.setParameters("resourceId", resourceId);
List<UserVmDetailVO> results = search(sc, null);
Map<String, String> details = new HashMap<String, String>(results.size());
for (UserVmDetailVO result : results) {
details.put(result.getName(), result.getValue());
}
return details;
}
}

View File

@ -0,0 +1,142 @@
//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 = null;
@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;
}
public void setQuotaAlertDate(Date quotaAlertDate) {
this.quotaAlertDate = quotaAlertDate;
}
public Date getQuotaBalanceDate() {
return quotaBalanceDate;
}
public void setQuotaBalanceDate(Date quotaBalanceDate) {
this.quotaBalanceDate = quotaBalanceDate;
}
public Date getLastStatementDate() {
return lastStatementDate;
}
public void setLastStatementDate(Date lastStatementDate) {
this.lastStatementDate = lastStatementDate;
}
}

View File

@ -0,0 +1,127 @@
//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() {
super();
}
public QuotaBalanceVO(QuotaCreditsVO credit) {
super();
this.accountId = credit.getAccountId();
this.domainId = credit.getDomainId();
this.creditBalance = credit.getCredit();
this.updatedOn = credit.getUpdatedOn();
this.creditsId = credit.getId();
}
public QuotaBalanceVO(Long accountId, Long domainId, BigDecimal creditBalance, Date updatedOn) {
super();
this.accountId = accountId;
this.domainId = domainId;
this.creditBalance = creditBalance;
this.creditsId=0L;
this.updatedOn = updatedOn;
}
@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;
}
public void setUpdatedOn(Date updatedOn) {
this.updatedOn = updatedOn;
}
}

View File

@ -0,0 +1,117 @@
//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;
}
public void setUpdatedOn(Date updatedOn) {
this.updatedOn = updatedOn;
}
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() {
// TODO Auto-generated method stub
return this.id;
}
}

View File

@ -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;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public String getLocale() {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
}

View File

@ -0,0 +1,162 @@
//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, 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;
this.updatedBy = updatedBy;
}
public void setId(Long id) {
this.id = id;
}
public Date getEffectiveOn() {
return effectiveOn;
}
public void setEffectiveOn(Date effectiveOn) {
this.effectiveOn = effectiveOn;
}
public Date getUpdatedOn() {
return updatedOn;
}
public void setUpdatedOn(Date updatedOn) {
this.updatedOn = updatedOn;
}
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);
}
@Override
public long getId() {
return this.id;
}
}

View File

@ -0,0 +1,172 @@
//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;
this.endDate = endDate;
}
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 = toclone.startDate;
this.endDate = toclone.endDate;
}
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() {
// TODO Auto-generated method stub
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;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public void setId(Long id) {
this.id = id;
}
}

View File

@ -0,0 +1,337 @@
//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;
}
}

View File

@ -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.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;
}
}

View File

@ -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. -->
<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.5.2</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>
</dependencies>
</project>

View File

@ -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

View File

@ -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>

View File

@ -0,0 +1,136 @@
//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.context.CallContext;
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
import org.apache.cloudstack.api.response.QuotaStatementItemResponse;
import com.cloud.user.Account;
@APICommand(name = "quotaBalance", responseObject = QuotaStatementItemResponse.class, description = "Create a quota balance statement", since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class QuotaBalanceCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(QuotaBalanceCmd.class.getName());
private static final String s_name = "quotabalanceresponse";
@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, 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);
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public QuotaBalanceCmd() {
super();
}
@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<QuotaBalanceVO> quotaUsage = _responseBuilder.getQuotaBalance(this);
QuotaBalanceResponse response;
if (getEndDate() == null) {
response = _responseBuilder.createQuotaLastBalanceResponse(quotaUsage, startDate);
} else {
response = _responseBuilder.createQuotaBalanceResponse(quotaUsage, startDate, endDate);
}
response.setResponseName(getCommandName());
setResponseObject(response);
}
}

View File

@ -0,0 +1,143 @@
//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.2.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.getName());
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 = _accountService.getActiveAccountByName(accountName, domainId).getAccountId();
if (accountId == null) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "The account does not exists or has been removed/disabled");
}
if (value == null) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please send a valid non-empty quota value");
}
if (getQuotaEnforce() != null) {
_quotaService.setLockAccount(accountId, getQuotaEnforce());
}
if (getMinBalance() != null) {
_quotaService.setMinBalance(accountId, getMinBalance());
}
else {
_quotaService.setMinBalance(accountId, 0.2 * value);
}
final QuotaCreditsResponse response = _responseBuilder.addQuotaCredits(accountId, domainId, value, CallContext.current().getCallingUserId());
response.setResponseName(getCommandName());
response.setObjectName("quotacredits");
setResponseObject(response);
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
}

View File

@ -0,0 +1,56 @@
//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.getName());
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;
}
@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;
}
}

View File

@ -0,0 +1,111 @@
//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.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class QuotaEmailTemplateUpdateCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(QuotaEmailTemplateUpdateCmd.class.getName());
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;
}
private 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;
}
}

View File

@ -0,0 +1,143 @@
//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.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class QuotaStatementCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(QuotaStatementCmd.class.getName());
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() : endDate);
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public QuotaStatementCmd() {
super();
}
@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.setResponseName(getCommandName());
setResponseObject(response);
}
}

View File

@ -0,0 +1,93 @@
//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.getName());
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) {
s_logger.info("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;
}
public Integer getUsageType() {
return usageType;
}
public void setUsageType(Integer usageType) {
this.usageType = usageType;
}
}

View File

@ -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.getName());
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;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
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;
}
}

View File

@ -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());
credits.add(0, cr);
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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.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);
QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate);
QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy, Date despositedOn);
public 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();
}

View File

@ -0,0 +1,412 @@
//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.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.db.TransactionLegacy;
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.constant.QuotaConfig;
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.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.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@Component
@Local(value = QuotaResponseBuilderImpl.class)
public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
private static final Logger s_logger = Logger.getLogger(QuotaResponseBuilderImpl.class.getName());
@Inject
private QuotaTariffDao _quotaTariffDao;
@Inject
private QuotaBalanceDao _quotaBalanceDao;
@Inject
private QuotaCreditsDao _quotaCreditsDao;
@Inject
private QuotaEmailTemplatesDao _quotaEmailTemplateDao;
@Inject
private UserDao _userDao;
@Inject
private QuotaService _quotaService;
@Inject
AccountDao _accountDao;
@Inject
private RegionManager _regionMgr;
@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 QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate, Date endDate) {
if (quotaBalance.size() == 0) {
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
}
});
QuotaBalanceResponse resp = new QuotaBalanceResponse();
BigDecimal lastCredits = new BigDecimal(0);
boolean consecutive = true;
for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) {
QuotaBalanceVO entry = it.next();
s_logger.info("createQuotaBalanceResponse: Date=" + entry.getUpdatedOn().toGMTString() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
if (entry.getCreditsId() > 0) {
if (consecutive) {
lastCredits = lastCredits.add(entry.getCreditBalance());
}
resp.addCredits(entry);
it.remove();
} else {
consecutive = false;
}
}
if (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(startDate);
resp.setStartQuota(startItem.getCreditBalance());
resp.setEndDate(endDate);
resp.setEndQuota(endItem.getCreditBalance().add(lastCredits));
} else {
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.size() == 0) {
throw new InvalidParameterValueException("There is no usage data found for period mentioned.");
}
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
QuotaStatementResponse statement = new QuotaStatementResponse();
HashMap<Integer, QuotaTariffVO> quotaTariffMap = new HashMap<Integer, QuotaTariffVO>();
List<QuotaTariffVO> result = _quotaTariffDao.listAll();
for (QuotaTariffVO quotaTariff : result) {
quotaTariffMap.put(quotaTariff.getUsageType(), quotaTariff);
// add dummy record for each usage type
QuotaUsageVO dummy = new QuotaUsageVO(quotaUsage.get(0));
dummy.setUsageType(quotaTariff.getUsageType());
dummy.setQuotaUsed(new BigDecimal(0));
quotaUsage.add(dummy);
}
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);
//s_logger.info("createQuotaStatementResponse record count=" + quotaUsage.size());
for (final QuotaUsageVO quotaRecord : quotaUsage) {
//s_logger.info("createQuotaStatementResponse Type=" + quotaRecord.getUsageType() + " usage=" + usage + " name" + quotaRecord.getUsageItemId());
if (type != quotaRecord.getUsageType()) {
if (type != -1) {
lineitem = new QuotaStatementItemResponse();
lineitem.setUsageType(type);
lineitem.setQuotaUsed(usage);
lineitem.setAccountId(prev.getAccountId());
lineitem.setDomainId(prev.getDomainId());
lineitem.setStartDate(prev.getStartDate());
lineitem.setEndDate(prev.getEndDate());
lineitem.setUsageUnit(quotaTariffMap.get(type).getUsageUnit());
lineitem.setUsageName(quotaTariffMap.get(type).getUsageName());
lineitem.setObjectName("quotausage");
items.add(lineitem);
totalUsage = totalUsage.add(usage);
usage = new BigDecimal(0);
}
type = quotaRecord.getUsageType();
}
prev = quotaRecord;
usage = usage.add(quotaRecord.getQuotaUsed());
}
TransactionLegacy.open(opendb).close();
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);
s_logger.info("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);
}
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close();
QuotaTariffVO result = null;
try {
result = new QuotaTariffVO();
result.setUsageType(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());
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);
} catch (Exception pokemon) {
s_logger.error("Error in update quota tariff plan: " + pokemon);
} finally {
TransactionLegacy.open(opendb).close();
}
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) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
QuotaCreditsVO result = null;
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
QuotaCreditsVO credits = new QuotaCreditsVO(accountId, domainId, new BigDecimal(amount), updatedBy);
s_logger.info("addQuotaCredits: Depositing " + amount + " on adjusted date " + despositedOn);
credits.setUpdatedOn(despositedOn);
result = _quotaCreditsDao.saveCredits(credits);
} finally {
txn.close();
}
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
final AccountVO account = _accountDao.findById(accountId);
final boolean lockAccountEnforcement = QuotaConfig.QuotaEnableEnforcement.value().equalsIgnoreCase("true");
final BigDecimal currentAccountBalance = _quotaBalanceDao.lastQuotaBalance(accountId, domainId, startOfNextDay(despositedOn));
if (lockAccountEnforcement && (currentAccountBalance.compareTo(new BigDecimal(0)) >= 0)) {
if (account.getState() == Account.State.locked) {
try {
_regionMgr.enableAccount(account.getAccountName(), domainId, accountId);
//_quotaMgr.sendQuotaAlert(account, currentAccountBalance, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_UNLOCK_ACCOUNT);
} catch (Exception e) {
s_logger.error(String.format("Unable to unlock account %s after getting enough quota credits", account.getAccountName()));
}
}
}
String creditor = String.valueOf(Account.ACCOUNT_ID_SYSTEM);
User creditorUser = _userDao.getUser(updatedBy);
if (creditorUser != null) {
creditor = creditorUser.getUsername();
}
TransactionLegacy.open(opendb).close();
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.size() == 0) {
new InvalidParameterValueException("There are no balance entries on or before the requested date.");
}
if (startDate == null) {
startDate = new Date();
}
QuotaBalanceResponse resp = new QuotaBalanceResponse();
BigDecimal lastCredits = new BigDecimal(0);
for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) {
QuotaBalanceVO entry = it.next();
s_logger.info("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;
}
}

View File

@ -0,0 +1,143 @@
//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;
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;
@SerializedName("startdate")
@Param(description = "start date")
private Date startDate = null;
@SerializedName("enddate")
@Param(description = "end date")
private Date endDate = null;
public QuotaStatementItemResponse() {
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 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);
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
}

View File

@ -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;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -0,0 +1,296 @@
//Licensed to the Apache Software Foundation (ASF) under one
//or more contributor license agreements. See the NOTICE file
//distributed with this work for additional information
//regarding copyright ownership. The ASF licenses this file
//to you under the Apache License, Version 2.0 (the
//"License"); you may not use this file except in compliance
//with the License. You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing,
//software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//KIND, either express or implied. See the License for the
//specific language governing permissions and limitations
//under the License.
package org.apache.cloudstack.quota;
import com.cloud.configuration.Config;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
import org.apache.cloudstack.api.command.QuotaCreditsCmd;
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
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.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.getName());
@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;
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 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;
}
s_logger.info("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(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, 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) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
Account userAccount = null;
Account caller = CallContext.current().getCallingAccount();
// if accountId is not specified, use accountName and domainId
if ((accountId == null) && (accountName != null) && (domainId != null)) {
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.size() > 0) {
userAccount = accounts.get(0);
}
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
} else {
throw new PermissionDeniedException("Invalid Domain Id or Account");
}
}
TransactionLegacy.open(opendb).close();
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));
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);
s_logger.info("Found records size=" + qbrecords.size());
if (qbrecords.size() == 0) {
throw new InvalidParameterValueException("Incorrect Date there are no quota records before this date " + adjustedStartDate);
} 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);
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);
s_logger.info("getQuotaBalance3: Found records size=" + qbrecords.size());
if (qbrecords.size() == 0) {
throw new InvalidParameterValueException("Incorrect Date range there are no quota records between these dates start date " + adjustedStartDate + " and end date:" + endDate);
} 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) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
Account userAccount = null;
Account caller = CallContext.current().getCallingAccount();
// if accountId is not specified, use accountName and domainId
if ((accountId == null) && (accountName != null) && (domainId != null)) {
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.size() > 0) {
userAccount = accounts.get(0);
}
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
} else {
throw new PermissionDeniedException("Invalid Domain Id or Account");
}
}
TransactionLegacy.open(opendb).close();
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);
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.findById(accountId);
if (acc == null) {
acc = new QuotaAccountVO(accountId);
acc.setQuotaEnforce(state ? 1 : 0);
_quotaAcc.persist(acc);
} else {
acc.setQuotaEnforce(state ? 1 : 0);
_quotaAcc.update(accountId, acc);
}
}
@Override
public void setMinBalance(Long accountId, Double balance) {
QuotaAccountVO acc = _quotaAcc.findById(accountId);
if (acc == null) {
acc = new QuotaAccountVO(accountId);
acc.setQuotaMinBalance(new BigDecimal(balance));
_quotaAcc.persist(acc);
} else {
acc.setQuotaMinBalance(new BigDecimal(balance));
_quotaAcc.update(accountId, acc);
}
}
}

View File

@ -90,6 +90,7 @@
<module>network-elements/internal-loadbalancer</module>
<module>network-elements/vxlan</module>
<module>network-elements/globodns</module>
<module>database/quota</module>
</modules>
<dependencies>

View File

@ -83,6 +83,7 @@
<cs.aws.sdk.version>1.3.22</cs.aws.sdk.version>
<cs.lang.version>2.6</cs.lang.version>
<cs.commons-io.version>1.4</cs.commons-io.version>
<cs.commons-lang3.version>3.4</cs.commons-lang3.version>
<cs.reflections.version>0.9.8</cs.reflections.version>
<cs.java-ipv6.version>0.10</cs.java-ipv6.version>
<cs.replace.properties>build/replace.properties</cs.replace.properties>
@ -96,6 +97,7 @@
<cs.findbugs.version>2.5.3</cs.findbugs.version>
<cs.javadoc.version>2.9.1</cs.javadoc.version>
<cs.opensaml.version>2.6.1</cs.opensaml.version>
<cs.joda-time.version>2.8.1</cs.joda-time.version>
</properties>
<distributionManagement>

View File

@ -291,6 +291,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

View File

@ -2179,8 +2179,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()))

View File

@ -19,7 +19,9 @@
-- Schema upgrade from 4.5.1 to 4.5.2;
--;
DELETE FROM `cloud`.`configuration` WHERE name like 'saml%';
-- SAML
DELETE FROM `cloud`.`configuration` WHERE name like 'saml%' and component='management-server';
ALTER TABLE `cloud`.`user` ADD COLUMN `external_entity` text DEFAULT NULL COMMENT "reference to external federation entity";
@ -33,3 +35,117 @@ CREATE TABLE `cloud`.`saml_token` (
PRIMARY KEY (`id`),
CONSTRAINT `fk_saml_token__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Quota
ALTER TABLE `cloud_usage`.`cloud_usage` ADD COLUMN `quota_calculated` tinyint(1) DEFAULT 0 COMMENT "quota calculation status";
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} is locked now', 'Your account ${accountName} in the domain ${domainName} has exhausted allocated quota and has been locked now, please contact the administrator.'),
('QUOTA_UNLOCK_ACCOUNT', 'Quota credits added, account ${accountName} is unlocked now', 'Your account ${accountName} in the domain ${domainName} has enough quota credits now with the current balance of ${quotaBalance}. Your account has been unlocked now.'),
('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;

View File

@ -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',

View File

@ -982,6 +982,13 @@ 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.rbd': '<fmt:message key="label.rbd" />',
'label.rbd.monitor': '<fmt:message key="label.rbd.monitor" />',
'label.rbd.pool': '<fmt:message key="label.rbd.pool" />',

View File

@ -16,6 +16,7 @@
// under the License.
(function($, cloudStack) {
cloudStack.plugins = [
// 'testPlugin'
//'quota',
//'testPlugin'
];
}(jQuery, cloudStack));

View File

@ -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.
(function (cloudStack) {
cloudStack.plugins.quota.config = {
title: 'Quota',
desc: 'CloudStack Quota',
externalLink: 'http://www.cloudstack.org/',
authorName: 'Apache CloudStack',
authorEmail: 'dev@cloudstack.apache.org'
};
}(cloudStack));

BIN
ui/plugins/quota/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -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.
*/
.quota-tariff-edit {
float: right;
}
.quota-bold {
font-size: 12px;
font-weight: bold;
color: #6D6D6D;
}
.quota-text {
font-size: 11px;
color: #282828;
}
.quota-element {
margin: 5px;
margin-left: 13px;
}
.quota-input {
background: #F6F6F6;
border: 1px solid #AFAFAF;
border-radius: 4px;
}
.quota-button {
border:1px solid #0077c7; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px;
font-size:11px;
padding: 8px;
margin-top: 12px;
text-shadow: -1px -1px 0 rgba(0,0,0,0.3);font-weight:bold; color: #FFFFFF;
background-color: #0099FF; background-image: -webkit-gradient(linear, left top, left bottom, from(#0099FF), to(#004FF7));
background-image: -webkit-linear-gradient(top, #0099FF, #004FF7);
background-image: -moz-linear-gradient(top, #0099FF, #004FF7);
background-image: -ms-linear-gradient(top, #0099FF, #004FF7);
background-image: -o-linear-gradient(top, #0099FF, #004FF7);
background-image: linear-gradient(to bottom, #0099FF, #004FF7);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#0099FF, endColorstr=#004FF7);
}
.quota-button:hover {
border:1px solid #005c99;
background-color: #0039B3; background-image: -webkit-gradient(linear, left top, left bottom, from(#0039B3), to(#004FF7));
background-image: -webkit-linear-gradient(top, #0039B3, #004FF7);
background-image: -moz-linear-gradient(top, #0039B3, #004FF7);
background-image: -ms-linear-gradient(top, #0039B3, #004FF7);
background-image: -o-linear-gradient(top, #0039B3, #004FF7);
background-image: linear-gradient(to bottom, #0039B3, #004FF7);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=#0039B3, endColorstr=#004FF7);
}

726
ui/plugins/quota/quota.js Normal file
View File

@ -0,0 +1,726 @@
// 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.
var g_quotaCurrency = '';
(function (cloudStack) {
cloudStack.plugins.quota = function(plugin) {
plugin.ui.addSection({
id: 'quota',
title: 'Quota',
showOnNavigation: true,
preFilter: function(args) {
return true;
},
show: function() {
var $quotaView = $('<div class="quota-container detail-view ui-tabs ui-widget ui-widget-content ui-corner-all">');
var $toolbar = $('<div class="toolbar"><div class="section-switcher reduced-hide"><div class="section-select"><label>Quota Management</label></div></div></div>');
var $tabs = $('<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">');
var $tabViews = [];
var sections = [{'id': 'quota-statement',
'name': 'Statement',
'render': function ($node) {
var statementView = $('<div class="details quota-text" style="padding: 10px">');
var generatedStatement = $('<div class="quota-generated-statement">');
var generatedBalanceStatement = $('<div class="quota-generated-balance-statement">');
var statementForm = $('<div class="quota-statement select-container">');
var domainDropdown = $('<div class="quota-domain-dropdown quota-element">');
var accountDropdown = $('<div class="quota-account-dropdown quota-element">');
var startDateInput = $('<input type="text" class="quota-input" id="quota-statement-start-date" style="margin-left: 13px">');
var endDateInput = $('<input type="text" class="quota-input" id="quota-statement-end-date" style="margin-left: 13px">');
var generateStatementButton = $('<button class="quota-element quota-button" id="quota-get-statement-button">').html("Generate Statement");
startDateInput.datepicker({
defaultDate: new Date(),
changeMonth: true,
dateFormat: "yy-mm-dd",
onClose: function (selectedDate) {
endDateInput.datepicker("option", "minDate", selectedDate);
}
});
endDateInput.datepicker({
defaultDate: new Date(),
changeMonth: true,
dateFormat: "yy-mm-dd",
onClose: function (selectedDate) {
startDateInput.datepicker("option", "maxDate", selectedDate);
}
});
generateStatementButton.click(function() {
var domainId = g_domainid;
if (isAdmin() || isDomainAdmin()) {
domainId = domainDropdown.find("select :selected").val();
}
var accountId = accountDropdown.find("select :selected").val();
var account = accountDropdown.find("select :selected").html();
var startDate = startDateInput.val();
var endDate = endDateInput.val();
if (!domainId || !account) {
generatedStatement.empty();
$("<br><hr>").appendTo(generatedStatement);
$("<p class='quota-text'>").html("Error: Please select valid domain and account").appendTo(generatedStatement);
return;
}
if (!startDate || !endDate) {
generatedStatement.empty();
$("<br><hr>").appendTo(generatedStatement);
$("<p class='quota-text'>").html("Error: Please select start and end dates").appendTo(generatedStatement);
return;
}
$.ajax({
url: createURL('quotaStatement'),
data: {
domainid: domainId,
accountid: accountId,
account: account,
startdate: startDate,
enddate: endDate
},
success: function(json) {
var statement = json.quotastatementresponse.statement;
var totalQuota = statement.totalquota;
var quotaUsage = statement.quotausage;
if (statement.currency) {
g_quotaCurrency = statement.currency.trim() + ' ';
}
generatedStatement.empty();
$("<hr>").appendTo(generatedStatement);
if (quotaUsage.length < 1) {
return;
}
$('<h1 class="quota-bold">').html("<br>Usage Statement").appendTo(generatedStatement);
var statementTable = $('<table>');
statementTable.appendTo($('<div class="data-table">').appendTo(generatedStatement));
var statementTableHead = $('<tr>');
$('<th>').html('Usage Description').appendTo(statementTableHead);
$('<th>').html('Usage Unit').appendTo(statementTableHead);
$('<th>').html('Amount').appendTo(statementTableHead);
statementTableHead.appendTo($('<thead>').appendTo(statementTable));
// Add total usage
quotaUsage.push({type: '', unit: '', name: '<span class="quota-bold">Total Quota Usage</span>', quota: totalQuota, });
var statementTableBody = $('<tbody>');
for (var i = 0; i < quotaUsage.length; i++) {
var statementTableBodyRow = $('<tr>');
if (i % 2 == 0) {
statementTableBodyRow.addClass('even');
} else {
statementTableBodyRow.addClass('odd');
}
$('<td>').html(quotaUsage[i].name).appendTo(statementTableBodyRow);
$('<td>').html(quotaUsage[i].unit).appendTo(statementTableBodyRow);
$('<td>').html(g_quotaCurrency + quotaUsage[i].quota).appendTo(statementTableBodyRow);
statementTableBodyRow.appendTo(statementTableBody);
}
statementTableBody.appendTo(statementTable);
},
error: function(data) {
generatedStatement.empty();
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
$.ajax({
url: createURL('quotaBalance'),
data: {
domainid: domainId,
account: account,
startdate: startDate,
enddate: endDate
},
success: function(json) {
var statement = json.quotabalanceresponse.balance;
var credits = statement.credits;
var startBalance = statement.startquota;
var startBalanceDate = statement.startdate;
var endBalance = statement.endquota;
var endBalanceDate = statement.enddate;
if (statement.currency) {
g_quotaCurrency = statement.currency.trim() + ' ';
}
generatedBalanceStatement.empty();
$("<br>").appendTo(generatedBalanceStatement);
$('<p class="quota-bold">').html("<br>Quota Balance Statement").appendTo(generatedBalanceStatement);
var statementTable = $('<table>');
statementTable.appendTo($('<div class="data-table">').appendTo(generatedBalanceStatement));
var statementTableHead = $('<tr>');
$('<th>').html('Description').appendTo(statementTableHead);
$('<th>').html("Date").appendTo(statementTableHead);
$('<th>').html('Amount').appendTo(statementTableHead);
statementTableHead.appendTo($('<thead>').appendTo(statementTable));
var statementTableBody = $('<tbody>');
if (typeof startBalance !== 'undefined') {
var statementTableBodyRow = $('<tr>');
$('<td>').html("Start Quota Balance").appendTo(statementTableBodyRow);
$('<td>').html(startBalanceDate).appendTo(statementTableBodyRow);
$('<td>').html(g_quotaCurrency + startBalance).appendTo(statementTableBodyRow);
statementTableBodyRow.appendTo(statementTableBody);
}
for (var i = 0; i < credits.length; i++) {
var statementTableBodyRow = $('<tr>');
if (i % 2 == 0) {
statementTableBodyRow.addClass('even');
} else {
statementTableBodyRow.addClass('odd');
}
$('<td>').html("Credit").appendTo(statementTableBodyRow);
$('<td>').html(credits[i].updated_on).appendTo(statementTableBodyRow);
$('<td>').html(g_quotaCurrency + credits[i].credits).appendTo(statementTableBodyRow);
statementTableBodyRow.appendTo(statementTableBody);
}
if (typeof endBalance !== 'undefined') {
var statementTableBodyRow = $('<tr>');
$('<td class="quota-bold">').html("Final Quota Balance").appendTo(statementTableBodyRow);
$('<td>').html(endBalanceDate).appendTo(statementTableBodyRow);
$('<td>').html(g_quotaCurrency + endBalance).appendTo(statementTableBodyRow);
statementTableBodyRow.appendTo(statementTableBody);
}
statementTableBody.appendTo(statementTable);
},
error: function(data) {
generatedBalanceStatement.empty();
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
});
domainDropdown.appendTo(statementForm);
accountDropdown.appendTo(statementForm);
$('<p class="quota-bold quota-element">').html('Start Date').appendTo(statementForm);
startDateInput.appendTo(statementForm);
$('<p class="quota-bold quota-element">').html('End Date').appendTo(statementForm);
endDateInput.appendTo(statementForm);
$('<br>').appendTo(statementForm);
generateStatementButton.appendTo(statementForm);
var accountLister = function(selectedDomainId) {
var data = {listall: true};
if (selectedDomainId) {
data.domainid = selectedDomainId;
}
$.ajax({
url: createURL('listAccounts'),
data : data,
success: function(json) {
accountDropdown.empty();
$('<p class="quota-bold" style="margin-bottom: 5px">').html('Account').appendTo(accountDropdown);
if (json.hasOwnProperty('listaccountsresponse') && json.listaccountsresponse.hasOwnProperty('account')) {
var accounts = json.listaccountsresponse.account;
var dropdown = $('<select class="quota-input">');
for (var i = 0; i < accounts.length; i++) {
$('<option value="' + accounts[i].id + '">' + accounts[i].name + '</option>').appendTo(dropdown);
}
dropdown.appendTo(accountDropdown);
} else {
$('<span class="quota-text">No accounts found in the selected domain</span>').appendTo(accountDropdown);
}
},
error: function(data) {
}
});
};
var domainLister = function() {
$.ajax({
url: createURL('listDomains'),
data: {
listall: true
},
success: function(json) {
var domains = json.listdomainsresponse.domain;
$('<p class="quota-bold" style="margin-bottom: 5px">').html('Domain').appendTo(domainDropdown);
var dropdown = $('<select class="quota-input">');
if (domains.length > 1) {
$('<option value="">--- Select Domain ---</option>').appendTo(dropdown);
}
for (var i = 0; i < domains.length; i++) {
$('<option value="' + domains[i].id + '">' + domains[i].name + '</option>').appendTo(dropdown);
}
dropdown.appendTo(domainDropdown);
dropdown.change(function() {
var selectedDomainId = $(this).find(':selected').val();
if (!selectedDomainId) {
accountDropdown.empty();
return;
}
accountLister(selectedDomainId);
});
dropdown.change();
},
error: function(data) {
}
});
};
if (isAdmin() || isDomainAdmin()) {
domainLister();
} else {
accountLister(g_domainid);
}
statementForm.appendTo(statementView);
generatedStatement.appendTo(statementView);
generatedBalanceStatement.appendTo(statementView);
statementView.appendTo($node);
}
},
{
'id': 'quota-tariff',
'name' : 'Tariff Plan',
'render': function($node) {
var tariffView = $('<div class="details quota-text" style="margin-top: -30px">');
var tariffViewList = $('<div class="view list-view">');
tariffViewList.appendTo(tariffView);
var renderDateForm = function(lastDate) {
var startDateInput = $('<input type="text" class="quota-input" id="quota-tariff-startdate">');
if (lastDate) {
startDateInput.val(lastDate);
}
startDateInput.datepicker({
defaultDate: new Date(),
changeMonth: true,
dateFormat: "yy-mm-dd",
onClose: function (selectedDate) {
if (!selectedDate) {
return;
}
tariffViewList.empty();
renderDateForm(selectedDate);
renderTariffTable(selectedDate);
}
});
startDateInput.appendTo($('<br><span class="quota-element quota-bold">').html('Effective Date ').appendTo(tariffViewList));
};
var renderTariffTable = function(startDate) {
var tariffTable = $('<table style="margin-top: 15px">');
tariffTable.appendTo(tariffViewList);
var tariffTableHead = $('<tr>');
$('<th>').html(_l('label.usage.type')).appendTo(tariffTableHead);
$('<th>').html(_l('label.usage.unit')).appendTo(tariffTableHead);
$('<th>').html(_l('label.quota.value')).appendTo(tariffTableHead);
$('<th>').html(_l('label.quota.description')).appendTo(tariffTableHead);
tariffTableHead.appendTo($('<thead>').appendTo(tariffTable));
$.ajax({
url: createURL('quotaTariffList'),
data: {startdate: startDate },
success: function(json) {
var items = json.quotatarifflistresponse.quotatariff;
if (items.constructor === Array && items[0].currency) {
g_quotaCurrency = items[0].currency.trim() + ' ';
}
var tariffTableBody = $('<tbody>');
for (var i = 0; i < items.length; i++) {
var tariffTableBodyRow = $('<tr>');
if (i % 2 == 0) {
tariffTableBodyRow.addClass('even');
} else {
tariffTableBodyRow.addClass('odd');
}
$('<td>').html(items[i].usageName).appendTo(tariffTableBodyRow);
$('<td>').html(items[i].usageUnit).appendTo(tariffTableBodyRow);
if (isAdmin()) {
var valueCell = $('<td class="value actions">');
var value = $('<span class="quota-element">').html(g_quotaCurrency + items[i].tariffValue);
value.appendTo(valueCell);
valueCell.appendTo(tariffTableBodyRow);
var usageType = items[i].usageType;
var editButton = $('<div class="action edit quota-tariff-edit" alt="Change value" title="Change value"><span class="icon">&nbsp;</span></div>');
editButton.appendTo(valueCell);
editButton.attr('id', 'quota-tariff-edit-' + items[i].usageType);
editButton.click(function() {
var usageTypeId = $(this).context.id.replace('quota-tariff-edit-', '');
var updateTariffForm = cloudStack.dialog.createForm({
form: {
title: 'label.quota.configuration',
fields: {
quotaValue: {
label: 'label.quota.value',
validation: {
required: true
}
},
effectiveDate: {
label: 'Effective Date',
validation: {
required: true
}
},
}
},
after: function(args) {
$.ajax({
url: createURL('quotaTariffUpdate'),
data: {
usagetype: usageTypeId,
value: args.data.quotaValue,
startDate: args.data.effectiveDate
},
type: "POST",
success: function(json) {
$('#quota-tariff').click();
},
error: function(data) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
}
});
updateTariffForm.find('input[name=effectiveDate]').datepicker({
defaultDate: new Date(),
changeMonth: true,
dateFormat: "yy-mm-dd",
});
});
} else {
$('<td>').html(g_quotaCurrency + items[i].tariffValue).appendTo(tariffTableBodyRow);
}
$('<td>').html(items[i].description).appendTo(tariffTableBodyRow);
tariffTableBodyRow.appendTo(tariffTableBody);
}
tariffTableBody.appendTo(tariffTable);
},
error: function(data) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
};
renderDateForm();
renderTariffTable();
tariffView.appendTo($node);
}
},
{'id': 'quota-credit',
'name': 'Manage Credits',
'render': function($node) {
var manageCreditView = $('<div class="details quota-text" style="padding: 10px">');
var creditStatement = $('<div class="quota-credit-statement">');
var creditForm = $('<div class="quota-credit">');
var domainDropdown = $('<div class="quota-domain-dropdown quota-element">');
var accountDropdown = $('<div class="quota-account-dropdown quota-element">');
var quotaValueInput = $('<input class="quota-input" type="text" style="margin-left: 12px">');
var quotaThresholdInput = $('<input class="quota-input" type="text" style="margin-left: 12px">');
var quotaThresholdLockCheckbox = $('<input class="quota-input quota-element" type="checkbox" style="margin-left: 12px" checked>');
var addCreditButton = $('<button class="quota-element quota-button" id="quota-add-credit-button">').html("Add Credit");
addCreditButton.click(function() {
if (isAdmin() || isDomainAdmin()) {
domainId = domainDropdown.find("select :selected").val();
} else {
return;
}
var account = accountDropdown.find("select :selected").val();
var quotaValue = quotaValueInput.val();
var quotaThreshold = quotaThresholdInput.val();
var isLockedOptionSelected = quotaThresholdLockCheckbox.is(':checked');
if (!quotaValue || !account) {
creditStatement.empty();
$('<br>').appendTo(creditStatement);
$('<p class="quota-element">').html('Please select domain/account and enter valid credit/debit value').appendTo(creditStatement);
return;
}
$.ajax({
url: createURL('quotaCredits'),
data: {
account: account,
domainid: domainId,
value: quotaValue,
quota_enforce: isLockedOptionSelected,
min_balance: quotaThreshold
},
success: function(json) {
quotaValueInput.val('');
creditStatement.empty();
if (json.quotacreditsresponse.quotacredits.currency) {
g_quotaCurrency = json.quotacreditsresponse.quotacredits.currency.trim() + ' ';
}
$('<hr>').appendTo(creditStatement);
$('<p class="quota-bold">').html('Credit amount ' + g_quotaCurrency + json.quotacreditsresponse.quotacredits.credits + ' added to the account ' + account).appendTo(creditStatement);
$.ajax({
url: createURL('quotaBalance'),
data: {
account: account,
domainid: domainId,
},
success: function(json) {
if (json.hasOwnProperty('quotabalanceresponse') && json.quotabalanceresponse.hasOwnProperty('balance')) {
$('<p class="quota-bold">').html('Current Quota Balance of "' + account + '": ' + g_quotaCurrency + json.quotabalanceresponse.balance.startquota).appendTo(creditStatement);
}
},
error: function(json) {
}
});
},
error: function(json) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(json)
});
}
});
});
domainDropdown.appendTo(creditForm);
accountDropdown.appendTo(creditForm);
$('<p class="quota-bold quota-element">').html('Credit Value').appendTo(creditForm);
quotaValueInput.appendTo(creditForm);
$('<p class="quota-bold quota-element">').html('Account Minimum Threshold').appendTo(creditForm);
quotaThresholdInput.appendTo(creditForm);
$('<br>').appendTo(creditForm);
quotaThresholdLockCheckbox.appendTo(creditForm);
$('<span class="quota-bold">').html('Lock account when quota balance is less than minimum threshold').appendTo(creditForm);
$('<br>').appendTo(creditForm);
addCreditButton.appendTo(creditForm);
var accountLister = function(selectedDomainId) {
var data = {listall: true};
if (selectedDomainId) {
data.domainid = selectedDomainId;
}
$.ajax({
url: createURL('listAccounts'),
data : data,
success: function(json) {
accountDropdown.empty();
$('<p class="quota-bold">').html('Account').appendTo(accountDropdown);
if (json.hasOwnProperty('listaccountsresponse') && json.listaccountsresponse.hasOwnProperty('account')) {
var accounts = json.listaccountsresponse.account;
var dropdown = $('<select class="quota-input">');
for (var i = 0; i < accounts.length; i++) {
$('<option value="' + accounts[i].name + '">' + accounts[i].name + '</option>').appendTo(dropdown);
}
dropdown.appendTo(accountDropdown);
} else {
$('<span>No accounts found in the selected domain</span>').appendTo(accountDropdown);
}
},
error: function(data) {
// TODO: Add error dialog?
}
});
};
var domainLister = function() {
$.ajax({
url: createURL('listDomains'),
data: {
listall: true
},
success: function(json) {
$('<p class="quota-bold">').html('Domain').appendTo(domainDropdown);
var domains = json.listdomainsresponse.domain;
var dropdown = $('<select class="quota-input">');
if (domains.length > 1) {
$('<option value="">--- Select Domain ---</option>').appendTo(dropdown);
}
for (var i = 0; i < domains.length; i++) {
$('<option value="' + domains[i].id + '">' + domains[i].name + '</option>').appendTo(dropdown);
}
dropdown.appendTo(domainDropdown);
dropdown.change(function() {
var selectedDomainId = $(this).find(':selected').val();
if (!selectedDomainId) {
accountDropdown.empty();
return;
}
accountLister(selectedDomainId);
});
dropdown.change();
},
error: function(data) {
// FIXME: what to do on error?
}
});
};
domainLister();
creditForm.appendTo(manageCreditView);
creditStatement.appendTo(manageCreditView);
manageCreditView.appendTo($node);
}
},
{'id': 'quota-email',
'name': 'Email Templates',
'render': function($node) {
var manageTemplatesView = $('<div class="details quota-text" style="padding: 10px">');
var emailTemplateForm = $('<div class="quota-email-form">');
var templateDropdown = $('<div class="quota-template-dropdown">');
var templateOptions = $('<select class="quota-input" style="margin: 0px 0px 5px 11px"><option value="QUOTA_LOW">Template for accounts with low quota balance</option><option value="QUOTA_EMPTY">Template for accounts with no quota balance that will be locked</option><option value="QUOTA_UNLOCK_ACCOUNT">Template for accounts with enough credits getting unlocked</option><option value="QUOTA_STATEMENT">Template for quota statement</option><</select>');
$('<p class="quota-bold quota-element">').html('Email Template').appendTo(templateDropdown);
templateOptions.appendTo(templateDropdown);
//templateOptions.appendTo($('<p class="quota-bold quota-element">Email Template</p>').appendTo(templateDropdown));
var templateSubjectTextArea = $('<textarea id="quota-template-subjectarea" class="quota-input" style="margin: 0px 0px 10px 12px; font-size: 12px">');
var templateBodyTextArea = $('<textarea id="quota-template-bodyarea" class="quota-input" style="height: 250px; margin: 0px 0px 10px 12px; font-size: 12px"></textarea>');
var saveTemplateButton = $('<button class="quota-button quota-element" id="quota-save-template-button">').html("Save Template");
templateOptions.change(function() {
var templateName = $(this).find(':selected').val();
templateSubjectTextArea.val('');
templateBodyTextArea.val('');
$.ajax({
url: createURL('quotaEmailTemplateList'),
data: {
templatetype: templateName
},
success: function(json) {
if (!json.hasOwnProperty('quotaemailtemplatelistresponse') || !json.quotaemailtemplatelistresponse.hasOwnProperty('quotaemailtemplate')) {
return;
}
var template = json.quotaemailtemplatelistresponse.quotaemailtemplate[0];
templateSubjectTextArea.val(template.templatesubject.replace(/\\n/g, '\n').replace(/\\"/g, '"').replace(/<br>/g, '\n'));
templateBodyTextArea.val(template.templatebody.replace(/\\n/g, '\n').replace(/\\"/g, '"').replace(/<br>/g, '\n'));
},
error: function(data) {
}
});
});
templateOptions.change();
saveTemplateButton.click(function() {
var templateName = templateOptions.find(':selected').val();
var templateSubject = templateSubjectTextArea.val().replace(/\n/g, '<br>');
var templateBody = templateBodyTextArea.val().replace(/\n/g, '<br>');
$.ajax({
url: createURL('quotaEmailTemplateUpdate'),
type: "POST",
data: {
templatetype: templateName,
templatesubject: templateSubject,
templatebody: unescape(templateBody),
},
success: function(json) {
templateOptions.change();
},
error: function(data) {
//handle error here
}
});
});
templateDropdown.appendTo(emailTemplateForm);
$('<p class="quota-bold quota-element">').html('Email Template Subject').appendTo(emailTemplateForm);
templateSubjectTextArea.appendTo(emailTemplateForm);
$('<p class="quota-bold quota-element">').html('Email Template Body').appendTo(emailTemplateForm);
templateBodyTextArea.appendTo(emailTemplateForm);
saveTemplateButton.appendTo(emailTemplateForm);
$('<hr>').appendTo(emailTemplateForm);
$('<p>').html("These options can be used in template as ${variable}: quotaBalance, quotaUsage, accountName, accountID, accountUsers, domainName, domainID").appendTo(emailTemplateForm);
emailTemplateForm.appendTo(manageTemplatesView);
manageTemplatesView.appendTo($node);
}
}];
if (isAdmin()) {
} else if (isDomainAdmin()) {
sections = $.grep(sections, function(item) {
return ['quota-credit', 'quota-email'].indexOf(item.id) < 0;
});
} else {
sections = $.grep(sections, function(item) {
return ['quota-credit', 'quota-email'].indexOf(item.id) < 0;
});
}
for (idx in sections) {
var tabLi = $('<li detail-view-tab="true" class="first ui-state-default ui-corner-top"><a href="#">' + sections[idx].name+ '</a></li>');
var tabView = $('<div class="detail-group ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">');
tabLi.attr('id', sections[idx].id);
tabView.attr('id', 'details-tab-' + sections[idx].id);
tabLi.click(function() {
var tabIdx = 0;
for (sidx in sections) {
$('#' + sections[sidx].id).removeClass('ui-tabs-selected ui-state-active');
$('#details-tab-' + sections[sidx].id).addClass('ui-tabs-hide');
$('#details-tab-' + sections[sidx].id).empty();
if (sections[sidx].id === $(this).context.id) {
tabIdx = sidx;
}
}
$(this).addClass('ui-tabs-selected ui-state-active');
var tabDetails = $('#details-tab-' + $(this).context.id);
tabDetails.removeClass('ui-tabs-hide');
sections[tabIdx].render(tabDetails);
});
if (idx == 0) {
tabLi.addClass('ui-tabs-selected ui-state-active');
tabView.removeClass('ui-tabs-hide');
sections[idx].render(tabView);
}
tabLi.appendTo($tabs);
$tabViews.push(tabView);
}
$toolbar.appendTo($quotaView);
$tabs.appendTo($quotaView);
for (idx in $tabViews) {
$tabViews[idx].appendTo($quotaView);
}
return $quotaView;
}
});
};
}(cloudStack));

View File

@ -19,6 +19,7 @@
plugin.ui.addSection({
id: 'testPlugin',
title: 'TestPlugin',
showOnNavigation: true,
preFilter: function(args) {
return isAdmin();
},

View File

@ -31,9 +31,12 @@
sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "regions", "affinityGroups"];
}
if (cloudStack.plugins.length) {
sections.push('plugins');
}
$.each(cloudStack.plugins, function(idx, plugin) {
if (cloudStack.sections.hasOwnProperty(plugin) && !cloudStack.sections[plugin].showOnNavigation) {
sections.push('plugins');
return false;
}
});
return sections;
},
@ -304,10 +307,11 @@
},
error: function(XMLHttpRequest) {
var errorMsg = parseXMLHttpResponse(XMLHttpRequest);
if (errorMsg.length == 0 && XMLHttpRequest.status == 0)
if (errorMsg.length == 0 && XMLHttpRequest.status == 0) {
errorMsg = dictionary['error.unable.to.reach.management.server'];
else
} else if (errorMsg.indexOf('Failed to authenticate') === 0) {
errorMsg = _l('error.invalid.username.password'); //override error message
}
args.response.error(errorMsg);
},
beforeSend: function(XMLHttpResponse) {

View File

@ -61,7 +61,7 @@
);
}
if (args.isPlugin) {
if (args.isPlugin && !args.showOnNavigation) {
$li.hide();
}
@ -88,7 +88,7 @@
return $(this).hasClass(sectionID);
});
var data = args.sections[sectionID];
var isPlugin = data.isPlugin;
var isPlugin = data.isPlugin && !data.showOnNavigation;
data.$browser = $browser;

View File

@ -35,10 +35,26 @@
<artifactId>cloud-engine-components-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-framework-quota</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>commons-daemon</groupId>
<artifactId>commons-daemon</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${cs.mysql.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
@ -49,6 +65,11 @@
<version>2.4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${cs.commons-lang3.version}</version>
</dependency>
</dependencies>
<build>
<resources>

View File

@ -17,36 +17,38 @@
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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" 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/tx
http://www.springframework.org/schema/tx/spring-tx-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">
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.cloud.usage, com.cloud.event.dao, com.cloud.user.dao, com.cloud.configuration.dao, com.cloud.alert.dao, com.cloud.domain.dao, org.apache.cloudstack.framework.config.dao">
</context:component-scan>
<!--
@DB support
-->
<bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
<context:annotation-config />
<context:component-scan
base-package="com.cloud.usage, com.cloud.event.dao, com.cloud.user.dao, com.cloud.configuration.dao, com.cloud.alert.dao, com.cloud.domain.dao, org.apache.cloudstack.framework.config.dao,
org.apache.cloudstack.quota.constant, org.apache.cloudstack.quota.dao, org.apache.cloudstack.quota.vo">
</context:component-scan>
<bean id="QuotaManager" class="org.apache.cloudstack.quota.QuotaManagerImpl" />
<bean id="QuotaAlertManager" class="org.apache.cloudstack.quota.QuotaAlertManagerImpl" />
<!-- @DB support -->
<bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
<bean id="instantiatePostProcessor"
class="com.cloud.utils.component.ComponentInstantiationPostProcessor">
<property name="Interceptors">
<list>
<ref bean="transactionContextBuilder" />
</list>
</property>
</bean>
<bean id="ComponentContext" class="com.cloud.utils.component.ComponentContext" />
<bean id="instantiatePostProcessor" class="com.cloud.utils.component.ComponentInstantiationPostProcessor">
<property name="Interceptors">
<list>
<ref bean="transactionContextBuilder" />
</list>
</property>
</bean>
<bean id="ComponentContext" class="com.cloud.utils.component.ComponentContext" />
</beans>

View File

@ -34,10 +34,11 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.quota.QuotaAlertManager;
import org.apache.cloudstack.quota.QuotaManager;
import org.apache.cloudstack.utils.usage.UsageUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.usage.UsageTypes;
@ -144,11 +145,16 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
ConfigurationDao _configDao;
@Inject
private UsageVMSnapshotDao _usageVMSnapshotDao;
@Inject
private QuotaManager _quotaManager;
@Inject
private QuotaAlertManager _alertManager;
private String _version = null;
private final Calendar _jobExecTime = Calendar.getInstance();
private int _aggregationDuration = 0;
private int _sanityCheckInterval = 0;
private boolean _runQuota=false;
String _hostname = null;
int _pid = 0;
TimeZone _usageTimezone = TimeZone.getTimeZone("GMT");;
@ -202,6 +208,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
String execTimeZone = configs.get("usage.execution.timezone");
String aggreagationTimeZone = configs.get("usage.aggregation.timezone");
String sanityCheckInterval = configs.get("usage.sanity.check.interval");
String quotaEnable = configs.get("quota.enable.service");
_runQuota = Boolean.valueOf(quotaEnable == null ? "false" : quotaEnable );
if (sanityCheckInterval != null) {
_sanityCheckInterval = Integer.parseInt(sanityCheckInterval);
}
@ -376,6 +384,26 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna
}
parse(job, startDate, endDate);
if (_runQuota){
try {
_quotaManager.calculateQuotaUsage();
}
catch (Exception e){
s_logger.fatal("Exception received while calculating quota " + e.getMessage());
if (s_logger.isDebugEnabled()){
e.printStackTrace();
}
}
try {
_alertManager.checkAndSendQuotaAlertEmails();
_alertManager.sendMonthlyStatement();
} catch (Exception e) {
s_logger.fatal("Exception received while sending alerts " + e.getMessage());
if (s_logger.isDebugEnabled()) {
e.printStackTrace();
}
}
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Not owner of usage job, skipping...");

View File

@ -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
//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 QuotaAlertManager extends Manager {
public void checkAndSendQuotaAlertEmails();
void sendMonthlyStatement();
}

View File

@ -0,0 +1,471 @@
//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.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.UserVO;
import com.cloud.user.Account.State;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.DateUtil;
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.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.Calendar;
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.getName());
@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;
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);
boolean _smtpDebug = false;
int _pid = 0;
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 = configs.get(QuotaConfig.QuotaEnableEnforcement.key()).equalsIgnoreCase("true");
_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");
}
_pid = Integer.parseInt(System.getProperty("pid"));
return true;
}
@Override
public boolean stop() {
if (s_logger.isInfoEnabled()) {
s_logger.info("Stopping Alert Manager");
}
return true;
}
@SuppressWarnings("deprecation")
@Override
public void sendMonthlyStatement() {
Date now = new Date();
Calendar aCalendar = Calendar.getInstance();
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);
Date firstDateOfPreviousMonth = aCalendar.getTime();
aCalendar.set(Calendar.DATE, aCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);
Date lastDateOfPreviousMonth = aCalendar.getTime(); // actually the first day of this month
//s_logger.info("firstDateOfPreviousMonth" + firstDateOfPreviousMonth + " lastDateOfPreviousMonth" + lastDateOfPreviousMonth);
List<DeferredQuotaEmail> deferredQuotaEmailList = new ArrayList<DeferredQuotaEmail>();
for (final QuotaAccountVO quotaAccount : _quotaAcc.listAll()) {
if (quotaAccount.getQuotaBalance() == null) continue; // no quota usage for this account ever, ignore
Date lastStatementDate = quotaAccount.getLastStatementDate();
if (now.getDate() < 6) {
AccountVO account = _accountDao.findById(quotaAccount.getId());
if (lastStatementDate == null) {
BigDecimal quotaUsage = _quotaUsage.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, firstDateOfPreviousMonth, lastDateOfPreviousMonth);
s_logger.info("For account=" + quotaAccount.getId() + ", quota used = " + quotaUsage);
// send statement
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, quotaUsage, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT));
} else if (getDifferenceDays(lastStatementDate, new Date()) < 7) {
s_logger.debug("For " + quotaAccount.getId() + " the statement has been sent recently");
} else {
BigDecimal quotaUsage = _quotaUsage.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, firstDateOfPreviousMonth, lastDateOfPreviousMonth);
s_logger.info("For account=" + quotaAccount.getId() + ", quota used = " + quotaUsage);
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, quotaUsage, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT));
}
} else {
s_logger.info("For " + quotaAccount.getId() + " it is already more than " + getDifferenceDays(lastStatementDate, new Date()) + " days, will send statement in next cycle");
}
}
for (DeferredQuotaEmail emailToBeSent : deferredQuotaEmailList) {
s_logger.debug("Attempting to send quota STATEMENT email to users of account: " + emailToBeSent.getAccount().getAccountName());
sendQuotaAlert(emailToBeSent);
}
}
@Override
public void checkAndSendQuotaAlertEmails() {
s_logger.info("Running checkAndSendQuotaAlertEmails");
List<DeferredQuotaEmail> deferredQuotaEmailList = new ArrayList<DeferredQuotaEmail>();
final BigDecimal zeroBalance = new BigDecimal(0);
for (final QuotaAccountVO quotaAccount : _quotaAcc.listAll()) {
s_logger.info("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());
// s_logger.info("Check id " + account.getId() + " bal="+ accountBalance + " alertDate"+ alertDate + " diff" + getDifferenceDays(alertDate, new Date()));
if (accountBalance.compareTo(zeroBalance) <= 0) {
if (_lockAccountEnforcement && (lockable == 1)) {
if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) {
lockAccount(account.getId());
}
}
if (alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1)) {
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)) {
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW));
}
}
}
}
for (DeferredQuotaEmail emailToBeSent : deferredQuotaEmailList) {
s_logger.debug("Attempting to send quota alert email to users of account: " + emailToBeSent.getAccount().getAccountName());
sendQuotaAlert(emailToBeSent);
}
}
private 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());
}
// s_logger.info("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();
} 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));
}
} 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()));
}
}
class DeferredQuotaEmail {
AccountVO account;
QuotaAccountVO quotaAccount;
QuotaConfig.QuotaEmailTemplateTypes emailTemplateType;
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 QuotaConfig.QuotaEmailTemplateTypes getEmailTemplateType() {
return emailTemplateType;
}
public void sentSuccessfully() {
if (emailTemplateType == QuotaEmailTemplateTypes.QUOTA_STATEMENT) {
quotaAccount.setLastStatementDate(new Date());
_quotaAcc.update(quotaAccount.getAccountId(), quotaAccount);
}
else {
quotaAccount.setQuotaAlertDate(new Date());
quotaAccount.setQuotaAlertType(emailTemplateType.ordinal());
_quotaAcc.update(quotaAccount.getAccountId(), quotaAccount);
}
}
};
class EmailQuotaAlert {
private Session _smtpSession;
private final String _smtpHost;
private int _smtpPort = -1;
private boolean _smtpUseAuth = false;
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 (_smtpHost != null) {
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 (smtpUsername != null) {
smtpProps.put("mail.smtps.user", smtpUsername);
}
if ((smtpUsername != null) && (smtpPassword != null)) {
_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) {
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(DateUtil.currentGMTTime().getTime() >> 10));
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();
} else {
throw new CloudRuntimeException("Unable to create smtp session.");
}
}
}
public Date startOfNextDay() {
Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.DATE, 1);
Date dt = c.getTime();
return dt;
}
public static long getDifferenceDays(Date d1, Date d2) {
long diff = d2.getTime() - d1.getTime();
return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
}
protected boolean lockAccount(long accountId) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
boolean success = false;
Account account = _accountDao.findById(accountId);
if (account != null) {
if (account.getState().equals(State.locked)) {
return true; // already locked, no-op
} else if (account.getState().equals(State.enabled)) {
AccountVO acctForUpdate = _accountDao.createForUpdate();
acctForUpdate.setState(State.locked);
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
} else {
if (s_logger.isInfoEnabled()) {
s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
}
}
} else {
s_logger.warn("Failed to lock account " + accountId + ", account not found.");
}
TransactionLegacy.open(opendb).close();
return success;
}
public boolean enableAccount(long accountId) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
boolean success = false;
AccountVO acctForUpdate = _accountDao.createForUpdate();
acctForUpdate.setState(State.enabled);
acctForUpdate.setNeedsCleanup(false);
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
TransactionLegacy.open(opendb).close();
return success;
}
}

View File

@ -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();
}

View File

@ -0,0 +1,465 @@
//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.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.Account.State;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.quota.constant.QuotaTypes;
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
import org.apache.cloudstack.quota.vo.ServiceOfferingVO;
import org.apache.cloudstack.quota.dao.ServiceOfferingDao;
import org.apache.cloudstack.utils.usage.UsageUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
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);
int _pid = 0;
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");
}
_pid = Integer.parseInt(System.getProperty("pid"));
return true;
}
@Override
public boolean stop() {
if (s_logger.isInfoEnabled()) {
s_logger.info("Stopping Quota Manager");
}
return true;
}
@Override
public boolean calculateQuotaUsage() {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
boolean jobResult = false;
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
// get all the active accounts for which there is usage
List<AccountVO> accounts = _accountDao.listAll();
for (AccountVO account : accounts) { // START ACCOUNT
Pair<List<? extends UsageVO>, Integer> usageRecords = null;
List<QuotaUsageVO> quotalistforaccount = new ArrayList<QuotaUsageVO>();
do {
s_logger.info("Account =" + account.getAccountName());
usageRecords = _usageDao.getUsageRecordsPendingQuotaAggregation(account.getAccountId(), account.getDomainId());
s_logger.debug("Usage records found " + usageRecords.second());
for (UsageVO usageRecord : usageRecords.first()) {
BigDecimal aggregationRatio = new BigDecimal(_aggregationDuration).divide(s_minutesInMonth, 8, RoundingMode.HALF_EVEN);
switch (usageRecord.getUsageType()) {
case QuotaTypes.RUNNING_VM:
quotalistforaccount.addAll(updateQuotaRunningVMUsage(usageRecord, aggregationRatio));
break;
case QuotaTypes.ALLOCATED_VM:
quotalistforaccount.add(updateQuotaAllocatedVMUsage(usageRecord, aggregationRatio));
break;
case QuotaTypes.SNAPSHOT:
quotalistforaccount.add(updateQuotaDiskUsage(usageRecord, aggregationRatio, QuotaTypes.SNAPSHOT));
break;
case QuotaTypes.TEMPLATE:
quotalistforaccount.add(updateQuotaDiskUsage(usageRecord, aggregationRatio, QuotaTypes.TEMPLATE));
break;
case QuotaTypes.ISO:
quotalistforaccount.add(updateQuotaDiskUsage(usageRecord, aggregationRatio, QuotaTypes.ISO));
break;
case QuotaTypes.VOLUME:
quotalistforaccount.add(updateQuotaDiskUsage(usageRecord, aggregationRatio, QuotaTypes.VOLUME));
break;
case QuotaTypes.VM_SNAPSHOT:
quotalistforaccount.add(updateQuotaDiskUsage(usageRecord, aggregationRatio, QuotaTypes.VM_SNAPSHOT));
break;
case QuotaTypes.LOAD_BALANCER_POLICY:
quotalistforaccount.add(updateQuotaRaw(usageRecord, aggregationRatio, QuotaTypes.LOAD_BALANCER_POLICY));
break;
case QuotaTypes.PORT_FORWARDING_RULE:
quotalistforaccount.add(updateQuotaRaw(usageRecord, aggregationRatio, QuotaTypes.PORT_FORWARDING_RULE));
break;
case QuotaTypes.IP_ADDRESS:
quotalistforaccount.add(updateQuotaRaw(usageRecord, aggregationRatio, QuotaTypes.IP_ADDRESS));
break;
case QuotaTypes.NETWORK_OFFERING:
quotalistforaccount.add(updateQuotaRaw(usageRecord, aggregationRatio, QuotaTypes.NETWORK_OFFERING));
break;
case QuotaTypes.SECURITY_GROUP:
quotalistforaccount.add(updateQuotaRaw(usageRecord, aggregationRatio, QuotaTypes.SECURITY_GROUP));
break;
case QuotaTypes.VPN_USERS:
quotalistforaccount.add(updateQuotaRaw(usageRecord, aggregationRatio, QuotaTypes.VPN_USERS));
break;
case QuotaTypes.NETWORK_BYTES_RECEIVED:
quotalistforaccount.add(updateQuotaNetwork(usageRecord, QuotaTypes.NETWORK_BYTES_RECEIVED));
break;
case QuotaTypes.NETWORK_BYTES_SENT:
quotalistforaccount.add(updateQuotaNetwork(usageRecord, QuotaTypes.NETWORK_BYTES_SENT));
break;
case QuotaTypes.VM_DISK_IO_READ:
case QuotaTypes.VM_DISK_IO_WRITE:
case QuotaTypes.VM_DISK_BYTES_READ:
case QuotaTypes.VM_DISK_BYTES_WRITE:
default:
break;
}
}
} while ((usageRecords != null) && !usageRecords.first().isEmpty());
// list of quotas for this account
s_logger.info("Quota entries size = " + quotalistforaccount.size() + ", accId" + account.getAccountId() + ", domId" + account.getDomainId());
if (quotalistforaccount.size() > 0) { // balance to be processed
quotalistforaccount.add(new QuotaUsageVO());
Date startDate = quotalistforaccount.get(0).getStartDate();
Date endDate = quotalistforaccount.get(0).getEndDate();
BigDecimal aggrUsage = new BigDecimal(0);
for (QuotaUsageVO entry : quotalistforaccount) {
if (startDate.compareTo(entry.getStartDate()) != 0) {
QuotaBalanceVO lastrealbalanceentry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), startDate);
Date lastbalancedate;
if (lastrealbalanceentry != null) {
lastbalancedate = lastrealbalanceentry.getUpdatedOn();
aggrUsage = aggrUsage.add(lastrealbalanceentry.getCreditBalance());
} else {
lastbalancedate = new Date(0);
}
List<QuotaBalanceVO> creditsrcvd = _quotaBalanceDao.findCreditBalance(account.getAccountId(), account.getDomainId(), lastbalancedate, endDate);
for (QuotaBalanceVO credit : creditsrcvd) {
aggrUsage = aggrUsage.add(credit.getCreditBalance());
}
QuotaBalanceVO newbalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, endDate);
// s_logger.info("Balance entry=" + aggrUsage + " on Date=" + endDate);
_quotaBalanceDao.persist(newbalance);
aggrUsage = new BigDecimal(0);
}
startDate = entry.getStartDate();
endDate = entry.getEndDate();
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
}
// update is quota_accounts
QuotaAccountVO quota_account = _quotaAcc.findById(account.getAccountId());
s_logger.info("Updating quota account bal=" + aggrUsage + " date=" + endDate);
if (quota_account == null) {
quota_account = new QuotaAccountVO(account.getAccountId());
quota_account.setQuotaBalance(aggrUsage);
quota_account.setQuotaBalanceDate(endDate);
_quotaAcc.persist(quota_account);
} else {
quota_account.setQuotaBalance(aggrUsage);
quota_account.setQuotaBalanceDate(endDate);
_quotaAcc.update(account.getAccountId(), quota_account);
}
}// balance processed
} // END ACCOUNT
jobResult = true;
} catch (Exception e) {
s_logger.error("Quota Manager error", e);
e.printStackTrace();
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close();
return jobResult;
}
@DB
private QuotaUsageVO updateQuotaDiskUsage(UsageVO usageRecord, final BigDecimal aggregationRatio, final int quotaType) {
QuotaUsageVO quota_usage = null;
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(quotaType, usageRecord.getEndDate());
if (tariff != null && !tariff.getCurrencyValue().equals(0)) {
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);
// s_logger.info(" No of GB In use = " + noofgbinuse +
// " onehour cost=" + onehourcostpergb);
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), usageRecord.getUsageType(), quotaUsgage,
usageRecord.getStartDate(), usageRecord.getEndDate());
_quotaUsageDao.persist(quota_usage);
}
usageRecord.setQuotaCalculated(1);
_usageDao.persist(usageRecord);
return quota_usage;
}
@DB
private 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;
// s_logger.info(usageRecord.getDescription() + ", " +
// usageRecord.getType() + ", " + usageRecord.getOfferingId() + ", " +
// usageRecord.getVmInstanceId() + ", " + usageRecord.getUsageDisplay()
// + ", aggrR=" + aggregationRatio);
// 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().equals(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.persist(quota_usage);
quotalist.add(quota_usage);
}
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_CLOCK_RATE, usageRecord.getEndDate());
if (tariff != null && !tariff.getCurrencyValue().equals(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.persist(quota_usage);
quotalist.add(quota_usage);
}
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.MEMORY, usageRecord.getEndDate());
if (tariff != null && !tariff.getCurrencyValue().equals(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.persist(quota_usage);
quotalist.add(quota_usage);
}
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.RUNNING_VM, usageRecord.getEndDate());
if (tariff != null && !tariff.getCurrencyValue().equals(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.persist(quota_usage);
quotalist.add(quota_usage);
}
usageRecord.setQuotaCalculated(1);
_usageDao.persist(usageRecord);
return quotalist;
}
@DB
private QuotaUsageVO updateQuotaAllocatedVMUsage(UsageVO usageRecord, final BigDecimal aggregationRatio) {
QuotaUsageVO quota_usage = null;
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.ALLOCATED_VM, usageRecord.getEndDate());
if (tariff != null && !tariff.getCurrencyValue().equals(0)) {
BigDecimal vmusage;
BigDecimal onehourcostforvmusage;
onehourcostforvmusage = tariff.getCurrencyValue().multiply(aggregationRatio);
// s_logger.info("Quotatariff onehourcostforvmusage=" +
// onehourcostforvmusage);
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.persist(quota_usage);
}
usageRecord.setQuotaCalculated(1);
_usageDao.persist(usageRecord);
return quota_usage;
}
@DB
private QuotaUsageVO updateQuotaRaw(UsageVO usageRecord, final BigDecimal aggregationRatio, final int ruleType) {
QuotaUsageVO quota_usage = null;
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(ruleType, usageRecord.getEndDate());
if (tariff != null && !tariff.getCurrencyValue().equals(0)) {
BigDecimal ruleusage;
BigDecimal onehourcost;
onehourcost = tariff.getCurrencyValue().multiply(aggregationRatio);
// s_logger.info("Quotatariff onehourcost=" + onehourcost);
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.persist(quota_usage);
}
usageRecord.setQuotaCalculated(1);
_usageDao.persist(usageRecord);
return quota_usage;
}
@DB
private QuotaUsageVO updateQuotaNetwork(UsageVO usageRecord, final int transferType) {
QuotaUsageVO quota_usage = null;
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(transferType, usageRecord.getEndDate());
if (tariff != null && !tariff.getCurrencyValue().equals(0)) {
BigDecimal onegbcost;
BigDecimal rawusageingb;
BigDecimal networkusage;
onegbcost = tariff.getCurrencyValue();
// s_logger.info("Quotatariff onegbcost=" + onegbcost);
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.persist(quota_usage);
}
usageRecord.setQuotaCalculated(1);
_usageDao.persist(usageRecord);
return quota_usage;
}
public Date startOfNextDay() {
Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.DATE, 1);
Date dt = c.getTime();
return dt;
}
protected boolean lockAccount(long accountId) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
boolean success = false;
Account account = _accountDao.findById(accountId);
if (account != null) {
if (account.getState().equals(State.locked)) {
return true; // already locked, no-op
} else if (account.getState().equals(State.enabled)) {
AccountVO acctForUpdate = _accountDao.createForUpdate();
acctForUpdate.setState(State.locked);
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
} else {
if (s_logger.isInfoEnabled()) {
s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
}
}
} else {
s_logger.warn("Failed to lock account " + accountId + ", account not found.");
}
TransactionLegacy.open(opendb).close();
return success;
}
public boolean enableAccount(long accountId) {
final short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
boolean success = false;
AccountVO acctForUpdate = _accountDao.createForUpdate();
acctForUpdate.setState(State.enabled);
acctForUpdate.setNeedsCleanup(false);
success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
TransactionLegacy.open(opendb).close();
return success;
}
}