mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-8592: calculation of quota
This commit is contained in:
parent
1b579afaeb
commit
135af2ceed
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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///////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -783,7 +783,6 @@ listOpenDaylightControllers=1
|
|||
addGloboDnsHost=1
|
||||
|
||||
### Quota Service
|
||||
quotaTypes=15
|
||||
quotaMapping=15
|
||||
quotaEditMapping=15
|
||||
quotaRefresh=15
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -392,6 +392,8 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
|
|||
|
||||
final String sql = str.toString();
|
||||
|
||||
s_logger.debug("Sql = " + sql);
|
||||
|
||||
PreparedStatement pstmt = null;
|
||||
final List<T> result = new ArrayList<T>();
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -27,12 +27,11 @@
|
|||
|
||||
<bean id="QuotaManager" class="org.apache.cloudstack.quota.QuotaManagerImpl" />
|
||||
<bean id="QuotaDBUtils" class="org.apache.cloudstack.quota.QuotaDBUtilsImpl" />
|
||||
<bean id="QuotaConfigurationDao" class="org.apache.cloudstack.quota.dao.QuotaConfigurationDaoImpl" />
|
||||
<bean id="QuotaConfigurationDao" class="org.apache.cloudstack.quota.dao.QuotaMappingDaoImpl" />
|
||||
<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="QuotaSentEmailDao" class="org.apache.cloudstack.quota.dao.QuotaSentEmailsDaoImpl"/>
|
||||
<bean id="QuotaUsageDao" class="org.apache.cloudstack.quota.dao.QuotaUsageDaoImpl"/>
|
||||
<bean id="QuotaJobDao" class="org.apache.cloudstack.quota.dao.QuotaJobDaoImpl"/>
|
||||
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -43,13 +43,13 @@ public class QuotaCreditsCmd extends BaseCmd {
|
|||
|
||||
private static final String s_name = "quotacreditsresponse";
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Account Id for which quota credits need to be added")
|
||||
@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, entityType = DomainResponse.class, description = "Domain for which quota credits need to be added")
|
||||
@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.INTEGER, entityType = DomainResponse.class, description = "Value of the credits to be added+, subtracted-")
|
||||
@Parameter(name = ApiConstants.VALUE, type = CommandType.DOUBLE, required=true, description = "Value of the credits to be added+, subtracted-")
|
||||
private Integer value;
|
||||
|
||||
public String getAccountName() {
|
||||
|
|
|
|||
|
|
@ -25,11 +25,10 @@ import org.apache.log4j.Logger;
|
|||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaCreditsResponse;
|
||||
import org.apache.cloudstack.quota.QuotaConfigurationVO;
|
||||
import org.apache.cloudstack.quota.QuotaMappingVO;
|
||||
import org.apache.cloudstack.quota.QuotaDBUtilsImpl;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
|
@ -45,25 +44,25 @@ public class QuotaEditMappingCmd extends BaseCmd {
|
|||
@Inject
|
||||
QuotaDBUtilsImpl _quotaDBUtils;
|
||||
|
||||
@Parameter(name = "type", type = CommandType.STRING, required = false, description = "Usage type of the resource")
|
||||
private String usageType;
|
||||
@Parameter(name = "type", type = CommandType.INTEGER, required = true, description = "Integer value for the usage type of the resource")
|
||||
private Integer usageType;
|
||||
|
||||
@Parameter(name = "value", type = CommandType.INTEGER, entityType = DomainResponse.class, description = "The quota vale of the resource as per the default unit")
|
||||
private Integer value;
|
||||
@Parameter(name = "value", type = CommandType.DOUBLE, required = true, description = "The quota vale of the resource as per the default unit")
|
||||
private Double value;
|
||||
|
||||
public String getUsageType() {
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(String usageType) {
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Integer value) {
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
|
@ -83,12 +82,12 @@ public class QuotaEditMappingCmd extends BaseCmd {
|
|||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Pair<List<QuotaConfigurationVO>, Integer> result = _quotaDBUtils.editQuotaMapping(this);
|
||||
final Pair<List<QuotaMappingVO>, Integer> result = _quotaDBUtils.editQuotaMapping(this);
|
||||
|
||||
final List<QuotaConfigurationResponse> responses = new ArrayList<QuotaConfigurationResponse>();
|
||||
for (final QuotaConfigurationVO resource : result.first()) {
|
||||
for (final QuotaMappingVO resource : result.first()) {
|
||||
final QuotaConfigurationResponse configurationResponse = _quotaDBUtils.createQuotaConfigurationResponse(resource);
|
||||
configurationResponse.setObjectName("QuotaConfiguration");
|
||||
configurationResponse.setObjectName("QuotaMapping");
|
||||
responses.add(configurationResponse);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ public class QuotaEmailTemplateAddCmd extends BaseListCmd {
|
|||
|
||||
private static final String s_name = "quotaemailtemplateresponse";
|
||||
|
||||
@Parameter(name = "templatename", type = CommandType.STRING, description = "The name of email template")
|
||||
@Parameter(name = "templatename", type = CommandType.STRING, required=true, description = "The name of email template")
|
||||
private String templateName;
|
||||
|
||||
@Parameter(name = "templatetext", type = CommandType.STRING, description = "The text of the email")
|
||||
@Parameter(name = "templatetext", type = CommandType.STRING, required=true, description = "The text of the email")
|
||||
private Long templateText;
|
||||
|
||||
@Parameter(name = "locale", type = CommandType.STRING, description = "The locale of the email text")
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import org.apache.cloudstack.api.BaseListCmd;
|
|||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.QuotaConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.quota.QuotaConfigurationVO;
|
||||
import org.apache.cloudstack.quota.QuotaMappingVO;
|
||||
import org.apache.cloudstack.quota.QuotaDBUtilsImpl;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
|
@ -57,10 +57,10 @@ public class QuotaMapping extends BaseListCmd {
|
|||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Pair<List<QuotaConfigurationVO>, Integer> result = _quotaDBUtils.listConfigurations(this);
|
||||
final Pair<List<QuotaMappingVO>, Integer> result = _quotaDBUtils.listConfigurations(this);
|
||||
|
||||
final List<QuotaConfigurationResponse> responses = new ArrayList<QuotaConfigurationResponse>();
|
||||
for (final QuotaConfigurationVO resource : result.first()) {
|
||||
for (final QuotaMappingVO resource : result.first()) {
|
||||
final QuotaConfigurationResponse configurationResponse = _quotaDBUtils.createQuotaConfigurationResponse(resource);
|
||||
configurationResponse.setObjectName("QuotaConfiguration");
|
||||
responses.add(configurationResponse);
|
||||
|
|
|
|||
|
|
@ -16,11 +16,14 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.QuotaRefreshResponse;
|
||||
import org.apache.cloudstack.quota.QuotaManagerImpl;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
|
|
@ -31,10 +34,18 @@ public class QuotaRefreshCmd extends BaseCmd {
|
|||
|
||||
private static final String s_name = "quotarefreshresponse";
|
||||
|
||||
@Inject
|
||||
QuotaManagerImpl _quotaManager;
|
||||
|
||||
public QuotaRefreshCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public QuotaRefreshCmd(final QuotaManagerImpl quotaManager) {
|
||||
super();
|
||||
_quotaManager = quotaManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
|
|
@ -42,6 +53,7 @@ public class QuotaRefreshCmd extends BaseCmd {
|
|||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
_quotaManager.calculateQuotaUsage();
|
||||
final QuotaRefreshResponse response = new QuotaRefreshResponse("Success");
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ public class QuotaStatementCmd extends BaseListCmd {
|
|||
|
||||
private static final String s_name = "quotastatementresponse";
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Optional, Account Id for which statement needs to be generated")
|
||||
@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, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.")
|
||||
@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;
|
||||
|
||||
public QuotaStatementCmd() {
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
//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.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.response.QuotaConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaTypeResponse;
|
||||
import org.apache.cloudstack.quota.QuotaUsageTypes;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "quotaTypes", responseObject = QuotaConfigurationResponse.class, description = "Lists all Quota type resources", since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaTypesCmd extends BaseListCmd {
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaTypesCmd.class.getName());
|
||||
|
||||
private static final String s_name = "quotatyperesponse";
|
||||
|
||||
public QuotaTypesCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final List<QuotaTypeResponse> responses = QuotaUsageTypes.listQuotaUsageTypes();
|
||||
final ListResponse<QuotaTypeResponse> response = new ListResponse<QuotaTypeResponse>();
|
||||
response.setResponses(responses, responses.size());
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
|
@ -26,7 +28,11 @@ public class QuotaConfigurationResponse extends BaseResponse {
|
|||
|
||||
@SerializedName("usageType")
|
||||
@Param(description = "usageType")
|
||||
private String usageType;
|
||||
private int usageType;
|
||||
|
||||
@SerializedName("usageName")
|
||||
@Param(description = "usageName")
|
||||
private String usageName;
|
||||
|
||||
@SerializedName("usageUnit")
|
||||
@Param(description = "usageUnit")
|
||||
|
|
@ -38,7 +44,7 @@ public class QuotaConfigurationResponse extends BaseResponse {
|
|||
|
||||
@SerializedName("currencyValue")
|
||||
@Param(description = "currencyValue")
|
||||
private int currencyValue;
|
||||
private BigDecimal currencyValue;
|
||||
|
||||
@SerializedName("include")
|
||||
@Param(description = "include")
|
||||
|
|
@ -52,16 +58,24 @@ public class QuotaConfigurationResponse extends BaseResponse {
|
|||
super();
|
||||
}
|
||||
|
||||
public QuotaConfigurationResponse(final String usageType) {
|
||||
public QuotaConfigurationResponse(final int usageType) {
|
||||
super();
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public String getUsageType() {
|
||||
public String getUsageName() {
|
||||
return usageName;
|
||||
}
|
||||
|
||||
public void setUsageName(String usageName) {
|
||||
this.usageName = usageName;
|
||||
}
|
||||
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(String usageType) {
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
|
|
@ -81,11 +95,11 @@ public class QuotaConfigurationResponse extends BaseResponse {
|
|||
this.usageDiscriminator = usageDiscriminator;
|
||||
}
|
||||
|
||||
public int getCurrencyValue() {
|
||||
public BigDecimal getCurrencyValue() {
|
||||
return currencyValue;
|
||||
}
|
||||
|
||||
public void setCurrencyValue(int currencyValue) {
|
||||
public void setCurrencyValue(BigDecimal currencyValue) {
|
||||
this.currencyValue = currencyValue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
//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 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> QuotaPeriodType = new ConfigKey<String>("Advanced", String.class, "quota.period.type", "2",
|
||||
"Quota period type: 1 for every x days, 2 for certain day of the month, 3 for yearly on activation day - default quota usage reporting cycl", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaPeriod = new ConfigKey<String>("Advanced", String.class, "quota.period.config", "15",
|
||||
"The period config in number of days for the quota period type", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaGenerateActivity = new ConfigKey<String>("Advanced", String.class, "quota.activity.generate", "true",
|
||||
"Set true to enable a detailed log of the quota usage, rating and billing activity, on daily basis. Valid values (true, false)", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaEmailRecordOutgoing = new ConfigKey<String>("Advanced", String.class, "quota.email.outgoing.record", "false",
|
||||
"true means all the emails sent out will be stored in local DB, by default it is false", 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 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> QuotaLimitCritical = new ConfigKey<String>("Advanced", String.class, "quota.limit.critical", "80",
|
||||
"A percentage limit for quota when it is reached user is sent and alert.", true);
|
||||
|
||||
public static final ConfigKey<String> QuotaLimitIncremental = new ConfigKey<String>("Advanced", String.class, "quota.limit.increment", "5",
|
||||
"Quota limit incremental", 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", "",
|
||||
"Quota SMTP authorization type", true);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -28,12 +28,13 @@ import com.cloud.utils.component.PluggableService;
|
|||
|
||||
public interface QuotaDBUtils extends PluggableService {
|
||||
|
||||
Pair<List<QuotaConfigurationVO>, Integer> editQuotaMapping(QuotaEditMappingCmd cmd);
|
||||
Pair<List<QuotaMappingVO>, Integer> editQuotaMapping(QuotaEditMappingCmd cmd);
|
||||
|
||||
Pair<List<QuotaConfigurationVO>, Integer> listConfigurations(QuotaMapping cmd);
|
||||
Pair<List<QuotaMappingVO>, Integer> listConfigurations(QuotaMapping cmd);
|
||||
|
||||
QuotaConfigurationResponse createQuotaConfigurationResponse(QuotaConfigurationVO configuration);
|
||||
QuotaConfigurationResponse createQuotaConfigurationResponse(QuotaMappingVO configuration);
|
||||
|
||||
QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Integer amount, Long updatedBy);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -26,7 +27,7 @@ import org.apache.cloudstack.api.command.QuotaEditMappingCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaMapping;
|
||||
import org.apache.cloudstack.api.response.QuotaConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaCreditsResponse;
|
||||
import org.apache.cloudstack.quota.dao.QuotaConfigurationDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaMappingDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaCreditsDao;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
@ -41,14 +42,16 @@ public class QuotaDBUtilsImpl {
|
|||
private static final Logger s_logger = Logger.getLogger(QuotaDBUtilsImpl.class.getName());
|
||||
|
||||
@Inject
|
||||
private QuotaConfigurationDao _quotaConfigurationDao;
|
||||
private QuotaMappingDao _quotaMappingDao;
|
||||
|
||||
@Inject
|
||||
private QuotaCreditsDao _quotaCreditsDao;
|
||||
|
||||
public QuotaConfigurationResponse createQuotaConfigurationResponse(final QuotaConfigurationVO configuration) {
|
||||
|
||||
public QuotaConfigurationResponse createQuotaConfigurationResponse(final QuotaMappingVO configuration) {
|
||||
final QuotaConfigurationResponse response = new QuotaConfigurationResponse();
|
||||
response.setUsageType(configuration.getUsageType());
|
||||
response.setUsageName(configuration.getUsageName());
|
||||
response.setUsageUnit(configuration.getUsageUnit());
|
||||
response.setUsageDiscriminator(configuration.getUsageDiscriminator());
|
||||
response.setCurrencyValue(configuration.getCurrencyValue());
|
||||
|
|
@ -57,28 +60,28 @@ public class QuotaDBUtilsImpl {
|
|||
return response;
|
||||
}
|
||||
|
||||
public Pair<List<QuotaConfigurationVO>, Integer> listConfigurations(final QuotaMapping cmd) {
|
||||
final Pair<List<QuotaConfigurationVO>, Integer> result = _quotaConfigurationDao.searchConfigurations();
|
||||
public Pair<List<QuotaMappingVO>, Integer> listConfigurations(final QuotaMapping cmd) {
|
||||
final Pair<List<QuotaMappingVO>, Integer> result = _quotaMappingDao.listAllMapping();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Pair<List<QuotaConfigurationVO>, Integer> editQuotaMapping(QuotaEditMappingCmd cmd) {
|
||||
String resourceName = cmd.getUsageType();
|
||||
Integer quotaMapping = cmd.getValue();
|
||||
public Pair<List<QuotaMappingVO>, Integer> editQuotaMapping(QuotaEditMappingCmd cmd) {
|
||||
int resourceType = cmd.getUsageType();
|
||||
BigDecimal quotaCost = new BigDecimal(cmd.getValue());
|
||||
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
QuotaConfigurationVO result = _quotaConfigurationDao.findByUsageType(resourceName);
|
||||
QuotaMappingVO result = _quotaMappingDao.findByUsageType(resourceType);
|
||||
if (result == null)
|
||||
throw new InvalidParameterValueException(resourceName);
|
||||
s_logger.info("Old value=" + result.getCurrencyValue() + ", new value = " + quotaMapping + ", for resource =" + resourceName);
|
||||
result.setCurrencyValue(quotaMapping);
|
||||
_quotaConfigurationDao.persist(result);
|
||||
throw new InvalidParameterValueException("Resource type " + resourceType);
|
||||
s_logger.info("Old value=" + result.getCurrencyValue() + ", new value = " + quotaCost + ", for resource =" + resourceType);
|
||||
result.setCurrencyValue(quotaCost);
|
||||
_quotaMappingDao.persist(result);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
final Pair<List<QuotaConfigurationVO>, Integer> result = _quotaConfigurationDao.searchConfigurations();
|
||||
final Pair<List<QuotaMappingVO>, Integer> result = _quotaMappingDao.listAllMapping();
|
||||
TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -97,4 +100,5 @@ public class QuotaDBUtilsImpl {
|
|||
return new QuotaCreditsResponse(result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,184 +0,0 @@
|
|||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
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 org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_job")
|
||||
public class QuotaJobVO implements InternalIdentity {
|
||||
|
||||
private static final long serialVersionUID = 78493278947123981L;
|
||||
|
||||
public static final int JOB_TYPE_RECURRING = 0;
|
||||
public static final int JOB_TYPE_SINGLE = 1;
|
||||
|
||||
public static final int JOB_NOT_SCHEDULED = 0;
|
||||
public static final int JOB_SCHEDULED = 1;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "host")
|
||||
private String host;
|
||||
|
||||
@Column(name = "pid")
|
||||
private Integer pid;
|
||||
|
||||
@Column(name = "job_type")
|
||||
private int jobType;
|
||||
|
||||
@Column(name = "scheduled")
|
||||
private int scheduled;
|
||||
|
||||
@Column(name = "start_millis")
|
||||
private long startMillis;
|
||||
|
||||
@Column(name = "end_millis")
|
||||
private long endMillis;
|
||||
|
||||
@Column(name = "exec_time")
|
||||
private long execTime;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "start_date")
|
||||
private Date startDate;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "end_date")
|
||||
private Date endDate;
|
||||
|
||||
@Column(name = "success")
|
||||
private Boolean success;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "heartbeat")
|
||||
private Date heartbeat;
|
||||
|
||||
public QuotaJobVO() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public Integer getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
public void setPid(Integer pid) {
|
||||
this.pid = pid;
|
||||
}
|
||||
|
||||
public int getJobType() {
|
||||
return jobType;
|
||||
}
|
||||
|
||||
public void setJobType(int jobType) {
|
||||
this.jobType = jobType;
|
||||
}
|
||||
|
||||
public int getScheduled() {
|
||||
return scheduled;
|
||||
}
|
||||
|
||||
public void setScheduled(int scheduled) {
|
||||
this.scheduled = scheduled;
|
||||
}
|
||||
|
||||
public long getStartMillis() {
|
||||
return startMillis;
|
||||
}
|
||||
|
||||
public void setStartMillis(long startMillis) {
|
||||
this.startMillis = startMillis;
|
||||
}
|
||||
|
||||
public long getEndMillis() {
|
||||
return endMillis;
|
||||
}
|
||||
|
||||
public void setEndMillis(long endMillis) {
|
||||
this.endMillis = endMillis;
|
||||
}
|
||||
|
||||
public long getExecTime() {
|
||||
return execTime;
|
||||
}
|
||||
|
||||
public void setExecTime(long execTime) {
|
||||
this.execTime = execTime;
|
||||
}
|
||||
|
||||
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 Boolean getSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(Boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public Date getHeartbeat() {
|
||||
return heartbeat;
|
||||
}
|
||||
|
||||
public void setHeartbeat(Date heartbeat) {
|
||||
this.heartbeat = heartbeat;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,6 @@ import com.cloud.utils.component.PluggableService;
|
|||
|
||||
public interface QuotaManager extends PluggableService {
|
||||
|
||||
public void calculateQuotaUsage(QuotaJobVO job, long startDateMillis, long endDateMillis);
|
||||
public void calculateQuotaUsage();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
|
@ -30,26 +31,45 @@ import org.apache.cloudstack.api.command.QuotaEditMappingCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaEmailTemplateAddCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaRefreshCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTypesCmd;
|
||||
import org.apache.cloudstack.quota.dao.QuotaJobDao;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.quota.dao.QuotaMappingDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.usage.UsageJobVO;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.usage.UsageVO;
|
||||
import com.cloud.usage.dao.UsageDao;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
|
||||
@Component
|
||||
@Local(value = QuotaManager.class)
|
||||
public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
||||
public class QuotaManagerImpl extends ManagerBase implements QuotaManager, Configurable, QuotaConfig, Runnable {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaManagerImpl.class.getName());
|
||||
|
||||
@Inject
|
||||
private QuotaJobDao _quotaJobDao;
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private UsageDao _usageDao;
|
||||
@Inject
|
||||
private QuotaMappingDao _quotaConfigurationDao;
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsageDao;
|
||||
@Inject
|
||||
private ServiceOfferingDao _serviceOfferingDao;
|
||||
|
||||
String _hostname = null;
|
||||
int _pid = 0;
|
||||
TimeZone _usageTimezone = TimeZone.getTimeZone("GMT");
|
||||
static BigDecimal s_hoursInMonth = new BigDecimal(30.00 * 24.00);
|
||||
static BigDecimal s_gb = new BigDecimal(1024 * 1024 * 1024);
|
||||
|
||||
public QuotaManagerImpl() {
|
||||
super();
|
||||
|
|
@ -58,7 +78,6 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
|||
@Override
|
||||
public List<Class<?>> getCommands() {
|
||||
final List<Class<?>> cmdList = new ArrayList<Class<?>>();
|
||||
cmdList.add(QuotaTypesCmd.class);
|
||||
cmdList.add(QuotaMapping.class);
|
||||
cmdList.add(QuotaCreditsCmd.class);
|
||||
cmdList.add(QuotaEmailTemplateAddCmd.class);
|
||||
|
|
@ -69,54 +88,258 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void calculateQuotaUsage(QuotaJobVO job, long startDateMillis, long endDateMillis) {
|
||||
public String getConfigComponentName() {
|
||||
return "QUOTA-PLUGIN";
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
long timeStart = System.currentTimeMillis();
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] { QuotaPluginEnabled, QuotaPeriodType, QuotaPeriod, QuotaGenerateActivity, QuotaEmailRecordOutgoing, QuotaEnableEnforcement, QuotaCurrencySymbol, QuotaLimitCritical,
|
||||
QuotaLimitIncremental, QuotaSmtpHost, QuotaSmtpTimeout, QuotaSmtpUser, QuotaSmtpPassword, QuotaSmtpPort, QuotaSmtpAuthType };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateQuotaUsage() {
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
if ((endDateMillis == 0) || (endDateMillis > timeStart)) {
|
||||
endDateMillis = timeStart;
|
||||
// get quota mappings
|
||||
final Pair<List<QuotaMappingVO>, Integer> result = _quotaConfigurationDao.listAllMapping();
|
||||
HashMap<Integer, QuotaMappingVO> mapping = new HashMap<Integer, QuotaMappingVO>();
|
||||
for (final QuotaMappingVO resource : result.first()) {
|
||||
s_logger.debug("QuotaConf=" + resource.getDescription());
|
||||
mapping.put(resource.getUsageType(), resource);
|
||||
}
|
||||
|
||||
long lastSuccess = _quotaJobDao.getLastJobSuccessDateMillis();
|
||||
if (lastSuccess != 0) {
|
||||
startDateMillis = lastSuccess + 1; // 1 millisecond after
|
||||
}
|
||||
|
||||
if (startDateMillis >= endDateMillis) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("not parsing usage records since start time mills (" + startDateMillis + ") is on or after end time millis (" + endDateMillis + ")");
|
||||
}
|
||||
|
||||
TransactionLegacy jobUpdateTxn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
jobUpdateTxn.start();
|
||||
// everything seemed to work...set endDate as the last
|
||||
// success date
|
||||
_quotaJobDao.updateJobSuccess(job.getId(), startDateMillis, endDateMillis, System.currentTimeMillis() - timeStart, success);
|
||||
|
||||
// create a new job if this is a recurring job
|
||||
if (job.getJobType() == UsageJobVO.JOB_TYPE_RECURRING) {
|
||||
_quotaJobDao.createNewJob(_hostname, _pid, UsageJobVO.JOB_TYPE_RECURRING);
|
||||
// get all the active accounts for which there is usage
|
||||
List<AccountVO> accounts = _accountDao.listAll();
|
||||
for (AccountVO account : accounts) {
|
||||
s_logger.info("Account =" + account.getAccountName());
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = getUsageRecords(account.getAccountId(), account.getDomainId());
|
||||
s_logger.debug("Usage records found " + usageRecords.second());
|
||||
for (UsageVO usageRecord : usageRecords.first()) {
|
||||
s_logger.info("Type=" + usageRecord.getUsageType());
|
||||
switch (usageRecord.getUsageType()) {
|
||||
case QuotaTypes.RUNNING_VM:
|
||||
updateQuotaRunningVMUsage(usageRecord, mapping);
|
||||
break;
|
||||
case QuotaTypes.ALLOCATED_VM:
|
||||
updateQuotaAllocatedVMUsage(usageRecord, mapping);
|
||||
break;
|
||||
case QuotaTypes.SNAPSHOT:
|
||||
updateQuotaDiskUsage(usageRecord, mapping, QuotaTypes.SNAPSHOT);
|
||||
break;
|
||||
case QuotaTypes.TEMPLATE:
|
||||
updateQuotaDiskUsage(usageRecord, mapping, QuotaTypes.TEMPLATE);
|
||||
break;
|
||||
case QuotaTypes.ISO:
|
||||
updateQuotaDiskUsage(usageRecord, mapping, QuotaTypes.ISO);
|
||||
break;
|
||||
case QuotaTypes.VOLUME:
|
||||
updateQuotaDiskUsage(usageRecord, mapping, QuotaTypes.VOLUME);
|
||||
break;
|
||||
case QuotaTypes.VM_SNAPSHOT:
|
||||
updateQuotaDiskUsage(usageRecord, mapping, QuotaTypes.VM_SNAPSHOT);
|
||||
break;
|
||||
case QuotaTypes.LOAD_BALANCER_POLICY:
|
||||
updateQuotaRaw(usageRecord, mapping, QuotaTypes.LOAD_BALANCER_POLICY);
|
||||
break;
|
||||
case QuotaTypes.PORT_FORWARDING_RULE:
|
||||
updateQuotaRaw(usageRecord, mapping, QuotaTypes.PORT_FORWARDING_RULE);
|
||||
break;
|
||||
case QuotaTypes.IP_ADDRESS:
|
||||
updateQuotaRaw(usageRecord, mapping, QuotaTypes.IP_ADDRESS);
|
||||
break;
|
||||
case QuotaTypes.NETWORK_OFFERING:
|
||||
updateQuotaRaw(usageRecord, mapping, QuotaTypes.NETWORK_OFFERING);
|
||||
break;
|
||||
case QuotaTypes.SECURITY_GROUP:
|
||||
updateQuotaRaw(usageRecord, mapping, QuotaTypes.SECURITY_GROUP);
|
||||
break;
|
||||
case QuotaTypes.VPN_USERS:
|
||||
updateQuotaRaw(usageRecord, mapping, QuotaTypes.VPN_USERS);
|
||||
break;
|
||||
case QuotaTypes.NETWORK_BYTES_RECEIVED:
|
||||
updateQuotaRaw(usageRecord, mapping, QuotaTypes.NETWORK_BYTES_RECEIVED);
|
||||
break;
|
||||
case QuotaTypes.NETWORK_BYTES_SENT:
|
||||
updateQuotaRaw(usageRecord, mapping, 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;
|
||||
}
|
||||
jobUpdateTxn.commit();
|
||||
} finally {
|
||||
jobUpdateTxn.close();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Date startDate = new Date(startDateMillis);
|
||||
Date endDate = new Date(endDateMillis);
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Calculating quota usage for records between " + startDate + " and " + endDate);
|
||||
}
|
||||
|
||||
// get all the accounts from usage db
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Quota Manager error", e);
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
}
|
||||
|
||||
@DB
|
||||
private void updateQuotaDiskUsage(UsageVO usageRecord, HashMap<Integer, QuotaMappingVO> mapping, int quotaType) {
|
||||
if (mapping.get(quotaType) != null) {
|
||||
QuotaUsageVO quota_usage;
|
||||
BigDecimal quotaUsgage;
|
||||
BigDecimal onehourcostpergb;
|
||||
BigDecimal noofgbinuse;
|
||||
s_logger.info(usageRecord.getDescription() + ", " + usageRecord.getType() + ", " + usageRecord.getOfferingId() + ", " + usageRecord.getTemplateId() + ", " + usageRecord.getUsageDisplay());
|
||||
onehourcostpergb = mapping.get(quotaType).getCurrencyValue().divide(s_hoursInMonth, 4, RoundingMode.HALF_EVEN);
|
||||
noofgbinuse = new BigDecimal(usageRecord.getSize()).divide(s_gb, 4, 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.getUsageType(), quotaUsgage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persist(quota_usage);
|
||||
}
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persist(usageRecord);
|
||||
}
|
||||
|
||||
@DB
|
||||
private void updateQuotaRunningVMUsage(UsageVO usageRecord, HashMap<Integer, QuotaMappingVO> mapping) {
|
||||
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());
|
||||
// get service offering details
|
||||
ServiceOfferingVO serviceoffering = findServiceOffering(usageRecord.getVmInstanceId(), usageRecord.getOfferingId());
|
||||
rawusage = new BigDecimal(usageRecord.getRawUsage());
|
||||
|
||||
if (mapping.get(QuotaTypes.CPU_NUMBER) == null) {
|
||||
BigDecimal cpu = new BigDecimal(serviceoffering.getCpu());
|
||||
onehourcostpercpu = mapping.get(QuotaTypes.CPU_NUMBER).getCurrencyValue().divide(s_hoursInMonth, 4, RoundingMode.HALF_EVEN);
|
||||
cpuquotausgage = rawusage.multiply(onehourcostpercpu).multiply(cpu);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), QuotaTypes.CPU_NUMBER, cpuquotausgage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persist(quota_usage);
|
||||
}
|
||||
if (mapping.get(QuotaTypes.CPU_CLOCK_RATE) == null) {
|
||||
BigDecimal speed = new BigDecimal(serviceoffering.getSpeed() / 100.00);
|
||||
onehourcostper100mhz = mapping.get(QuotaTypes.CPU_CLOCK_RATE).getCurrencyValue().divide(s_hoursInMonth, 4, RoundingMode.HALF_EVEN);
|
||||
speedquotausage = rawusage.multiply(onehourcostper100mhz).multiply(speed);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), QuotaTypes.CPU_CLOCK_RATE, speedquotausage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persist(quota_usage);
|
||||
}
|
||||
if (mapping.get(QuotaTypes.MEMORY) == null) {
|
||||
BigDecimal memory = new BigDecimal(serviceoffering.getRamSize());
|
||||
onehourcostper1mb = mapping.get(QuotaTypes.MEMORY).getCurrencyValue().divide(s_hoursInMonth, 4, RoundingMode.HALF_EVEN);
|
||||
memoryquotausage = rawusage.multiply(onehourcostper1mb).multiply(memory);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), QuotaTypes.MEMORY, memoryquotausage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persist(quota_usage);
|
||||
}
|
||||
if (mapping.get(QuotaTypes.RUNNING_VM) == null) {
|
||||
onehourcostforvmusage = mapping.get(QuotaTypes.RUNNING_VM).getCurrencyValue().divide(s_hoursInMonth, 4, RoundingMode.HALF_EVEN);
|
||||
vmusage = rawusage.multiply(onehourcostforvmusage);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), QuotaTypes.RUNNING_VM, vmusage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persist(quota_usage);
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persist(usageRecord);
|
||||
}
|
||||
|
||||
@DB
|
||||
private void updateQuotaAllocatedVMUsage(UsageVO usageRecord, HashMap<Integer, QuotaMappingVO> mapping) {
|
||||
if (mapping.get(QuotaTypes.ALLOCATED_VM) != null) {
|
||||
QuotaUsageVO quota_usage;
|
||||
BigDecimal vmusage;
|
||||
BigDecimal onehourcostforvmusage;
|
||||
s_logger.info(usageRecord.getDescription() + ", " + usageRecord.getType() + ", " + usageRecord.getOfferingId() + ", " + usageRecord.getVmInstanceId() + ", "
|
||||
+ usageRecord.getUsageDisplay());
|
||||
|
||||
onehourcostforvmusage = mapping.get(QuotaTypes.ALLOCATED_VM).getCurrencyValue().divide(s_hoursInMonth, 4, RoundingMode.HALF_EVEN);
|
||||
vmusage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcostforvmusage);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), QuotaTypes.ALLOCATED_VM, vmusage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persist(quota_usage);
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persist(usageRecord);
|
||||
}
|
||||
|
||||
@DB
|
||||
private void updateQuotaRaw(UsageVO usageRecord, HashMap<Integer, QuotaMappingVO> mapping, int ruleType) {
|
||||
if (mapping.get(ruleType) != null) {
|
||||
QuotaUsageVO quota_usage;
|
||||
BigDecimal ruleusage;
|
||||
BigDecimal onehourcost;
|
||||
s_logger.info(usageRecord.getDescription() + ", " + usageRecord.getType() + ", " + usageRecord.getOfferingId() + ", " + usageRecord.getVmInstanceId() + ", "
|
||||
+ usageRecord.getUsageDisplay());
|
||||
|
||||
onehourcost = mapping.get(ruleType).getCurrencyValue().divide(s_hoursInMonth, 4, RoundingMode.HALF_EVEN);
|
||||
ruleusage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcost);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), ruleType, ruleusage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persist(quota_usage);
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persist(usageRecord);
|
||||
}
|
||||
|
||||
@DB
|
||||
private void updateQuotaNetwork(UsageVO usageRecord, HashMap<Integer, QuotaMappingVO> mapping, int transferType) {
|
||||
if (mapping.get(transferType) != null) {
|
||||
QuotaUsageVO quota_usage;
|
||||
BigDecimal onehourcost;
|
||||
BigDecimal rawusageingb;
|
||||
BigDecimal networkusage;
|
||||
s_logger.info(usageRecord.getDescription() + ", " + usageRecord.getType() + ", " + usageRecord.getOfferingId() + ", " + usageRecord.getVmInstanceId() + ", "
|
||||
+ usageRecord.getUsageDisplay());
|
||||
|
||||
onehourcost = mapping.get(transferType).getCurrencyValue().divide(s_hoursInMonth, 4, RoundingMode.HALF_EVEN);
|
||||
rawusageingb = new BigDecimal(usageRecord.getRawUsage()).divide(s_gb, 4, RoundingMode.HALF_EVEN);
|
||||
networkusage = rawusageingb.multiply(onehourcost);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), transferType, networkusage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persist(quota_usage);
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persist(usageRecord);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public Pair<List<? extends UsageVO>, Integer> getUsageRecords(long accountId, long domainId) {
|
||||
s_logger.debug("getting usage records for account: " + accountId + ", domainId: " + domainId);
|
||||
Filter usageFilter = new Filter(UsageVO.class, "id", true, 10000L, null);
|
||||
SearchCriteria<UsageVO> sc = _usageDao.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 = _usageDao.searchAndCountAllRecords(sc, usageFilter);
|
||||
return new Pair<List<? extends UsageVO>, Integer>(usageRecords.first(), usageRecords.second());
|
||||
}
|
||||
|
||||
public ServiceOfferingVO findServiceOffering(Long vmId, long serviceOfferingId) {
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
|
||||
ServiceOfferingVO result;
|
||||
try {
|
||||
result = _serviceOfferingDao.findById(vmId, serviceOfferingId);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
(new ManagedContextRunnable() {
|
||||
@Override
|
||||
protected void runInContext() {
|
||||
calculateQuotaUsage();
|
||||
}
|
||||
}).run();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
|
@ -24,25 +26,8 @@ import javax.persistence.Table;
|
|||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_configuration")
|
||||
public class QuotaConfigurationVO implements InternalIdentity {
|
||||
/**
|
||||
* enable.quota.service: Enable quota service by default all of this
|
||||
* functionality is disabled. quota.period.type : Quota period type: 1 for
|
||||
* every x days, 2 for certain day of the month, 3 for yearly on activation
|
||||
* day - default usage reporting cycle quota.period.config : The value for
|
||||
* the above quota period type quota.activity.generate : Set “Y” to enable a
|
||||
* detailed log of the quota usage, rating and billing activity, on daily
|
||||
* basis. Valid values (“Y”, “N”); record.outgoingEmail: Boolean, yes means
|
||||
* all the emails sent out will be stored in local DB, by default it is no.
|
||||
* quota.enable : enable the usage quota enforcement quota.currencySymbol :
|
||||
* The symbol for the currency in use to measure usage. quota.criticalLimit:
|
||||
* A limit when it is reached user is sent and alert.
|
||||
* quota.incrementalLimit: A incremental limit that is added to
|
||||
* criticalLimit in this increments, when breached a email is send to the
|
||||
* user with details.
|
||||
* */
|
||||
|
||||
@Table(name = "quota_mapping")
|
||||
public class QuotaMappingVO implements InternalIdentity {
|
||||
private static final long serialVersionUID = -7117933766387653203L;
|
||||
|
||||
@Id
|
||||
|
|
@ -50,7 +35,10 @@ public class QuotaConfigurationVO implements InternalIdentity {
|
|||
private Long id;
|
||||
|
||||
@Column(name = "usage_type")
|
||||
private String usageType;
|
||||
private int usageType;
|
||||
|
||||
@Column(name = "usage_name")
|
||||
private String usageName;
|
||||
|
||||
@Column(name = "usage_unit")
|
||||
private String usageUnit;
|
||||
|
|
@ -59,7 +47,7 @@ public class QuotaConfigurationVO implements InternalIdentity {
|
|||
private String usageDiscriminator;
|
||||
|
||||
@Column(name = "currency_value")
|
||||
private int currencyValue;
|
||||
private BigDecimal currencyValue;
|
||||
|
||||
@Column(name = "include")
|
||||
private int include;
|
||||
|
|
@ -67,11 +55,12 @@ public class QuotaConfigurationVO implements InternalIdentity {
|
|||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
public QuotaConfigurationVO() {
|
||||
public QuotaMappingVO() {
|
||||
}
|
||||
|
||||
public QuotaConfigurationVO(final String usagetype, final String usageunit, final String usagediscriminator, final int currencyvalue, final int include, final String description) {
|
||||
public QuotaMappingVO(final int usagetype, final String usagename, final String usageunit, final String usagediscriminator, final BigDecimal currencyvalue, final int include, final String description) {
|
||||
this.usageType = usagetype;
|
||||
this.usageName = usagename;
|
||||
this.usageUnit = usageunit;
|
||||
this.usageDiscriminator = usagediscriminator;
|
||||
this.currencyValue = currencyvalue;
|
||||
|
|
@ -79,14 +68,22 @@ public class QuotaConfigurationVO implements InternalIdentity {
|
|||
this.description = description;
|
||||
}
|
||||
|
||||
public String getUsageType() {
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(String 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;
|
||||
}
|
||||
|
|
@ -103,11 +100,11 @@ public class QuotaConfigurationVO implements InternalIdentity {
|
|||
this.usageDiscriminator = usageDiscriminator;
|
||||
}
|
||||
|
||||
public int getCurrencyValue() {
|
||||
public BigDecimal getCurrencyValue() {
|
||||
return currencyValue;
|
||||
}
|
||||
|
||||
public void setCurrencyValue(int currencyValue) {
|
||||
public void setCurrencyValue(BigDecimal currencyValue) {
|
||||
this.currencyValue = currencyValue;
|
||||
}
|
||||
|
||||
|
|
@ -22,10 +22,10 @@ import java.util.List;
|
|||
import org.apache.cloudstack.api.response.QuotaTypeResponse;
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
|
||||
public class QuotaUsageTypes extends UsageTypes {
|
||||
public static final int CPU_CLOCK_RATE = 24;
|
||||
public static final int CPU_NUMBER = 25;
|
||||
public static final int MEMORY = 26;
|
||||
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;
|
||||
|
||||
public static List<QuotaTypeResponse> responseList = new ArrayList<QuotaTypeResponse>();
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ public class QuotaUsageVO implements InternalIdentity {
|
|||
private Long usageItemId;
|
||||
|
||||
@Column(name = "usage_type")
|
||||
private String usageType;
|
||||
private int usageType;
|
||||
|
||||
@Column(name = "quota_used")
|
||||
private BigDecimal quotaUsed;
|
||||
|
|
@ -58,7 +58,7 @@ public class QuotaUsageVO implements InternalIdentity {
|
|||
public QuotaUsageVO() {
|
||||
}
|
||||
|
||||
public QuotaUsageVO(Long usageItemId, String usageType, BigDecimal quotaUsed, Date startDate, Date endDate) {
|
||||
public QuotaUsageVO(Long usageItemId, int usageType, BigDecimal quotaUsed, Date startDate, Date endDate) {
|
||||
super();
|
||||
this.usageItemId = usageItemId;
|
||||
this.usageType = usageType;
|
||||
|
|
@ -81,11 +81,11 @@ public class QuotaUsageVO implements InternalIdentity {
|
|||
this.usageItemId = usageItemId;
|
||||
}
|
||||
|
||||
public String getUsageType() {
|
||||
public int getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(String usageType) {
|
||||
public void setUsageType(int usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
//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 org.apache.cloudstack.quota.QuotaJobVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface QuotaJobDao extends GenericDao<QuotaJobVO, Long> {
|
||||
Long checkHeartbeat(String hostname, int pid, int aggregationDuration);
|
||||
|
||||
void createNewJob(String hostname, int pid, int jobType);
|
||||
|
||||
QuotaJobVO getLastJob();
|
||||
|
||||
QuotaJobVO getNextImmediateJob();
|
||||
|
||||
long getLastJobSuccessDateMillis();
|
||||
|
||||
Date getLastHeartbeat();
|
||||
|
||||
QuotaJobVO isOwner(String hostname, int pid);
|
||||
|
||||
void updateJobSuccess(Long jobId, long startMillis, long endMillis, long execTime, boolean success);
|
||||
}
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
//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.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.apache.cloudstack.quota.QuotaJobVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Component
|
||||
@Local(value = { QuotaJobDao.class })
|
||||
public class QuotaJobDaoImpl extends GenericDaoBase<QuotaJobVO, Long> implements QuotaJobDao {
|
||||
private static final Logger s_logger = Logger.getLogger(QuotaJobDaoImpl.class.getName());
|
||||
|
||||
private static final String GET_LAST_JOB_SUCCESS_DATE_MILLIS = "SELECT end_millis FROM cloud_usage.usage_job WHERE end_millis > 0 and success = 1 ORDER BY end_millis DESC LIMIT 1";
|
||||
|
||||
@Override
|
||||
public long getLastJobSuccessDateMillis() {
|
||||
TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||
PreparedStatement pstmt = null;
|
||||
String sql = GET_LAST_JOB_SUCCESS_DATE_MILLIS;
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
if (rs.next()) {
|
||||
return rs.getLong(1);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
s_logger.error("error getting last usage job success date", ex);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateJobSuccess(Long jobId, long startMillis, long endMillis, long execTime, boolean success) {
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
txn.start();
|
||||
|
||||
QuotaJobVO job = lockRow(jobId, Boolean.TRUE);
|
||||
QuotaJobVO jobForUpdate = createForUpdate();
|
||||
jobForUpdate.setStartMillis(startMillis);
|
||||
jobForUpdate.setEndMillis(endMillis);
|
||||
jobForUpdate.setExecTime(execTime);
|
||||
jobForUpdate.setStartDate(new Date(startMillis));
|
||||
jobForUpdate.setEndDate(new Date(endMillis));
|
||||
jobForUpdate.setSuccess(success);
|
||||
update(job.getId(), jobForUpdate);
|
||||
|
||||
txn.commit();
|
||||
} catch (Exception ex) {
|
||||
txn.rollback();
|
||||
s_logger.error("error updating job success date", ex);
|
||||
throw new CloudRuntimeException(ex.getMessage());
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long checkHeartbeat(String hostname, int pid, int aggregationDuration) {
|
||||
QuotaJobVO job = getNextRecurringJob();
|
||||
if (job == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (job.getHost().equals(hostname) && (job.getPid() != null) && (job.getPid().intValue() == pid)) {
|
||||
return job.getId();
|
||||
}
|
||||
|
||||
Date lastHeartbeat = job.getHeartbeat();
|
||||
if (lastHeartbeat == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long sinceLastHeartbeat = System.currentTimeMillis() - lastHeartbeat.getTime();
|
||||
|
||||
// TODO: Make this check a little smarter..but in the mean time we want
|
||||
// the mgmt
|
||||
// server to monitor the usage server, we need to make sure other usage
|
||||
// servers take over as the usage job owner more aggressively. For now
|
||||
// this is hardcoded to 5 minutes.
|
||||
if (sinceLastHeartbeat > (5 * 60 * 1000)) {
|
||||
return job.getId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaJobVO isOwner(String hostname, int pid) {
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
if ((hostname == null) || (pid <= 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
QuotaJobVO job = getLastJob();
|
||||
if (job == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (hostname.equals(job.getHost()) && (job.getPid() != null) && (pid == job.getPid().intValue())) {
|
||||
return job;
|
||||
}
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createNewJob(String hostname, int pid, int jobType) {
|
||||
QuotaJobVO newJob = new QuotaJobVO();
|
||||
newJob.setHost(hostname);
|
||||
newJob.setPid(pid);
|
||||
newJob.setHeartbeat(new Date());
|
||||
newJob.setJobType(jobType);
|
||||
persist(newJob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaJobVO getLastJob() {
|
||||
Filter filter = new Filter(QuotaJobVO.class, "id", false, Long.valueOf(0), Long.valueOf(1));
|
||||
SearchCriteria<QuotaJobVO> sc = createSearchCriteria();
|
||||
sc.addAnd("endMillis", SearchCriteria.Op.EQ, Long.valueOf(0));
|
||||
List<QuotaJobVO> jobs = search(sc, filter);
|
||||
|
||||
if ((jobs == null) || jobs.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return jobs.get(0);
|
||||
}
|
||||
|
||||
private QuotaJobVO getNextRecurringJob() {
|
||||
Filter filter = new Filter(QuotaJobVO.class, "id", false, Long.valueOf(0), Long.valueOf(1));
|
||||
SearchCriteria<QuotaJobVO> sc = createSearchCriteria();
|
||||
sc.addAnd("endMillis", SearchCriteria.Op.EQ, Long.valueOf(0));
|
||||
sc.addAnd("jobType", SearchCriteria.Op.EQ, Integer.valueOf(QuotaJobVO.JOB_TYPE_RECURRING));
|
||||
List<QuotaJobVO> jobs = search(sc, filter);
|
||||
|
||||
if ((jobs == null) || jobs.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return jobs.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaJobVO getNextImmediateJob() {
|
||||
Filter filter = new Filter(QuotaJobVO.class, "id", false, Long.valueOf(0), Long.valueOf(1));
|
||||
SearchCriteria<QuotaJobVO> sc = createSearchCriteria();
|
||||
sc.addAnd("endMillis", SearchCriteria.Op.EQ, Long.valueOf(0));
|
||||
sc.addAnd("jobType", SearchCriteria.Op.EQ, Integer.valueOf(QuotaJobVO.JOB_TYPE_SINGLE));
|
||||
sc.addAnd("scheduled", SearchCriteria.Op.EQ, Integer.valueOf(0));
|
||||
List<QuotaJobVO> jobs = search(sc, filter);
|
||||
|
||||
if ((jobs == null) || jobs.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return jobs.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getLastHeartbeat() {
|
||||
Filter filter = new Filter(QuotaJobVO.class, "heartbeat", false, Long.valueOf(0), Long.valueOf(1));
|
||||
SearchCriteria<QuotaJobVO> sc = createSearchCriteria();
|
||||
List<QuotaJobVO> jobs = search(sc, filter);
|
||||
|
||||
if ((jobs == null) || jobs.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return jobs.get(0).getHeartbeat();
|
||||
}
|
||||
}
|
||||
|
|
@ -18,15 +18,15 @@ package org.apache.cloudstack.quota.dao;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.QuotaConfigurationVO;
|
||||
import org.apache.cloudstack.quota.QuotaMappingVO;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface QuotaConfigurationDao extends GenericDao<QuotaConfigurationVO, Long> {
|
||||
public interface QuotaMappingDao extends GenericDao<QuotaMappingVO, Long> {
|
||||
|
||||
QuotaConfigurationVO findByUsageType(String usageType);
|
||||
QuotaMappingVO findByUsageType(int usageType);
|
||||
|
||||
Pair<List<QuotaConfigurationVO>, Integer> searchConfigurations();
|
||||
Pair<List<QuotaMappingVO>, Integer> listAllMapping();
|
||||
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
|||
import javax.ejb.Local;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.cloudstack.quota.QuotaConfigurationVO;
|
||||
import org.apache.cloudstack.quota.QuotaMappingVO;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
|
|
@ -30,12 +30,12 @@ import com.cloud.utils.db.SearchCriteria;
|
|||
import com.cloud.utils.db.TransactionLegacy;
|
||||
|
||||
@Component
|
||||
@Local(value = { QuotaConfigurationDao.class })
|
||||
public class QuotaConfigurationDaoImpl extends GenericDaoBase<QuotaConfigurationVO, Long> implements QuotaConfigurationDao {
|
||||
private final SearchBuilder<QuotaConfigurationVO> searchUsageType;
|
||||
private final SearchBuilder<QuotaConfigurationVO> listAllIncludedUsageType;
|
||||
@Local(value = { QuotaMappingDao.class })
|
||||
public class QuotaMappingDaoImpl extends GenericDaoBase<QuotaMappingVO, Long> implements QuotaMappingDao {
|
||||
private final SearchBuilder<QuotaMappingVO> searchUsageType;
|
||||
private final SearchBuilder<QuotaMappingVO> listAllIncludedUsageType;
|
||||
|
||||
public QuotaConfigurationDaoImpl() {
|
||||
public QuotaMappingDaoImpl() {
|
||||
super();
|
||||
searchUsageType = createSearchBuilder();
|
||||
searchUsageType.and("usage_type", searchUsageType.entity().getUsageType(), SearchCriteria.Op.EQ);
|
||||
|
|
@ -47,17 +47,22 @@ public class QuotaConfigurationDaoImpl extends GenericDaoBase<QuotaConfiguration
|
|||
}
|
||||
|
||||
@Override
|
||||
public QuotaConfigurationVO findByUsageType(final String usageType) {
|
||||
final SearchCriteria<QuotaConfigurationVO> sc = searchUsageType.create();
|
||||
sc.setParameters("usage_type", usageType);
|
||||
return findOneBy(sc);
|
||||
public QuotaMappingVO findByUsageType(final int usageType) {
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
final SearchCriteria<QuotaMappingVO> sc = searchUsageType.create();
|
||||
sc.setParameters("usage_type", usageType);
|
||||
return findOneBy(sc);
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaConfigurationVO>, Integer> searchConfigurations() {
|
||||
public Pair<List<QuotaMappingVO>, Integer> listAllMapping() {
|
||||
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
|
||||
try {
|
||||
final SearchCriteria<QuotaConfigurationVO> sc = listAllIncludedUsageType.create();
|
||||
final SearchCriteria<QuotaMappingVO> sc = listAllIncludedUsageType.create();
|
||||
sc.setParameters("include", 1);
|
||||
return searchAndCount(sc, null);
|
||||
} finally {
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue