mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Quota custom tariffs (#5909)
Co-authored-by: GutoVeronezi <daniel@scclouds.com.br> Co-authored-by: dahn <daan.hoogland@gmail.com>
This commit is contained in:
parent
289a43f758
commit
2ca164ac96
@ -23,6 +23,7 @@ public class ApiConstants {
|
||||
public static final String ACCOUNT_ID = "accountid";
|
||||
public static final String ACCOUNT_IDS = "accountids";
|
||||
public static final String ACCUMULATE = "accumulate";
|
||||
public static final String ACTIVATION_RULE = "activationrule";
|
||||
public static final String ACTIVITY = "activity";
|
||||
public static final String ADAPTER_TYPE = "adaptertype";
|
||||
public static final String ADDRESS = "address";
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
// 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.usage;
|
||||
|
||||
public enum UsageUnitTypes {
|
||||
COMPUTE_MONTH ("Compute*Month"),
|
||||
IP_MONTH ("IP*Month"),
|
||||
GB ("GB"),
|
||||
GB_MONTH ("GB*Month"),
|
||||
POLICY_MONTH ("Policy*Month");
|
||||
|
||||
private final String description;
|
||||
|
||||
private UsageUnitTypes(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the UsageUnitTypes according to the parameter.<br/><br/>
|
||||
* If there are no UsageUnitTypes with the description, it will try to retrieve it with {@link UsageUnitTypes#valueOf(String)} and will throw an
|
||||
* {@link IllegalArgumentException} if it not exist.
|
||||
*/
|
||||
public static UsageUnitTypes getByDescription(String description) {
|
||||
for (UsageUnitTypes type : UsageUnitTypes.values()) {
|
||||
if (type.toString().equals(description)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return UsageUnitTypes.valueOf(description);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.cloudstack.usage;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UsageUnitTypesTest {
|
||||
|
||||
private List<UsageUnitTypes> usageUnitTypes = Arrays.asList(UsageUnitTypes.values());
|
||||
|
||||
@Test
|
||||
public void getByDescriptionTestAllTheDescriptionsMustReturnUsageUnitTypes() {
|
||||
usageUnitTypes.forEach(type -> {
|
||||
UsageUnitTypes usageUnitType = UsageUnitTypes.getByDescription(type.toString());
|
||||
Assert.assertEquals(type, usageUnitType);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getByDescriptionTestAllTheConstantNamesMustReturnUsageUnitTypes() {
|
||||
usageUnitTypes.forEach(type -> {
|
||||
UsageUnitTypes usageUnitType = UsageUnitTypes.getByDescription(type.name());
|
||||
Assert.assertEquals(type, usageUnitType);
|
||||
});
|
||||
}
|
||||
|
||||
@Test (expected = IllegalArgumentException.class)
|
||||
public void getByDescriptionTestPassWrongTypeOrDescriptionAndThrowsIllegalArgumentException() {
|
||||
UsageUnitTypes.getByDescription("test");
|
||||
}
|
||||
}
|
||||
@ -18,10 +18,16 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
public interface SnapshotInfo extends DataObject, Snapshot {
|
||||
ConfigKey<Boolean> BackupSnapshotAfterTakingSnapshot = new ConfigKey<>(Boolean.class, "snapshot.backup.to.secondary", "Snapshots", "true", "Indicates whether to always"
|
||||
+ " backup primary storage snapshot to secondary storage. Keeping snapshots only on Primary storage is applicable for KVM + Ceph only.", false, ConfigKey.Scope.Global,
|
||||
null);
|
||||
|
||||
SnapshotInfo getParent();
|
||||
|
||||
String getPath();
|
||||
|
||||
@ -625,8 +625,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
||||
final VirtualMachineGuru guru = getVmGuru(vm);
|
||||
guru.finalizeExpunge(vm);
|
||||
|
||||
userVmDetailsDao.removeDetails(vm.getId());
|
||||
|
||||
userVmDeployAsIsDetailsDao.removeDetails(vm.getId());
|
||||
|
||||
// Remove comments (if any)
|
||||
|
||||
@ -126,7 +126,6 @@ import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.VMTemplateDetailsDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.dao.VolumeDetailsDao;
|
||||
import com.cloud.storage.snapshot.SnapshotManager;
|
||||
import com.cloud.template.TemplateManager;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.user.Account;
|
||||
@ -243,7 +242,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
||||
private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine;
|
||||
protected List<StoragePoolAllocator> _storagePoolAllocators;
|
||||
|
||||
protected boolean backupSnapshotAfterTakingSnapshot = SnapshotManager.BackupSnapshotAfterTakingSnapshot.value();
|
||||
protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value();
|
||||
|
||||
public List<StoragePoolAllocator> getStoragePoolAllocators() {
|
||||
return _storagePoolAllocators;
|
||||
|
||||
@ -18,6 +18,7 @@ package com.cloud.upgrade.dao;
|
||||
|
||||
import com.cloud.upgrade.SystemVmTemplateRegistration;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@ -0,0 +1,233 @@
|
||||
// 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 com.cloud.upgrade.dao;
|
||||
|
||||
import com.cloud.upgrade.SystemVmTemplateRegistration;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.api.response.UsageTypeResponse;
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Upgrade41700to41800 implements DbUpgrade, DbUpgradeSystemVmTemplate {
|
||||
|
||||
final static Logger LOG = Logger.getLogger(Upgrade41700to41800.class);
|
||||
private SystemVmTemplateRegistration systemVmTemplateRegistration;
|
||||
|
||||
@Override
|
||||
public String[] getUpgradableVersionRange() {
|
||||
return new String[] {"4.17.0.0", "4.18.0.0"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUpgradedVersion() {
|
||||
return "4.18.0.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRollingUpgrade() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream[] getPrepareScripts() {
|
||||
final String scriptFile = "META-INF/db/schema-41700to41800.sql";
|
||||
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
|
||||
if (script == null) {
|
||||
throw new CloudRuntimeException("Unable to find " + scriptFile);
|
||||
}
|
||||
|
||||
return new InputStream[] {script};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performDataMigration(Connection conn) {
|
||||
convertQuotaTariffsToNewParadigm(conn);
|
||||
convertVmResourcesQuotaTypesToRunningVmQuotaType(conn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream[] getCleanupScripts() {
|
||||
final String scriptFile = "META-INF/db/schema-41700to41800-cleanup.sql";
|
||||
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
|
||||
if (script == null) {
|
||||
throw new CloudRuntimeException("Unable to find " + scriptFile);
|
||||
}
|
||||
|
||||
return new InputStream[] {script};
|
||||
}
|
||||
|
||||
private void initSystemVmTemplateRegistration() {
|
||||
systemVmTemplateRegistration = new SystemVmTemplateRegistration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSystemVmTemplates(Connection conn) {
|
||||
LOG.debug("Updating System Vm template IDs");
|
||||
initSystemVmTemplateRegistration();
|
||||
try {
|
||||
systemVmTemplateRegistration.updateSystemVmTemplates(conn);
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Failed to find / register SystemVM template(s)");
|
||||
}
|
||||
}
|
||||
|
||||
protected void convertQuotaTariffsToNewParadigm(Connection conn) {
|
||||
LOG.info("Converting quota tariffs to new paradigm.");
|
||||
|
||||
List<UsageTypeResponse> usageTypeResponses = UsageTypes.listUsageTypes();
|
||||
|
||||
for (UsageTypeResponse usageTypeResponse : usageTypeResponses) {
|
||||
Integer usageType = usageTypeResponse.getUsageType();
|
||||
|
||||
String tariffTypeDescription = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(usageTypeResponse, "description", "usageType");
|
||||
|
||||
LOG.info(String.format("Converting quota tariffs of type %s to new paradigm.", tariffTypeDescription));
|
||||
|
||||
for (boolean previousTariff : Arrays.asList(true, false)) {
|
||||
Map<Long, Date> tariffs = selectTariffs(conn, usageType, previousTariff, tariffTypeDescription);
|
||||
|
||||
int tariffsSize = tariffs.size();
|
||||
if (tariffsSize < 2) {
|
||||
LOG.info(String.format("Quota tariff of type %s has [%s] %s register(s). Tariffs with less than 2 register do not need to be converted to new paradigm.",
|
||||
tariffTypeDescription, tariffsSize, previousTariff ? "previous of current" : "next to current"));
|
||||
continue;
|
||||
}
|
||||
|
||||
executeUpdateQuotaTariffSetEndDateAndRemoved(conn, usageType, tariffs, previousTariff, tariffTypeDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<Long, Date> selectTariffs(Connection conn, Integer usageType, boolean previousTariff, String tariffTypeDescription) {
|
||||
Map<Long, Date> quotaTariffs = new LinkedHashMap<>();
|
||||
|
||||
String selectQuotaTariffs = String.format("SELECT id, effective_on FROM cloud_usage.quota_tariff WHERE %s AND usage_type = ? ORDER BY effective_on, updated_on;",
|
||||
previousTariff ? "usage_name = name" : "removed is null");
|
||||
|
||||
LOG.info(String.format("Selecting %s quota tariffs of type [%s] according to SQL [%s].", previousTariff ? "previous of current" : "next to current",
|
||||
tariffTypeDescription, selectQuotaTariffs));
|
||||
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(selectQuotaTariffs)) {
|
||||
pstmt.setInt(1, usageType);
|
||||
|
||||
try (ResultSet result = pstmt.executeQuery()) {
|
||||
while (result.next()) {
|
||||
quotaTariffs.put(result.getLong("id"), result.getDate("effective_on"));
|
||||
}
|
||||
}
|
||||
return quotaTariffs;
|
||||
} catch (SQLException e) {
|
||||
String message = String.format("Unable to retrieve %s quota tariffs of type [%s] due to [%s].", previousTariff ? "previous" : "next", tariffTypeDescription,
|
||||
e.getMessage());
|
||||
LOG.error(message, e);
|
||||
throw new CloudRuntimeException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void executeUpdateQuotaTariffSetEndDateAndRemoved(Connection conn, Integer usageType, Map<Long, Date> tariffs, boolean setRemoved, String tariffTypeDescription) {
|
||||
String updateQuotaTariff = String.format("UPDATE cloud_usage.quota_tariff SET end_date = ? %s WHERE id = ?;", setRemoved ? ", removed = ?" : "");
|
||||
|
||||
Object[] ids = tariffs.keySet().toArray();
|
||||
|
||||
LOG.info(String.format("Updating %s registers of %s quota tariffs of type [%s] with SQL [%s].", tariffs.size() -1, setRemoved ? "previous of current" :
|
||||
"next to current", tariffTypeDescription, updateQuotaTariff));
|
||||
|
||||
for (int i = 0; i < tariffs.size() - 1; i++) {
|
||||
Long id = Long.valueOf(String.valueOf(ids[i]));
|
||||
Long nextId = Long.valueOf(String.valueOf(ids[i + 1]));
|
||||
|
||||
Date endDate = tariffs.get(nextId);
|
||||
|
||||
if (!DateUtils.isSameDay(endDate, tariffs.get(id))) {
|
||||
endDate = DateUtils.addDays(endDate, -1);
|
||||
}
|
||||
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(updateQuotaTariff)) {
|
||||
java.sql.Date sqlEndDate = new java.sql.Date(endDate.getTime());
|
||||
pstmt.setDate(1, sqlEndDate);
|
||||
|
||||
String updateRemoved = "";
|
||||
if (setRemoved) {
|
||||
pstmt.setDate(2, sqlEndDate);
|
||||
pstmt.setLong(3, id);
|
||||
|
||||
updateRemoved = String.format("and \"removed\" to [%s] ", sqlEndDate);
|
||||
} else {
|
||||
pstmt.setLong(2, id);
|
||||
}
|
||||
|
||||
LOG.info(String.format("Updating \"end_date\" to [%s] %sof quota tariff with ID [%s].", sqlEndDate, updateRemoved, id));
|
||||
pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
String message = String.format("Unable to update \"end_date\" %s of quota tariffs of usage type [%s] due to [%s].", setRemoved ? "and \"removed\"" : "",
|
||||
usageType, e.getMessage());
|
||||
LOG.error(message, e);
|
||||
throw new CloudRuntimeException(message, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void convertVmResourcesQuotaTypesToRunningVmQuotaType(Connection conn) {
|
||||
LOG.info("Converting quota tariffs of type \"vCPU\", \"CPU_SPEED\" and \"MEMORY\" to \"RUNNING_VM\".");
|
||||
|
||||
String insertSql = String.format("INSERT INTO cloud_usage.quota_tariff (usage_type, usage_name, usage_unit, usage_discriminator, currency_value, effective_on, updated_on,"
|
||||
+ " updated_by, uuid, name, description, removed, end_date, activation_rule)\n"
|
||||
+ "SELECT 1, 'RUNNING_VM', usage_unit, '', 0, effective_on, updated_on, updated_by, UUID(), name, description, removed, end_date,\n"
|
||||
+ " CASE\n"
|
||||
+ " WHEN usage_type = 15 THEN CONCAT('((value.computingResources ? (value.computingResources.cpuSpeed * value.computingResources.cpuNumber) : 0) / 100) * ', currency_value)\n"
|
||||
+ " WHEN usage_type = 16 THEN CONCAT('(value.computingResources ? value.computingResources.cpuNumber : 0) * ', currency_value)\n"
|
||||
+ " WHEN usage_type = 17 THEN CONCAT('(value.computingResources ? value.computingResources.memory : 0)* ', currency_value)\n"
|
||||
+ " END\n"
|
||||
+ "FROM cloud_usage.quota_tariff \n"
|
||||
+ "WHERE usage_type in (15, 16, 17) \n"
|
||||
+ "AND currency_value > 0.0;");
|
||||
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
|
||||
pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
String message = String.format("Failed to convert quota tariffs of type \"vCPU\", \"CPU_SPEED\" and \"MEMORY\" to \"RUNNING_VM\" due to [%s].", e.getMessage());
|
||||
LOG.error(message, e);
|
||||
throw new CloudRuntimeException(message, e);
|
||||
}
|
||||
|
||||
LOG.info("Disabling unused quota tariffs of type \"vCPU\", \"CPU_SPEED\" and \"MEMORY\".");
|
||||
|
||||
String updateSql = "UPDATE cloud_usage.quota_tariff SET removed = now() WHERE usage_type in (15, 16, 17) and removed is null;";
|
||||
|
||||
try (PreparedStatement pstmt = conn.prepareStatement(updateSql)) {
|
||||
pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
String message = String.format("Failed disable quota tariffs of type \"vCPU\", \"CPU_SPEED\" and \"MEMORY\" due to [%s].", e.getMessage());
|
||||
LOG.error(message, e);
|
||||
throw new CloudRuntimeException(message, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,6 +29,7 @@ import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.usage.Usage;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
@Entity
|
||||
@Table(name = "cloud_usage")
|
||||
@ -396,4 +397,9 @@ public class UsageVO implements Usage, InternalIdentity {
|
||||
public void setHidden(boolean hidden) {
|
||||
this.isHidden = hidden;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "usageId", "usageType", "startDate", "endDate");
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface UsageDao extends GenericDao<UsageVO, Long> {
|
||||
@ -58,5 +59,7 @@ public interface UsageDao extends GenericDao<UsageVO, Long> {
|
||||
|
||||
UsageVO persistUsage(final UsageVO usage);
|
||||
|
||||
Pair<List<? extends UsageVO>, Integer> getUsageRecordsPendingQuotaAggregation(long accountId, long domainId);
|
||||
Pair<List<UsageVO>, Integer> listUsageRecordsPendingForQuotaAggregation(long accountId, long domainId);
|
||||
|
||||
List<Pair<String, String>> listAccountResourcesInThePeriod(long accountId, int usageType, Date startDate, Date endDate);
|
||||
}
|
||||
|
||||
@ -38,6 +38,8 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
@ -73,6 +75,13 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
||||
|
||||
protected final static TimeZone s_gmtTimeZone = TimeZone.getTimeZone("GMT");
|
||||
|
||||
private static final String LIST_ACCOUNT_RESOURCES_IN_PERIOD = "SELECT zone.uuid as zone_uuid, domain.uuid as domain_uuid\n "
|
||||
+ "FROM cloud_usage.cloud_usage cloud_usage\n "
|
||||
+ "INNER JOIN cloud.data_center zone ON (zone.id = cloud_usage.zone_id)\n "
|
||||
+ "INNER JOIN cloud.domain domain ON (domain.id = cloud_usage.domain_id)\n "
|
||||
+ "WHERE cloud_usage.usage_type = ? AND cloud_usage.account_id = ? AND cloud_usage.start_date >= ? AND cloud_usage.end_date <= ? "
|
||||
+ "GROUP BY cloud_usage.usage_id ";
|
||||
|
||||
public UsageDaoImpl() {
|
||||
}
|
||||
|
||||
@ -486,30 +495,61 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
||||
});
|
||||
}
|
||||
|
||||
public Pair<List<? extends UsageVO>, Integer> getUsageRecordsPendingQuotaAggregation(final long accountId, final long domainId) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Getting usage records for account: " + accountId + ", domainId: " + domainId);
|
||||
}
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<Pair<List<? extends UsageVO>, Integer>>() {
|
||||
@Override
|
||||
public Pair<List<? extends UsageVO>, Integer> doInTransaction(final TransactionStatus status) {
|
||||
Pair<List<UsageVO>, Integer> usageRecords = new Pair<List<UsageVO>, Integer>(new ArrayList<UsageVO>(), 0);
|
||||
Filter usageFilter = new Filter(UsageVO.class, "startDate", true, 0L, Long.MAX_VALUE);
|
||||
public Pair<List<UsageVO>, Integer> listUsageRecordsPendingForQuotaAggregation(long accountId, long domainId) {
|
||||
s_logger.debug(String.format("Retrieving pending usage records for accountId [%s] and domainId [%s].", accountId, domainId));
|
||||
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<Pair<List<UsageVO>, Integer>>) status -> {
|
||||
Filter usageFilter = new Filter(UsageVO.class, "startDate", true, null, null);
|
||||
QueryBuilder<UsageVO> qb = QueryBuilder.create(UsageVO.class);
|
||||
|
||||
if (accountId != -1) {
|
||||
qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId);
|
||||
}
|
||||
|
||||
if (domainId != -1) {
|
||||
qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId);
|
||||
}
|
||||
|
||||
qb.and(qb.entity().getQuotaCalculated(), SearchCriteria.Op.NEQ, 1);
|
||||
qb.and(qb.entity().getRawUsage(), SearchCriteria.Op.GT, 0);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Getting usage records" + usageFilter.getOrderBy());
|
||||
}
|
||||
usageRecords = searchAndCountAllRecords(qb.create(), usageFilter);
|
||||
return new Pair<List<? extends UsageVO>, Integer>(usageRecords.first(), usageRecords.second());
|
||||
}
|
||||
|
||||
return searchAndCountAllRecords(qb.create(), usageFilter);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<String, String>> listAccountResourcesInThePeriod(long accountId, int usageType, Date startDate, Date endDate) {
|
||||
String startDateString = DateUtil.getOutputString(startDate);
|
||||
String endDateString = DateUtil.getOutputString(endDate);
|
||||
|
||||
s_logger.debug(String.format("Retrieving account resources between [%s] and [%s] for accountId [%s] and usageType [%s].", startDateString, endDateString, accountId,
|
||||
usageType));
|
||||
|
||||
TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||
try (PreparedStatement pstmt = txn.prepareStatement(LIST_ACCOUNT_RESOURCES_IN_PERIOD)) {
|
||||
List<Pair<String, String>> accountResourcesOfTheLastDay = new ArrayList<>();
|
||||
|
||||
pstmt.setInt(1, usageType);
|
||||
pstmt.setLong(2, accountId);
|
||||
pstmt.setTimestamp(3, new Timestamp(startDate.getTime()));
|
||||
pstmt.setTimestamp(4, new Timestamp(endDate.getTime()));
|
||||
|
||||
try (ResultSet rs = pstmt.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
String zoneUuid = rs.getString("zone_uuid");
|
||||
String domainUuid = rs.getString("domain_uuid");
|
||||
|
||||
accountResourcesOfTheLastDay.add(new Pair<>(zoneUuid, domainUuid));
|
||||
}
|
||||
}
|
||||
|
||||
return accountResourcesOfTheLastDay;
|
||||
} catch (SQLException e) {
|
||||
s_logger.error(String.format("Failed to retrieve account resources between [%s] and [%s] for accountId [%s] and usageType [%s] due to [%s]. Returning an empty list of"
|
||||
+ " resources.", startDateString, endDateString, accountId, usageType, e.getMessage()), e);
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,4 +225,8 @@ public class AccountVO implements Account {
|
||||
public String getName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public String reflectionToString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "uuid", "accountName", "domainId");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 com.cloud.vm.constants;
|
||||
|
||||
public enum VmDetails {
|
||||
MEMORY("memory"), CPU_NUMBER("cpuNumber"), CPU_SPEED("cpuSpeed");
|
||||
|
||||
private String name;
|
||||
|
||||
private VmDetails(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@ -14,7 +14,7 @@
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.storage.image.db;
|
||||
package org.apache.cloudstack.storage.datastore.db;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@ -30,8 +30,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -0,0 +1,70 @@
|
||||
<!--
|
||||
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.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd"
|
||||
>
|
||||
|
||||
<bean id="accountGuestVlanMapDaoImpl" class="com.cloud.network.dao.AccountGuestVlanMapDaoImpl" />
|
||||
<bean id="clusterDaoImpl" class="com.cloud.dc.dao.ClusterDaoImpl" />
|
||||
<bean id="clusterDetailsDaoImpl" class="com.cloud.dc.ClusterDetailsDaoImpl" />
|
||||
<bean id="dataCenterDaoImpl" class="com.cloud.dc.dao.DataCenterDaoImpl" />
|
||||
<bean id="dataCenterDetailsDaoImpl" class="com.cloud.dc.dao.DataCenterDetailsDaoImpl" />
|
||||
<bean id="dataCenterIpAddressDaoImpl" class="com.cloud.dc.dao.DataCenterIpAddressDaoImpl" />
|
||||
<bean id="dataCenterLinkLocalIpAddressDaoImpl" class="com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl" />
|
||||
<bean id="dataCenterVnetDaoImpl" class="com.cloud.dc.dao.DataCenterVnetDaoImpl" />
|
||||
<bean id="diskOfferingDaoImpl" class="com.cloud.storage.dao.DiskOfferingDaoImpl" />
|
||||
<bean id="DiskOfferingDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDaoImpl" />
|
||||
<bean id="guestOSDaoImpl" class="com.cloud.storage.dao.GuestOSDaoImpl" />
|
||||
<bean id="hostDaoImpl" class="com.cloud.host.dao.HostDaoImpl" />
|
||||
<bean id="hostDetailsDaoImpl" class="com.cloud.host.dao.HostDetailsDaoImpl" />
|
||||
<bean id="hostGpuGroupsDaoImpl" class="com.cloud.gpu.dao.HostGpuGroupsDaoImpl" />
|
||||
<bean id="hostPodDaoImpl" class="com.cloud.dc.dao.HostPodDaoImpl" />
|
||||
<bean id="hostTagsDaoImpl" class="com.cloud.host.dao.HostTagsDaoImpl" />
|
||||
<bean id="hostTransferMapDaoImpl" class="com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl" />
|
||||
<bean id="imageStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl" />
|
||||
<bean id="networkOfferingDaoImpl" class="com.cloud.offerings.dao.NetworkOfferingDaoImpl" />
|
||||
<bean id="networkOfferingDetailsDaoImpl" class="com.cloud.offerings.dao.NetworkOfferingDetailsDaoImpl" />
|
||||
<bean id="networkOfferingServiceMapDaoImpl" class="com.cloud.offerings.dao.NetworkOfferingServiceMapDaoImpl" />
|
||||
<bean id="nicDaoImpl" class="com.cloud.vm.dao.NicDaoImpl" />
|
||||
<bean id="podVlanDaoImpl" class="com.cloud.dc.dao.PodVlanDaoImpl" />
|
||||
<bean id="primaryDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl" />
|
||||
<bean id="resourceTagsDaoImpl" class="com.cloud.tags.dao.ResourceTagsDaoImpl" />
|
||||
<bean id="roleDaoImpl" class="org.apache.cloudstack.acl.dao.RoleDaoImpl" />
|
||||
<bean id="serviceOfferingDaoImpl" class="com.cloud.service.dao.ServiceOfferingDaoImpl" />
|
||||
<bean id="serviceOfferingDetailsDaoImpl" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl"/>
|
||||
<bean id="snapshotDaoImpl" class="com.cloud.storage.dao.SnapshotDaoImpl" />
|
||||
<bean id="snapshotDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDaoImpl" />
|
||||
<bean id="storagePoolDetailsDaoImpl" class="com.cloud.storage.dao.StoragePoolDetailsDaoImpl" />
|
||||
<bean id="storagePoolHostDaoImpl" class="com.cloud.storage.dao.StoragePoolHostDaoImpl" />
|
||||
<bean id="storagePoolTagsDaoImpl" class="com.cloud.storage.dao.StoragePoolTagsDaoImpl" />
|
||||
<bean id="userVmDetailsDaoImpl" class="com.cloud.vm.dao.UserVmDetailsDaoImpl" />
|
||||
<bean id="vGPUTypesDaoImpl" class="com.cloud.gpu.dao.VGPUTypesDaoImpl" />
|
||||
<bean id="vMInstanceDaoImpl" class="com.cloud.vm.dao.VMInstanceDaoImpl" />
|
||||
<bean id="vMSnapshotDaoImpl" class="com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl" />
|
||||
<bean id="VmTemplateDaoImpl" class="org.apache.cloudstack.quota.dao.VmTemplateDaoImpl" />
|
||||
<bean id="volumeDaoImpl" class="com.cloud.storage.dao.VolumeDaoImpl" />
|
||||
<bean id="backupOfferingDaoImpl" class="org.apache.cloudstack.backup.dao.BackupOfferingDaoImpl" />
|
||||
</beans>
|
||||
@ -27,26 +27,22 @@
|
||||
http://www.springframework.org/schema/context/spring-context.xsd"
|
||||
>
|
||||
|
||||
<import resource="spring-engine-schema-core-common-daos-between-management-and-usage-context.xml" />
|
||||
|
||||
<!--
|
||||
DAOs with default configuration
|
||||
-->
|
||||
<bean id="serviceOfferingDaoImpl" class="com.cloud.service.dao.ServiceOfferingDaoImpl" />
|
||||
<bean id="diskOfferingDaoImpl" class="com.cloud.storage.dao.DiskOfferingDaoImpl" />
|
||||
<bean id="dataCenterDaoImpl" class="com.cloud.dc.dao.DataCenterDaoImpl" />
|
||||
<bean id="hostPodDaoImpl" class="com.cloud.dc.dao.HostPodDaoImpl" />
|
||||
<bean id="vlanDaoImpl" class="com.cloud.dc.dao.VlanDaoImpl" />
|
||||
<bean id="userDaoImpl" class="com.cloud.user.dao.UserDaoImpl" />
|
||||
<bean id="VMTemplateDaoImpl" class="com.cloud.storage.dao.VMTemplateDaoImpl" />
|
||||
<bean id="hypervisorCapabilitiesDaoImpl" class="com.cloud.hypervisor.dao.HypervisorCapabilitiesDaoImpl" />
|
||||
<bean id="dedicatedResourceDaoImpl" class="com.cloud.dc.dao.DedicatedResourceDaoImpl" />
|
||||
<bean id="roleDaoImpl" class="org.apache.cloudstack.acl.dao.RoleDaoImpl" />
|
||||
<bean id="rolePermissionsDaoImpl" class="org.apache.cloudstack.acl.dao.RolePermissionsDaoImpl" />
|
||||
<bean id="projectRoleDaoImpl" class="org.apache.cloudstack.acl.dao.ProjectRoleDaoImpl"/>
|
||||
<bean id="projectRolePermissionsDaoImpl" class="org.apache.cloudstack.acl.dao.ProjectRolePermissionsDaoImpl" />
|
||||
<bean id="accountDaoImpl" class="com.cloud.user.dao.AccountDaoImpl" />
|
||||
<bean id="accountDetailsDaoImpl" class="com.cloud.user.AccountDetailsDaoImpl" />
|
||||
<bean id="accountJoinDaoImpl" class="com.cloud.api.query.dao.AccountJoinDaoImpl" />
|
||||
<bean id="accountGuestVlanMapDaoImpl" class="com.cloud.network.dao.AccountGuestVlanMapDaoImpl" />
|
||||
<bean id="accountVlanMapDaoImpl" class="com.cloud.dc.dao.AccountVlanMapDaoImpl" />
|
||||
<bean id="alertDaoImpl" class="com.cloud.alert.dao.AlertDaoImpl" />
|
||||
<bean id="asyncJobJoinDaoImpl" class="com.cloud.api.query.dao.AsyncJobJoinDaoImpl" />
|
||||
@ -59,18 +55,12 @@
|
||||
<bean id="capacityDaoImpl" class="com.cloud.capacity.dao.CapacityDaoImpl" />
|
||||
<bean id="certificateDaoImpl" class="com.cloud.certificate.dao.CertificateDaoImpl" />
|
||||
<bean id="crlDaoImpl" class="com.cloud.certificate.dao.CrlDaoImpl" />
|
||||
<bean id="clusterDaoImpl" class="com.cloud.dc.dao.ClusterDaoImpl" />
|
||||
<bean id="clusterDetailsDaoImpl" class="com.cloud.dc.ClusterDetailsDaoImpl" />
|
||||
<bean id="clusterVSMMapDaoImpl" class="com.cloud.dc.dao.ClusterVSMMapDaoImpl" />
|
||||
<bean id="commandExecLogDaoImpl" class="com.cloud.secstorage.CommandExecLogDaoImpl" />
|
||||
<bean id="conditionDaoImpl" class="com.cloud.network.as.dao.ConditionDaoImpl" />
|
||||
<bean id="consoleProxyDaoImpl" class="com.cloud.vm.dao.ConsoleProxyDaoImpl" />
|
||||
<bean id="counterDaoImpl" class="com.cloud.network.as.dao.CounterDaoImpl" />
|
||||
<bean id="dataCenterIpAddressDaoImpl" class="com.cloud.dc.dao.DataCenterIpAddressDaoImpl" />
|
||||
<bean id="dataCenterJoinDaoImpl" class="com.cloud.api.query.dao.DataCenterJoinDaoImpl" />
|
||||
<bean id="dataCenterLinkLocalIpAddressDaoImpl" class="com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl" />
|
||||
<bean id="dataCenterVnetDaoImpl" class="com.cloud.dc.dao.DataCenterVnetDaoImpl" />
|
||||
<bean id="dataCenterDetailsDaoImpl" class="com.cloud.dc.dao.DataCenterDetailsDaoImpl" />
|
||||
<bean id="domainVlanMapDaoImpl" class="com.cloud.dc.dao.DomainVlanMapDaoImpl" />
|
||||
<bean id="engineDcDetailsDaoImpl" class="org.apache.cloudstack.engine.datacenter.entity.api.db.dao.DcDetailsDaoImpl" />
|
||||
<bean id="diskOfferingJoinDaoImpl" class="com.cloud.api.query.dao.DiskOfferingJoinDaoImpl" />
|
||||
@ -95,24 +85,17 @@
|
||||
<bean id="globalLoadBalancerDaoImpl" class="org.apache.cloudstack.region.gslb.GlobalLoadBalancerDaoImpl" />
|
||||
<bean id="globalLoadBalancerLbRuleMapDaoImpl" class="org.apache.cloudstack.region.gslb.GlobalLoadBalancerLbRuleMapDaoImpl" />
|
||||
<bean id="guestOSCategoryDaoImpl" class="com.cloud.storage.dao.GuestOSCategoryDaoImpl" />
|
||||
<bean id="guestOSDaoImpl" class="com.cloud.storage.dao.GuestOSDaoImpl" />
|
||||
<bean id="guestOSHypervisorDaoImpl" class="com.cloud.storage.dao.GuestOSHypervisorDaoImpl" />
|
||||
<!-- New HA Config -->
|
||||
<bean id="haConfigDaoImpl" class="org.apache.cloudstack.ha.dao.HAConfigDaoImpl" />
|
||||
<bean id="highAvailabilityDaoImpl" class="com.cloud.ha.dao.HighAvailabilityDaoImpl" />
|
||||
<bean id="hostDaoImpl" class="com.cloud.host.dao.HostDaoImpl" />
|
||||
<bean id="engineHostDetailsDaoImpl" class="org.apache.cloudstack.engine.datacenter.entity.api.db.dao.HostDetailsDaoImpl" />
|
||||
<bean id="hostDetailsDaoImpl" class="com.cloud.host.dao.HostDetailsDaoImpl" />
|
||||
<bean id="hostJoinDaoImpl" class="com.cloud.api.query.dao.HostJoinDaoImpl" />
|
||||
<bean id="engineHostTagsDaoImpl" class="org.apache.cloudstack.engine.datacenter.entity.api.db.dao.HostTagsDaoImpl" />
|
||||
<bean id="hostTagsDaoImpl" class="com.cloud.host.dao.HostTagsDaoImpl" />
|
||||
<bean id="hostTransferMapDaoImpl" class="com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl" />
|
||||
<bean id="iPAddressDaoImpl" class="com.cloud.network.dao.IPAddressDaoImpl" />
|
||||
<bean id="ip6GuestPrefixSubnetNetworkMapDaoImpl" class="com.cloud.network.dao.Ipv6GuestPrefixSubnetNetworkMapDaoImpl" />
|
||||
<bean id="imageStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl" />
|
||||
<bean id="imageStoreDetailsDaoImpl" class="org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDaoImpl" />
|
||||
<bean id="imageStoreJoinDaoImpl" class="com.cloud.api.query.dao.ImageStoreJoinDaoImpl" />
|
||||
<bean id="snapshotDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.SnapshotDataStoreDaoImpl" />
|
||||
<bean id="templateDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.TemplateDataStoreDaoImpl" />
|
||||
<bean id="templateJoinDaoImpl" class="com.cloud.api.query.dao.TemplateJoinDaoImpl" />
|
||||
<bean id="volumeDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.VolumeDataStoreDaoImpl" />
|
||||
@ -139,13 +122,10 @@
|
||||
<bean id="networkDomainDaoImpl" class="com.cloud.network.dao.NetworkDomainDaoImpl" />
|
||||
<bean id="networkExternalFirewallDaoImpl" class="com.cloud.network.dao.NetworkExternalFirewallDaoImpl" />
|
||||
<bean id="networkExternalLoadBalancerDaoImpl" class="com.cloud.network.dao.NetworkExternalLoadBalancerDaoImpl" />
|
||||
<bean id="networkOfferingDaoImpl" class="com.cloud.offerings.dao.NetworkOfferingDaoImpl" />
|
||||
<bean id="networkOfferingJoinDaoImpl" class="com.cloud.api.query.dao.NetworkOfferingJoinDaoImpl" />
|
||||
<bean id="networkOfferingServiceMapDaoImpl" class="com.cloud.offerings.dao.NetworkOfferingServiceMapDaoImpl" />
|
||||
<bean id="networkOpDaoImpl" class="com.cloud.network.dao.NetworkOpDaoImpl" />
|
||||
<bean id="networkRuleConfigDaoImpl" class="com.cloud.network.dao.NetworkRuleConfigDaoImpl" />
|
||||
<bean id="networkServiceMapDaoImpl" class="com.cloud.network.dao.NetworkServiceMapDaoImpl" />
|
||||
<bean id="nicDaoImpl" class="com.cloud.vm.dao.NicDaoImpl" />
|
||||
<bean id="nicDetailsDaoImpl" class="com.cloud.vm.dao.NicDetailsDaoImpl" />
|
||||
<bean id="nicExtraDhcpOptionDaoImpl" class="com.cloud.vm.dao.NicExtraDhcpOptionDaoImpl" />
|
||||
<bean id="nicSecondaryIpDaoImpl" class="com.cloud.vm.dao.NicSecondaryIpDaoImpl" />
|
||||
@ -157,14 +137,11 @@
|
||||
<bean id="physicalNetworkServiceProviderDaoImpl" class="com.cloud.network.dao.PhysicalNetworkServiceProviderDaoImpl" />
|
||||
<bean id="physicalNetworkTagDaoImpl" class="com.cloud.network.dao.PhysicalNetworkTagDaoImpl" />
|
||||
<bean id="physicalNetworkTrafficTypeDaoImpl" class="com.cloud.network.dao.PhysicalNetworkTrafficTypeDaoImpl" />
|
||||
<bean id="podVlanDaoImpl" class="com.cloud.dc.dao.PodVlanDaoImpl" />
|
||||
<bean id="podVlanMapDaoImpl" class="com.cloud.dc.dao.PodVlanMapDaoImpl" />
|
||||
<bean id="PortableIpDaoImpl" class="org.apache.cloudstack.region.PortableIpDaoImpl" />
|
||||
<bean id="PortableIpRangeDaoImpl" class="org.apache.cloudstack.region.PortableIpRangeDaoImpl" />
|
||||
<bean id="portForwardingRulesDaoImpl" class="com.cloud.network.rules.dao.PortForwardingRulesDaoImpl" />
|
||||
<bean id="portProfileDaoImpl" class="com.cloud.network.dao.PortProfileDaoImpl" />
|
||||
<bean id="storagePoolHostDaoImpl" class="com.cloud.storage.dao.StoragePoolHostDaoImpl" />
|
||||
<bean id="primaryDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl" />
|
||||
<bean id="primaryDataStoreDetailsDaoImpl" class="org.apache.cloudstack.storage.volume.db.PrimaryDataStoreDetailsDaoImpl" />
|
||||
<bean id="privateIpDaoImpl" class="com.cloud.network.vpc.dao.PrivateIpDaoImpl" />
|
||||
<bean id="projectAccountDaoImpl" class="com.cloud.projects.dao.ProjectAccountDaoImpl" />
|
||||
@ -180,7 +157,6 @@
|
||||
<bean id="resourceIconDaoImpl" class="com.cloud.resource.icon.dao.ResourceIconDaoImpl" />
|
||||
<bean id="resourceLimitDaoImpl" class="com.cloud.configuration.dao.ResourceLimitDaoImpl" />
|
||||
<bean id="resourceTagJoinDaoImpl" class="com.cloud.api.query.dao.ResourceTagJoinDaoImpl" />
|
||||
<bean id="resourceTagsDaoImpl" class="com.cloud.tags.dao.ResourceTagsDaoImpl" />
|
||||
<bean id="routerNetworkDaoImpl" class="com.cloud.network.dao.RouterNetworkDaoImpl" />
|
||||
<bean id="sSHKeyPairDaoImpl" class="com.cloud.user.dao.SSHKeyPairDaoImpl" />
|
||||
<bean id="userDataDaoImpl" class="com.cloud.user.dao.UserDataDaoImpl" />
|
||||
@ -195,7 +171,6 @@
|
||||
<bean id="site2SiteCustomerGatewayDaoImpl" class="com.cloud.network.dao.Site2SiteCustomerGatewayDaoImpl" />
|
||||
<bean id="site2SiteVpnConnectionDaoImpl" class="com.cloud.network.dao.Site2SiteVpnConnectionDaoImpl" />
|
||||
<bean id="site2SiteVpnGatewayDaoImpl" class="com.cloud.network.dao.Site2SiteVpnGatewayDaoImpl" />
|
||||
<bean id="snapshotDaoImpl" class="com.cloud.storage.dao.SnapshotDaoImpl" />
|
||||
<bean id="snapshotDetailsDaoImpl" class="com.cloud.storage.dao.SnapshotDetailsDaoImpl" />
|
||||
<bean id="snapshotPolicyDaoImpl" class="com.cloud.storage.dao.SnapshotPolicyDaoImpl" />
|
||||
<bean id="snapshotPolicyDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.SnapshotPolicyDetailsDaoImpl" />
|
||||
@ -205,9 +180,7 @@
|
||||
<bean id="dataCenterGuestIpv6PrefixDaoImpl" class="com.cloud.dc.dao.DataCenterGuestIpv6PrefixDaoImpl" />
|
||||
<bean id="storageNetworkIpAddressDaoImpl" class="com.cloud.dc.dao.StorageNetworkIpAddressDaoImpl" />
|
||||
<bean id="storageNetworkIpRangeDaoImpl" class="com.cloud.dc.dao.StorageNetworkIpRangeDaoImpl" />
|
||||
<bean id="storagePoolDetailsDaoImpl" class="com.cloud.storage.dao.StoragePoolDetailsDaoImpl" />
|
||||
<bean id="storagePoolJoinDaoImpl" class="com.cloud.api.query.dao.StoragePoolJoinDaoImpl" />
|
||||
<bean id="storagePoolTagsDaoImpl" class="com.cloud.storage.dao.StoragePoolTagsDaoImpl" />
|
||||
<bean id="hostTagDaoImpl" class="com.cloud.api.query.dao.HostTagDaoImpl" />
|
||||
<bean id="storagePoolWorkDaoImpl" class="com.cloud.storage.dao.StoragePoolWorkDaoImpl" />
|
||||
<bean id="uploadDaoImpl" class="com.cloud.storage.dao.UploadDaoImpl" />
|
||||
@ -235,15 +208,12 @@
|
||||
<bean id="userVmDiskStatsDaoImpl" class="com.cloud.user.dao.VmDiskStatisticsDaoImpl" />
|
||||
<bean id="userVmCloneSettingDaoImpl" class="com.cloud.vm.dao.UserVmCloneSettingDaoImpl" />
|
||||
<bean id="userVmDaoImpl" class="com.cloud.vm.dao.UserVmDaoImpl" />
|
||||
<bean id="userVmDetailsDaoImpl" class="com.cloud.vm.dao.UserVmDetailsDaoImpl" />
|
||||
<bean id="userVmJoinDaoImpl" class="com.cloud.api.query.dao.UserVmJoinDaoImpl" />
|
||||
<bean id="vMComputeTagDaoImpl" class="org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMComputeTagDaoImpl" />
|
||||
<bean id="vMEntityDaoImpl" class="org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMEntityDaoImpl" />
|
||||
<bean id="vMInstanceDaoImpl" class="com.cloud.vm.dao.VMInstanceDaoImpl" />
|
||||
<bean id="vMNetworkMapDaoImpl" class="org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMNetworkMapDaoImpl" />
|
||||
<bean id="vMReservationDaoImpl" class="org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMReservationDaoImpl" />
|
||||
<bean id="vMRootDiskTagDaoImpl" class="org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMRootDiskTagDaoImpl" />
|
||||
<bean id="vMSnapshotDaoImpl" class="com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl" />
|
||||
<bean id="vMSnapshotDetailsDaoImpl" class="com.cloud.vm.snapshot.dao.VMSnapshotDetailsDaoImpl" />
|
||||
<bean id="vmStatsDaoImpl" class="com.cloud.vm.dao.VmStatsDaoImpl" />
|
||||
<bean id="vMTemplateDetailsDaoImpl" class="com.cloud.storage.dao.VMTemplateDetailsDaoImpl" />
|
||||
@ -251,7 +221,6 @@
|
||||
<bean id="vMTemplateZoneDaoImpl" class="com.cloud.storage.dao.VMTemplateZoneDaoImpl" />
|
||||
<bean id="virtualRouterProviderDaoImpl" class="com.cloud.network.dao.VirtualRouterProviderDaoImpl" />
|
||||
<bean id="vmRulesetLogDaoImpl" class="com.cloud.network.security.dao.VmRulesetLogDaoImpl" />
|
||||
<bean id="volumeDaoImpl" class="com.cloud.storage.dao.VolumeDaoImpl" />
|
||||
<bean id="volumeDetailsDaoImpl" class="com.cloud.storage.dao.VolumeDetailsDaoImpl" />
|
||||
<bean id="volumeJoinDaoImpl" class="com.cloud.api.query.dao.VolumeJoinDaoImpl" />
|
||||
<bean id="volumeReservationDaoImpl" class="org.apache.cloudstack.engine.cloud.entity.api.db.dao.VolumeReservationDaoImpl" />
|
||||
@ -263,13 +232,9 @@
|
||||
<bean id="vpcServiceMapDaoImpl" class="com.cloud.network.vpc.dao.VpcServiceMapDaoImpl" />
|
||||
<bean id="vpnUserDaoImpl" class="com.cloud.network.dao.VpnUserDaoImpl" />
|
||||
<bean id="applicationLbRuleDaoImpl" class="org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDaoImpl" />
|
||||
<bean id="networkOfferingDetailsDaoImpl" class="com.cloud.offerings.dao.NetworkOfferingDetailsDaoImpl" />
|
||||
<bean id="serviceOfferingDetailsDaoImpl" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl"/>
|
||||
<bean id="vpcOfferingDetailsDaoImpl" class="com.cloud.network.vpc.dao.VpcOfferingDetailsDaoImpl"/>
|
||||
<bean id="networkDetailsDaoImpl" class="com.cloud.network.dao.NetworkDetailsDaoImpl" />
|
||||
<bean id="vlanDetailsDaoImpl" class="com.cloud.dc.dao.VlanDetailsDaoImpl" />
|
||||
<bean id="hostGpuGroupsDaoImpl" class="com.cloud.gpu.dao.HostGpuGroupsDaoImpl" />
|
||||
<bean id="vGPUTypesDaoImpl" class="com.cloud.gpu.dao.VGPUTypesDaoImpl" />
|
||||
<bean id="AffinityGroupDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupDaoImpl" />
|
||||
<bean id="AffinityGroupVMMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDaoImpl" />
|
||||
<bean id="AffinityGroupDomainMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDaoImpl" />
|
||||
@ -283,7 +248,6 @@
|
||||
<bean id="Site2SiteVpnGatewayDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.Site2SiteVpnGatewayDetailsDaoImpl" />
|
||||
<bean id="Site2SiteCustomerGatewayDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.Site2SiteCustomerGatewayDetailsDaoImpl" />
|
||||
<bean id="Site2SiteVpnConnectionDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.Site2SiteVpnConnectionDetailsDaoImpl" />
|
||||
<bean id="DiskOfferingDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDaoImpl" />
|
||||
<bean id="UserDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.UserDetailsDaoImpl" />
|
||||
<bean id="AutoScaleVmProfileDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.AutoScaleVmProfileDetailsDaoImpl" />
|
||||
<bean id="AutoScaleVmGroupDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.AutoScaleVmGroupDetailsDaoImpl" />
|
||||
@ -293,7 +257,6 @@
|
||||
<bean id="outOfBandManagementDaoImpl" class="org.apache.cloudstack.outofbandmanagement.dao.OutOfBandManagementDaoImpl" />
|
||||
<bean id="GuestOsDetailsDaoImpl" class="org.apache.cloudstack.resourcedetail.dao.GuestOsDetailsDaoImpl" />
|
||||
<bean id="annotationDaoImpl" class="org.apache.cloudstack.annotation.dao.AnnotationDaoImpl" />
|
||||
<bean id="backupOfferingDaoImpl" class="org.apache.cloudstack.backup.dao.BackupOfferingDaoImpl" />
|
||||
<bean id="backupScheduleDaoImpl" class="org.apache.cloudstack.backup.dao.BackupScheduleDaoImpl" />
|
||||
<bean id="backupDaoImpl" class="org.apache.cloudstack.backup.dao.BackupDaoImpl" />
|
||||
<bean id="directDownloadCertificateDaoImpl" class="org.apache.cloudstack.direct.download.DirectDownloadCertificateDaoImpl" />
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
-- 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.
|
||||
|
||||
--;
|
||||
-- Schema upgrade from 4.17.0.0 to 4.18.0.0
|
||||
--;
|
||||
|
||||
----- PR Quota custom tariffs #5909---
|
||||
-- Create column 'uuid'
|
||||
ALTER TABLE cloud_usage.quota_tariff
|
||||
ADD COLUMN `uuid` varchar(40);
|
||||
|
||||
UPDATE cloud_usage.quota_tariff
|
||||
SET uuid = UUID()
|
||||
WHERE uuid is null;
|
||||
|
||||
ALTER TABLE cloud_usage.quota_tariff
|
||||
MODIFY `uuid` varchar(40) NOT NULL;
|
||||
|
||||
|
||||
-- Create column 'name'
|
||||
ALTER TABLE cloud_usage.quota_tariff
|
||||
ADD COLUMN `name` text
|
||||
COMMENT 'A name, defined by the user, to the tariff. This column will be used as identifier along the tariff updates.';
|
||||
|
||||
UPDATE cloud_usage.quota_tariff
|
||||
SET name = case when effective_on <= now() then usage_name else concat(usage_name, '-', id) end
|
||||
WHERE name is null;
|
||||
|
||||
ALTER TABLE cloud_usage.quota_tariff
|
||||
MODIFY `name` text NOT NULL;
|
||||
|
||||
|
||||
-- Create column 'description'
|
||||
ALTER TABLE cloud_usage.quota_tariff
|
||||
ADD COLUMN `description` text DEFAULT NULL
|
||||
COMMENT 'The description of the tariff.';
|
||||
|
||||
|
||||
-- Create column 'activation_rule'
|
||||
ALTER TABLE cloud_usage.quota_tariff
|
||||
ADD COLUMN `activation_rule` text DEFAULT NULL
|
||||
COMMENT 'JS expression that defines when the tariff should be activated.';
|
||||
|
||||
|
||||
-- Create column 'removed'
|
||||
ALTER TABLE cloud_usage.quota_tariff
|
||||
ADD COLUMN `removed` datetime DEFAULT NULL;
|
||||
|
||||
|
||||
-- Create column 'end_date'
|
||||
ALTER TABLE cloud_usage.quota_tariff
|
||||
ADD COLUMN `end_date` datetime DEFAULT NULL
|
||||
COMMENT 'Defines the end date of the tarrif.';
|
||||
|
||||
|
||||
-- Change usage unit to right unit
|
||||
UPDATE cloud_usage.quota_tariff
|
||||
SET usage_unit = 'Compute*Month'
|
||||
WHERE usage_unit = 'Compute-Month';
|
||||
|
||||
UPDATE cloud_usage.quota_tariff
|
||||
SET usage_unit = 'IP*Month'
|
||||
WHERE usage_unit = 'IP-Month';
|
||||
|
||||
UPDATE cloud_usage.quota_tariff
|
||||
SET usage_unit = 'GB*Month'
|
||||
WHERE usage_unit = 'GB-Month';
|
||||
|
||||
UPDATE cloud_usage.quota_tariff
|
||||
SET usage_unit = 'Policy*Month'
|
||||
WHERE usage_unit = 'Policy-Month';
|
||||
|
||||
----- PR Quota custom tariffs #5909 -----
|
||||
@ -71,7 +71,6 @@ import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import static com.cloud.storage.snapshot.SnapshotManager.BackupSnapshotAfterTakingSnapshot;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
@ -585,7 +584,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
||||
}
|
||||
Map<String, String> options = new HashMap<String, String>();
|
||||
options.put("fullSnapshot", fullSnapshot.toString());
|
||||
options.put(BackupSnapshotAfterTakingSnapshot.key(), String.valueOf(BackupSnapshotAfterTakingSnapshot.value()));
|
||||
options.put(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key(), String.valueOf(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()));
|
||||
boolean encryptionRequired = anyVolumeRequiresEncryption(srcData, destData);
|
||||
|
||||
Answer answer = null;
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
<bean id="imageStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl" />
|
||||
<bean id="imageStoreDetailsDaoImpl" class="org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDaoImpl" />
|
||||
<bean id="snapshotDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.SnapshotDataStoreDaoImpl" />
|
||||
<bean id="snapshotDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDaoImpl" />
|
||||
<bean id="templateDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.TemplateDataStoreDaoImpl" />
|
||||
<bean id="volumeDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.VolumeDataStoreDaoImpl" />
|
||||
<bean id="objectInDataStoreDaoImpl" class="org.apache.cloudstack.storage.db.ObjectInDataStoreDaoImpl" />
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
<bean id="imageStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl" />
|
||||
<bean id="imageStoreDetailsDaoImpl" class="org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDaoImpl" />
|
||||
<bean id="snapshotDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.SnapshotDataStoreDaoImpl" />
|
||||
<bean id="snapshotDataStoreDaoImpl" class="org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDaoImpl" />
|
||||
<bean id="templateDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.TemplateDataStoreDaoImpl" />
|
||||
<bean id="volumeDataStoreDaoImpl" class="org.apache.cloudstack.storage.image.db.VolumeDataStoreDaoImpl" />
|
||||
<bean id="objectInDataStoreDaoImpl" class="org.apache.cloudstack.storage.db.ObjectInDataStoreDaoImpl" />
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cloudstack.storage.image.db;
|
||||
package org.apache.cloudstack.storage.datastore.db;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
@ -25,7 +25,6 @@ import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -270,6 +270,8 @@ public interface GenericDao<T, ID extends Serializable> {
|
||||
*/
|
||||
Pair<List<T>, Integer> searchAndCount(SearchCriteria<T> sc, Filter filter);
|
||||
|
||||
Pair<List<T>, Integer> searchAndCount(SearchCriteria<T> sc, Filter filter, boolean includeRemoved);
|
||||
|
||||
/**
|
||||
* @param sc
|
||||
* @param filter
|
||||
|
||||
@ -56,7 +56,6 @@ import javax.persistence.Enumerated;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.TableGenerator;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.utils.DateUtil;
|
||||
@ -71,6 +70,8 @@ import com.cloud.utils.db.SearchCriteria.SelectType;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.net.Ip;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
|
||||
import net.sf.cglib.proxy.Callback;
|
||||
import net.sf.cglib.proxy.CallbackFilter;
|
||||
@ -1320,17 +1321,43 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB()
|
||||
public Pair<List<T>, Integer> searchAndCount(final SearchCriteria<T> sc, final Filter filter) {
|
||||
List<T> objects = search(sc, filter, null, false);
|
||||
Integer count = getCount(sc);
|
||||
// Count cannot be less than the result set but can be higher due to pagination, see CLOUDSTACK-10320
|
||||
if (count < objects.size()) {
|
||||
count = objects.size();
|
||||
return searchAndCount(sc, filter, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB()
|
||||
public Pair<List<T>, Integer> searchAndCount(SearchCriteria<T> sc, final Filter filter, boolean includeRemoved) {
|
||||
if (!includeRemoved) {
|
||||
sc = checkAndSetRemovedIsNull(sc);
|
||||
}
|
||||
|
||||
List<T> objects = searchIncludingRemoved(sc, filter, null, false);
|
||||
int count = getCountIncludingRemoved(sc);
|
||||
|
||||
count = checkCountOfRecordsAgainstTheResultSetSize(count, objects.size());
|
||||
|
||||
return new Pair<List<T>, Integer>(objects, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if the count of records is higher or equal to the result set's size.<br/><br/>
|
||||
* Count cannot be less than the result set, however, it can be higher due to pagination (see CLOUDSTACK-10320).
|
||||
* @return Count if it is higher or equal to the result set's size, otherwise the result set's size.
|
||||
*/
|
||||
protected int checkCountOfRecordsAgainstTheResultSetSize(int count, int resultSetSize) {
|
||||
if (count >= resultSetSize) {
|
||||
return count;
|
||||
}
|
||||
|
||||
String stackTrace = ExceptionUtils.getStackTrace(new CloudRuntimeException(String.format("The query to count all the records of [%s] resulted in a value smaller than"
|
||||
+ " the result set's size [count of records: %s, result set's size: %s]. Using the result set's size instead.", _entityBeanType,
|
||||
count, resultSetSize)));
|
||||
s_logger.warn(stackTrace);
|
||||
|
||||
return resultSetSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB()
|
||||
public Pair<List<T>, Integer> searchAndDistinctCount(final SearchCriteria<T> sc, final Filter filter) {
|
||||
|
||||
@ -23,6 +23,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.SearchBase.Condition;
|
||||
import com.cloud.utils.db.SearchBase.Select;
|
||||
@ -157,6 +159,12 @@ public class SearchCriteria<K> {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public void setParametersIfNotNull(String conditionName, Object... params) {
|
||||
if (ArrayUtils.isNotEmpty(params) && (params.length > 1 || params[0] != null)) {
|
||||
setParameters(conditionName, params);
|
||||
}
|
||||
}
|
||||
|
||||
public void setParameters(String conditionName, Object... params) {
|
||||
assert _conditions.contains(new Condition(conditionName)) || _additionals.contains(new Condition(conditionName)) : "Couldn't find " + conditionName;
|
||||
_params.put(conditionName, params);
|
||||
|
||||
@ -39,6 +39,8 @@ public class GenericDaoBaseTest {
|
||||
private static final String INTEGRITY_CONSTRAINT_VIOLATION = "23000";
|
||||
private static final int DUPLICATE_ENTRY_ERRO_CODE = 1062;
|
||||
|
||||
GenericDaoBase genericDaoBaseMock = Mockito.mock(GenericDaoBase.class, Mockito.CALLS_REAL_METHODS);
|
||||
|
||||
@Before
|
||||
public void prepareTests() throws SQLException {
|
||||
Mockito.when(resultSet.getObject(1)).thenReturn(false);
|
||||
@ -182,4 +184,34 @@ public class GenericDaoBaseTest {
|
||||
GenericDaoBase.handleEntityExistsException(mockedSQLException);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkCountOfRecordsAgainstTheResultSetSizeTestCountHigherThanResultSetSize() {
|
||||
int count = 10;
|
||||
int resultSetSize = 5;
|
||||
|
||||
int result = genericDaoBaseMock.checkCountOfRecordsAgainstTheResultSetSize(count, resultSetSize);
|
||||
|
||||
Assert.assertEquals(count, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkCountOfRecordsAgainstTheResultSetSizeTestCountEqualToResultSetSize() {
|
||||
int count = 10;
|
||||
int resultSetSize = 10;
|
||||
|
||||
int result = genericDaoBaseMock.checkCountOfRecordsAgainstTheResultSetSize(count, resultSetSize);
|
||||
|
||||
Assert.assertEquals(count, result);
|
||||
Assert.assertEquals(resultSetSize, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkCountOfRecordsAgainstTheResultSetSizeTestCountSmallerThanResultSetSize() {
|
||||
int count = 5;
|
||||
int resultSetSize = 10;
|
||||
|
||||
int result = genericDaoBaseMock.checkCountOfRecordsAgainstTheResultSetSize(count, resultSetSize);
|
||||
|
||||
Assert.assertEquals(resultSetSize, result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,28 +19,42 @@ package org.apache.cloudstack.quota;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableHelper;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.dao.ServiceOfferingDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.quota.vo.ServiceOfferingVO;
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
import org.apache.cloudstack.usage.UsageUnitTypes;
|
||||
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
|
||||
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.cloudstack.utils.usage.UsageUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -48,6 +62,7 @@ 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.DateUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
|
||||
@ -66,18 +81,22 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
||||
@Inject
|
||||
private QuotaUsageDao _quotaUsageDao;
|
||||
@Inject
|
||||
private ServiceOfferingDao _serviceOfferingDao;
|
||||
@Inject
|
||||
private QuotaBalanceDao _quotaBalanceDao;
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
|
||||
@Inject
|
||||
protected PresetVariableHelper presetVariableHelper;
|
||||
|
||||
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);
|
||||
static final BigDecimal s_hoursInMonth = BigDecimal.valueOf(DateUtil.HOURS_IN_A_MONTH);
|
||||
static final BigDecimal GiB_DECIMAL = BigDecimal.valueOf(ByteScaleUtils.GiB);
|
||||
List<Account.Type> lockablesAccountTypes = Arrays.asList(Account.Type.NORMAL, Account.Type.DOMAIN_ADMIN);
|
||||
|
||||
List<Integer> usageTypesToAvoidCalculation = Arrays.asList(UsageTypes.VM_DISK_IO_READ, UsageTypes.VM_DISK_IO_WRITE, UsageTypes.VM_DISK_BYTES_READ,
|
||||
UsageTypes.VM_DISK_BYTES_WRITE);
|
||||
|
||||
public QuotaManagerImpl() {
|
||||
super();
|
||||
@ -133,342 +152,408 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<QuotaUsageVO> aggregatePendingQuotaRecordsForAccount(final AccountVO account, final Pair<List<? extends UsageVO>, Integer> usageRecords) {
|
||||
List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
|
||||
if (usageRecords == null || usageRecords.first() == null || usageRecords.first().isEmpty()) {
|
||||
return quotaListForAccount;
|
||||
}
|
||||
s_logger.info("Getting pending quota records for account=" + account.getAccountName());
|
||||
for (UsageVO usageRecord : usageRecords.first()) {
|
||||
switch (usageRecord.getUsageType()) {
|
||||
case QuotaTypes.RUNNING_VM:
|
||||
List<QuotaUsageVO> lq = updateQuotaRunningVMUsage(usageRecord);
|
||||
if (!lq.isEmpty()) {
|
||||
quotaListForAccount.addAll(lq);
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.ALLOCATED_VM:
|
||||
QuotaUsageVO qu = updateQuotaAllocatedVMUsage(usageRecord);
|
||||
if (qu != null) {
|
||||
quotaListForAccount.add(qu);
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.SNAPSHOT:
|
||||
case QuotaTypes.TEMPLATE:
|
||||
case QuotaTypes.ISO:
|
||||
case QuotaTypes.VOLUME:
|
||||
case QuotaTypes.VM_SNAPSHOT:
|
||||
case QuotaTypes.BACKUP:
|
||||
qu = updateQuotaDiskUsage(usageRecord, usageRecord.getUsageType());
|
||||
if (qu != null) {
|
||||
quotaListForAccount.add(qu);
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.LOAD_BALANCER_POLICY:
|
||||
case QuotaTypes.PORT_FORWARDING_RULE:
|
||||
case QuotaTypes.IP_ADDRESS:
|
||||
case QuotaTypes.NETWORK_OFFERING:
|
||||
case QuotaTypes.SECURITY_GROUP:
|
||||
case QuotaTypes.VPN_USERS:
|
||||
qu = updateQuotaRaw(usageRecord, usageRecord.getUsageType());
|
||||
if (qu != null) {
|
||||
quotaListForAccount.add(qu);
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.NETWORK_BYTES_RECEIVED:
|
||||
case QuotaTypes.NETWORK_BYTES_SENT:
|
||||
qu = updateQuotaNetwork(usageRecord, usageRecord.getUsageType());
|
||||
if (qu != null) {
|
||||
quotaListForAccount.add(qu);
|
||||
}
|
||||
break;
|
||||
case QuotaTypes.VM_DISK_IO_READ:
|
||||
case QuotaTypes.VM_DISK_IO_WRITE:
|
||||
case QuotaTypes.VM_DISK_BYTES_READ:
|
||||
case QuotaTypes.VM_DISK_BYTES_WRITE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return quotaListForAccount;
|
||||
}
|
||||
protected void processQuotaBalanceForAccount(AccountVO accountVo, List<QuotaUsageVO> accountQuotaUsages) {
|
||||
String accountToString = accountVo.reflectionToString();
|
||||
|
||||
public void processQuotaBalanceForAccount(final AccountVO account, final List<QuotaUsageVO> quotaListForAccount) {
|
||||
if (quotaListForAccount == null || quotaListForAccount.isEmpty()) {
|
||||
if (CollectionUtils.isEmpty(accountQuotaUsages)) {
|
||||
s_logger.info(String.format("Account [%s] does not have quota usages to process. Skipping it.", accountToString));
|
||||
return;
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(quotaListForAccount.get(0));
|
||||
}
|
||||
Date startDate = quotaListForAccount.get(0).getStartDate();
|
||||
Date endDate = quotaListForAccount.get(0).getEndDate();
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("processQuotaBalanceForAccount startDate " + startDate + " endDate=" + endDate);
|
||||
s_logger.debug("processQuotaBalanceForAccount last items startDate " + quotaListForAccount.get(quotaListForAccount.size() - 1).getStartDate() + " items endDate="
|
||||
+ quotaListForAccount.get(quotaListForAccount.size() - 1).getEndDate());
|
||||
}
|
||||
quotaListForAccount.add(new QuotaUsageVO());
|
||||
BigDecimal aggrUsage = new BigDecimal(0);
|
||||
List<QuotaBalanceVO> creditsReceived = null;
|
||||
|
||||
//bootstrapping
|
||||
QuotaUsageVO lastQuotaUsage = _quotaUsageDao.findLastQuotaUsageEntry(account.getAccountId(), account.getDomainId(), startDate);
|
||||
if (lastQuotaUsage == null) {
|
||||
aggrUsage = aggrUsage.add(aggregateCreditBetweenDates(account, new Date(0), startDate));
|
||||
// create a balance entry for these accumulated credits
|
||||
QuotaBalanceVO firstBalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, startDate);
|
||||
_quotaBalanceDao.saveQuotaBalance(firstBalance);
|
||||
} else {
|
||||
QuotaBalanceVO lastRealBalanceEntry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), endDate);
|
||||
if (lastRealBalanceEntry != null){
|
||||
aggrUsage = aggrUsage.add(lastRealBalanceEntry.getCreditBalance());
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Last balance entry " + lastRealBalanceEntry + " AggrUsage=" + aggrUsage);
|
||||
}
|
||||
// get all the credit entries after this balance and add
|
||||
aggrUsage = aggrUsage.add(aggregateCreditBetweenDates(account, lastRealBalanceEntry.getUpdatedOn(), endDate));
|
||||
}
|
||||
QuotaUsageVO firstQuotaUsage = accountQuotaUsages.get(0);
|
||||
Date startDate = firstQuotaUsage.getStartDate();
|
||||
Date endDate = firstQuotaUsage.getStartDate();
|
||||
|
||||
for (QuotaUsageVO entry : quotaListForAccount) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Usage entry found " + entry);
|
||||
}
|
||||
if (entry.getQuotaUsed().compareTo(BigDecimal.ZERO) == 0) {
|
||||
// check if there were credits and aggregate
|
||||
aggrUsage = aggrUsage.add(aggregateCreditBetweenDates(account, entry.getStartDate(), entry.getEndDate()));
|
||||
s_logger.info(String.format("Processing quota balance for account [%s] between [%s] and [%s].", accountToString, startDate,
|
||||
accountQuotaUsages.get(accountQuotaUsages.size() - 1).getEndDate()));
|
||||
|
||||
BigDecimal aggregatedUsage = BigDecimal.ZERO;
|
||||
long accountId = accountVo.getAccountId();
|
||||
long domainId = accountVo.getDomainId();
|
||||
|
||||
aggregatedUsage = getUsageValueAccordingToLastQuotaUsageEntryAndLastQuotaBalance(accountId, domainId, startDate, endDate, aggregatedUsage, accountToString);
|
||||
|
||||
for (QuotaUsageVO quotaUsage : accountQuotaUsages) {
|
||||
Date quotaUsageStartDate = quotaUsage.getStartDate();
|
||||
Date quotaUsageEndDate = quotaUsage.getEndDate();
|
||||
BigDecimal quotaUsed = quotaUsage.getQuotaUsed();
|
||||
|
||||
if (quotaUsed.equals(BigDecimal.ZERO)) {
|
||||
aggregatedUsage = aggregatedUsage.add(aggregateCreditBetweenDates(accountId, domainId, quotaUsageStartDate, quotaUsageEndDate, accountToString));
|
||||
continue;
|
||||
}
|
||||
if (startDate.compareTo(entry.getStartDate()) != 0) {
|
||||
saveQuotaBalance(account, aggrUsage, endDate);
|
||||
|
||||
//New balance entry
|
||||
aggrUsage = new BigDecimal(0);
|
||||
startDate = entry.getStartDate();
|
||||
endDate = entry.getEndDate();
|
||||
if (startDate.compareTo(quotaUsageStartDate) == 0) {
|
||||
aggregatedUsage = aggregatedUsage.subtract(quotaUsed);
|
||||
continue;
|
||||
}
|
||||
|
||||
QuotaBalanceVO lastRealBalanceEntry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), endDate);
|
||||
_quotaBalanceDao.saveQuotaBalance(new QuotaBalanceVO(accountId, domainId, aggregatedUsage, endDate));
|
||||
|
||||
aggregatedUsage = BigDecimal.ZERO;
|
||||
startDate = quotaUsageStartDate;
|
||||
endDate = quotaUsageEndDate;
|
||||
|
||||
QuotaBalanceVO lastRealBalanceEntry = _quotaBalanceDao.findLastBalanceEntry(accountId, domainId, endDate);
|
||||
Date lastBalanceDate = new Date(0);
|
||||
|
||||
if (lastRealBalanceEntry != null) {
|
||||
lastBalanceDate = lastRealBalanceEntry.getUpdatedOn();
|
||||
aggrUsage = aggrUsage.add(lastRealBalanceEntry.getCreditBalance());
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Getting Balance" + account.getAccountName() + ",Balance entry=" + aggrUsage + " on Date=" + endDate);
|
||||
}
|
||||
aggrUsage = aggrUsage.add(aggregateCreditBetweenDates(account, lastBalanceDate, endDate));
|
||||
}
|
||||
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
|
||||
}
|
||||
saveQuotaBalance(account, aggrUsage, endDate);
|
||||
|
||||
// update quota_balance
|
||||
saveQuotaAccount(account, aggrUsage, endDate);
|
||||
aggregatedUsage = aggregatedUsage.add(lastRealBalanceEntry.getCreditBalance());
|
||||
}
|
||||
|
||||
private QuotaBalanceVO saveQuotaBalance(final AccountVO account, final BigDecimal aggrUsage, final Date endDate) {
|
||||
QuotaBalanceVO newBalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, endDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Saving Balance" + newBalance);
|
||||
}
|
||||
return _quotaBalanceDao.saveQuotaBalance(newBalance);
|
||||
aggregatedUsage = aggregatedUsage.add(aggregateCreditBetweenDates(accountId, domainId, lastBalanceDate, endDate, accountToString));
|
||||
aggregatedUsage = aggregatedUsage.subtract(quotaUsed);
|
||||
}
|
||||
|
||||
private boolean saveQuotaAccount(final AccountVO account, final BigDecimal aggrUsage, final Date endDate) {
|
||||
// update quota_accounts
|
||||
QuotaAccountVO quota_account = _quotaAcc.findByIdQuotaAccount(account.getAccountId());
|
||||
|
||||
if (quota_account == null) {
|
||||
quota_account = new QuotaAccountVO(account.getAccountId());
|
||||
quota_account.setQuotaBalance(aggrUsage);
|
||||
quota_account.setQuotaBalanceDate(endDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(quota_account);
|
||||
_quotaBalanceDao.saveQuotaBalance(new QuotaBalanceVO(accountId, domainId, aggregatedUsage, endDate));
|
||||
saveQuotaAccount(accountId, aggregatedUsage, endDate);
|
||||
}
|
||||
_quotaAcc.persistQuotaAccount(quota_account);
|
||||
return true;
|
||||
|
||||
protected BigDecimal getUsageValueAccordingToLastQuotaUsageEntryAndLastQuotaBalance(long accountId, long domainId, Date startDate, Date endDate, BigDecimal aggregatedUsage,
|
||||
String accountToString) {
|
||||
QuotaUsageVO lastQuotaUsage = _quotaUsageDao.findLastQuotaUsageEntry(accountId, domainId, startDate);
|
||||
|
||||
if (lastQuotaUsage == null) {
|
||||
aggregatedUsage = aggregatedUsage.add(aggregateCreditBetweenDates(accountId, domainId, new Date(0), startDate, accountToString));
|
||||
QuotaBalanceVO firstBalance = new QuotaBalanceVO(accountId, domainId, aggregatedUsage, startDate);
|
||||
|
||||
s_logger.debug(String.format("Persisting the first quota balance [%s] for account [%s].", firstBalance, accountToString));
|
||||
_quotaBalanceDao.saveQuotaBalance(firstBalance);
|
||||
} else {
|
||||
quota_account.setQuotaBalance(aggrUsage);
|
||||
quota_account.setQuotaBalanceDate(endDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(quota_account);
|
||||
}
|
||||
return _quotaAcc.updateQuotaAccount(account.getAccountId(), quota_account);
|
||||
QuotaBalanceVO lastRealBalance = _quotaBalanceDao.findLastBalanceEntry(accountId, domainId, endDate);
|
||||
|
||||
if (lastRealBalance != null) {
|
||||
aggregatedUsage = aggregatedUsage.add(lastRealBalance.getCreditBalance());
|
||||
aggregatedUsage = aggregatedUsage.add(aggregateCreditBetweenDates(accountId, domainId, lastRealBalance.getUpdatedOn(), endDate, accountToString));
|
||||
} else {
|
||||
s_logger.warn(String.format("Account [%s] has quota usage entries, however it does not have a quota balance.", accountToString));
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal aggregateCreditBetweenDates(final AccountVO account, final Date startDate, final Date endDate) {
|
||||
BigDecimal aggrUsage = new BigDecimal(0);
|
||||
List<QuotaBalanceVO> creditsReceived = null;
|
||||
creditsReceived = _quotaBalanceDao.findCreditBalance(account.getAccountId(), account.getDomainId(), startDate, endDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Credit entries count " + creditsReceived.size() + " on Before Date=" + endDate);
|
||||
return aggregatedUsage;
|
||||
}
|
||||
if (creditsReceived != null) {
|
||||
|
||||
protected void saveQuotaAccount(long accountId, BigDecimal aggregatedUsage, Date endDate) {
|
||||
QuotaAccountVO quotaAccount = _quotaAcc.findByIdQuotaAccount(accountId);
|
||||
|
||||
if (quotaAccount != null) {
|
||||
quotaAccount.setQuotaBalance(aggregatedUsage);
|
||||
quotaAccount.setQuotaBalanceDate(endDate);
|
||||
_quotaAcc.updateQuotaAccount(accountId, quotaAccount);
|
||||
return;
|
||||
}
|
||||
|
||||
quotaAccount = new QuotaAccountVO(accountId);
|
||||
quotaAccount.setQuotaBalance(aggregatedUsage);
|
||||
quotaAccount.setQuotaBalanceDate(endDate);
|
||||
_quotaAcc.persistQuotaAccount(quotaAccount);
|
||||
}
|
||||
|
||||
protected BigDecimal aggregateCreditBetweenDates(Long accountId, Long domainId, Date startDate, Date endDate, String accountToString) {
|
||||
List<QuotaBalanceVO> creditsReceived = _quotaBalanceDao.findCreditBalance(accountId, domainId, startDate, endDate);
|
||||
s_logger.debug(String.format("Account [%s] has [%s] credit entries before [%s].", accountToString, creditsReceived.size(), endDate));
|
||||
|
||||
BigDecimal aggregatedUsage = BigDecimal.ZERO;
|
||||
|
||||
s_logger.debug(String.format("Aggregating the account [%s] credit entries before [%s].", accountToString, endDate));
|
||||
|
||||
for (QuotaBalanceVO credit : creditsReceived) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Credit entry found " + credit);
|
||||
s_logger.debug("Total = " + aggrUsage);
|
||||
aggregatedUsage = aggregatedUsage.add(credit.getCreditBalance());
|
||||
}
|
||||
aggrUsage = aggrUsage.add(credit.getCreditBalance());
|
||||
}
|
||||
}
|
||||
return aggrUsage;
|
||||
|
||||
s_logger.debug(String.format("The aggregation of the account [%s] credit entries before [%s] resulted in the value [%s].", accountToString, endDate, aggregatedUsage));
|
||||
|
||||
return aggregatedUsage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean calculateQuotaUsage() {
|
||||
List<AccountVO> accounts = _accountDao.listAll();
|
||||
String accountsToString = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(accounts, "id", "uuid", "accountName", "domainId");
|
||||
|
||||
s_logger.info(String.format("Starting quota usage calculation for accounts [%s].", accountsToString));
|
||||
|
||||
Map<Integer, Pair<List<QuotaTariffVO>, Boolean>> mapQuotaTariffsPerUsageType = createMapQuotaTariffsPerUsageType();
|
||||
|
||||
for (AccountVO account : accounts) {
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = _usageDao.getUsageRecordsPendingQuotaAggregation(account.getAccountId(), account.getDomainId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Usage entries size = " + usageRecords.second().intValue() + ", accId" + account.getAccountId() + ", domId" + account.getDomainId());
|
||||
List<UsageVO> usageRecords = getPendingUsageRecordsForQuotaAggregation(account);
|
||||
|
||||
if (usageRecords == null) {
|
||||
s_logger.debug(String.format("Account [%s] does not have pending usage records. Skipping to next account.", account.reflectionToString()));
|
||||
continue;
|
||||
}
|
||||
List<QuotaUsageVO> quotaListForAccount = aggregatePendingQuotaRecordsForAccount(account, usageRecords);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Quota entries size = " + quotaListForAccount.size() + ", accId" + account.getAccountId() + ", domId" + account.getDomainId());
|
||||
}
|
||||
processQuotaBalanceForAccount(account, quotaListForAccount);
|
||||
|
||||
List<QuotaUsageVO> quotaUsages = createQuotaUsagesAccordingToQuotaTariffs(account, usageRecords, mapQuotaTariffsPerUsageType);
|
||||
processQuotaBalanceForAccount(account, quotaUsages);
|
||||
}
|
||||
|
||||
s_logger.info(String.format("Finished quota usage calculation for accounts [%s].", accountsToString));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public QuotaUsageVO updateQuotaDiskUsage(UsageVO usageRecord, final int quotaType) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(quotaType, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal quotaUsgage;
|
||||
BigDecimal onehourcostpergb;
|
||||
BigDecimal noofgbinuse;
|
||||
onehourcostpergb = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
|
||||
noofgbinuse = new BigDecimal(usageRecord.getSize()).divide(s_gb, 8, RoundingMode.HALF_EVEN);
|
||||
quotaUsgage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcostpergb).multiply(noofgbinuse);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), usageRecord.getUsageType(),
|
||||
quotaUsgage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
}
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quota_usage;
|
||||
protected List<UsageVO> getPendingUsageRecordsForQuotaAggregation(AccountVO account) {
|
||||
Long accountId = account.getId();
|
||||
Long domainId = account.getDomainId();
|
||||
|
||||
Pair<List<UsageVO>, Integer> usageRecords = _usageDao.listUsageRecordsPendingForQuotaAggregation(accountId, domainId);
|
||||
|
||||
List<UsageVO> records = usageRecords.first();
|
||||
if (CollectionUtils.isEmpty(records)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<QuotaUsageVO> updateQuotaRunningVMUsage(UsageVO usageRecord) {
|
||||
List<QuotaUsageVO> quotalist = new ArrayList<QuotaUsageVO>();
|
||||
QuotaUsageVO quota_usage;
|
||||
BigDecimal cpuquotausgage, speedquotausage, memoryquotausage, vmusage;
|
||||
BigDecimal onehourcostpercpu, onehourcostper100mhz, onehourcostper1mb, onehourcostforvmusage;
|
||||
BigDecimal rawusage;
|
||||
// get service offering details
|
||||
ServiceOfferingVO serviceoffering = _serviceOfferingDao.findServiceOffering(usageRecord.getVmInstanceId(), usageRecord.getOfferingId());
|
||||
if (serviceoffering == null) {
|
||||
return quotalist;
|
||||
}
|
||||
rawusage = new BigDecimal(usageRecord.getRawUsage());
|
||||
s_logger.debug(String.format("Retrieved [%s] pending usage records for account [%s].", usageRecords.second(), account.reflectionToString()));
|
||||
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_NUMBER, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getCpu() != null) {
|
||||
BigDecimal cpu = new BigDecimal(serviceoffering.getCpu());
|
||||
onehourcostpercpu = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
|
||||
cpuquotausgage = rawusage.multiply(onehourcostpercpu).multiply(cpu);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.CPU_NUMBER,
|
||||
cpuquotausgage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
quotalist.add(quota_usage);
|
||||
}
|
||||
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_CLOCK_RATE, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getSpeed() != null) {
|
||||
BigDecimal speed = new BigDecimal(serviceoffering.getSpeed()*serviceoffering.getCpu() / 100.00);
|
||||
onehourcostper100mhz = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
|
||||
speedquotausage = rawusage.multiply(onehourcostper100mhz).multiply(speed);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.CPU_CLOCK_RATE,
|
||||
speedquotausage, usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
quotalist.add(quota_usage);
|
||||
}
|
||||
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.MEMORY, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getRamSize() != null) {
|
||||
BigDecimal memory = new BigDecimal(serviceoffering.getRamSize());
|
||||
onehourcostper1mb = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
|
||||
memoryquotausage = rawusage.multiply(onehourcostper1mb).multiply(memory);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.MEMORY, memoryquotausage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
quotalist.add(quota_usage);
|
||||
}
|
||||
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.RUNNING_VM, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
onehourcostforvmusage = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
|
||||
vmusage = rawusage.multiply(onehourcostforvmusage);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.RUNNING_VM, vmusage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
quotalist.add(quota_usage);
|
||||
return records;
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quotalist;
|
||||
protected List<QuotaUsageVO> createQuotaUsagesAccordingToQuotaTariffs(AccountVO account, List<UsageVO> usageRecords,
|
||||
Map<Integer, Pair<List<QuotaTariffVO>, Boolean>> mapQuotaTariffsPerUsageType) {
|
||||
String accountToString = account.reflectionToString();
|
||||
s_logger.info(String.format("Calculating quota usage of [%s] usage records for account [%s].", usageRecords.size(), accountToString));
|
||||
|
||||
List<Pair<UsageVO, QuotaUsageVO>> pairsUsageAndQuotaUsage = new ArrayList<>();
|
||||
|
||||
try (JsInterpreter jsInterpreter = new JsInterpreter(QuotaConfig.QuotaActivationRuleTimeout.value())) {
|
||||
for (UsageVO usageRecord : usageRecords) {
|
||||
int usageType = usageRecord.getUsageType();
|
||||
|
||||
if (usageTypesToAvoidCalculation.contains(usageType)) {
|
||||
s_logger.debug(String.format("Considering usage record [%s] as calculated and skipping it because the calculation of the types [%s] has not been implemented yet.",
|
||||
usageRecord.toString(), usageTypesToAvoidCalculation));
|
||||
pairsUsageAndQuotaUsage.add(new Pair<>(usageRecord, null));
|
||||
continue;
|
||||
}
|
||||
|
||||
public QuotaUsageVO updateQuotaAllocatedVMUsage(UsageVO usageRecord) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.ALLOCATED_VM, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal vmusage;
|
||||
BigDecimal onehourcostforvmusage;
|
||||
onehourcostforvmusage = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
|
||||
vmusage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcostforvmusage);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.ALLOCATED_VM, vmusage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
Pair<List<QuotaTariffVO>, Boolean> pairQuotaTariffsPerUsageTypeAndHasActivationRule = mapQuotaTariffsPerUsageType.get(usageType);
|
||||
List<QuotaTariffVO> quotaTariffs = pairQuotaTariffsPerUsageTypeAndHasActivationRule.first();
|
||||
boolean hasAnyQuotaTariffWithActivationRule = pairQuotaTariffsPerUsageTypeAndHasActivationRule.second();
|
||||
|
||||
BigDecimal aggregatedQuotaTariffsValue = aggregateQuotaTariffsValues(usageRecord, quotaTariffs, hasAnyQuotaTariffWithActivationRule, jsInterpreter, accountToString);
|
||||
|
||||
QuotaUsageVO quotaUsage = createQuotaUsageAccordingToUsageUnit(usageRecord, aggregatedQuotaTariffsValue, accountToString);
|
||||
|
||||
pairsUsageAndQuotaUsage.add(new Pair<>(usageRecord, quotaUsage));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.error(String.format("Failed to calculate the quota usage for account [%s] due to [%s].", accountToString, e.getMessage()), e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quota_usage;
|
||||
return persistUsagesAndQuotaUsagesAndRetrievePersistedQuotaUsages(pairsUsageAndQuotaUsage);
|
||||
}
|
||||
|
||||
public QuotaUsageVO updateQuotaRaw(UsageVO usageRecord, final int ruleType) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(ruleType, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal ruleusage;
|
||||
BigDecimal onehourcost;
|
||||
onehourcost = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
|
||||
ruleusage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcost);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), ruleType, ruleusage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
protected List<QuotaUsageVO> persistUsagesAndQuotaUsagesAndRetrievePersistedQuotaUsages(List<Pair<UsageVO, QuotaUsageVO>> pairsUsageAndQuotaUsage) {
|
||||
List<QuotaUsageVO> quotaUsages = new ArrayList<>();
|
||||
|
||||
for (Pair<UsageVO, QuotaUsageVO> pairUsageAndQuotaUsage : pairsUsageAndQuotaUsage) {
|
||||
UsageVO usageVo = pairUsageAndQuotaUsage.first();
|
||||
usageVo.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageVo);
|
||||
|
||||
QuotaUsageVO quotaUsageVo = pairUsageAndQuotaUsage.second();
|
||||
if (quotaUsageVo != null) {
|
||||
_quotaUsageDao.persistQuotaUsage(quotaUsageVo);
|
||||
quotaUsages.add(quotaUsageVo);
|
||||
}
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quota_usage;
|
||||
return quotaUsages;
|
||||
}
|
||||
|
||||
public QuotaUsageVO updateQuotaNetwork(UsageVO usageRecord, final int transferType) {
|
||||
QuotaUsageVO quota_usage = null;
|
||||
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(transferType, usageRecord.getEndDate());
|
||||
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
|
||||
BigDecimal onegbcost;
|
||||
BigDecimal rawusageingb;
|
||||
BigDecimal networkusage;
|
||||
onegbcost = tariff.getCurrencyValue();
|
||||
rawusageingb = new BigDecimal(usageRecord.getRawUsage()).divide(s_gb, 8, RoundingMode.HALF_EVEN);
|
||||
networkusage = rawusageingb.multiply(onegbcost);
|
||||
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), transferType, networkusage,
|
||||
usageRecord.getStartDate(), usageRecord.getEndDate());
|
||||
_quotaUsageDao.persistQuotaUsage(quota_usage);
|
||||
protected BigDecimal aggregateQuotaTariffsValues(UsageVO usageRecord, List<QuotaTariffVO> quotaTariffs, boolean hasAnyQuotaTariffWithActivationRule,
|
||||
JsInterpreter jsInterpreter, String accountToString) {
|
||||
String usageRecordToString = usageRecord.toString();
|
||||
s_logger.debug(String.format("Validating usage record [%s] for account [%s] against [%s] quota tariffs.", usageRecordToString, accountToString,
|
||||
quotaTariffs.size()));
|
||||
|
||||
PresetVariables presetVariables = getPresetVariables(hasAnyQuotaTariffWithActivationRule, usageRecord);
|
||||
BigDecimal aggregatedQuotaTariffsValue = BigDecimal.ZERO;
|
||||
|
||||
for (QuotaTariffVO quotaTariff : quotaTariffs) {
|
||||
if (isQuotaTariffInPeriodToBeApplied(usageRecord, quotaTariff, accountToString)) {
|
||||
aggregatedQuotaTariffsValue = aggregatedQuotaTariffsValue.add(getQuotaTariffValueToBeApplied(quotaTariff, jsInterpreter, presetVariables));
|
||||
}
|
||||
}
|
||||
|
||||
usageRecord.setQuotaCalculated(1);
|
||||
_usageDao.persistUsage(usageRecord);
|
||||
return quota_usage;
|
||||
s_logger.debug(String.format("The aggregation of the quota tariffs resulted in the value [%s] for the usage record [%s]. We will use this value to calculate the final"
|
||||
+ " usage value.", aggregatedQuotaTariffsValue, usageRecordToString));
|
||||
|
||||
return aggregatedQuotaTariffsValue;
|
||||
}
|
||||
|
||||
protected PresetVariables getPresetVariables(boolean hasAnyQuotaTariffWithActivationRule, UsageVO usageRecord) {
|
||||
if (hasAnyQuotaTariffWithActivationRule) {
|
||||
return presetVariableHelper.getPresetVariables(usageRecord);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quota tariff value according to the result of the activation rule.<br/>
|
||||
* <ul>
|
||||
* <li>If the activation rule is null or empty, returns {@link QuotaTariffVO#getCurrencyValue()}.</li>
|
||||
* <li>If the activation rule result in a number, returns it.</li>
|
||||
* <li>If the activation rule result in a boolean and its is true, returns {@link QuotaTariffVO#getCurrencyValue()}.</li>
|
||||
* <li>If the activation rule result in a boolean and its is false, returns {@link BigDecimal#ZERO}.</li>
|
||||
* <li>If the activation rule result in something else, returns {@link BigDecimal#ZERO}.</li>
|
||||
* </ul>
|
||||
*/
|
||||
protected BigDecimal getQuotaTariffValueToBeApplied(QuotaTariffVO quotaTariff, JsInterpreter jsInterpreter, PresetVariables presetVariables) {
|
||||
String activationRule = quotaTariff.getActivationRule();
|
||||
BigDecimal quotaTariffValue = quotaTariff.getCurrencyValue();
|
||||
String quotaTariffToString = quotaTariff.toString();
|
||||
|
||||
if (StringUtils.isEmpty(activationRule)) {
|
||||
s_logger.debug(String.format("Quota tariff [%s] does not have an activation rule, therefore we will use the quota tariff value [%s] in the calculation.",
|
||||
quotaTariffToString, quotaTariffValue));
|
||||
return quotaTariffValue;
|
||||
}
|
||||
|
||||
injectPresetVariablesIntoJsInterpreter(jsInterpreter, presetVariables);
|
||||
|
||||
String scriptResult = jsInterpreter.executeScript(activationRule).toString();
|
||||
|
||||
if (NumberUtils.isParsable(scriptResult)) {
|
||||
s_logger.debug(String.format("The script [%s] of quota tariff [%s] had a numeric value [%s], therefore we will use it in the calculation.", activationRule,
|
||||
quotaTariffToString, scriptResult));
|
||||
|
||||
return new BigDecimal(scriptResult);
|
||||
}
|
||||
|
||||
if (BooleanUtils.toBoolean(scriptResult)) {
|
||||
s_logger.debug(String.format("The script [%s] of quota tariff [%s] had a true boolean result, therefore we will use the quota tariff's value [%s] in the calculation.",
|
||||
activationRule, quotaTariffToString, quotaTariffValue));
|
||||
|
||||
return quotaTariffValue;
|
||||
}
|
||||
|
||||
s_logger.debug(String.format("The script [%s] of quota tariff [%s] had the result [%s], therefore we will not use this quota tariff in the calculation.", activationRule,
|
||||
quotaTariffToString, quotaTariffValue));
|
||||
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the preset variables into the JS interpreter.
|
||||
*/
|
||||
protected void injectPresetVariablesIntoJsInterpreter(JsInterpreter jsInterpreter, PresetVariables presetVariables) {
|
||||
jsInterpreter.discardCurrentVariables();
|
||||
|
||||
jsInterpreter.injectVariable("account", presetVariables.getAccount().toString());
|
||||
jsInterpreter.injectVariable("domain", presetVariables.getDomain().toString());
|
||||
|
||||
GenericPresetVariable project = presetVariables.getProject();
|
||||
if (project != null) {
|
||||
jsInterpreter.injectVariable("project", project.toString());
|
||||
|
||||
}
|
||||
|
||||
jsInterpreter.injectVariable("resourceType", presetVariables.getResourceType());
|
||||
jsInterpreter.injectVariable("value", presetVariables.getValue().toString());
|
||||
jsInterpreter.injectVariable("zone", presetVariables.getZone().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the quota tariff should be applied on the usage record according to their respectively start and end date.<br/><br/>
|
||||
*/
|
||||
protected boolean isQuotaTariffInPeriodToBeApplied(UsageVO usageRecord, QuotaTariffVO quotaTariff, String accountToString) {
|
||||
Date usageRecordStartDate = usageRecord.getStartDate();
|
||||
Date usageRecordEndDate = usageRecord.getEndDate();
|
||||
Date quotaTariffStartDate = quotaTariff.getEffectiveOn();
|
||||
Date quotaTariffEndDate = quotaTariff.getEndDate();
|
||||
|
||||
if ((quotaTariffEndDate != null && usageRecordStartDate.after(quotaTariffEndDate)) || usageRecordEndDate.before(quotaTariffStartDate)) {
|
||||
s_logger.debug(String.format("Not applying quota tariff [%s] in usage record [%s] of account [%s] due to it is out of the period to be applied. Period of the usage"
|
||||
+ " record [startDate: %s, endDate: %s], period of the quota tariff [startDate: %s, endDate: %s].", quotaTariff, usageRecord.toString(), accountToString,
|
||||
DateUtil.getOutputString(usageRecordStartDate), DateUtil.getOutputString(usageRecordEndDate), DateUtil.getOutputString(quotaTariffStartDate),
|
||||
DateUtil.getOutputString(quotaTariffEndDate)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Map<Integer, Pair<List<QuotaTariffVO>, Boolean>> createMapQuotaTariffsPerUsageType() {
|
||||
List<QuotaTariffVO> quotaTariffs = _quotaTariffDao.listQuotaTariffs(null, null, null, null, null, false, null, null).first();
|
||||
|
||||
Map<Integer, Pair<List<QuotaTariffVO>, Boolean>> mapQuotaTariffsPerUsageType = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Integer, QuotaTypes> entry : QuotaTypes.listQuotaTypes().entrySet()) {
|
||||
int quotaType = entry.getKey();
|
||||
|
||||
List<QuotaTariffVO> quotaTariffsFiltered = quotaTariffs.stream().filter(quotaTariff -> quotaTariff.getUsageType() == quotaType).collect(Collectors.toList());
|
||||
Boolean hasAnyQuotaTariffWithActivationRule = quotaTariffsFiltered.stream().anyMatch(quotaTariff -> StringUtils.isNotEmpty(quotaTariff.getActivationRule()));
|
||||
|
||||
mapQuotaTariffsPerUsageType.put(quotaType, new Pair<>(quotaTariffsFiltered, hasAnyQuotaTariffWithActivationRule));
|
||||
}
|
||||
|
||||
return mapQuotaTariffsPerUsageType;
|
||||
}
|
||||
|
||||
protected QuotaUsageVO createQuotaUsageAccordingToUsageUnit(UsageVO usageRecord, BigDecimal aggregatedQuotaTariffsValue, String accountToString) {
|
||||
String usageRecordToString = usageRecord.toString();
|
||||
|
||||
if (aggregatedQuotaTariffsValue.equals(BigDecimal.ZERO)) {
|
||||
s_logger.debug(String.format("Usage record [%s] for account [%s] does not have quota tariffs to be calculated, therefore we will mark it as calculated.",
|
||||
usageRecordToString, accountToString));
|
||||
return null;
|
||||
}
|
||||
|
||||
QuotaTypes quotaType = QuotaTypes.listQuotaTypes().get(usageRecord.getUsageType());
|
||||
String quotaUnit = quotaType.getQuotaUnit();
|
||||
|
||||
s_logger.debug(String.format("Calculating value of usage record [%s] for account [%s] according to the aggregated quota tariffs value [%s] and its usage unit [%s].",
|
||||
usageRecordToString, accountToString, aggregatedQuotaTariffsValue, quotaUnit));
|
||||
|
||||
BigDecimal usageValue = getUsageValueAccordingToUsageUnitType(usageRecord, aggregatedQuotaTariffsValue, quotaUnit);
|
||||
|
||||
s_logger.debug(String.format("The calculation of the usage record [%s] for account [%s] according to the aggregated quota tariffs value [%s] and its usage unit [%s] "
|
||||
+ "resulted in the value [%s].", usageRecordToString, accountToString, aggregatedQuotaTariffsValue, quotaUnit, usageValue));
|
||||
|
||||
QuotaUsageVO quotaUsageVo = new QuotaUsageVO();
|
||||
quotaUsageVo.setUsageItemId(usageRecord.getId());
|
||||
quotaUsageVo.setZoneId(usageRecord.getZoneId());
|
||||
quotaUsageVo.setAccountId(usageRecord.getAccountId());
|
||||
quotaUsageVo.setDomainId(usageRecord.getDomainId());
|
||||
quotaUsageVo.setUsageType(quotaType.getQuotaType());
|
||||
quotaUsageVo.setQuotaUsed(usageValue);
|
||||
quotaUsageVo.setStartDate(usageRecord.getStartDate());
|
||||
quotaUsageVo.setEndDate(usageRecord.getEndDate());
|
||||
|
||||
return quotaUsageVo;
|
||||
}
|
||||
|
||||
protected BigDecimal getUsageValueAccordingToUsageUnitType(UsageVO usageRecord, BigDecimal aggregatedQuotaTariffsValue, String quotaUnit) {
|
||||
BigDecimal rawUsage = BigDecimal.valueOf(usageRecord.getRawUsage());
|
||||
BigDecimal costPerHour = aggregatedQuotaTariffsValue.divide(s_hoursInMonth, 8, RoundingMode.HALF_EVEN);
|
||||
|
||||
switch (UsageUnitTypes.getByDescription(quotaUnit)) {
|
||||
case COMPUTE_MONTH:
|
||||
case IP_MONTH:
|
||||
case POLICY_MONTH:
|
||||
return rawUsage.multiply(costPerHour);
|
||||
|
||||
case GB:
|
||||
BigDecimal rawUsageInGb = rawUsage.divide(GiB_DECIMAL, 8, RoundingMode.HALF_EVEN);
|
||||
return rawUsageInGb.multiply(aggregatedQuotaTariffsValue);
|
||||
|
||||
case GB_MONTH:
|
||||
BigDecimal gbInUse = BigDecimal.valueOf(usageRecord.getSize()).divide(GiB_DECIMAL, 8, RoundingMode.HALF_EVEN);
|
||||
return rawUsage.multiply(costPerHour).multiply(gbInUse);
|
||||
|
||||
default:
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLockable(AccountVO account) {
|
||||
return (account.getType() == Account.Type.NORMAL || account.getType() == Account.Type.DOMAIN_ADMIN);
|
||||
return lockablesAccountTypes.contains(account.getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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.activationrule.presetvariables;
|
||||
|
||||
public class Account extends GenericPresetVariable{
|
||||
private Role role;
|
||||
|
||||
public Role getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(Role role) {
|
||||
this.role = role;
|
||||
fieldNamesToIncludeInToString.add("role");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.activationrule.presetvariables;
|
||||
|
||||
public class BackupOffering extends GenericPresetVariable {
|
||||
private String externalId;
|
||||
|
||||
public String getExternalId() {
|
||||
return externalId;
|
||||
}
|
||||
|
||||
public void setExternalId(String externalId) {
|
||||
this.externalId = externalId;
|
||||
fieldNamesToIncludeInToString.add("externalId");
|
||||
}
|
||||
}
|
||||
@ -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.activationrule.presetvariables;
|
||||
|
||||
public class ComputeOffering extends GenericPresetVariable {
|
||||
private boolean customized;
|
||||
|
||||
public boolean isCustomized() {
|
||||
return customized;
|
||||
}
|
||||
|
||||
public void setCustomized(boolean customized) {
|
||||
this.customized = customized;
|
||||
fieldNamesToIncludeInToString.add("customized");
|
||||
}
|
||||
|
||||
}
|
||||
@ -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.activationrule.presetvariables;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class ComputingResources {
|
||||
private Integer memory;
|
||||
private Integer cpuNumber;
|
||||
private Integer cpuSpeed;
|
||||
|
||||
public Integer getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
public void setMemory(Integer memory) {
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
public Integer getCpuNumber() {
|
||||
return cpuNumber;
|
||||
}
|
||||
|
||||
public void setCpuNumber(Integer cpuNumber) {
|
||||
this.cpuNumber = cpuNumber;
|
||||
}
|
||||
|
||||
public Integer getCpuSpeed() {
|
||||
return cpuSpeed;
|
||||
}
|
||||
|
||||
public void setCpuSpeed(Integer cpuSpeed) {
|
||||
this.cpuSpeed = cpuSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
|
||||
}
|
||||
}
|
||||
@ -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.activationrule.presetvariables;
|
||||
|
||||
public class Domain extends GenericPresetVariable {
|
||||
private String path;
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
fieldNamesToIncludeInToString.add("path");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
// 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.activationrule.presetvariables;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
public class GenericPresetVariable {
|
||||
private String id;
|
||||
private String name;
|
||||
protected transient Set<String> fieldNamesToIncludeInToString = new HashSet<>();
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
fieldNamesToIncludeInToString.add("id");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
fieldNamesToIncludeInToString.add("name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, fieldNamesToIncludeInToString.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Host extends GenericPresetVariable {
|
||||
private List<String> tags;
|
||||
|
||||
public List<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(List<String> tags) {
|
||||
this.tags = tags;
|
||||
fieldNamesToIncludeInToString.add("tags");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,653 @@
|
||||
// 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.activationrule.presetvariables;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleVO;
|
||||
import org.apache.cloudstack.acl.dao.RoleDao;
|
||||
import org.apache.cloudstack.backup.BackupOfferingVO;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.VmTemplateDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
|
||||
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.host.dao.HostTagsDao;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.server.ResourceTag;
|
||||
import com.cloud.server.ResourceTag.ResourceObjectType;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.StoragePoolTagsDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.tags.dao.ResourceTagDao;
|
||||
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.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.UserVmDetailVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.constants.VmDetails;
|
||||
import com.cloud.vm.dao.UserVmDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
|
||||
/**
|
||||
* Retrieves data from the database to inject into the {@link JsInterpreter} to provide more flexibility when defining quota tariffs' activation rules.<br/></br>
|
||||
* As this class is strictly used to retrieve data to inject into the {@link JsInterpreter}, there is no need for logging the retrieved data, because {@link JsInterpreter} already
|
||||
* logs the injected data in TRACE level.
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class PresetVariableHelper {
|
||||
protected Logger logger = Logger.getLogger(PresetVariableHelper.class);
|
||||
|
||||
@Inject
|
||||
AccountDao accountDao;
|
||||
|
||||
@Inject
|
||||
RoleDao roleDao;
|
||||
|
||||
@Inject
|
||||
DomainDao domainDao;
|
||||
|
||||
@Inject
|
||||
DataCenterDao dataCenterDao;
|
||||
|
||||
@Inject
|
||||
UsageDao usageDao;
|
||||
|
||||
@Inject
|
||||
VMInstanceDao vmInstanceDao;
|
||||
|
||||
@Inject
|
||||
HostDao hostDao;
|
||||
|
||||
@Inject
|
||||
HostTagsDao hostTagsDao;
|
||||
|
||||
@Inject
|
||||
GuestOSDao guestOsDao;
|
||||
|
||||
@Inject
|
||||
ServiceOfferingDao serviceOfferingDao;
|
||||
|
||||
@Inject
|
||||
VmTemplateDao vmTemplateDao;
|
||||
|
||||
@Inject
|
||||
ResourceTagDao resourceTagDao;
|
||||
|
||||
@Inject
|
||||
VolumeDao volumeDao;
|
||||
|
||||
@Inject
|
||||
DiskOfferingDao diskOfferingDao;
|
||||
|
||||
@Inject
|
||||
PrimaryDataStoreDao primaryStorageDao;
|
||||
|
||||
@Inject
|
||||
StoragePoolTagsDao storagePoolTagsDao;
|
||||
|
||||
@Inject
|
||||
ImageStoreDao imageStoreDao;
|
||||
|
||||
@Inject
|
||||
SnapshotDao snapshotDao;
|
||||
|
||||
@Inject
|
||||
SnapshotDataStoreDao snapshotDataStoreDao;
|
||||
|
||||
@Inject
|
||||
NetworkOfferingDao networkOfferingDao;
|
||||
|
||||
@Inject
|
||||
VMSnapshotDao vmSnapshotDao;
|
||||
|
||||
@Inject
|
||||
UserVmDetailsDao userVmDetailsDao;
|
||||
|
||||
@Inject
|
||||
BackupOfferingDao backupOfferingDao;
|
||||
|
||||
protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value();
|
||||
|
||||
private List<Integer> runningAndAllocatedVmUsageTypes = Arrays.asList(UsageTypes.RUNNING_VM, UsageTypes.ALLOCATED_VM);
|
||||
private List<Integer> templateAndIsoUsageTypes = Arrays.asList(UsageTypes.TEMPLATE, UsageTypes.ISO);
|
||||
private String usageRecordToString = null;
|
||||
|
||||
public PresetVariables getPresetVariables(UsageVO usageRecord) {
|
||||
this.usageRecordToString = usageRecord.toString();
|
||||
PresetVariables presetVariables = new PresetVariables();
|
||||
|
||||
presetVariables.setAccount(getPresetVariableAccount(usageRecord.getAccountId()));
|
||||
setPresetVariableProject(presetVariables);
|
||||
|
||||
presetVariables.setDomain(getPresetVariableDomain(usageRecord.getDomainId()));
|
||||
presetVariables.setResourceType(usageRecord.getType());
|
||||
presetVariables.setValue(getPresetVariableValue(usageRecord));
|
||||
presetVariables.setZone(getPresetVariableZone(usageRecord.getZoneId()));
|
||||
|
||||
return presetVariables;
|
||||
}
|
||||
|
||||
protected void setPresetVariableProject(PresetVariables presetVariables) {
|
||||
Account account = presetVariables.getAccount();
|
||||
|
||||
if (account.getRole() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GenericPresetVariable project = new GenericPresetVariable();
|
||||
project.setId(account.getId());
|
||||
project.setName(account.getName());
|
||||
|
||||
presetVariables.setProject(project);
|
||||
}
|
||||
|
||||
protected Account getPresetVariableAccount(Long accountId) {
|
||||
AccountVO accountVo = accountDao.findByIdIncludingRemoved(accountId);
|
||||
validateIfObjectIsNull(accountVo, accountId, "account");
|
||||
|
||||
Account account = new Account();
|
||||
account.setId(accountVo.getUuid());
|
||||
account.setName(accountVo.getName());
|
||||
|
||||
setPresetVariableRoleInAccountIfAccountIsNotAProject(accountVo.getType(), accountVo.getRoleId(), account);
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
protected void setPresetVariableRoleInAccountIfAccountIsNotAProject(com.cloud.user.Account.Type accountType, Long roleId, Account account) {
|
||||
if (accountType != com.cloud.user.Account.Type.PROJECT) {
|
||||
account.setRole(getPresetVariableRole(roleId));
|
||||
}
|
||||
}
|
||||
|
||||
protected Role getPresetVariableRole(Long roleId) {
|
||||
RoleVO roleVo = roleDao.findByIdIncludingRemoved(roleId);
|
||||
validateIfObjectIsNull(roleVo, roleId, "role");
|
||||
|
||||
Role role = new Role();
|
||||
role.setId(roleVo.getUuid());
|
||||
role.setName(roleVo.getName());
|
||||
role.setType(roleVo.getRoleType());
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
protected Domain getPresetVariableDomain(Long domainId) {
|
||||
DomainVO domainVo = domainDao.findByIdIncludingRemoved(domainId);
|
||||
validateIfObjectIsNull(domainVo, domainId, "domain");
|
||||
|
||||
Domain domain = new Domain();
|
||||
domain.setId(domainVo.getUuid());
|
||||
domain.setName(domainVo.getName());
|
||||
domain.setPath(domainVo.getPath());
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
protected GenericPresetVariable getPresetVariableZone(Long zoneId) {
|
||||
DataCenterVO dataCenterVo = dataCenterDao.findByIdIncludingRemoved(zoneId);
|
||||
validateIfObjectIsNull(dataCenterVo, zoneId, "zone");
|
||||
|
||||
GenericPresetVariable zone = new GenericPresetVariable();
|
||||
zone.setId(dataCenterVo.getUuid());
|
||||
zone.setName(dataCenterVo.getName());
|
||||
|
||||
return zone;
|
||||
}
|
||||
|
||||
protected Value getPresetVariableValue(UsageVO usageRecord) {
|
||||
Long accountId = usageRecord.getAccountId();
|
||||
int usageType = usageRecord.getUsageType();
|
||||
|
||||
Value value = new Value();
|
||||
|
||||
value.setAccountResources(getPresetVariableAccountResources(usageRecord, accountId, usageType));
|
||||
loadPresetVariableValueForRunningAndAllocatedVm(usageRecord, value);
|
||||
loadPresetVariableValueForVolume(usageRecord, value);
|
||||
loadPresetVariableValueForTemplateAndIso(usageRecord, value);
|
||||
loadPresetVariableValueForSnapshot(usageRecord, value);
|
||||
loadPresetVariableValueForNetworkOffering(usageRecord, value);
|
||||
loadPresetVariableValueForVmSnapshot(usageRecord, value);
|
||||
loadPresetVariableValueForBackup(usageRecord, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of zone and domain IDs of the records allocated in the same period and same usage type of the usage record.
|
||||
*/
|
||||
protected List<Resource> getPresetVariableAccountResources(UsageVO usageRecord, Long accountId, int usageType) {
|
||||
Date startDate = usageRecord.getStartDate();
|
||||
Date endDate = usageRecord.getEndDate();
|
||||
|
||||
List<Pair<String, String>> pairResources = usageDao.listAccountResourcesInThePeriod(accountId, usageType, startDate, endDate);
|
||||
|
||||
List<Resource> resourcesInThePeriod = new ArrayList<>();
|
||||
|
||||
for (Pair<String, String> pairResource : pairResources) {
|
||||
Resource resource = new Resource();
|
||||
resource.setZoneId(pairResource.first());
|
||||
resource.setDomainId(pairResource.second());
|
||||
|
||||
resourcesInThePeriod.add(resource);
|
||||
}
|
||||
|
||||
return resourcesInThePeriod;
|
||||
}
|
||||
|
||||
protected void loadPresetVariableValueForRunningAndAllocatedVm(UsageVO usageRecord, Value value) {
|
||||
int usageType = usageRecord.getUsageType();
|
||||
|
||||
if (!runningAndAllocatedVmUsageTypes.contains(usageType)) {
|
||||
logNotLoadingMessageInTrace("running/allocated VM", usageType);
|
||||
return;
|
||||
}
|
||||
|
||||
Long vmId = usageRecord.getUsageId();
|
||||
|
||||
VMInstanceVO vmVo = vmInstanceDao.findByIdIncludingRemoved(vmId);
|
||||
validateIfObjectIsNull(vmVo, vmId, "VM");
|
||||
|
||||
setPresetVariableHostInValueIfUsageTypeIsRunningVm(value, usageType, vmVo);
|
||||
|
||||
value.setId(vmVo.getUuid());
|
||||
value.setName(vmVo.getHostName());
|
||||
value.setOsName(getPresetVariableValueOsName(vmVo.getGuestOSId()));
|
||||
|
||||
setPresetVariableValueServiceOfferingAndComputingResources(value, usageType, vmVo);
|
||||
|
||||
value.setTags(getPresetVariableValueResourceTags(vmId, ResourceObjectType.UserVm));
|
||||
value.setTemplate(getPresetVariableValueTemplate(vmVo.getTemplateId()));
|
||||
}
|
||||
|
||||
protected void logNotLoadingMessageInTrace(String resource, int usageType) {
|
||||
logger.trace(String.format("Not loading %s preset variables because the usage record [%s] is of type [%s].", resource, usageRecordToString,
|
||||
QuotaTypes.listQuotaTypes().get(usageType).getQuotaName()));
|
||||
}
|
||||
|
||||
protected void setPresetVariableHostInValueIfUsageTypeIsRunningVm(Value value, int quotaType, VMInstanceVO vmVo) {
|
||||
if (quotaType != UsageTypes.RUNNING_VM) {
|
||||
return;
|
||||
}
|
||||
|
||||
Long hostId = vmVo.getHostId();
|
||||
if (hostId == null) {
|
||||
hostId = vmVo.getLastHostId();
|
||||
}
|
||||
|
||||
value.setHost(getPresetVariableValueHost(hostId));
|
||||
}
|
||||
|
||||
protected Host getPresetVariableValueHost(Long hostId) {
|
||||
HostVO hostVo = hostDao.findByIdIncludingRemoved(hostId);
|
||||
validateIfObjectIsNull(hostVo, hostId, "host");
|
||||
|
||||
Host host = new Host();
|
||||
host.setId(hostVo.getUuid());
|
||||
host.setName(hostVo.getName());
|
||||
host.setTags(hostTagsDao.getHostTags(hostId));
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
protected String getPresetVariableValueOsName(Long guestOsId) {
|
||||
GuestOSVO guestOsVo = guestOsDao.findByIdIncludingRemoved(guestOsId);
|
||||
validateIfObjectIsNull(guestOsVo, guestOsId, "guest OS");
|
||||
|
||||
return guestOsVo.getDisplayName();
|
||||
}
|
||||
|
||||
protected ComputeOffering getPresetVariableValueComputeOffering(ServiceOfferingVO serviceOfferingVo) {
|
||||
ComputeOffering computeOffering = new ComputeOffering();
|
||||
computeOffering.setId(serviceOfferingVo.getUuid());
|
||||
computeOffering.setName(serviceOfferingVo.getName());
|
||||
computeOffering.setCustomized(serviceOfferingVo.isDynamic());
|
||||
|
||||
return computeOffering;
|
||||
}
|
||||
|
||||
|
||||
protected void setPresetVariableValueServiceOfferingAndComputingResources(Value value, int usageType, VMInstanceVO vmVo) {
|
||||
long computeOfferingId = vmVo.getServiceOfferingId();
|
||||
ServiceOfferingVO serviceOfferingVo = serviceOfferingDao.findByIdIncludingRemoved(computeOfferingId);
|
||||
validateIfObjectIsNull(serviceOfferingVo, computeOfferingId, "compute offering");
|
||||
value.setComputeOffering(getPresetVariableValueComputeOffering(serviceOfferingVo));
|
||||
|
||||
if (usageType == UsageTypes.RUNNING_VM) {
|
||||
value.setComputingResources(getPresetVariableValueComputingResource(vmVo, serviceOfferingVo));
|
||||
}
|
||||
}
|
||||
|
||||
protected ComputingResources getPresetVariableValueComputingResource(VMInstanceVO vmVo, ServiceOfferingVO serviceOfferingVo) {
|
||||
ComputingResources computingResources = new ComputingResources();
|
||||
computingResources.setMemory(serviceOfferingVo.getRamSize());
|
||||
computingResources.setCpuNumber(serviceOfferingVo.getCpu());
|
||||
computingResources.setCpuSpeed(serviceOfferingVo.getSpeed());
|
||||
|
||||
if (serviceOfferingVo.isDynamic()) {
|
||||
List<UserVmDetailVO> details = userVmDetailsDao.listDetails(vmVo.getId());
|
||||
|
||||
computingResources.setMemory(getDetailByName(details, VmDetails.MEMORY.getName(), computingResources.getMemory()));
|
||||
computingResources.setCpuNumber(getDetailByName(details, VmDetails.CPU_NUMBER.getName(), computingResources.getCpuNumber()));
|
||||
computingResources.setCpuSpeed(getDetailByName(details, VmDetails.CPU_SPEED.getName(), computingResources.getCpuSpeed()));
|
||||
}
|
||||
|
||||
warnIfComputingResourceIsNull(VmDetails.MEMORY.getName(), computingResources.getMemory(), vmVo);
|
||||
warnIfComputingResourceIsNull(VmDetails.CPU_NUMBER.getName(), computingResources.getCpuNumber(), vmVo);
|
||||
warnIfComputingResourceIsNull(VmDetails.CPU_SPEED.getName(), computingResources.getCpuSpeed(), vmVo);
|
||||
|
||||
return computingResources;
|
||||
}
|
||||
|
||||
protected void warnIfComputingResourceIsNull(String name, Integer value, VMInstanceVO vmVo) {
|
||||
if (value == null) {
|
||||
logger.warn(String.format("Could not get %s of %s. Injecting \"value.computingResources.[%s]\" as null.", name, vmVo, name));
|
||||
}
|
||||
}
|
||||
|
||||
protected Integer getDetailByName(List<UserVmDetailVO> details, String name, Integer defaultValue) {
|
||||
List<UserVmDetailVO> detailFiltered = details.stream().filter(det -> name.equals(det.getName())).collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(detailFiltered)) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
UserVmDetailVO detail = detailFiltered.get(0);
|
||||
|
||||
if (detail.getValue() != null) {
|
||||
return Integer.valueOf(detail.getValue());
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
protected GenericPresetVariable getPresetVariableValueTemplate(Long templateId) {
|
||||
VMTemplateVO vmTemplateVo = vmTemplateDao.findByIdIncludingRemoved(templateId);
|
||||
validateIfObjectIsNull(vmTemplateVo, templateId, "template");
|
||||
|
||||
GenericPresetVariable template = new GenericPresetVariable();
|
||||
template.setId(vmTemplateVo.getUuid());
|
||||
template.setName(vmTemplateVo.getName());
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
protected Map<String, String> getPresetVariableValueResourceTags(Long resourceId, ResourceObjectType resourceType) {
|
||||
List<? extends ResourceTag> listResourceTags = resourceTagDao.listBy(resourceId, resourceType);
|
||||
|
||||
Map<String, String> mapResourceTags = new HashMap<>();
|
||||
for (ResourceTag resourceTag : listResourceTags) {
|
||||
mapResourceTags.put(resourceTag.getKey(), resourceTag.getValue());
|
||||
}
|
||||
|
||||
return mapResourceTags;
|
||||
}
|
||||
|
||||
protected void loadPresetVariableValueForVolume(UsageVO usageRecord, Value value) {
|
||||
int usageType = usageRecord.getUsageType();
|
||||
|
||||
if (usageType != UsageTypes.VOLUME) {
|
||||
logNotLoadingMessageInTrace("volume", usageType);
|
||||
return;
|
||||
}
|
||||
|
||||
Long volumeId = usageRecord.getUsageId();
|
||||
|
||||
VolumeVO volumeVo = volumeDao.findByIdIncludingRemoved(volumeId);
|
||||
validateIfObjectIsNull(volumeVo, volumeId, "volume");
|
||||
|
||||
value.setDiskOffering(getPresetVariableValueDiskOffering(volumeVo.getDiskOfferingId()));
|
||||
value.setId(volumeVo.getUuid());
|
||||
value.setName(volumeVo.getName());
|
||||
value.setProvisioningType(volumeVo.getProvisioningType());
|
||||
|
||||
Long poolId = volumeVo.getPoolId();
|
||||
if (poolId == null) {
|
||||
logger.debug(String.format("Volume [%s] from usage record [%s] has a NULL pool ID; therefore, the preset variable \"storage\" will not be loaded for this record.",
|
||||
volumeId, usageRecordToString));
|
||||
} else {
|
||||
value.setStorage(getPresetVariableValueStorage(poolId, usageType));
|
||||
}
|
||||
|
||||
value.setTags(getPresetVariableValueResourceTags(volumeId, ResourceObjectType.Volume));
|
||||
value.setSize(ByteScaleUtils.bytesToMib(volumeVo.getSize()));
|
||||
}
|
||||
|
||||
protected GenericPresetVariable getPresetVariableValueDiskOffering(Long diskOfferingId) {
|
||||
DiskOfferingVO diskOfferingVo = diskOfferingDao.findByIdIncludingRemoved(diskOfferingId);
|
||||
validateIfObjectIsNull(diskOfferingVo, diskOfferingId, "disk offering");
|
||||
|
||||
GenericPresetVariable diskOffering = new GenericPresetVariable();
|
||||
diskOffering.setId(diskOfferingVo.getUuid());
|
||||
diskOffering.setName(diskOfferingVo.getName());
|
||||
|
||||
return diskOffering;
|
||||
}
|
||||
|
||||
protected Storage getPresetVariableValueStorage(Long storageId, int usageType) {
|
||||
Storage storage = getSecondaryStorageForSnapshot(storageId, usageType);
|
||||
|
||||
if (storage != null) {
|
||||
return storage;
|
||||
}
|
||||
|
||||
StoragePoolVO storagePoolVo = primaryStorageDao.findByIdIncludingRemoved(storageId);
|
||||
validateIfObjectIsNull(storagePoolVo, storageId, "primary storage");
|
||||
|
||||
storage = new Storage();
|
||||
storage.setId(storagePoolVo.getUuid());
|
||||
storage.setName(storagePoolVo.getName());
|
||||
storage.setScope(storagePoolVo.getScope());
|
||||
storage.setTags(storagePoolTagsDao.getStoragePoolTags(storageId));
|
||||
|
||||
return storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the usage type is {@link UsageTypes#SNAPSHOT} and {@link SnapshotInfo#BackupSnapshotAfterTakingSnapshot} is enabled, returns the data from the secondary storage.
|
||||
* Otherwise, returns null.
|
||||
*/
|
||||
protected Storage getSecondaryStorageForSnapshot(Long storageId, int usageType) {
|
||||
if (usageType != UsageTypes.SNAPSHOT || !backupSnapshotAfterTakingSnapshot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageStoreVO imageStoreVo = imageStoreDao.findByIdIncludingRemoved(storageId);
|
||||
validateIfObjectIsNull(imageStoreVo, storageId, "secondary storage");
|
||||
|
||||
Storage storage = new Storage();
|
||||
storage.setId(imageStoreVo.getUuid());
|
||||
storage.setName(imageStoreVo.getName());
|
||||
return storage;
|
||||
}
|
||||
|
||||
protected void loadPresetVariableValueForTemplateAndIso(UsageVO usageRecord, Value value) {
|
||||
int usageType = usageRecord.getUsageType();
|
||||
if (!templateAndIsoUsageTypes.contains(usageType)) {
|
||||
logNotLoadingMessageInTrace("template/ISO", usageType);
|
||||
return;
|
||||
}
|
||||
|
||||
Long templateOrIsoId = usageRecord.getUsageId();
|
||||
|
||||
VMTemplateVO vmTemplateVo = vmTemplateDao.findByIdIncludingRemoved(templateOrIsoId);
|
||||
validateIfObjectIsNull(vmTemplateVo, templateOrIsoId, "template/ISO");
|
||||
|
||||
value.setId(vmTemplateVo.getUuid());
|
||||
value.setName(vmTemplateVo.getName());
|
||||
value.setOsName(getPresetVariableValueOsName(vmTemplateVo.getGuestOSId()));
|
||||
value.setTags(getPresetVariableValueResourceTags(templateOrIsoId, usageType == UsageTypes.ISO ? ResourceObjectType.ISO : ResourceObjectType.Template));
|
||||
value.setSize(ByteScaleUtils.bytesToMib(vmTemplateVo.getSize()));
|
||||
}
|
||||
|
||||
protected void loadPresetVariableValueForSnapshot(UsageVO usageRecord, Value value) {
|
||||
int usageType = usageRecord.getUsageType();
|
||||
|
||||
if (usageType != UsageTypes.SNAPSHOT) {
|
||||
logNotLoadingMessageInTrace("snapshot", usageType);
|
||||
return;
|
||||
}
|
||||
|
||||
Long snapshotId = usageRecord.getUsageId();
|
||||
|
||||
SnapshotVO snapshotVo = snapshotDao.findByIdIncludingRemoved(snapshotId);
|
||||
validateIfObjectIsNull(snapshotVo, snapshotId, "snapshot");
|
||||
|
||||
value.setId(snapshotVo.getUuid());
|
||||
value.setName(snapshotVo.getName());
|
||||
value.setSize(ByteScaleUtils.bytesToMib(snapshotVo.getSize()));
|
||||
value.setSnapshotType(Snapshot.Type.values()[snapshotVo.getSnapshotType()]);
|
||||
value.setStorage(getPresetVariableValueStorage(getSnapshotDataStoreId(snapshotId), usageType));
|
||||
value.setTags(getPresetVariableValueResourceTags(snapshotId, ResourceObjectType.Snapshot));
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@link SnapshotInfo#BackupSnapshotAfterTakingSnapshot} is enabled, returns the secondary storage's ID where the snapshot is. Otherwise, returns the primary storage's ID
|
||||
* where the snapshot is.
|
||||
*/
|
||||
protected long getSnapshotDataStoreId(Long snapshotId) {
|
||||
if (backupSnapshotAfterTakingSnapshot) {
|
||||
SnapshotDataStoreVO snapshotStore = snapshotDataStoreDao.findBySnapshot(snapshotId, DataStoreRole.Image);
|
||||
validateIfObjectIsNull(snapshotStore, snapshotId, "data store for snapshot");
|
||||
return snapshotStore.getDataStoreId();
|
||||
}
|
||||
|
||||
SnapshotDataStoreVO snapshotStore = snapshotDataStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
|
||||
validateIfObjectIsNull(snapshotStore, snapshotId, "data store for snapshot");
|
||||
return snapshotStore.getDataStoreId();
|
||||
}
|
||||
|
||||
protected void loadPresetVariableValueForNetworkOffering(UsageVO usageRecord, Value value) {
|
||||
int usageType = usageRecord.getUsageType();
|
||||
|
||||
if (usageType != UsageTypes.NETWORK_OFFERING) {
|
||||
logNotLoadingMessageInTrace("network offering", usageType);
|
||||
return;
|
||||
}
|
||||
|
||||
Long networkOfferingId = usageRecord.getOfferingId();
|
||||
|
||||
NetworkOfferingVO networkOfferingVo = networkOfferingDao.findByIdIncludingRemoved(networkOfferingId);
|
||||
validateIfObjectIsNull(networkOfferingVo, networkOfferingId, "network offering");
|
||||
|
||||
value.setId(networkOfferingVo.getUuid());
|
||||
value.setName(networkOfferingVo.getName());
|
||||
value.setTag(networkOfferingVo.getTags());
|
||||
}
|
||||
|
||||
protected void loadPresetVariableValueForVmSnapshot(UsageVO usageRecord, Value value) {
|
||||
int usageType = usageRecord.getUsageType();
|
||||
if (usageType != UsageTypes.VM_SNAPSHOT) {
|
||||
logNotLoadingMessageInTrace("VM snapshot", usageType);
|
||||
return;
|
||||
}
|
||||
|
||||
Long vmSnapshotId = usageRecord.getUsageId();
|
||||
|
||||
VMSnapshotVO vmSnapshotVo = vmSnapshotDao.findByIdIncludingRemoved(vmSnapshotId);
|
||||
validateIfObjectIsNull(vmSnapshotVo, vmSnapshotId, "VM snapshot");
|
||||
|
||||
value.setId(vmSnapshotVo.getUuid());
|
||||
value.setName(vmSnapshotVo.getName());
|
||||
value.setTags(getPresetVariableValueResourceTags(vmSnapshotId, ResourceObjectType.VMSnapshot));
|
||||
value.setVmSnapshotType(vmSnapshotVo.getType());
|
||||
}
|
||||
|
||||
protected void loadPresetVariableValueForBackup(UsageVO usageRecord, Value value) {
|
||||
int usageType = usageRecord.getUsageType();
|
||||
if (usageType != UsageTypes.BACKUP) {
|
||||
logNotLoadingMessageInTrace("Backup", usageType);
|
||||
return;
|
||||
}
|
||||
|
||||
value.setSize(usageRecord.getSize());
|
||||
value.setVirtualSize(usageRecord.getVirtualSize());
|
||||
value.setBackupOffering(getPresetVariableValueBackupOffering(usageRecord.getOfferingId()));
|
||||
}
|
||||
|
||||
protected BackupOffering getPresetVariableValueBackupOffering(Long offeringId) {
|
||||
BackupOfferingVO backupOfferingVo = backupOfferingDao.findByIdIncludingRemoved(offeringId);
|
||||
validateIfObjectIsNull(backupOfferingVo, offeringId, "backup offering");
|
||||
|
||||
BackupOffering backupOffering = new BackupOffering();
|
||||
backupOffering.setId(backupOfferingVo.getUuid());
|
||||
backupOffering.setName(backupOfferingVo.getName());
|
||||
backupOffering.setExternalId(backupOfferingVo.getExternalId());
|
||||
|
||||
return backupOffering;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a {@link CloudRuntimeException} if the object is null;
|
||||
*/
|
||||
protected void validateIfObjectIsNull(Object object, Long id, String resource) {
|
||||
if (object != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message = String.format("Unable to load preset variable [%s] for usage record [%s] due to: [%s] with ID [%s] does not exist.", resource, usageRecordToString,
|
||||
resource, id);
|
||||
|
||||
logger.error(message);
|
||||
throw new CloudRuntimeException(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
// 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.activationrule.presetvariables;
|
||||
|
||||
public class PresetVariables {
|
||||
|
||||
private Account account;
|
||||
private Domain domain;
|
||||
private GenericPresetVariable project;
|
||||
private String resourceType;
|
||||
private Value value;
|
||||
private GenericPresetVariable zone;
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Domain getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public void setDomain(Domain domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public GenericPresetVariable getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public void setProject(GenericPresetVariable project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return resourceType;
|
||||
}
|
||||
|
||||
public void setResourceType(String resourceType) {
|
||||
this.resourceType = resourceType;
|
||||
}
|
||||
|
||||
public Value getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Value value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public GenericPresetVariable getZone() {
|
||||
return zone;
|
||||
}
|
||||
|
||||
public void setZone(GenericPresetVariable zone) {
|
||||
this.zone = zone;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class Resource {
|
||||
private String zoneId;
|
||||
private String domainId;
|
||||
|
||||
public String getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public void setZoneId(String zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
public String getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(String domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
|
||||
public class Role extends GenericPresetVariable {
|
||||
private RoleType type;
|
||||
|
||||
public RoleType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(RoleType type) {
|
||||
this.type = type;
|
||||
fieldNamesToIncludeInToString.add("type");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
// 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.activationrule.presetvariables;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.storage.ScopeType;
|
||||
|
||||
public class Storage extends GenericPresetVariable {
|
||||
private List<String> tags;
|
||||
private ScopeType scope;
|
||||
|
||||
public List<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(List<String> tags) {
|
||||
this.tags = tags;
|
||||
fieldNamesToIncludeInToString.add("tags");
|
||||
}
|
||||
|
||||
public ScopeType getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(ScopeType scope) {
|
||||
this.scope = scope;
|
||||
fieldNamesToIncludeInToString.add("scope");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,188 @@
|
||||
// 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.activationrule.presetvariables;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.Storage.ProvisioningType;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
|
||||
public class Value extends GenericPresetVariable {
|
||||
private Host host;
|
||||
private String osName;
|
||||
private List<Resource> accountResources;
|
||||
private Map<String, String> tags;
|
||||
private String tag;
|
||||
private Long size;
|
||||
private Long virtualSize;
|
||||
private ProvisioningType provisioningType;
|
||||
private Snapshot.Type snapshotType;
|
||||
private VMSnapshot.Type vmSnapshotType;
|
||||
private ComputeOffering computeOffering;
|
||||
private GenericPresetVariable template;
|
||||
private GenericPresetVariable diskOffering;
|
||||
private Storage storage;
|
||||
private ComputingResources computingResources;
|
||||
private BackupOffering backupOffering;
|
||||
|
||||
public Host getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(Host host) {
|
||||
this.host = host;
|
||||
fieldNamesToIncludeInToString.add("host");
|
||||
}
|
||||
|
||||
public String getOsName() {
|
||||
return osName;
|
||||
}
|
||||
|
||||
public void setOsName(String osName) {
|
||||
this.osName = osName;
|
||||
fieldNamesToIncludeInToString.add("osName");
|
||||
}
|
||||
|
||||
public List<Resource> getAccountResources() {
|
||||
return accountResources;
|
||||
}
|
||||
|
||||
public void setAccountResources(List<Resource> accountResources) {
|
||||
this.accountResources = accountResources;
|
||||
fieldNamesToIncludeInToString.add("accountResources");
|
||||
}
|
||||
|
||||
public Map<String, String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(Map<String, String> tags) {
|
||||
this.tags = tags;
|
||||
fieldNamesToIncludeInToString.add("tags");
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
fieldNamesToIncludeInToString.add("tag");
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
fieldNamesToIncludeInToString.add("size");
|
||||
}
|
||||
|
||||
public ProvisioningType getProvisioningType() {
|
||||
return provisioningType;
|
||||
}
|
||||
|
||||
public void setProvisioningType(ProvisioningType provisioningType) {
|
||||
this.provisioningType = provisioningType;
|
||||
fieldNamesToIncludeInToString.add("provisioningType");
|
||||
}
|
||||
|
||||
public Snapshot.Type getSnapshotType() {
|
||||
return snapshotType;
|
||||
}
|
||||
|
||||
public void setSnapshotType(Snapshot.Type snapshotType) {
|
||||
this.snapshotType = snapshotType;
|
||||
fieldNamesToIncludeInToString.add("snapshotType");
|
||||
}
|
||||
|
||||
public VMSnapshot.Type getVmSnapshotType() {
|
||||
return vmSnapshotType;
|
||||
}
|
||||
|
||||
public void setVmSnapshotType(VMSnapshot.Type vmSnapshotType) {
|
||||
this.vmSnapshotType = vmSnapshotType;
|
||||
fieldNamesToIncludeInToString.add("vmSnapshotType");
|
||||
}
|
||||
|
||||
public ComputeOffering getComputeOffering() {
|
||||
return computeOffering;
|
||||
}
|
||||
|
||||
public void setComputeOffering(ComputeOffering computeOffering) {
|
||||
this.computeOffering = computeOffering;
|
||||
fieldNamesToIncludeInToString.add("computeOffering");
|
||||
}
|
||||
|
||||
public GenericPresetVariable getTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
public void setTemplate(GenericPresetVariable template) {
|
||||
this.template = template;
|
||||
fieldNamesToIncludeInToString.add("template");
|
||||
}
|
||||
|
||||
public GenericPresetVariable getDiskOffering() {
|
||||
return diskOffering;
|
||||
}
|
||||
|
||||
public void setDiskOffering(GenericPresetVariable diskOffering) {
|
||||
this.diskOffering = diskOffering;
|
||||
fieldNamesToIncludeInToString.add("diskOffering");
|
||||
}
|
||||
|
||||
public Storage getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
public void setStorage(Storage storage) {
|
||||
this.storage = storage;
|
||||
fieldNamesToIncludeInToString.add("storage");
|
||||
}
|
||||
|
||||
public ComputingResources getComputingResources() {
|
||||
return computingResources;
|
||||
}
|
||||
|
||||
public void setComputingResources(ComputingResources computingResources) {
|
||||
this.computingResources = computingResources;
|
||||
fieldNamesToIncludeInToString.add("computingResources");
|
||||
}
|
||||
|
||||
public Long getVirtualSize() {
|
||||
return virtualSize;
|
||||
}
|
||||
|
||||
public void setVirtualSize(Long virtualSize) {
|
||||
this.virtualSize = virtualSize;
|
||||
fieldNamesToIncludeInToString.add("virtualSize");
|
||||
}
|
||||
|
||||
public BackupOffering getBackupOffering() {
|
||||
return backupOffering;
|
||||
}
|
||||
|
||||
public void setBackupOffering(BackupOffering backupOffering) {
|
||||
this.backupOffering = backupOffering;
|
||||
fieldNamesToIncludeInToString.add("backupOffering");
|
||||
}
|
||||
}
|
||||
@ -57,6 +57,9 @@ public interface QuotaConfig {
|
||||
public static final ConfigKey<String> QuotaSmtpUseStartTLS = new ConfigKey<String>("Advanced", String.class, "quota.usage.smtp.useStartTLS", "false",
|
||||
"If set to true and if we enable security via quota.usage.smtp.useAuth, this will enable StartTLS to secure the connection.", true);
|
||||
|
||||
public static final ConfigKey<Long> QuotaActivationRuleTimeout = new ConfigKey<>("Advanced", Long.class, "quota.activationrule.timeout", "2000", "The maximum runtime,"
|
||||
+ " in milliseconds, to execute the quota tariff's activation rule; if it is reached, a timeout will happen.", true);
|
||||
|
||||
enum QuotaEmailTemplateTypes {
|
||||
QUOTA_LOW, QUOTA_EMPTY, QUOTA_UNLOCK_ACCOUNT, QUOTA_STATEMENT
|
||||
}
|
||||
|
||||
@ -21,12 +21,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
import org.apache.cloudstack.usage.UsageUnitTypes;
|
||||
|
||||
public class QuotaTypes extends UsageTypes {
|
||||
public static final int CPU_CLOCK_RATE = 15;
|
||||
public static final int CPU_NUMBER = 16;
|
||||
public static final int MEMORY = 17;
|
||||
|
||||
private final Integer quotaType;
|
||||
private final String quotaName;
|
||||
private final String quotaUnit;
|
||||
@ -36,31 +33,28 @@ public class QuotaTypes extends UsageTypes {
|
||||
|
||||
static {
|
||||
final HashMap<Integer, QuotaTypes> quotaTypeList = new HashMap<Integer, QuotaTypes>();
|
||||
quotaTypeList.put(RUNNING_VM, new QuotaTypes(RUNNING_VM, "RUNNING_VM", "Compute-Month", "Running Vm Usage"));
|
||||
quotaTypeList.put(ALLOCATED_VM, new QuotaTypes(ALLOCATED_VM, "ALLOCATED_VM", "Compute-Month", "Allocated Vm Usage"));
|
||||
quotaTypeList.put(IP_ADDRESS, new QuotaTypes(IP_ADDRESS, "IP_ADDRESS", "IP-Month", "IP Address Usage"));
|
||||
quotaTypeList.put(NETWORK_BYTES_SENT, new QuotaTypes(NETWORK_BYTES_SENT, "NETWORK_BYTES_SENT", "GB", "Network Usage (Bytes Sent)"));
|
||||
quotaTypeList.put(NETWORK_BYTES_RECEIVED, new QuotaTypes(NETWORK_BYTES_RECEIVED, "NETWORK_BYTES_RECEIVED", "GB", "Network Usage (Bytes Received)"));
|
||||
quotaTypeList.put(VOLUME, new QuotaTypes(VOLUME, "VOLUME", "GB-Month", "Volume Usage"));
|
||||
quotaTypeList.put(TEMPLATE, new QuotaTypes(TEMPLATE, "TEMPLATE", "GB-Month", "Template Usage"));
|
||||
quotaTypeList.put(ISO, new QuotaTypes(ISO, "ISO", "GB-Month", "ISO Usage"));
|
||||
quotaTypeList.put(SNAPSHOT, new QuotaTypes(SNAPSHOT, "SNAPSHOT", "GB-Month", "Snapshot Usage"));
|
||||
quotaTypeList.put(SECURITY_GROUP, new QuotaTypes(SECURITY_GROUP, "SECURITY_GROUP", "Policy-Month", "Security Group Usage"));
|
||||
quotaTypeList.put(LOAD_BALANCER_POLICY, new QuotaTypes(LOAD_BALANCER_POLICY, "LOAD_BALANCER_POLICY", "Policy-Month", "Load Balancer Usage"));
|
||||
quotaTypeList.put(PORT_FORWARDING_RULE, new QuotaTypes(PORT_FORWARDING_RULE, "PORT_FORWARDING_RULE", "Policy-Month", "Port Forwarding Usage"));
|
||||
quotaTypeList.put(NETWORK_OFFERING, new QuotaTypes(NETWORK_OFFERING, "NETWORK_OFFERING", "Policy-Month", "Network Offering Usage"));
|
||||
quotaTypeList.put(VPN_USERS, new QuotaTypes(VPN_USERS, "VPN_USERS", "Policy-Month", "VPN users usage"));
|
||||
quotaTypeList.put(VM_DISK_IO_READ, new QuotaTypes(VM_DISK_IO_READ, "VM_DISK_IO_READ", "GB", "VM Disk usage(I/O Read)"));
|
||||
quotaTypeList.put(VM_DISK_IO_WRITE, new QuotaTypes(VM_DISK_IO_WRITE, "VM_DISK_IO_WRITE", "GB", "VM Disk usage(I/O Write)"));
|
||||
quotaTypeList.put(VM_DISK_BYTES_READ, new QuotaTypes(VM_DISK_BYTES_READ, "VM_DISK_BYTES_READ", "GB", "VM Disk usage(Bytes Read)"));
|
||||
quotaTypeList.put(VM_DISK_BYTES_WRITE, new QuotaTypes(VM_DISK_BYTES_WRITE, "VM_DISK_BYTES_WRITE", "GB", "VM Disk usage(Bytes Write)"));
|
||||
quotaTypeList.put(VM_SNAPSHOT, new QuotaTypes(VM_SNAPSHOT, "VM_SNAPSHOT", "GB-Month", "VM Snapshot storage usage"));
|
||||
quotaTypeList.put(VOLUME_SECONDARY, new QuotaTypes(VOLUME_SECONDARY, "VOLUME_SECONDARY", "GB-Month", "Volume secondary storage usage"));
|
||||
quotaTypeList.put(VM_SNAPSHOT_ON_PRIMARY, new QuotaTypes(VM_SNAPSHOT_ON_PRIMARY, "VM_SNAPSHOT_ON_PRIMARY", "GB-Month", "VM Snapshot primary storage usage"));
|
||||
quotaTypeList.put(BACKUP, new QuotaTypes(BACKUP, "BACKUP", "GB-Month", "Backup storage usage"));
|
||||
quotaTypeList.put(CPU_CLOCK_RATE, new QuotaTypes(CPU_CLOCK_RATE, "CPU_CLOCK_RATE", "Compute-Month", "Quota tariff for using 1 CPU of clock rate 100MHz"));
|
||||
quotaTypeList.put(CPU_NUMBER, new QuotaTypes(CPU_NUMBER, "CPU_NUMBER", "Compute-Month", "Quota tariff for running VM that has 1vCPU"));
|
||||
quotaTypeList.put(MEMORY, new QuotaTypes(MEMORY, "MEMORY", "Compute-Month", "Quota tariff for using 1MB of RAM"));
|
||||
quotaTypeList.put(RUNNING_VM, new QuotaTypes(RUNNING_VM, "RUNNING_VM", UsageUnitTypes.COMPUTE_MONTH.toString(), "Running Vm Usage"));
|
||||
quotaTypeList.put(ALLOCATED_VM, new QuotaTypes(ALLOCATED_VM, "ALLOCATED_VM", UsageUnitTypes.COMPUTE_MONTH.toString(), "Allocated Vm Usage"));
|
||||
quotaTypeList.put(IP_ADDRESS, new QuotaTypes(IP_ADDRESS, "IP_ADDRESS", UsageUnitTypes.IP_MONTH.toString(), "IP Address Usage"));
|
||||
quotaTypeList.put(NETWORK_BYTES_SENT, new QuotaTypes(NETWORK_BYTES_SENT, "NETWORK_BYTES_SENT", UsageUnitTypes.GB.toString(), "Network Usage (Bytes Sent)"));
|
||||
quotaTypeList.put(NETWORK_BYTES_RECEIVED, new QuotaTypes(NETWORK_BYTES_RECEIVED, "NETWORK_BYTES_RECEIVED", UsageUnitTypes.GB.toString(), "Network Usage (Bytes Received)"));
|
||||
quotaTypeList.put(VOLUME, new QuotaTypes(VOLUME, "VOLUME", UsageUnitTypes.GB_MONTH.toString(), "Volume Usage"));
|
||||
quotaTypeList.put(TEMPLATE, new QuotaTypes(TEMPLATE, "TEMPLATE", UsageUnitTypes.GB_MONTH.toString(), "Template Usage"));
|
||||
quotaTypeList.put(ISO, new QuotaTypes(ISO, "ISO", UsageUnitTypes.GB_MONTH.toString(), "ISO Usage"));
|
||||
quotaTypeList.put(SNAPSHOT, new QuotaTypes(SNAPSHOT, "SNAPSHOT", UsageUnitTypes.GB_MONTH.toString(), "Snapshot Usage"));
|
||||
quotaTypeList.put(SECURITY_GROUP, new QuotaTypes(SECURITY_GROUP, "SECURITY_GROUP", UsageUnitTypes.POLICY_MONTH.toString(), "Security Group Usage"));
|
||||
quotaTypeList.put(LOAD_BALANCER_POLICY, new QuotaTypes(LOAD_BALANCER_POLICY, "LOAD_BALANCER_POLICY", UsageUnitTypes.POLICY_MONTH.toString(), "Load Balancer Usage"));
|
||||
quotaTypeList.put(PORT_FORWARDING_RULE, new QuotaTypes(PORT_FORWARDING_RULE, "PORT_FORWARDING_RULE", UsageUnitTypes.POLICY_MONTH.toString(), "Port Forwarding Usage"));
|
||||
quotaTypeList.put(NETWORK_OFFERING, new QuotaTypes(NETWORK_OFFERING, "NETWORK_OFFERING", UsageUnitTypes.POLICY_MONTH.toString(), "Network Offering Usage"));
|
||||
quotaTypeList.put(VPN_USERS, new QuotaTypes(VPN_USERS, "VPN_USERS", UsageUnitTypes.POLICY_MONTH.toString(), "VPN users usage"));
|
||||
quotaTypeList.put(VM_DISK_IO_READ, new QuotaTypes(VM_DISK_IO_READ, "VM_DISK_IO_READ", UsageUnitTypes.GB.toString(), "VM Disk usage(I/O Read)"));
|
||||
quotaTypeList.put(VM_DISK_IO_WRITE, new QuotaTypes(VM_DISK_IO_WRITE, "VM_DISK_IO_WRITE", UsageUnitTypes.GB.toString(), "VM Disk usage(I/O Write)"));
|
||||
quotaTypeList.put(VM_DISK_BYTES_READ, new QuotaTypes(VM_DISK_BYTES_READ, "VM_DISK_BYTES_READ", UsageUnitTypes.GB.toString(), "VM Disk usage(Bytes Read)"));
|
||||
quotaTypeList.put(VM_DISK_BYTES_WRITE, new QuotaTypes(VM_DISK_BYTES_WRITE, "VM_DISK_BYTES_WRITE", UsageUnitTypes.GB.toString(), "VM Disk usage(Bytes Write)"));
|
||||
quotaTypeList.put(VM_SNAPSHOT, new QuotaTypes(VM_SNAPSHOT, "VM_SNAPSHOT", UsageUnitTypes.GB_MONTH.toString(), "VM Snapshot storage usage"));
|
||||
quotaTypeList.put(VOLUME_SECONDARY, new QuotaTypes(VOLUME_SECONDARY, "VOLUME_SECONDARY", UsageUnitTypes.GB_MONTH.toString(), "Volume secondary storage usage"));
|
||||
quotaTypeList.put(VM_SNAPSHOT_ON_PRIMARY, new QuotaTypes(VM_SNAPSHOT_ON_PRIMARY, "VM_SNAPSHOT_ON_PRIMARY", UsageUnitTypes.GB_MONTH.toString(), "VM Snapshot primary storage usage"));
|
||||
quotaTypeList.put(BACKUP, new QuotaTypes(BACKUP, "BACKUP", UsageUnitTypes.GB_MONTH.toString(), "Backup storage usage"));
|
||||
quotaTypeMap = Collections.unmodifiableMap(quotaTypeList);
|
||||
}
|
||||
|
||||
|
||||
@ -26,6 +26,10 @@ import java.util.List;
|
||||
|
||||
public interface QuotaTariffDao extends GenericDao<QuotaTariffVO, Long> {
|
||||
|
||||
Pair<List<QuotaTariffVO>, Integer> listQuotaTariffs(Date startDate, Date endDate, Integer usageType, String name, String uuid, boolean listAll, Long startIndex, Long pageSize);
|
||||
|
||||
QuotaTariffVO findByName(String name);
|
||||
|
||||
QuotaTariffVO findTariffPlanByUsageType(int quotaType, Date onOrBefore);
|
||||
|
||||
Pair<List<QuotaTariffVO>, Integer> listAllTariffPlans();
|
||||
|
||||
@ -23,6 +23,7 @@ import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -124,7 +125,7 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
|
||||
if (result != null && !result.isEmpty()) {
|
||||
tariffs.add(result.get(0));
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("ListAllTariffPlans on or before " + effectiveDate + " quota type " + result.get(0).getDescription() + " , effective Date="
|
||||
s_logger.debug("ListAllTariffPlans on or before " + effectiveDate + " quota type " + result.get(0).getUsageTypeDescription() + " , effective Date="
|
||||
+ result.get(0).getEffectiveOn() + " val=" + result.get(0).getCurrencyValue());
|
||||
}
|
||||
}
|
||||
@ -156,4 +157,78 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaTariffVO>, Integer> listQuotaTariffs(Date startDate, Date endDate, Integer usageType, String name, String uuid, boolean listAll, Long startIndex, Long pageSize) {
|
||||
SearchCriteria<QuotaTariffVO> searchCriteria = createListQuotaTariffsSearchCriteria(startDate, endDate, usageType, name, uuid);
|
||||
Filter sorter = new Filter(QuotaTariffVO.class, "usageType", false, startIndex, pageSize);
|
||||
sorter.addOrderBy(QuotaTariffVO.class, "effectiveOn", false);
|
||||
sorter.addOrderBy(QuotaTariffVO.class, "updatedOn", false);
|
||||
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<Pair<List<QuotaTariffVO>, Integer>>) status -> searchAndCount(searchCriteria, sorter, listAll));
|
||||
}
|
||||
|
||||
protected SearchCriteria<QuotaTariffVO> createListQuotaTariffsSearchCriteria(Date startDate, Date endDate, Integer usageType, String name, String uuid) {
|
||||
SearchCriteria<QuotaTariffVO> searchCriteria = createListQuotaTariffsSearchBuilder(startDate, endDate, usageType, name, uuid).create();
|
||||
|
||||
searchCriteria.setParametersIfNotNull("start_date", startDate);
|
||||
searchCriteria.setParametersIfNotNull("end_date", endDate);
|
||||
searchCriteria.setParametersIfNotNull("usage_type", usageType);
|
||||
searchCriteria.setParametersIfNotNull("name", name);
|
||||
searchCriteria.setParametersIfNotNull("uuid", uuid);
|
||||
|
||||
return searchCriteria;
|
||||
}
|
||||
|
||||
protected SearchBuilder<QuotaTariffVO> createListQuotaTariffsSearchBuilder(Date startDate, Date endDate, Integer usageType, String name, String uuid) {
|
||||
SearchBuilder<QuotaTariffVO> searchBuilder = createSearchBuilder();
|
||||
|
||||
if (startDate != null) {
|
||||
searchBuilder.and("start_date", searchBuilder.entity().getEffectiveOn(), SearchCriteria.Op.GTEQ);
|
||||
}
|
||||
|
||||
if (endDate != null) {
|
||||
searchBuilder.and("end_date", searchBuilder.entity().getEndDate(), SearchCriteria.Op.LTEQ);
|
||||
}
|
||||
|
||||
if (usageType != null) {
|
||||
searchBuilder.and("usage_type", searchBuilder.entity().getUsageType(), SearchCriteria.Op.EQ);
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
searchBuilder.and("name", searchBuilder.entity().getName(), SearchCriteria.Op.EQ);
|
||||
}
|
||||
|
||||
if (uuid != null) {
|
||||
searchBuilder.and("uuid", searchBuilder.entity().getUuid(), SearchCriteria.Op.EQ);
|
||||
}
|
||||
|
||||
return searchBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaTariffVO findByName(String name) {
|
||||
Pair<List<QuotaTariffVO>, Integer> pairQuotaTariffs = listQuotaTariffs(null, null, null, name, null, false, null, null);
|
||||
List<QuotaTariffVO> quotaTariffs = pairQuotaTariffs.first();
|
||||
|
||||
if (CollectionUtils.isEmpty(quotaTariffs)) {
|
||||
s_logger.debug(String.format("Could not find quota tariff with name [%s].", name));
|
||||
return null;
|
||||
}
|
||||
|
||||
return quotaTariffs.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaTariffVO findByUuid(String uuid) {
|
||||
Pair<List<QuotaTariffVO>, Integer> pairQuotaTariffs = listQuotaTariffs(null, null, null, null, uuid, false, null, null);
|
||||
List<QuotaTariffVO> quotaTariffs = pairQuotaTariffs.first();
|
||||
|
||||
if (CollectionUtils.isEmpty(quotaTariffs)) {
|
||||
s_logger.debug(String.format("Could not find quota tariff with UUID [%s].", uuid));
|
||||
return null;
|
||||
}
|
||||
|
||||
return quotaTariffs.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
// 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.storage.VMTemplateVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface VmTemplateDao extends GenericDao<VMTemplateVO, Long> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
// 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.activationrule.presetvariables.PresetVariableHelper;
|
||||
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.VMTemplateDaoImpl;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
|
||||
/**
|
||||
* This class was created to specifically use in {@link PresetVariableHelper}.<br/><br/>
|
||||
* It was not possible to inject {@link VMTemplateDaoImpl} due to its complex injection hierarchy.
|
||||
*/
|
||||
|
||||
public class VmTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implements VmTemplateDao {
|
||||
|
||||
}
|
||||
@ -18,6 +18,9 @@ package org.apache.cloudstack.quota.vo;
|
||||
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
@ -30,6 +33,7 @@ import javax.persistence.TemporalType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_tariff")
|
||||
@ -67,6 +71,25 @@ public class QuotaTariffVO implements InternalIdentity {
|
||||
@Column(name = "updated_by")
|
||||
private Long updatedBy = null;
|
||||
|
||||
@Column(name = "uuid")
|
||||
private String uuid = UUID.randomUUID().toString();
|
||||
|
||||
@Column(name = "name", nullable = false, length = 65535)
|
||||
protected String name = null;
|
||||
|
||||
@Column(name = "description", length = 65535)
|
||||
protected String description;
|
||||
|
||||
@Column(name = "activation_rule", length = 65535)
|
||||
protected String activationRule;
|
||||
|
||||
@Column(name = GenericDao.REMOVED_COLUMN)
|
||||
protected Date removed;
|
||||
|
||||
@Column(name = "end_date")
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date endDate;
|
||||
|
||||
public QuotaTariffVO() {
|
||||
}
|
||||
|
||||
@ -87,6 +110,15 @@ public class QuotaTariffVO implements InternalIdentity {
|
||||
}
|
||||
|
||||
|
||||
public QuotaTariffVO(QuotaTariffVO that) {
|
||||
this(that.getUsageType(), that.getUsageName(), that.getUsageUnit(), that.getUsageDiscriminator(), that.getCurrencyValue(), that.getEffectiveOn(), that.getUpdatedOn(),
|
||||
that.getUpdatedBy());
|
||||
this.setName(that.getName());
|
||||
this.setDescription(that.getDescription());
|
||||
this.setActivationRule(that.getActivationRule());
|
||||
this.setEndDate(that.getEndDate());
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
@ -155,7 +187,7 @@ public class QuotaTariffVO implements InternalIdentity {
|
||||
this.currencyValue = currencyValue;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
public String getUsageTypeDescription() {
|
||||
return QuotaTypes.getDescription(usageType);
|
||||
}
|
||||
|
||||
@ -167,4 +199,68 @@ public class QuotaTariffVO implements InternalIdentity {
|
||||
public long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getActivationRule() {
|
||||
return activationRule;
|
||||
}
|
||||
|
||||
public void setActivationRule(String activationRule) {
|
||||
this.activationRule = activationRule;
|
||||
}
|
||||
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void setRemoved(Date removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public boolean setUsageTypeData(int usageType) {
|
||||
QuotaTypes quotaType = QuotaTypes.listQuotaTypes().get(usageType);
|
||||
|
||||
if (quotaType == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.setUsageType(usageType);
|
||||
this.setUsageName(quotaType.getQuotaName());
|
||||
this.setUsageUnit(quotaType.getQuotaUnit());
|
||||
this.setUsageDiscriminator(quotaType.getDiscriminator());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "uuid", "name", "effectiveOn", "endDate");
|
||||
};
|
||||
}
|
||||
@ -17,6 +17,7 @@
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<bean id="presetVariableHelper" class="org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableHelper" />
|
||||
<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" />
|
||||
|
||||
@ -16,228 +16,508 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.Domain;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableHelper;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.Value;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.dao.ServiceOfferingDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
import org.junit.Before;
|
||||
import org.apache.cloudstack.usage.UsageUnitTypes;
|
||||
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
|
||||
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.usage.UsageVO;
|
||||
import com.cloud.usage.dao.UsageDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaManagerImplTest extends TestCase {
|
||||
public class QuotaManagerImplTest {
|
||||
|
||||
@Mock
|
||||
private AccountDao accountDao;
|
||||
@Mock
|
||||
private QuotaAccountDao quotaAcc;
|
||||
@Mock
|
||||
private UsageDao usageDao;
|
||||
@Mock
|
||||
private QuotaTariffDao quotaTariffDao;
|
||||
@Mock
|
||||
private QuotaUsageDao quotaUsageDao;
|
||||
@Mock
|
||||
private ServiceOfferingDao serviceOfferingDao;
|
||||
@Mock
|
||||
private QuotaBalanceDao quotaBalanceDao;
|
||||
@Mock
|
||||
private ConfigurationDao configDao;
|
||||
UsageDao usageDaoMock;
|
||||
|
||||
@Spy
|
||||
QuotaManagerImpl quotaManager = new QuotaManagerImpl();
|
||||
@Mock
|
||||
PresetVariableHelper presetVariableHelperMock;
|
||||
|
||||
private void injectMockToField(Object mock, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field f = QuotaManagerImpl.class.getDeclaredField(fieldName);
|
||||
f.setAccessible(true);
|
||||
f.set(quotaManager, mock);
|
||||
}
|
||||
@Mock
|
||||
QuotaUsageDao quotaUsageDaoMock;
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
|
||||
// Dummy transaction stack setup
|
||||
TransactionLegacy.open("QuotaManagerImplTest");
|
||||
@InjectMocks
|
||||
QuotaManagerImpl quotaManagerImplSpy = Mockito.spy(QuotaManagerImpl.class);
|
||||
|
||||
injectMockToField(accountDao, "_accountDao");
|
||||
injectMockToField(quotaAcc, "_quotaAcc");
|
||||
injectMockToField(usageDao, "_usageDao");
|
||||
injectMockToField(quotaTariffDao, "_quotaTariffDao");
|
||||
injectMockToField(quotaUsageDao, "_quotaUsageDao");
|
||||
injectMockToField(serviceOfferingDao, "_serviceOfferingDao");
|
||||
injectMockToField(quotaBalanceDao, "_quotaBalanceDao");
|
||||
injectMockToField(configDao, "_configDao");
|
||||
}
|
||||
@Mock
|
||||
AccountVO accountVoMock;
|
||||
|
||||
@Mock
|
||||
Pair<List<UsageVO>, Integer> pairMock;
|
||||
|
||||
@Mock
|
||||
UsageVO usageVoMock;
|
||||
|
||||
@Mock
|
||||
QuotaTariffDao quotaTariffDaoMock;
|
||||
|
||||
@Mock
|
||||
QuotaTariffVO quotaTariffVoMock;
|
||||
|
||||
@Mock
|
||||
JsInterpreter jsInterpreterMock;
|
||||
|
||||
@Mock
|
||||
PresetVariables presetVariablesMock;
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Test
|
||||
public void testConfig() throws ConfigurationException {
|
||||
Mockito.when(configDao.getConfiguration(Mockito.anyMapOf(String.class, Object.class))).thenReturn(new HashMap<String, String>());
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("usage.stats.job.aggregation.range", "0");
|
||||
assertTrue(quotaManager.configure("quotaManager", map));
|
||||
}
|
||||
public void isLockableTestValidateAccountTypes() {
|
||||
List<Account.Type> lockablesAccountTypes = Arrays.asList(Account.Type.NORMAL, Account.Type.DOMAIN_ADMIN);
|
||||
|
||||
@Test
|
||||
public void testCalculateQuotaUsage() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.Type.NORMAL);
|
||||
List<AccountVO> accountVOList = new ArrayList<>();
|
||||
accountVOList.add(accountVO);
|
||||
Mockito.when(accountDao.listAll()).thenReturn(accountVOList);
|
||||
Arrays.asList(Account.Type.values()).forEach(accountType -> {
|
||||
accountVO.setType(accountType);
|
||||
|
||||
UsageVO usageVO = new UsageVO();
|
||||
usageVO.setQuotaCalculated(0);
|
||||
List<UsageVO> usageVOList = new ArrayList<UsageVO>();
|
||||
usageVOList.add(usageVO);
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = new Pair<List<? extends UsageVO>, Integer>(usageVOList, usageVOList.size());
|
||||
Mockito.when(usageDao.getUsageRecordsPendingQuotaAggregation(Mockito.anyLong(), Mockito.anyLong())).thenReturn(usageRecords);
|
||||
|
||||
QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
|
||||
quotaUsageVO.setAccountId(2L);
|
||||
List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
|
||||
quotaListForAccount.add(quotaUsageVO);
|
||||
Mockito.doReturn(quotaListForAccount).when(quotaManager).aggregatePendingQuotaRecordsForAccount(Mockito.eq(accountVO), Mockito.eq(usageRecords));
|
||||
Mockito.doNothing().when(quotaManager).processQuotaBalanceForAccount(Mockito.eq(accountVO), Mockito.eq(quotaListForAccount));
|
||||
|
||||
assertTrue(quotaManager.calculateQuotaUsage());
|
||||
if (lockablesAccountTypes.contains(accountType)) {
|
||||
Assert.assertTrue(quotaManagerImplSpy.isLockable(accountVO));
|
||||
} else {
|
||||
Assert.assertFalse(quotaManagerImplSpy.isLockable(accountVO));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAggregatePendingQuotaRecordsForAccount() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.Type.NORMAL);
|
||||
public void getPendingUsageRecordsForQuotaAggregationTestNullListReturnNull() {
|
||||
Mockito.doReturn(pairMock).when(usageDaoMock).listUsageRecordsPendingForQuotaAggregation(Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(null).when(pairMock).first();
|
||||
|
||||
UsageVO usageVO = new UsageVO();
|
||||
usageVO.setQuotaCalculated(0);
|
||||
usageVO.setUsageType(UsageTypes.ALLOCATED_VM);
|
||||
List<UsageVO> usageVOList = new ArrayList<UsageVO>();
|
||||
usageVOList.add(usageVO);
|
||||
Pair<List<? extends UsageVO>, Integer> usageRecords = new Pair<List<? extends UsageVO>, Integer>(usageVOList, usageVOList.size());
|
||||
List<UsageVO> result = quotaManagerImplSpy.getPendingUsageRecordsForQuotaAggregation(accountVoMock);
|
||||
|
||||
QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
|
||||
quotaUsageVO.setAccountId(2L);
|
||||
Mockito.doReturn(quotaUsageVO).when(quotaManager).updateQuotaAllocatedVMUsage(Mockito.eq(usageVO));
|
||||
|
||||
assertTrue(quotaManager.aggregatePendingQuotaRecordsForAccount(accountVO, new Pair<List<? extends UsageVO>, Integer>(null, 0)).size() == 0);
|
||||
assertTrue(quotaManager.aggregatePendingQuotaRecordsForAccount(accountVO, usageRecords).size() == 1);
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateQuotaRecords() {
|
||||
UsageVO usageVO = new UsageVO();
|
||||
usageVO.setId(100L);
|
||||
usageVO.setQuotaCalculated(0);
|
||||
usageVO.setUsageType(UsageTypes.NETWORK_BYTES_SENT);
|
||||
usageVO.setRawUsage(9000000000.0);
|
||||
usageVO.setSize(1010101010L);
|
||||
public void getPendingUsageRecordsForQuotaAggregationTestEmptyListReturnNull() {
|
||||
Mockito.doReturn(pairMock).when(usageDaoMock).listUsageRecordsPendingForQuotaAggregation(Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(new ArrayList<>()).when(pairMock).first();
|
||||
|
||||
QuotaTariffVO tariffVO = new QuotaTariffVO();
|
||||
tariffVO.setCurrencyValue(new BigDecimal(1));
|
||||
Mockito.when(quotaTariffDao.findTariffPlanByUsageType(nullable(Integer.class), nullable(Date.class))).thenReturn(tariffVO);
|
||||
List<UsageVO> result = quotaManagerImplSpy.getPendingUsageRecordsForQuotaAggregation(accountVoMock);
|
||||
|
||||
QuotaUsageVO qu = quotaManager.updateQuotaNetwork(usageVO, UsageTypes.NETWORK_BYTES_SENT);
|
||||
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
|
||||
qu = quotaManager.updateQuotaAllocatedVMUsage(usageVO);
|
||||
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
|
||||
qu = quotaManager.updateQuotaDiskUsage(usageVO, UsageTypes.VOLUME);
|
||||
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
|
||||
qu = quotaManager.updateQuotaRaw(usageVO, UsageTypes.VPN_USERS);
|
||||
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
|
||||
|
||||
Mockito.verify(quotaUsageDao, Mockito.times(4)).persistQuotaUsage(Mockito.any(QuotaUsageVO.class));
|
||||
Mockito.verify(usageDao, Mockito.times(4)).persistUsage(Mockito.any(UsageVO.class));
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessQuotaBalanceForAccount() {
|
||||
Date now = new Date();
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.Type.NORMAL);
|
||||
public void getPendingUsageRecordsForQuotaAggregationTesNotEmptyListReturnList() {
|
||||
List<UsageVO> expected = Arrays.asList(new UsageVO());
|
||||
|
||||
QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
|
||||
quotaUsageVO.setAccountId(2L);
|
||||
quotaUsageVO.setStartDate(new Date(now.getTime()));
|
||||
quotaUsageVO.setEndDate(new Date(now.getTime()));
|
||||
List<QuotaUsageVO> quotaListForAccount = new ArrayList<>();
|
||||
quotaListForAccount.add(quotaUsageVO);
|
||||
Mockito.doReturn(pairMock).when(usageDaoMock).listUsageRecordsPendingForQuotaAggregation(Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(expected).when(pairMock).first();
|
||||
|
||||
quotaManager.processQuotaBalanceForAccount(accountVO, quotaListForAccount);
|
||||
Mockito.verify(quotaAcc, Mockito.times(1)).persistQuotaAccount(Mockito.any(QuotaAccountVO.class));
|
||||
}
|
||||
List<UsageVO> result = quotaManagerImplSpy.getPendingUsageRecordsForQuotaAggregation(accountVoMock);
|
||||
|
||||
private AccountVO accountVO = new AccountVO();
|
||||
|
||||
@Test
|
||||
public void testAdminLockableAccount() {
|
||||
accountVO.setType(Account.Type.ADMIN);
|
||||
assertFalse(quotaManager.isLockable(accountVO));
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalLockableAccount() {
|
||||
accountVO.setType(Account.Type.NORMAL);
|
||||
assertTrue(quotaManager.isLockable(accountVO));
|
||||
public void getUsageValueAccordingToUsageUnitTypeTestAllTypes() {
|
||||
Mockito.doReturn(10.0).when(usageVoMock).getRawUsage();
|
||||
Mockito.doReturn(ByteScaleUtils.GiB).when(usageVoMock).getSize();
|
||||
BigDecimal aggregatedQuotaTariffsValue = new BigDecimal(400);
|
||||
|
||||
Arrays.asList(UsageUnitTypes.values()).forEach(type -> {
|
||||
BigDecimal result = quotaManagerImplSpy.getUsageValueAccordingToUsageUnitType(usageVoMock, aggregatedQuotaTariffsValue, type.toString());
|
||||
Double expected = null;
|
||||
|
||||
switch (type) {
|
||||
case COMPUTE_MONTH:
|
||||
case IP_MONTH:
|
||||
case POLICY_MONTH:
|
||||
//The value 5.5555556 is referent to the calculation (( tariffs values / hours in month ) * raw usage ).
|
||||
expected = 5.5555556;
|
||||
break;
|
||||
|
||||
case GB:
|
||||
//The value 0.000004 is referent to the calculation (( raw usage / gib) * tariffs values ).
|
||||
expected = 0.000004;
|
||||
break;
|
||||
|
||||
case GB_MONTH:
|
||||
//The value 5.5555556 is referent to the calculation (( usage size / gib ) * raw usage * ( tariffs values / hours in month )).
|
||||
expected = 5.5555556;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.assertEquals(expected, result.doubleValue(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
private void mockUsageRecordAndQuotaTariffForTests(Date usageRecordStartDate, Date usageRecordEndDate, Date quotaTariffStartDate, Date quotaTariffEndDate) {
|
||||
Mockito.doReturn(usageRecordStartDate).when(usageVoMock).getStartDate();
|
||||
Mockito.doReturn(usageRecordEndDate).when(usageVoMock).getEndDate();
|
||||
Mockito.doReturn(quotaTariffStartDate).when(quotaTariffVoMock).getEffectiveOn();
|
||||
Mockito.doReturn(quotaTariffEndDate).when(quotaTariffVoMock).getEndDate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tesDomainAdmingLockableAccount() {
|
||||
accountVO.setType(Account.Type.DOMAIN_ADMIN);
|
||||
assertTrue(quotaManager.isLockable(accountVO));
|
||||
public void isQuotaTariffInPeriodToBeAppliedTestQuotaTariffEndDateIsNullAndUsageRecordEndDateIsBeforeQuotaTariffStartDateReturnFalse() throws ParseException {
|
||||
mockUsageRecordAndQuotaTariffForTests(null, sdf.parse("2022-01-20 10:00:00"), sdf.parse("2022-01-20 12:00:00"), null);
|
||||
boolean result = quotaManagerImplSpy.isQuotaTariffInPeriodToBeApplied(usageVoMock, quotaTariffVoMock, "");
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadOnlyAdminLockableAccount() {
|
||||
accountVO.setType(Account.Type.READ_ONLY_ADMIN);
|
||||
assertFalse(quotaManager.isLockable(accountVO));
|
||||
public void isQuotaTariffInPeriodToBeAppliedTestQuotaTariffEndDateIsNullAndUsageRecordEndDateIsAfterQuotaTariffStartDateReturnTrue() throws ParseException {
|
||||
mockUsageRecordAndQuotaTariffForTests(null, sdf.parse("2022-01-21 20:00:00"), sdf.parse("2022-01-18 11:30:00"), null);
|
||||
boolean result = quotaManagerImplSpy.isQuotaTariffInPeriodToBeApplied(usageVoMock, quotaTariffVoMock, "");
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceDomainAdminLockableAccount() {
|
||||
accountVO.setType(Account.Type.RESOURCE_DOMAIN_ADMIN);
|
||||
assertFalse(quotaManager.isLockable(accountVO));
|
||||
public void isQuotaTariffInPeriodToBeAppliedTestQuotaTariffEndDateIsNullAndUsageRecordEndDateIsEqualToQuotaTariffStartDateReturnTrue() throws ParseException {
|
||||
mockUsageRecordAndQuotaTariffForTests(null, sdf.parse("2022-01-12 00:00:00"), sdf.parse("2022-01-12 00:00:00"), null);
|
||||
boolean result = quotaManagerImplSpy.isQuotaTariffInPeriodToBeApplied(usageVoMock, quotaTariffVoMock, "");
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProjectLockableAccount() {
|
||||
accountVO.setType(Account.Type.PROJECT);
|
||||
assertFalse(quotaManager.isLockable(accountVO));
|
||||
public void isQuotaTariffInPeriodToBeAppliedTestUsageRecordStartDateIsAfterQuotaTariffEndDateAndUsageRecordEndDateIsAfterQuotaTariffStartDateReturnFalse() throws ParseException {
|
||||
mockUsageRecordAndQuotaTariffForTests(sdf.parse("2022-01-11 00:00:00"), sdf.parse("2022-01-12 00:00:00"), sdf.parse("2022-01-08 00:00:00"), sdf.parse("2022-01-10 00:00:00"));
|
||||
boolean result = quotaManagerImplSpy.isQuotaTariffInPeriodToBeApplied(usageVoMock, quotaTariffVoMock, "");
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isQuotaTariffInPeriodToBeAppliedTestUsageRecordStartDateIsEqualToQuotaTariffEndDateAndUsageRecordEndDateIsAfterQuotaTariffStartDateReturnTrue() throws ParseException {
|
||||
mockUsageRecordAndQuotaTariffForTests(sdf.parse("2022-01-18 17:35:12"), sdf.parse("2022-01-12 00:00:00"), sdf.parse("2022-01-08 00:00:00"), sdf.parse("2022-01-18 17:35:12"));
|
||||
boolean result = quotaManagerImplSpy.isQuotaTariffInPeriodToBeApplied(usageVoMock, quotaTariffVoMock, "");
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isQuotaTariffInPeriodToBeAppliedTestUsageRecordStartDateIsBeforeQuotaTariffEndDateAndUsageRecordEndDateIsAfterQuotaTariffStartDateReturnTrue() throws ParseException {
|
||||
mockUsageRecordAndQuotaTariffForTests(sdf.parse("2022-01-15 00:23:15"), sdf.parse("2022-01-16 00:23:15"), sdf.parse("2022-01-08 00:00:00"), sdf.parse("2022-01-16 00:50:08"));
|
||||
boolean result = quotaManagerImplSpy.isQuotaTariffInPeriodToBeApplied(usageVoMock, quotaTariffVoMock, "");
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isQuotaTariffInPeriodToBeAppliedTestUsageRecordStartDateIsBeforeQuotaTariffEndDateAndUsageRecordEndDateIsBeforeQuotaTariffStartDateReturnFalse() throws ParseException {
|
||||
mockUsageRecordAndQuotaTariffForTests(sdf.parse("2022-01-20 11:44:37"), sdf.parse("2022-01-21 11:44:37"), sdf.parse("2022-01-22 15:06:32"), sdf.parse("2022-01-28 18:33:01"));
|
||||
boolean result = quotaManagerImplSpy.isQuotaTariffInPeriodToBeApplied(usageVoMock, quotaTariffVoMock, "");
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isQuotaTariffInPeriodToBeAppliedTestUsageRecordStartDateIsBeforeQuotaTariffEndDateAndUsageRecordEndDateIsEqualToQuotaTariffStartDateReturnTrue() throws ParseException {
|
||||
mockUsageRecordAndQuotaTariffForTests(sdf.parse("2022-01-20 11:44:37"), sdf.parse("2022-01-22 15:06:32"), sdf.parse("2022-01-22 15:06:32"), sdf.parse("2022-01-28 18:33:01"));
|
||||
boolean result = quotaManagerImplSpy.isQuotaTariffInPeriodToBeApplied(usageVoMock, quotaTariffVoMock, "");
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void injectPresetVariablesIntoJsInterpreterTestProjectIsNullDoNotInjectProject() {
|
||||
Mockito.doNothing().when(jsInterpreterMock).injectVariable(Mockito.anyString(), Mockito.anyString());
|
||||
|
||||
Mockito.doReturn(new org.apache.cloudstack.quota.activationrule.presetvariables.Account()).when(presetVariablesMock).getAccount();
|
||||
Mockito.doReturn(new Domain()).when(presetVariablesMock).getDomain();
|
||||
Mockito.doReturn(null).when(presetVariablesMock).getProject();
|
||||
Mockito.doReturn("test").when(presetVariablesMock).getResourceType();
|
||||
Mockito.doReturn(new Value()).when(presetVariablesMock).getValue();
|
||||
Mockito.doReturn(new GenericPresetVariable()).when(presetVariablesMock).getZone();
|
||||
|
||||
quotaManagerImplSpy.injectPresetVariablesIntoJsInterpreter(jsInterpreterMock, presetVariablesMock);
|
||||
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("account"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("domain"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock, Mockito.never()).injectVariable(Mockito.eq("project"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("resourceType"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("value"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("zone"), Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void injectPresetVariablesIntoJsInterpreterTestProjectIsNotNullInjectProject() {
|
||||
Mockito.doNothing().when(jsInterpreterMock).injectVariable(Mockito.anyString(), Mockito.anyString());
|
||||
|
||||
Mockito.doReturn(new org.apache.cloudstack.quota.activationrule.presetvariables.Account()).when(presetVariablesMock).getAccount();
|
||||
Mockito.doReturn(new Domain()).when(presetVariablesMock).getDomain();
|
||||
Mockito.doReturn(new GenericPresetVariable()).when(presetVariablesMock).getProject();
|
||||
Mockito.doReturn("test").when(presetVariablesMock).getResourceType();
|
||||
Mockito.doReturn(new Value()).when(presetVariablesMock).getValue();
|
||||
Mockito.doReturn(new GenericPresetVariable()).when(presetVariablesMock).getZone();
|
||||
|
||||
quotaManagerImplSpy.injectPresetVariablesIntoJsInterpreter(jsInterpreterMock, presetVariablesMock);
|
||||
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("account"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("domain"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("project"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("resourceType"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("value"), Mockito.anyString());
|
||||
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("zone"), Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createMapQuotaTariffsPerUsageTypeTestNoTariffs() {
|
||||
Mockito.doReturn(new Pair<>(new ArrayList<>(), 0)).when(quotaTariffDaoMock).listQuotaTariffs(Mockito.any(), Mockito.any(), Mockito.any(),Mockito.any(), Mockito.any(),
|
||||
Mockito.anyBoolean(), Mockito.any(), Mockito.any());
|
||||
|
||||
Map<Integer, Pair<List<QuotaTariffVO>, Boolean>> result = quotaManagerImplSpy.createMapQuotaTariffsPerUsageType();
|
||||
|
||||
for (Map.Entry<Integer, QuotaTypes> entry : QuotaTypes.listQuotaTypes().entrySet()) {
|
||||
Pair<List<QuotaTariffVO>, Boolean> pair = result.get(entry.getKey());
|
||||
Assert.assertTrue(pair.first().isEmpty());
|
||||
Assert.assertFalse(pair.second());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createMapQuotaTariffsPerUsageTypeTestTariffsWithEmptyActivationRule() {
|
||||
List<QuotaTariffVO> tariffs = new ArrayList<>();
|
||||
QuotaTariffVO tariff = new QuotaTariffVO(1);
|
||||
tariff.setActivationRule("");
|
||||
tariffs.add(tariff);
|
||||
|
||||
Mockito.doReturn(new Pair<>(tariffs, tariffs.size())).when(quotaTariffDaoMock).listQuotaTariffs(Mockito.any(), Mockito.any(), Mockito.any(),Mockito.any(), Mockito.any(),
|
||||
Mockito.anyBoolean(), Mockito.any(), Mockito.any());
|
||||
|
||||
Map<Integer, Pair<List<QuotaTariffVO>, Boolean>> result = quotaManagerImplSpy.createMapQuotaTariffsPerUsageType();
|
||||
|
||||
for (Map.Entry<Integer, QuotaTypes> entry : QuotaTypes.listQuotaTypes().entrySet()) {
|
||||
Pair<List<QuotaTariffVO>, Boolean> pair = result.get(entry.getKey());
|
||||
if (entry.getKey() == 1) {
|
||||
Assert.assertFalse(pair.first().isEmpty());
|
||||
} else {
|
||||
Assert.assertTrue(pair.first().isEmpty());
|
||||
}
|
||||
Assert.assertFalse(pair.second());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createMapQuotaTariffsPerUsageTypeTestTariffsWithActivationRule() {
|
||||
List<QuotaTariffVO> tariffs = new ArrayList<>();
|
||||
QuotaTariffVO tariff = new QuotaTariffVO(1);
|
||||
tariff.setActivationRule(" ");
|
||||
tariffs.add(tariff);
|
||||
|
||||
Mockito.doReturn(new Pair<>(tariffs, tariffs.size())).when(quotaTariffDaoMock).listQuotaTariffs(Mockito.any(), Mockito.any(), Mockito.any(),Mockito.any(), Mockito.any(),
|
||||
Mockito.anyBoolean(), Mockito.any(), Mockito.any());
|
||||
|
||||
Map<Integer, Pair<List<QuotaTariffVO>, Boolean>> result = quotaManagerImplSpy.createMapQuotaTariffsPerUsageType();
|
||||
|
||||
for (Map.Entry<Integer, QuotaTypes> entry : QuotaTypes.listQuotaTypes().entrySet()) {
|
||||
Pair<List<QuotaTariffVO>, Boolean> pair = result.get(entry.getKey());
|
||||
if (entry.getKey() == 1) {
|
||||
Assert.assertFalse(pair.first().isEmpty());
|
||||
Assert.assertTrue(pair.second());
|
||||
} else {
|
||||
Assert.assertTrue(pair.first().isEmpty());
|
||||
Assert.assertFalse(pair.second());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQuotaUsageAccordingToUsageUnitTariffValueZeroReturnNull() {
|
||||
QuotaUsageVO result = quotaManagerImplSpy.createQuotaUsageAccordingToUsageUnit(usageVoMock, BigDecimal.ZERO, null);
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQuotaUsageAccordingToUsageUnitTariffValueIsNotZeroReturnObject() {
|
||||
Date startDate = new Date();
|
||||
Date endDate = new Date();
|
||||
|
||||
QuotaTypes.listQuotaTypes().entrySet().forEach(entry -> {
|
||||
Mockito.doReturn(entry.getKey()).when(usageVoMock).getUsageType();
|
||||
Mockito.doReturn(BigDecimal.TEN).when(quotaManagerImplSpy).getUsageValueAccordingToUsageUnitType(Mockito.any(), Mockito.any(), Mockito.anyString());
|
||||
Mockito.doReturn(2l).when(usageVoMock).getId();
|
||||
Mockito.doReturn(3l).when(usageVoMock).getZoneId();
|
||||
Mockito.doReturn(4l).when(usageVoMock).getAccountId();
|
||||
Mockito.doReturn(5l).when(usageVoMock).getDomainId();
|
||||
Mockito.doReturn(startDate).when(usageVoMock).getStartDate();
|
||||
Mockito.doReturn(endDate).when(usageVoMock).getEndDate();
|
||||
|
||||
QuotaUsageVO result = quotaManagerImplSpy.createQuotaUsageAccordingToUsageUnit(usageVoMock, BigDecimal.ONE, null);
|
||||
|
||||
Assert.assertEquals(2l, result.getUsageItemId().longValue());
|
||||
Assert.assertEquals(3l, result.getZoneId().longValue());
|
||||
Assert.assertEquals(4l, result.getAccountId().longValue());
|
||||
Assert.assertEquals(5l, result.getDomainId().longValue());
|
||||
Assert.assertEquals(entry.getKey().intValue(), result.getUsageType());
|
||||
Assert.assertEquals(BigDecimal.TEN, result.getQuotaUsed());
|
||||
Assert.assertEquals(startDate, result.getStartDate());
|
||||
Assert.assertEquals(endDate, result.getEndDate());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaTariffValueToBeAppliedTestActivationRuleIsNullReturnTariffValue() {
|
||||
Mockito.doReturn(null).when(quotaTariffVoMock).getActivationRule();
|
||||
Mockito.doReturn(BigDecimal.ONE).when(quotaTariffVoMock).getCurrencyValue();
|
||||
|
||||
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, null, null);
|
||||
|
||||
Assert.assertEquals(BigDecimal.ONE, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaTariffValueToBeAppliedTestActivationRuleIsEmptyReturnTariffValue() {
|
||||
Mockito.doReturn("").when(quotaTariffVoMock).getActivationRule();
|
||||
Mockito.doReturn(BigDecimal.TEN).when(quotaTariffVoMock).getCurrencyValue();
|
||||
|
||||
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, null, null);
|
||||
|
||||
Assert.assertEquals(BigDecimal.TEN, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaTariffValueToBeAppliedTestScriptResultIsNumberReturnIt() {
|
||||
BigDecimal expected = new BigDecimal(50.1);
|
||||
|
||||
Mockito.doReturn(" ").when(quotaTariffVoMock).getActivationRule();
|
||||
Mockito.doReturn(BigDecimal.TEN).when(quotaTariffVoMock).getCurrencyValue();
|
||||
Mockito.doNothing().when(quotaManagerImplSpy).injectPresetVariablesIntoJsInterpreter(Mockito.any(), Mockito.any());
|
||||
Mockito.doReturn(expected).when(jsInterpreterMock).executeScript(Mockito.anyString());
|
||||
|
||||
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock);
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaTariffValueToBeAppliedTestScriptResultIsTrueReturnTariffValue() {
|
||||
BigDecimal expected = new BigDecimal(236.84);
|
||||
|
||||
Mockito.doReturn(" ").when(quotaTariffVoMock).getActivationRule();
|
||||
Mockito.doReturn(expected).when(quotaTariffVoMock).getCurrencyValue();
|
||||
Mockito.doNothing().when(quotaManagerImplSpy).injectPresetVariablesIntoJsInterpreter(Mockito.any(), Mockito.any());
|
||||
Mockito.doReturn(true).when(jsInterpreterMock).executeScript(Mockito.anyString());
|
||||
|
||||
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock);
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaTariffValueToBeAppliedTestScriptResultIsFalseReturnZero() {
|
||||
Mockito.doReturn(" ").when(quotaTariffVoMock).getActivationRule();
|
||||
Mockito.doReturn(BigDecimal.TEN).when(quotaTariffVoMock).getCurrencyValue();
|
||||
Mockito.doNothing().when(quotaManagerImplSpy).injectPresetVariablesIntoJsInterpreter(Mockito.any(), Mockito.any());
|
||||
Mockito.doReturn(false).when(jsInterpreterMock).executeScript(Mockito.anyString());
|
||||
|
||||
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock);
|
||||
|
||||
Assert.assertEquals(BigDecimal.ZERO, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaTariffValueToBeAppliedTestScriptResultIsNotBooleanNorNumericReturnZero() {
|
||||
Mockito.doReturn(" ").when(quotaTariffVoMock).getActivationRule();
|
||||
Mockito.doReturn(BigDecimal.TEN).when(quotaTariffVoMock).getCurrencyValue();
|
||||
Mockito.doNothing().when(quotaManagerImplSpy).injectPresetVariablesIntoJsInterpreter(Mockito.any(), Mockito.any());
|
||||
Mockito.doReturn("test").when(jsInterpreterMock).executeScript(Mockito.anyString());
|
||||
|
||||
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock);
|
||||
|
||||
Assert.assertEquals(BigDecimal.ZERO, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPresetVariablesTestDoesNotHaveTariffsWithActivationRuleReturnNull() {
|
||||
PresetVariables result = quotaManagerImplSpy.getPresetVariables(false, usageVoMock);
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPresetVariablesTestHasTariffsWithActivationRuleReturnPresetVariables() {
|
||||
Mockito.doReturn(presetVariablesMock).when(presetVariableHelperMock).getPresetVariables(Mockito.any());
|
||||
PresetVariables result = quotaManagerImplSpy.getPresetVariables(true, usageVoMock);
|
||||
Assert.assertEquals(presetVariablesMock, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aggregateQuotaTariffsValuesTestTariffsWereNotInPeriodToBeAppliedReturnZero() {
|
||||
List<QuotaTariffVO> tariffs = new ArrayList<>();
|
||||
tariffs.add(new QuotaTariffVO());
|
||||
tariffs.add(new QuotaTariffVO());
|
||||
tariffs.add(new QuotaTariffVO());
|
||||
|
||||
Mockito.doReturn(false).when(quotaManagerImplSpy).isQuotaTariffInPeriodToBeApplied(Mockito.any(), Mockito.any(), Mockito.anyString());
|
||||
BigDecimal result = quotaManagerImplSpy.aggregateQuotaTariffsValues(usageVoMock, tariffs, false, jsInterpreterMock, "");
|
||||
|
||||
Assert.assertEquals(BigDecimal.ZERO, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aggregateQuotaTariffsValuesTestTariffsIsEmptyReturnZero() {
|
||||
BigDecimal result = quotaManagerImplSpy.aggregateQuotaTariffsValues(usageVoMock, new ArrayList<>(), false, jsInterpreterMock, "");
|
||||
|
||||
Assert.assertEquals(BigDecimal.ZERO, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aggregateQuotaTariffsValuesTestTariffsAreInPeriodToBeAppliedReturnAggregation() {
|
||||
List<QuotaTariffVO> tariffs = new ArrayList<>();
|
||||
tariffs.add(new QuotaTariffVO());
|
||||
tariffs.add(new QuotaTariffVO());
|
||||
tariffs.add(new QuotaTariffVO());
|
||||
|
||||
Mockito.doReturn(true, false, true).when(quotaManagerImplSpy).isQuotaTariffInPeriodToBeApplied(Mockito.any(), Mockito.any(), Mockito.anyString());
|
||||
Mockito.doReturn(BigDecimal.TEN).when(quotaManagerImplSpy).getQuotaTariffValueToBeApplied(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
BigDecimal result = quotaManagerImplSpy.aggregateQuotaTariffsValues(usageVoMock, tariffs, false, jsInterpreterMock, "");
|
||||
|
||||
Assert.assertEquals(BigDecimal.TEN.multiply(new BigDecimal(2)), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void persistUsagesAndQuotaUsagesAndRetrievePersistedQuotaUsagesTestReturnOnlyPersistedQuotaUsageVo() {
|
||||
List<Pair<UsageVO, QuotaUsageVO>> listPair = new ArrayList<>();
|
||||
QuotaUsageVO quotaUsageVoMock1 = Mockito.mock(QuotaUsageVO.class);
|
||||
QuotaUsageVO quotaUsageVoMock2 = Mockito.mock(QuotaUsageVO.class);
|
||||
|
||||
listPair.add(new Pair<>(new UsageVO(), quotaUsageVoMock1));
|
||||
listPair.add(new Pair<>(new UsageVO(), null));
|
||||
listPair.add(new Pair<>(new UsageVO(), quotaUsageVoMock2));
|
||||
|
||||
Mockito.doReturn(null).when(usageDaoMock).persistUsage(Mockito.any());
|
||||
Mockito.doReturn(null).when(quotaUsageDaoMock).persistQuotaUsage(Mockito.any());
|
||||
|
||||
List<QuotaUsageVO> result = quotaManagerImplSpy.persistUsagesAndQuotaUsagesAndRetrievePersistedQuotaUsages(listPair);
|
||||
|
||||
Assert.assertEquals(2, result.size());
|
||||
Assert.assertEquals(quotaUsageVoMock1, result.get(0));
|
||||
Assert.assertEquals(quotaUsageVoMock2, result.get(1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AccountTest {
|
||||
|
||||
@Test
|
||||
public void setRoleTestAddFieldRoleToCollection() {
|
||||
Account variable = new Account();
|
||||
variable.setRole(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("role"));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.activationrule.presetvariables;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BackupOfferingTest {
|
||||
@Test
|
||||
public void setExternalIdTestAddFieldExternalIdToCollection() {
|
||||
BackupOffering backupOffering = new BackupOffering();
|
||||
backupOffering.setExternalId("any-external-id");
|
||||
Assert.assertTrue(backupOffering.fieldNamesToIncludeInToString.contains("externalId"));
|
||||
}
|
||||
|
||||
}
|
||||
@ -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.activationrule.presetvariables;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ComputeOfferingTest {
|
||||
|
||||
@Test
|
||||
public void setCustomizedTestAddFieldCustomizedToCollection() {
|
||||
ComputeOffering variable = new ComputeOffering();
|
||||
variable.setCustomized(true);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("customized"));
|
||||
}
|
||||
|
||||
}
|
||||
@ -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.activationrule.presetvariables;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ComputingResourcesTest {
|
||||
|
||||
@Test
|
||||
public void toStringTestReturnAJson() {
|
||||
ComputingResources variable = new ComputingResources();
|
||||
|
||||
String expected = ToStringBuilder.reflectionToString(variable, ToStringStyle.JSON_STYLE);
|
||||
String result = variable.toString();
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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.activationrule.presetvariables;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DomainTest {
|
||||
|
||||
@Test
|
||||
public void setPathTestAddFieldPathToCollection() {
|
||||
Domain variable = new Domain();
|
||||
variable.setPath("test path");
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("path"));
|
||||
}
|
||||
|
||||
}
|
||||
@ -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.activationrule.presetvariables;
|
||||
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GenericPresetVariableTest {
|
||||
|
||||
@Test
|
||||
public void setIdTestAddFieldIdToCollection() {
|
||||
GenericPresetVariable variable = new GenericPresetVariable();
|
||||
variable.setId("test");
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNameTestAddFieldNameToCollection() {
|
||||
GenericPresetVariable variable = new GenericPresetVariable();
|
||||
variable.setName("test");
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringTestSetAllFieldsAndReturnAJson() {
|
||||
GenericPresetVariable variable = new GenericPresetVariable();
|
||||
variable.setId("test id");
|
||||
variable.setName("test name");
|
||||
|
||||
String expected = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(variable, "id", "name");
|
||||
String result = variable.toString();
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringTestSetSomeFieldsAndReturnAJson() {
|
||||
GenericPresetVariable variable = new GenericPresetVariable();
|
||||
variable.setId("test id");
|
||||
|
||||
String expected = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(variable, "id");
|
||||
String result = variable.toString();
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
|
||||
variable = new GenericPresetVariable();
|
||||
variable.setName("test name");
|
||||
|
||||
expected = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(variable, "name");
|
||||
result = variable.toString();
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class HostTest {
|
||||
|
||||
@Test
|
||||
public void setTagsTestAddFieldTagsToCollection() {
|
||||
Host variable = new Host();
|
||||
variable.setTags(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("tags"));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -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.activationrule.presetvariables;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ResourceTest {
|
||||
|
||||
@Test
|
||||
public void toStringTestReturnAJson() {
|
||||
Resource variable = new Resource();
|
||||
|
||||
String expected = ToStringBuilder.reflectionToString(variable, ToStringStyle.JSON_STYLE);
|
||||
String result = variable.toString();
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RoleTest {
|
||||
|
||||
@Test
|
||||
public void setTagsTestAddFieldTagsToCollection() {
|
||||
Role variable = new Role();
|
||||
variable.setType(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("type"));
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
|
||||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StorageTest {
|
||||
|
||||
@Test
|
||||
public void setTagsTestAddFieldTagsToCollection() {
|
||||
Storage variable = new Storage();
|
||||
variable.setTags(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("tags"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setScopeTestAddFieldScopeToCollection() {
|
||||
Storage variable = new Storage();
|
||||
variable.setScope(null);;
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("scope"));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,139 @@
|
||||
// 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.activationrule.presetvariables;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ValueTest {
|
||||
|
||||
@Test
|
||||
public void setHostTestAddFieldHostToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setHost(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("host"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setOsNameTestAddFieldOsNameToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setOsName(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("osName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAccountResourcesTestAddFieldAccountResourcesToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setAccountResources(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("accountResources"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTagsTestAddFieldTagsToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setTags(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("tags"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTagTestAddFieldTagToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setTag(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("tag"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSizeTestAddFieldSizeToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setSize(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("size"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setProvisioningTypeTestAddFieldProvisioningTypeToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setProvisioningType(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("provisioningType"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSnapshotTypeTestAddFieldSnapshotTypeToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setSnapshotType(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("snapshotType"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVmSnapshotTypeTestAddFieldVmSnapshotTypeToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setVmSnapshotType(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("vmSnapshotType"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setComputeOfferingTestAddFieldComputeOfferingToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setComputeOffering(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("computeOffering"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTemplateTestAddFieldTemplateToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setTemplate(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("template"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDiskOfferingTestAddFieldDiskOfferingToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setDiskOffering(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("diskOffering"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setStorageTestAddFieldStorageToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setStorage(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("storage"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setComputingResourcesTestAddFieldComputingResourcesToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setComputingResources(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("computingResources"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVirtualSizeTestAddFieldVirtualSizeToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setVirtualSize(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("virtualSize"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setBackupOfferingTestAddFieldBackupOfferingToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setBackupOffering(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("backupOffering"));
|
||||
}
|
||||
}
|
||||
@ -43,6 +43,6 @@ public class QuotaTypesTest extends TestCase {
|
||||
@Test
|
||||
public void testQuotaTypeDescription() {
|
||||
assertNull(QuotaTypes.getDescription(-1));
|
||||
assertNotNull(QuotaTypes.getDescription(QuotaTypes.MEMORY));
|
||||
assertNotNull(QuotaTypes.getDescription(QuotaTypes.VOLUME));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Licensed 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 org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuotaTariffVOTest {
|
||||
|
||||
@Test
|
||||
public void setUsageTypeDataTestSetAllDataAndReturnTrueToAllexistingQuotaType() {
|
||||
QuotaTariffVO quotaTariffVoTest = new QuotaTariffVO();
|
||||
|
||||
for (Map.Entry<Integer, QuotaTypes> quotaType: QuotaTypes.listQuotaTypes().entrySet()) {
|
||||
boolean result = quotaTariffVoTest.setUsageTypeData(quotaType.getKey());
|
||||
|
||||
Assert.assertTrue(result);
|
||||
Assert.assertEquals((int) quotaType.getKey(), quotaTariffVoTest.getUsageType());
|
||||
Assert.assertEquals(quotaType.getValue().getQuotaName(), quotaTariffVoTest.getUsageName());
|
||||
Assert.assertEquals(quotaType.getValue().getQuotaUnit(), quotaTariffVoTest.getUsageUnit());
|
||||
Assert.assertEquals(quotaType.getValue().getDiscriminator(), quotaTariffVoTest.getUsageDiscriminator());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setUsageTypeDataTestReturnFalseToInvalidUsageType() {
|
||||
QuotaTariffVO quotaTariffVoTest = new QuotaTariffVO();
|
||||
|
||||
boolean result = quotaTariffVoTest.setUsageTypeData(0);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
}
|
||||
@ -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.command;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
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 = QuotaTariffCreateCmd.API_NAME, responseObject = QuotaTariffResponse.class, description = "Creates a quota tariff for a resource.", since = "4.17.0.0",
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
|
||||
public class QuotaTariffCreateCmd extends BaseCmd {
|
||||
protected Logger logger = Logger.getLogger(getClass());
|
||||
public static final String API_NAME = "quotaTariffCreate";
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Quota tariff's name", length = 32)
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Quota tariff's description.", length = 256)
|
||||
private String description;
|
||||
|
||||
@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.ACTIVATION_RULE, type = CommandType.STRING, description = "Quota tariff's activation rule.",
|
||||
length = 65535)
|
||||
private String activationRule;
|
||||
|
||||
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "The effective start date on/after which the quota tariff is effective. Use yyyy-MM-dd as"
|
||||
+ " the date format, e.g. startDate=2009-06-03. Inform null to use the current date.")
|
||||
private Date startDate;
|
||||
|
||||
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "The end date of the quota tariff. Use yyyy-MM-dd as the date format, e.g."
|
||||
+ " endDate=2009-06-03.")
|
||||
private Date endDate;
|
||||
|
||||
public QuotaTariffCreateCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return QuotaTariffCreateCmd.API_NAME.toLowerCase() + RESPONSE_SUFFIX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
QuotaTariffVO result = responseBuilder.createQuotaTariff(this);
|
||||
|
||||
if (result == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create new quota tariff.");
|
||||
}
|
||||
|
||||
QuotaTariffResponse response = responseBuilder.createQuotaTariffResponse(result);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Integer getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(Integer usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getActivationRule() {
|
||||
return activationRule;
|
||||
}
|
||||
|
||||
public void setActivationRule(String activationRule) {
|
||||
this.activationRule = activationRule;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
//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.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.api.response.QuotaTariffResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = QuotaTariffDeleteCmd.API_NAME, description = "Marks a quota tariff as removed.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false, since = "4.17.0.0", authorized = {RoleType.Admin})
|
||||
public class QuotaTariffDeleteCmd extends BaseCmd {
|
||||
public static final String API_NAME = "quotaTariffDelete";
|
||||
protected Logger logger = Logger.getLogger(getClass());
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Parameter(name = ApiConstants.UUID, type = BaseCmd.CommandType.STRING, required = true, entityType = QuotaTariffResponse.class,
|
||||
description = "UUID of the quota tariff", validations = {ApiArgValidator.UuidString})
|
||||
private String quotaTariffUuid;
|
||||
|
||||
public String getQuotaTariffUuid() {
|
||||
return quotaTariffUuid;
|
||||
}
|
||||
|
||||
public void setQuotaTariffId(String quotaTariffUuid) {
|
||||
this.quotaTariffUuid = quotaTariffUuid;
|
||||
}
|
||||
|
||||
public QuotaTariffDeleteCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return QuotaTariffDeleteCmd.API_NAME.toLowerCase() + RESPONSE_SUFFIX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
boolean result = responseBuilder.deleteQuotaTariff(getQuotaTariffUuid());
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
response.setSuccess(result);
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
}
|
||||
@ -27,6 +27,7 @@ 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.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -46,9 +47,21 @@ public class QuotaTariffListCmd extends BaseListCmd {
|
||||
@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.")
|
||||
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = false, description = "The start date of the quota tariff. Use yyyy-MM-dd as the date format, "
|
||||
+ "e.g. startDate=2009-06-03.")
|
||||
private Date effectiveDate;
|
||||
|
||||
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = false, description = "The end date of the quota tariff. Use yyyy-MM-dd as the date format, e.g. "
|
||||
+ "endDate=2021-11-03.")
|
||||
private Date endDate;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = false, description = "The name of the quota tariff.")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, required = false, description = "False will list only not removed quota tariffs. If set to True, we will "
|
||||
+ "list all, including the removed ones. The default is false.")
|
||||
private boolean listAll = false;
|
||||
|
||||
public QuotaTariffListCmd() {
|
||||
super();
|
||||
}
|
||||
@ -58,10 +71,10 @@ public class QuotaTariffListCmd extends BaseListCmd {
|
||||
final Pair<List<QuotaTariffVO>, Integer> result = _responseBuilder.listQuotaTariffPlans(this);
|
||||
|
||||
final List<QuotaTariffResponse> responses = new ArrayList<QuotaTariffResponse>();
|
||||
|
||||
s_logger.trace(String.format("Adding quota tariffs [%s] to response of API quotaTariffList.", ReflectionToStringBuilderUtils.reflectCollection(responses)));
|
||||
|
||||
for (final QuotaTariffVO resource : result.first()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Result desc=" + resource.getDescription() + " date=" + resource.getEffectiveOn() + " val=" + resource.getCurrencyValue());
|
||||
}
|
||||
responses.add(_responseBuilder.createQuotaTariffResponse(resource));
|
||||
}
|
||||
|
||||
@ -93,4 +106,16 @@ public class QuotaTariffListCmd extends BaseListCmd {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isListAll() {
|
||||
return listAll;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
@ -33,7 +34,8 @@ import javax.inject.Inject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@APICommand(name = "quotaTariffUpdate", responseObject = QuotaTariffResponse.class, description = "Update the tariff plan for a resource", since = "4.7.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
@APICommand(name = "quotaTariffUpdate", responseObject = QuotaTariffResponse.class, description = "Update the tariff plan for a resource", since = "4.7.0",
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
|
||||
public class QuotaTariffUpdateCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(QuotaTariffUpdateCmd.class);
|
||||
private static final String s_name = "quotatariffupdateresponse";
|
||||
@ -41,20 +43,34 @@ public class QuotaTariffUpdateCmd extends BaseCmd {
|
||||
@Inject
|
||||
QuotaResponseBuilder _responseBuilder;
|
||||
|
||||
@Parameter(name = ApiConstants.USAGE_TYPE, type = CommandType.INTEGER, required = true, description = "Integer value for the usage type of the resource")
|
||||
@Parameter(name = ApiConstants.USAGE_TYPE, type = CommandType.INTEGER, 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")
|
||||
@Parameter(name = ApiConstants.VALUE, type = CommandType.DOUBLE, 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.")
|
||||
@Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "The effective start date on/after which the quota tariff is effective. Use yyyy-MM-dd as"
|
||||
+ " the date format, e.g. startDate=2009-06-03.")
|
||||
private Date startDate;
|
||||
|
||||
public int getUsageType() {
|
||||
@Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "The end date of the quota tariff. Use yyyy-MM-dd as the date format, e.g."
|
||||
+ " endDate=2009-06-03.")
|
||||
private Date endDate;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Quota tariff's name")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Quota tariff's description. Inform empty to remove the description.")
|
||||
private String description;
|
||||
|
||||
@Parameter(name = ApiConstants.ACTIVATION_RULE, type = CommandType.STRING, description = "Quota tariff's activation rule. Inform empty to remove the activation rule.")
|
||||
private String activationRule;
|
||||
|
||||
public Integer getUsageType() {
|
||||
return usageType;
|
||||
}
|
||||
|
||||
public void setUsageType(int usageType) {
|
||||
public void setUsageType(Integer usageType) {
|
||||
this.usageType = usageType;
|
||||
}
|
||||
|
||||
@ -74,6 +90,22 @@ public class QuotaTariffUpdateCmd extends BaseCmd {
|
||||
this.startDate = startDate == null ? null : new Date(startDate.getTime());
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getActivationRule() {
|
||||
return activationRule;
|
||||
}
|
||||
|
||||
public QuotaTariffUpdateCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ 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.QuotaTariffCreateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
@ -64,4 +65,8 @@ public interface QuotaResponseBuilder {
|
||||
Date startOfNextDay(Date dt);
|
||||
|
||||
Date startOfNextDay();
|
||||
|
||||
QuotaTariffVO createQuotaTariff(QuotaTariffCreateCmd cmd);
|
||||
|
||||
boolean deleteQuotaTariff(String quotaTariffUuid);
|
||||
}
|
||||
|
||||
@ -30,13 +30,17 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
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.QuotaTariffCreateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
import org.apache.cloudstack.quota.QuotaManager;
|
||||
@ -56,6 +60,7 @@ 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.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -113,8 +118,14 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
response.setUsageDiscriminator(tariff.getUsageDiscriminator());
|
||||
response.setTariffValue(tariff.getCurrencyValue());
|
||||
response.setEffectiveOn(tariff.getEffectiveOn());
|
||||
response.setDescription(tariff.getDescription());
|
||||
response.setUsageTypeDescription(tariff.getUsageTypeDescription());
|
||||
response.setCurrency(QuotaConfig.QuotaCurrencySymbol.value());
|
||||
response.setActivationRule(tariff.getActivationRule());
|
||||
response.setName(tariff.getName());
|
||||
response.setEndDate(tariff.getEndDate());
|
||||
response.setDescription(tariff.getDescription());
|
||||
response.setUuid(tariff.getUuid());
|
||||
response.setRemoved(tariff.getRemoved());
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -354,58 +365,119 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
|
||||
@Override
|
||||
public Pair<List<QuotaTariffVO>, Integer> listQuotaTariffPlans(final QuotaTariffListCmd cmd) {
|
||||
Pair<List<QuotaTariffVO>, Integer> result;
|
||||
Date effectiveDate = cmd.getEffectiveDate() == null ? new Date() : cmd.getEffectiveDate();
|
||||
Date adjustedEffectiveDate = _quotaService.computeAdjustedTime(effectiveDate);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Effective datec=" + effectiveDate + " quotatype=" + cmd.getUsageType() + " Adjusted date=" + adjustedEffectiveDate);
|
||||
}
|
||||
if (cmd.getUsageType() != null) {
|
||||
QuotaTariffVO tariffPlan = _quotaTariffDao.findTariffPlanByUsageType(cmd.getUsageType(), adjustedEffectiveDate);
|
||||
if (tariffPlan != null) {
|
||||
List<QuotaTariffVO> list = new ArrayList<>();
|
||||
list.add(tariffPlan);
|
||||
result = new Pair<>(list, list.size());
|
||||
} else {
|
||||
result = new Pair<>(new ArrayList<>(), 0);
|
||||
}
|
||||
} else {
|
||||
result = _quotaTariffDao.listAllTariffPlans(adjustedEffectiveDate, cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||
}
|
||||
return result;
|
||||
Date startDate = _quotaService.computeAdjustedTime(cmd.getEffectiveDate());
|
||||
Date endDate = _quotaService.computeAdjustedTime(cmd.getEndDate());
|
||||
Integer usageType = cmd.getUsageType();
|
||||
String name = cmd.getName();
|
||||
boolean listAll = cmd.isListAll();
|
||||
Long startIndex = cmd.getStartIndex();
|
||||
Long pageSize = cmd.getPageSizeVal();
|
||||
|
||||
s_logger.debug(String.format("Listing quota tariffs for parameters [%s].", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(cmd, "effectiveDate",
|
||||
"endDate", "listAll", "name", "page", "pageSize", "usageType")));
|
||||
|
||||
return _quotaTariffDao.listQuotaTariffs(startDate, endDate, usageType, name, null, listAll, startIndex, pageSize);
|
||||
}
|
||||
|
||||
@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);
|
||||
String name = cmd.getName();
|
||||
Double value = cmd.getValue();
|
||||
Date endDate = _quotaService.computeAdjustedTime(cmd.getEndDate());
|
||||
String description = cmd.getDescription();
|
||||
String activationRule = cmd.getActivationRule();
|
||||
Date now = _quotaService.computeAdjustedTime(new Date());
|
||||
|
||||
warnQuotaTariffUpdateDeprecatedFields(cmd);
|
||||
|
||||
QuotaTariffVO currentQuotaTariff = _quotaTariffDao.findByName(name);
|
||||
|
||||
if (currentQuotaTariff == null) {
|
||||
throw new InvalidParameterValueException(String.format("There is no quota tariffs with name [%s].", name));
|
||||
}
|
||||
|
||||
QuotaTariffVO result = null;
|
||||
result = new QuotaTariffVO(quotaType);
|
||||
result.setUsageName(quotaConstant.getQuotaName());
|
||||
result.setUsageUnit(quotaConstant.getQuotaUnit());
|
||||
result.setUsageDiscriminator(quotaConstant.getDiscriminator());
|
||||
result.setCurrencyValue(quotaCost);
|
||||
result.setEffectiveOn(effectiveDate);
|
||||
result.setUpdatedOn(now);
|
||||
result.setUpdatedBy(cmd.getEntityOwnerId());
|
||||
Date currentQuotaTariffStartDate = currentQuotaTariff.getEffectiveOn();
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(String.format("Updating Quota Tariff Plan: New value=%s for resource type=%d effective on date=%s", quotaCost, quotaType, effectiveDate));
|
||||
currentQuotaTariff.setRemoved(now);
|
||||
|
||||
QuotaTariffVO newQuotaTariff = persistNewQuotaTariff(currentQuotaTariff, name, 0, currentQuotaTariffStartDate, cmd.getEntityOwnerId(), endDate, value, description,
|
||||
activationRule);
|
||||
_quotaTariffDao.updateQuotaTariff(currentQuotaTariff);
|
||||
return newQuotaTariff;
|
||||
}
|
||||
_quotaTariffDao.addQuotaTariff(result);
|
||||
|
||||
return result;
|
||||
protected void warnQuotaTariffUpdateDeprecatedFields(QuotaTariffUpdateCmd cmd) {
|
||||
String warnMessage = "The parameter 's%s' for API 'quotaTariffUpdate' is no longer needed and it will be removed in future releases.";
|
||||
|
||||
if (cmd.getStartDate() != null) {
|
||||
s_logger.warn(String.format(warnMessage,"startdate"));
|
||||
}
|
||||
|
||||
if (cmd.getUsageType() != null) {
|
||||
s_logger.warn(String.format(warnMessage,"usagetype"));
|
||||
}
|
||||
}
|
||||
|
||||
protected QuotaTariffVO persistNewQuotaTariff(QuotaTariffVO currentQuotaTariff, String name, int usageType, Date startDate, Long entityOwnerId, Date endDate, Double value,
|
||||
String description, String activationRule) {
|
||||
|
||||
QuotaTariffVO newQuotaTariff = getNewQuotaTariffObject(currentQuotaTariff, name, usageType);
|
||||
|
||||
newQuotaTariff.setEffectiveOn(startDate);
|
||||
newQuotaTariff.setUpdatedOn(startDate);
|
||||
newQuotaTariff.setUpdatedBy(entityOwnerId);
|
||||
|
||||
validateEndDateOnCreatingNewQuotaTariff(newQuotaTariff, startDate, endDate);
|
||||
validateValueOnCreatingNewQuotaTariff(newQuotaTariff, value);
|
||||
validateStringsOnCreatingNewQuotaTariff(newQuotaTariff::setDescription, description);
|
||||
validateStringsOnCreatingNewQuotaTariff(newQuotaTariff::setActivationRule, activationRule);
|
||||
|
||||
_quotaTariffDao.addQuotaTariff(newQuotaTariff);
|
||||
return newQuotaTariff;
|
||||
}
|
||||
|
||||
protected QuotaTariffVO getNewQuotaTariffObject(QuotaTariffVO currentQuotaTariff, String name, int usageType) {
|
||||
if (currentQuotaTariff != null) {
|
||||
return new QuotaTariffVO(currentQuotaTariff);
|
||||
}
|
||||
|
||||
QuotaTariffVO newQuotaTariff = new QuotaTariffVO();
|
||||
|
||||
if (!newQuotaTariff.setUsageTypeData(usageType)) {
|
||||
throw new InvalidParameterValueException(String.format("There is no usage type with value [%s].", usageType));
|
||||
}
|
||||
|
||||
newQuotaTariff.setName(name);
|
||||
return newQuotaTariff;
|
||||
}
|
||||
|
||||
protected void validateStringsOnCreatingNewQuotaTariff(Consumer<String> method, String value){
|
||||
if (value != null) {
|
||||
method.accept(value.isBlank() ? null : value);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateValueOnCreatingNewQuotaTariff(QuotaTariffVO newQuotaTariff, Double value) {
|
||||
if (value != null) {
|
||||
newQuotaTariff.setCurrencyValue(BigDecimal.valueOf(value));
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateEndDateOnCreatingNewQuotaTariff(QuotaTariffVO newQuotaTariff, Date startDate, Date endDate) {
|
||||
if (endDate == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (endDate.compareTo(startDate) < 0) {
|
||||
throw new InvalidParameterValueException(String.format("The quota tariff's end date [%s] cannot be less than the start date [%s]", endDate, startDate));
|
||||
}
|
||||
|
||||
Date now = _quotaService.computeAdjustedTime(new Date());
|
||||
if (endDate.compareTo(now) < 0) {
|
||||
throw new InvalidParameterValueException(String.format("The quota tariff's end date [%s] cannot be less than now [%s].", endDate, now));
|
||||
}
|
||||
|
||||
newQuotaTariff.setEndDate(endDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -546,4 +618,39 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
return Date.from(nextDayLocalDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaTariffVO createQuotaTariff(QuotaTariffCreateCmd cmd) {
|
||||
String name = cmd.getName();
|
||||
int usageType = cmd.getUsageType();
|
||||
Date startDate = cmd.getStartDate();
|
||||
Date now = new Date();
|
||||
startDate = _quotaService.computeAdjustedTime(startDate == null ? now : startDate);
|
||||
Date endDate = _quotaService.computeAdjustedTime(cmd.getEndDate());
|
||||
Double value = cmd.getValue();
|
||||
String description = cmd.getDescription();
|
||||
String activationRule = cmd.getActivationRule();
|
||||
|
||||
QuotaTariffVO currentQuotaTariff = _quotaTariffDao.findByName(name);
|
||||
|
||||
if (currentQuotaTariff != null) {
|
||||
throw new InvalidParameterValueException(String.format("A quota tariff with name [%s] already exist.", name));
|
||||
}
|
||||
|
||||
if (startDate.compareTo(now) < 0) {
|
||||
throw new InvalidParameterValueException(String.format("The quota tariff's start date [%s] cannot be less than now [%s]", startDate, now));
|
||||
}
|
||||
|
||||
return persistNewQuotaTariff(null, name, usageType, startDate, cmd.getEntityOwnerId(), endDate, value, description, activationRule);
|
||||
}
|
||||
|
||||
public boolean deleteQuotaTariff(String quotaTariffUuid) {
|
||||
QuotaTariffVO quotaTariff = _quotaTariffDao.findByUuid(quotaTariffUuid);
|
||||
|
||||
if (quotaTariff == null) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Quota tariff with the provided UUID does not exist.");
|
||||
}
|
||||
|
||||
quotaTariff.setRemoved(_quotaService.computeAdjustedTime(new Date()));
|
||||
return _quotaTariffDao.updateQuotaTariff(quotaTariff);
|
||||
}
|
||||
}
|
||||
@ -47,16 +47,40 @@ public class QuotaTariffResponse extends BaseResponse {
|
||||
private BigDecimal tariffValue;
|
||||
|
||||
@SerializedName("effectiveDate")
|
||||
@Param(description = "the date on/after which this quota value will be effective")
|
||||
@Param(description = "the start date of the quota tariff")
|
||||
private Date effectiveOn = null;
|
||||
|
||||
@SerializedName("usageTypeDescription")
|
||||
@Param(description = "usage type description")
|
||||
private String usageTypeDescription;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "currency")
|
||||
private String currency;
|
||||
|
||||
@SerializedName("endDate")
|
||||
@Param(description = "the end date of the quota tariff")
|
||||
private Date endDate;
|
||||
|
||||
@SerializedName("activationRule")
|
||||
@Param(description = "activation rule of the quota tariff")
|
||||
private String activationRule;
|
||||
|
||||
@SerializedName("name")
|
||||
@Param(description = "name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("description")
|
||||
@Param(description = "description")
|
||||
private String description;
|
||||
|
||||
@SerializedName("currency")
|
||||
@Param(description = "currency")
|
||||
private String currency;
|
||||
@SerializedName("uuid")
|
||||
@Param(description = "uuid")
|
||||
private String uuid;
|
||||
|
||||
@SerializedName("removed")
|
||||
@Param(description = "when the quota tariff was removed")
|
||||
private Date removed;
|
||||
|
||||
public QuotaTariffResponse() {
|
||||
super();
|
||||
@ -108,12 +132,12 @@ public class QuotaTariffResponse extends BaseResponse {
|
||||
this.tariffValue = tariffValue;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
public String getUsageTypeDescription() {
|
||||
return usageTypeDescription;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
public void setUsageTypeDescription(String usageTypeDescription) {
|
||||
this.usageTypeDescription = usageTypeDescription;
|
||||
}
|
||||
|
||||
public Date getEffectiveOn() {
|
||||
@ -131,4 +155,53 @@ public class QuotaTariffResponse extends BaseResponse {
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public String getActivationRule() {
|
||||
return activationRule;
|
||||
}
|
||||
|
||||
public void setActivationRule(String activationRule) {
|
||||
this.activationRule = activationRule;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void setRemoved(Date removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,6 +34,8 @@ import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEnabledCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaSummaryCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffDeleteCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaUpdateCmd;
|
||||
@ -126,6 +128,8 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
||||
cmdList.add(QuotaCreditsCmd.class);
|
||||
cmdList.add(QuotaEmailTemplateListCmd.class);
|
||||
cmdList.add(QuotaEmailTemplateUpdateCmd.class);
|
||||
cmdList.add(QuotaTariffCreateCmd.class);
|
||||
cmdList.add(QuotaTariffDeleteCmd.class);
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
@ -137,7 +141,7 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {QuotaPluginEnabled, QuotaEnableEnforcement, QuotaCurrencySymbol, QuotaStatementPeriod, QuotaSmtpHost, QuotaSmtpPort, QuotaSmtpTimeout,
|
||||
QuotaSmtpUser, QuotaSmtpPassword, QuotaSmtpAuthType, QuotaSmtpSender, QuotaSmtpEnabledSecurityProtocols, QuotaSmtpUseStartTLS};
|
||||
QuotaSmtpUser, QuotaSmtpPassword, QuotaSmtpAuthType, QuotaSmtpSender, QuotaSmtpEnabledSecurityProtocols, QuotaSmtpUseStartTLS, QuotaActivationRuleTimeout};
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -248,6 +252,10 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
||||
|
||||
@Override
|
||||
public Date computeAdjustedTime(final Date date) {
|
||||
if (date == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
TimeZone localTZ = cal.getTimeZone();
|
||||
|
||||
@ -52,7 +52,7 @@ public class QuotaTariffListCmdTest extends TestCase {
|
||||
QuotaTariffVO tariff = new QuotaTariffVO();
|
||||
tariff.setEffectiveOn(new Date());
|
||||
tariff.setCurrencyValue(new BigDecimal(100));
|
||||
tariff.setUsageType(QuotaTypes.MEMORY);
|
||||
tariff.setUsageType(QuotaTypes.VOLUME);
|
||||
|
||||
quotaTariffVOList.add(new QuotaTariffVO());
|
||||
Mockito.when(responseBuilder.listQuotaTariffPlans(Mockito.eq(cmd))).thenReturn(new Pair<>(quotaTariffVOList, quotaTariffVOList.size()));
|
||||
|
||||
@ -50,7 +50,7 @@ public class QuotaTariffUpdateCmdTest extends TestCase {
|
||||
QuotaTariffVO tariff = new QuotaTariffVO();
|
||||
tariff.setEffectiveOn(new Date());
|
||||
tariff.setCurrencyValue(new BigDecimal(100));
|
||||
tariff.setUsageType(QuotaTypes.MEMORY);
|
||||
tariff.setUsageType(QuotaTypes.VOLUME);
|
||||
|
||||
Mockito.when(responseBuilder.updateQuotaTariffPlan(Mockito.eq(cmd))).thenReturn(null);
|
||||
try {
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
@ -24,9 +23,9 @@ import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
@ -39,84 +38,59 @@ 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.commons.lang3.time.DateUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@RunWith(PowerMockRunner.class)
|
||||
public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
|
||||
@Mock
|
||||
QuotaTariffDao quotaTariffDao;
|
||||
@Mock
|
||||
QuotaBalanceDao quotaBalanceDao;
|
||||
@Mock
|
||||
QuotaCreditsDao quotaCreditsDao;
|
||||
@Mock
|
||||
QuotaEmailTemplatesDao quotaEmailTemplateDao;
|
||||
QuotaTariffDao quotaTariffDaoMock;
|
||||
|
||||
@Mock
|
||||
UserDao userDao;
|
||||
QuotaBalanceDao quotaBalanceDaoMock;
|
||||
|
||||
@Mock
|
||||
QuotaService quotaService;
|
||||
QuotaCreditsDao quotaCreditsDaoMock;
|
||||
|
||||
@Mock
|
||||
AccountDao accountDao;
|
||||
@Inject
|
||||
AccountManager accountMgr;
|
||||
QuotaEmailTemplatesDao quotaEmailTemplateDaoMock;
|
||||
|
||||
QuotaResponseBuilderImpl quotaResponseBuilder = new QuotaResponseBuilderImpl();
|
||||
@Mock
|
||||
UserDao userDaoMock;
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException {
|
||||
// Dummy transaction stack setup
|
||||
TransactionLegacy.open("QuotaResponseBuilderImplTest");
|
||||
@Mock
|
||||
QuotaService quotaServiceMock;
|
||||
|
||||
Field tariffDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaTariffDao");
|
||||
tariffDaoField.setAccessible(true);
|
||||
tariffDaoField.set(quotaResponseBuilder, quotaTariffDao);
|
||||
@Mock
|
||||
AccountDao accountDaoMock;
|
||||
|
||||
Field balanceDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaBalanceDao");
|
||||
balanceDaoField.setAccessible(true);
|
||||
balanceDaoField.set(quotaResponseBuilder, quotaBalanceDao);
|
||||
@Mock
|
||||
Consumer<String> consumerStringMock;
|
||||
|
||||
Field quotaCreditsDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaCreditsDao");
|
||||
quotaCreditsDaoField.setAccessible(true);
|
||||
quotaCreditsDaoField.set(quotaResponseBuilder, quotaCreditsDao);
|
||||
@Mock
|
||||
QuotaTariffVO quotaTariffVoMock;
|
||||
|
||||
Field quotaEmailTemplateDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaEmailTemplateDao");
|
||||
quotaEmailTemplateDaoField.setAccessible(true);
|
||||
quotaEmailTemplateDaoField.set(quotaResponseBuilder, quotaEmailTemplateDao);
|
||||
@InjectMocks
|
||||
QuotaResponseBuilderImpl quotaResponseBuilderSpy = Mockito.spy(QuotaResponseBuilderImpl.class);
|
||||
|
||||
Field userDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_userDao");
|
||||
userDaoField.setAccessible(true);
|
||||
userDaoField.set(quotaResponseBuilder, userDao);
|
||||
|
||||
Field quotaServiceField = QuotaResponseBuilderImpl.class.getDeclaredField("_quotaService");
|
||||
quotaServiceField.setAccessible(true);
|
||||
quotaServiceField.set(quotaResponseBuilder, quotaService);
|
||||
|
||||
Field accountDaoField = QuotaResponseBuilderImpl.class.getDeclaredField("_accountDao");
|
||||
accountDaoField.setAccessible(true);
|
||||
accountDaoField.set(quotaResponseBuilder, accountDao);
|
||||
|
||||
Field regionMgrField = QuotaResponseBuilderImpl.class.getDeclaredField("_accountMgr");
|
||||
regionMgrField.setAccessible(true);
|
||||
regionMgrField.set(quotaResponseBuilder, accountMgr);
|
||||
}
|
||||
Date date = new Date();
|
||||
|
||||
private QuotaTariffVO makeTariffTestData() {
|
||||
QuotaTariffVO tariffVO = new QuotaTariffVO();
|
||||
@ -132,7 +106,7 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
@Test
|
||||
public void testQuotaResponse() {
|
||||
QuotaTariffVO tariffVO = makeTariffTestData();
|
||||
QuotaTariffResponse response = quotaResponseBuilder.createQuotaTariffResponse(tariffVO);
|
||||
QuotaTariffResponse response = quotaResponseBuilderSpy.createQuotaTariffResponse(tariffVO);
|
||||
assertTrue(tariffVO.getUsageType() == response.getUsageType());
|
||||
assertTrue(tariffVO.getCurrencyValue().equals(response.getTariffValue()));
|
||||
}
|
||||
@ -147,15 +121,15 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
QuotaCreditsVO credit = new QuotaCreditsVO();
|
||||
credit.setCredit(new BigDecimal(amount));
|
||||
|
||||
Mockito.when(quotaCreditsDao.saveCredits(Mockito.any(QuotaCreditsVO.class))).thenReturn(credit);
|
||||
Mockito.when(quotaBalanceDao.lastQuotaBalance(Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Date.class))).thenReturn(new BigDecimal(111));
|
||||
Mockito.when(quotaService.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date());
|
||||
Mockito.when(quotaCreditsDaoMock.saveCredits(Mockito.any(QuotaCreditsVO.class))).thenReturn(credit);
|
||||
Mockito.when(quotaBalanceDaoMock.lastQuotaBalance(Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Date.class))).thenReturn(new BigDecimal(111));
|
||||
Mockito.when(quotaServiceMock.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date());
|
||||
|
||||
AccountVO account = new AccountVO();
|
||||
account.setState(Account.State.LOCKED);
|
||||
Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(account);
|
||||
Mockito.when(accountDaoMock.findById(Mockito.anyLong())).thenReturn(account);
|
||||
|
||||
QuotaCreditsResponse resp = quotaResponseBuilder.addQuotaCredits(accountId, domainId, amount, updatedBy, true);
|
||||
QuotaCreditsResponse resp = quotaResponseBuilderSpy.addQuotaCredits(accountId, domainId, amount, updatedBy, true);
|
||||
assertTrue(resp.getCredits().compareTo(credit.getCredit()) == 0);
|
||||
}
|
||||
|
||||
@ -167,9 +141,9 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
QuotaEmailTemplatesVO template = new QuotaEmailTemplatesVO();
|
||||
template.setTemplateName("template");
|
||||
templates.add(template);
|
||||
Mockito.when(quotaEmailTemplateDao.listAllQuotaEmailTemplates(Mockito.anyString())).thenReturn(templates);
|
||||
Mockito.when(quotaEmailTemplateDaoMock.listAllQuotaEmailTemplates(Mockito.anyString())).thenReturn(templates);
|
||||
|
||||
assertTrue(quotaResponseBuilder.listQuotaEmailTemplates(cmd).size() == 1);
|
||||
Assert.assertEquals(1, quotaResponseBuilderSpy.listQuotaEmailTemplates(cmd).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -181,17 +155,17 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
|
||||
List<QuotaEmailTemplatesVO> templates = new ArrayList<>();
|
||||
|
||||
Mockito.when(quotaEmailTemplateDao.listAllQuotaEmailTemplates(Mockito.anyString())).thenReturn(templates);
|
||||
Mockito.when(quotaEmailTemplateDao.updateQuotaEmailTemplate(Mockito.any(QuotaEmailTemplatesVO.class))).thenReturn(true);
|
||||
Mockito.when(quotaEmailTemplateDaoMock.listAllQuotaEmailTemplates(Mockito.anyString())).thenReturn(templates);
|
||||
Mockito.when(quotaEmailTemplateDaoMock.updateQuotaEmailTemplate(Mockito.any(QuotaEmailTemplatesVO.class))).thenReturn(true);
|
||||
|
||||
// invalid template test
|
||||
assertFalse(quotaResponseBuilder.updateQuotaEmailTemplate(cmd));
|
||||
assertFalse(quotaResponseBuilderSpy.updateQuotaEmailTemplate(cmd));
|
||||
|
||||
// valid template test
|
||||
QuotaEmailTemplatesVO template = new QuotaEmailTemplatesVO();
|
||||
template.setTemplateName("template");
|
||||
templates.add(template);
|
||||
assertTrue(quotaResponseBuilder.updateQuotaEmailTemplate(cmd));
|
||||
assertTrue(quotaResponseBuilderSpy.updateQuotaEmailTemplate(cmd));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -199,14 +173,14 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
List<QuotaBalanceVO> quotaBalance = new ArrayList<>();
|
||||
// null balance test
|
||||
try {
|
||||
quotaResponseBuilder.createQuotaLastBalanceResponse(null, new Date());
|
||||
quotaResponseBuilderSpy.createQuotaLastBalanceResponse(null, new Date());
|
||||
} catch (InvalidParameterValueException e) {
|
||||
assertTrue(e.getMessage().equals("There are no balance entries on or before the requested date."));
|
||||
}
|
||||
|
||||
// empty balance test
|
||||
try {
|
||||
quotaResponseBuilder.createQuotaLastBalanceResponse(quotaBalance, new Date());
|
||||
quotaResponseBuilderSpy.createQuotaLastBalanceResponse(quotaBalance, new Date());
|
||||
} catch (InvalidParameterValueException e) {
|
||||
assertTrue(e.getMessage().equals("There are no balance entries on or before the requested date."));
|
||||
}
|
||||
@ -217,14 +191,14 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
entry.setCreditBalance(new BigDecimal(100));
|
||||
quotaBalance.add(entry);
|
||||
quotaBalance.add(entry);
|
||||
Mockito.lenient().when(quotaService.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date());
|
||||
QuotaBalanceResponse resp = quotaResponseBuilder.createQuotaLastBalanceResponse(quotaBalance, null);
|
||||
Mockito.lenient().when(quotaServiceMock.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date());
|
||||
QuotaBalanceResponse resp = quotaResponseBuilderSpy.createQuotaLastBalanceResponse(quotaBalance, null);
|
||||
assertTrue(resp.getStartQuota().compareTo(new BigDecimal(200)) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartOfNextDayWithoutParameters() {
|
||||
Date nextDate = quotaResponseBuilder.startOfNextDay();
|
||||
Date nextDate = quotaResponseBuilderSpy.startOfNextDay();
|
||||
|
||||
LocalDateTime tomorrowAtStartOfTheDay = LocalDate.now().atStartOfDay().plusDays(1);
|
||||
Date expectedNextDate = Date.from(tomorrowAtStartOfTheDay.atZone(ZoneId.systemDefault()).toInstant());
|
||||
@ -236,11 +210,133 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
public void testStartOfNextDayWithParameter() {
|
||||
Date anyDate = new Date(1242421545757532l);
|
||||
|
||||
Date nextDayDate = quotaResponseBuilder.startOfNextDay(anyDate);
|
||||
Date nextDayDate = quotaResponseBuilderSpy.startOfNextDay(anyDate);
|
||||
|
||||
LocalDateTime nextDayLocalDateTimeAtStartOfTheDay = anyDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().plusDays(1).atStartOfDay();
|
||||
Date expectedNextDate = Date.from(nextDayLocalDateTimeAtStartOfTheDay.atZone(ZoneId.systemDefault()).toInstant());
|
||||
|
||||
Assert.assertEquals(expectedNextDate, nextDayDate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateStringsOnCreatingNewQuotaTariffTestNullValueDoNothing() {
|
||||
quotaResponseBuilderSpy.validateStringsOnCreatingNewQuotaTariff(consumerStringMock, null);
|
||||
Mockito.verify(consumerStringMock, Mockito.never()).accept(Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateStringsOnCreatingNewQuotaTariffTestEmptyValueCallMethodWithNull() {
|
||||
quotaResponseBuilderSpy.validateStringsOnCreatingNewQuotaTariff(consumerStringMock, "");
|
||||
Mockito.verify(consumerStringMock).accept(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateStringsOnCreatingNewQuotaTariffTestValueCallMethodWithValue() {
|
||||
String value = "test";
|
||||
quotaResponseBuilderSpy.validateStringsOnCreatingNewQuotaTariff(consumerStringMock, value);
|
||||
Mockito.verify(consumerStringMock).accept(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateValueOnCreatingNewQuotaTariffTestNullValueDoNothing() {
|
||||
quotaResponseBuilderSpy.validateValueOnCreatingNewQuotaTariff(quotaTariffVoMock, null);
|
||||
Mockito.verify(quotaTariffVoMock, Mockito.never()).setCurrencyValue(Mockito.any(BigDecimal.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateValueOnCreatingNewQuotaTariffTestAnyValueIsSet() {
|
||||
Double value = 0.0;
|
||||
quotaResponseBuilderSpy.validateValueOnCreatingNewQuotaTariff(quotaTariffVoMock, value);
|
||||
Mockito.verify(quotaTariffVoMock).setCurrencyValue(BigDecimal.valueOf(value));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateEndDateOnCreatingNewQuotaTariffTestNullEndDateDoNothing() {
|
||||
Date startDate = null;
|
||||
Date endDate = null;
|
||||
|
||||
quotaResponseBuilderSpy.validateEndDateOnCreatingNewQuotaTariff(quotaTariffVoMock, startDate, endDate);
|
||||
Mockito.verify(quotaTariffVoMock, Mockito.never()).setEndDate(Mockito.any(Date.class));
|
||||
}
|
||||
|
||||
@Test (expected = InvalidParameterValueException.class)
|
||||
public void validateEndDateOnCreatingNewQuotaTariffTestEndDateLessThanStartDateThrowInvalidParameterValueException() {
|
||||
Date startDate = date;
|
||||
Date endDate = DateUtils.addSeconds(startDate, -1);
|
||||
|
||||
quotaResponseBuilderSpy.validateEndDateOnCreatingNewQuotaTariff(quotaTariffVoMock, startDate, endDate);
|
||||
}
|
||||
|
||||
@Test (expected = InvalidParameterValueException.class)
|
||||
public void validateEndDateOnCreatingNewQuotaTariffTestEndDateLessThanNowThrowInvalidParameterValueException() {
|
||||
Date startDate = DateUtils.addDays(date, -100);
|
||||
Date endDate = DateUtils.addDays(new Date(), -1);
|
||||
|
||||
Mockito.doReturn(date).when(quotaServiceMock).computeAdjustedTime(Mockito.any(Date.class));
|
||||
quotaResponseBuilderSpy.validateEndDateOnCreatingNewQuotaTariff(quotaTariffVoMock, startDate, endDate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateEndDateOnCreatingNewQuotaTariffTestSetValidEndDate() {
|
||||
Date startDate = DateUtils.addDays(date, -100);
|
||||
Date endDate = date;
|
||||
|
||||
Mockito.doReturn(DateUtils.addDays(date, -10)).when(quotaServiceMock).computeAdjustedTime(Mockito.any(Date.class));
|
||||
quotaResponseBuilderSpy.validateEndDateOnCreatingNewQuotaTariff(quotaTariffVoMock, startDate, endDate);
|
||||
Mockito.verify(quotaTariffVoMock).setEndDate(Mockito.any(Date.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@PrepareForTest(QuotaResponseBuilderImpl.class)
|
||||
public void getNewQuotaTariffObjectTestCreateFromCurrentQuotaTariff() throws Exception {
|
||||
PowerMockito.whenNew(QuotaTariffVO.class).withArguments(Mockito.any(QuotaTariffVO.class)).thenReturn(quotaTariffVoMock);
|
||||
|
||||
quotaResponseBuilderSpy.getNewQuotaTariffObject(quotaTariffVoMock, "", 0);
|
||||
PowerMockito.verifyNew(QuotaTariffVO.class).withArguments(Mockito.any(QuotaTariffVO.class));
|
||||
}
|
||||
|
||||
@Test (expected = InvalidParameterValueException.class)
|
||||
public void getNewQuotaTariffObjectTestSetInvalidUsageTypeThrowsInvalidParameterValueException() throws InvalidParameterValueException {
|
||||
quotaResponseBuilderSpy.getNewQuotaTariffObject(null, "test", 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNewQuotaTariffObjectTestReturnValidObject() throws InvalidParameterValueException {
|
||||
String name = "test";
|
||||
int usageType = 1;
|
||||
QuotaTariffVO result = quotaResponseBuilderSpy.getNewQuotaTariffObject(null, name, usageType);
|
||||
|
||||
Assert.assertEquals(name, result.getName());
|
||||
Assert.assertEquals(usageType, result.getUsageType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void persistNewQuotaTariffTestpersistNewQuotaTariff() {
|
||||
Mockito.doReturn(quotaTariffVoMock).when(quotaResponseBuilderSpy).getNewQuotaTariffObject(Mockito.any(QuotaTariffVO.class), Mockito.anyString(), Mockito.anyInt());
|
||||
Mockito.doNothing().when(quotaResponseBuilderSpy).validateEndDateOnCreatingNewQuotaTariff(Mockito.any(QuotaTariffVO.class), Mockito.any(Date.class), Mockito.any(Date.class));
|
||||
Mockito.doNothing().when(quotaResponseBuilderSpy).validateValueOnCreatingNewQuotaTariff(Mockito.any(QuotaTariffVO.class), Mockito.anyDouble());
|
||||
Mockito.doNothing().when(quotaResponseBuilderSpy).validateStringsOnCreatingNewQuotaTariff(Mockito.any(Consumer.class), Mockito.anyString());
|
||||
Mockito.doReturn(quotaTariffVoMock).when(quotaTariffDaoMock).addQuotaTariff(Mockito.any(QuotaTariffVO.class));
|
||||
|
||||
quotaResponseBuilderSpy.persistNewQuotaTariff(quotaTariffVoMock, "", 1, date, 1l, date, 1.0, "", "");
|
||||
|
||||
Mockito.verify(quotaTariffDaoMock).addQuotaTariff(Mockito.any(QuotaTariffVO.class));
|
||||
}
|
||||
|
||||
@Test (expected = ServerApiException.class)
|
||||
public void deleteQuotaTariffTestQuotaDoesNotExistThrowsServerApiException() {
|
||||
Mockito.doReturn(null).when(quotaTariffDaoMock).findById(Mockito.anyLong());
|
||||
quotaResponseBuilderSpy.deleteQuotaTariff("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteQuotaTariffTestUpdateRemoved() {
|
||||
Mockito.doReturn(quotaTariffVoMock).when(quotaTariffDaoMock).findByUuid(Mockito.anyString());
|
||||
Mockito.doReturn(true).when(quotaTariffDaoMock).updateQuotaTariff(Mockito.any(QuotaTariffVO.class));
|
||||
Mockito.doReturn(new Date()).when(quotaServiceMock).computeAdjustedTime(Mockito.any(Date.class));
|
||||
|
||||
Assert.assertTrue(quotaResponseBuilderSpy.deleteQuotaTariff(""));
|
||||
|
||||
Mockito.verify(quotaTariffVoMock).setRemoved(Mockito.any(Date.class));
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ import org.apache.cloudstack.agent.directdownload.HttpDirectDownloadCommand;
|
||||
import org.apache.cloudstack.agent.directdownload.HttpsDirectDownloadCommand;
|
||||
import org.apache.cloudstack.agent.directdownload.MetalinkDirectDownloadCommand;
|
||||
import org.apache.cloudstack.agent.directdownload.NfsDirectDownloadCommand;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand;
|
||||
@ -118,7 +119,6 @@ import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.storage.resource.StorageProcessor;
|
||||
import static com.cloud.storage.snapshot.SnapshotManager.BackupSnapshotAfterTakingSnapshot;
|
||||
import com.cloud.storage.template.Processor;
|
||||
import com.cloud.storage.template.Processor.FormatInfo;
|
||||
import com.cloud.storage.template.QCOW2Processor;
|
||||
@ -1046,7 +1046,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
s_logger.debug("Ignoring removal of vm snapshot on primary as this snapshot is created from vm snapshot");
|
||||
} else if (primaryPool.getType() != StoragePoolType.RBD) {
|
||||
String snapshotPath = snapshot.getPath();
|
||||
String backupSnapshotAfterTakingSnapshot = cmd.getOptions() == null ? null : cmd.getOptions().get(BackupSnapshotAfterTakingSnapshot.key());
|
||||
String backupSnapshotAfterTakingSnapshot = cmd.getOptions() == null ? null : cmd.getOptions().get(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key());
|
||||
|
||||
if (backupSnapshotAfterTakingSnapshot == null || BooleanUtils.toBoolean(backupSnapshotAfterTakingSnapshot)) {
|
||||
try {
|
||||
|
||||
@ -531,7 +531,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
||||
final String key = (String)keysIter.next();
|
||||
final String[] value = (String[])params.get(key);
|
||||
// fail if parameter value contains ASCII control (non-printable) characters
|
||||
if (value[0] != null) {
|
||||
if (value[0] != null && !ApiConstants.ACTIVATION_RULE.equals(key)) {
|
||||
final Pattern pattern = Pattern.compile(CONTROL_CHARACTERS);
|
||||
final Matcher matcher = pattern.matcher(value[0]);
|
||||
if (matcher.find()) {
|
||||
|
||||
@ -56,9 +56,6 @@ public interface SnapshotManager extends Configurable {
|
||||
public static final ConfigKey<Integer> BackupRetryInterval = new ConfigKey<Integer>(Integer.class, "backup.retry.interval", "Advanced", "300",
|
||||
"Time in seconds between retries in backing up snapshot to secondary", false, ConfigKey.Scope.Global, null);
|
||||
|
||||
public static final ConfigKey<Boolean> BackupSnapshotAfterTakingSnapshot = new ConfigKey<Boolean>(Boolean.class, "snapshot.backup.to.secondary", "Snapshots", "true",
|
||||
"Indicates whether to always backup primary storage snapshot to secondary storage. Keeping snapshots only on Primary storage is applicable for KVM + Ceph only.", false, ConfigKey.Scope.Global, null);
|
||||
|
||||
public static final ConfigKey<Boolean> VmStorageSnapshotKvm = new ConfigKey<>(Boolean.class, "kvm.vmstoragesnapshot.enabled", "Snapshots", "false", "For live snapshot of virtual machine instance on KVM hypervisor without memory. Requieres qemu version 1.6+ (on NFS or Local file system) and qemu-guest-agent installed on guest VM", true, ConfigKey.Scope.Global, null);
|
||||
|
||||
void deletePoliciesForVolume(Long volumeId);
|
||||
|
||||
@ -231,7 +231,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {BackupRetryAttempts, BackupRetryInterval, SnapshotHourlyMax, SnapshotDailyMax, SnapshotMonthlyMax, SnapshotWeeklyMax, usageSnapshotSelection,
|
||||
BackupSnapshotAfterTakingSnapshot, VmStorageSnapshotKvm};
|
||||
SnapshotInfo.BackupSnapshotAfterTakingSnapshot, VmStorageSnapshotKvm};
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1250,7 +1250,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
||||
}
|
||||
|
||||
SnapshotInfo snapshotOnPrimary = snapshotStrategy.takeSnapshot(snapshot);
|
||||
boolean backupSnapToSecondary = BackupSnapshotAfterTakingSnapshot.value() == null || BackupSnapshotAfterTakingSnapshot.value();
|
||||
boolean backupSnapToSecondary = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value() == null || SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value();
|
||||
|
||||
if (backupSnapToSecondary) {
|
||||
backupSnapshotToSecondary(payload.getAsyncBackup(), snapshotStrategy, snapshotOnPrimary);
|
||||
|
||||
@ -28,7 +28,6 @@ import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
|
||||
import static com.cloud.storage.snapshot.SnapshotManager.BackupSnapshotAfterTakingSnapshot;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -82,7 +81,7 @@ public class SnapshotHelper {
|
||||
@Inject
|
||||
protected PrimaryDataStoreDao primaryDataStoreDao;
|
||||
|
||||
protected boolean backupSnapshotAfterTakingSnapshot = BackupSnapshotAfterTakingSnapshot.value();
|
||||
protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value();
|
||||
|
||||
protected final Set<StoragePoolType> storagePoolTypesToValidateWithBackupSnapshotAfterTakingSnapshot = new HashSet<>(Arrays.asList(StoragePoolType.RBD,
|
||||
StoragePoolType.PowerFlex));
|
||||
@ -103,7 +102,7 @@ public class SnapshotHelper {
|
||||
}
|
||||
|
||||
logger.debug(String.format("Expunging snapshot [%s] due to it is a temporary backup to create a volume from snapshot. It is occurring because the global setting [%s]"
|
||||
+ " has the value [%s].", snapInfo.getId(), BackupSnapshotAfterTakingSnapshot.key(), backupSnapshotAfterTakingSnapshot));
|
||||
+ " has the value [%s].", snapInfo.getId(), SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key(), backupSnapshotAfterTakingSnapshot));
|
||||
|
||||
try {
|
||||
snapshotService.deleteSnapshot(snapInfo);
|
||||
|
||||
@ -318,4 +318,9 @@ public class MockUsageEventDao implements UsageEventDao{
|
||||
public void saveDetails(long eventId, Map<String, String> details) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<UsageEventVO>, Integer> searchAndCount(SearchCriteria<UsageEventVO> sc, Filter filter, boolean includeRemoved) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,11 +29,17 @@
|
||||
http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:annotation-config />
|
||||
|
||||
<!-- It is doing a granular scanning to avoid a complex injection hierarchy. -->
|
||||
<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,
|
||||
org.apache.cloudstack.quota.constant, org.apache.cloudstack.quota.dao, org.apache.cloudstack.quota.vo">
|
||||
</context:component-scan>
|
||||
|
||||
<import resource="META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml"/>
|
||||
|
||||
<bean id="managementServiceConfigurationImpl" class="com.cloud.configuration.ManagementServiceConfigurationImpl" />
|
||||
|
||||
<!-- @DB support -->
|
||||
<bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
|
||||
|
||||
|
||||
@ -205,6 +205,11 @@
|
||||
<artifactId>commons-email</artifactId>
|
||||
<version>1.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.nashorn</groupId>
|
||||
<artifactId>nashorn-core</artifactId>
|
||||
<version>15.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@ -33,6 +33,8 @@ import java.time.OffsetDateTime;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
public class DateUtil {
|
||||
public static final int HOURS_IN_A_MONTH = 30 * 24;
|
||||
|
||||
public static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT");
|
||||
public static final String YYYYMMDD_FORMAT = "yyyyMMddHHmmss";
|
||||
private static final DateFormat s_outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
|
||||
@ -22,6 +22,7 @@ public class ByteScaleUtils {
|
||||
|
||||
public static final long KiB = 1024;
|
||||
public static final long MiB = KiB * 1024;
|
||||
public static final long GiB = MiB * 1024;
|
||||
|
||||
private ByteScaleUtils() {}
|
||||
|
||||
@ -44,4 +45,14 @@ public class ByteScaleUtils {
|
||||
public static long bytesToKib(long b) {
|
||||
return b / KiB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts bytes to mebibytes.
|
||||
*
|
||||
* @param b The value in bytes to convert to mebibytes.
|
||||
* @return The parameter divided by 1024 * 1024 (1 MiB).
|
||||
*/
|
||||
public static long bytesToMib(long b) {
|
||||
return b / MiB;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,146 @@
|
||||
// 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.utils.jsinterpreter;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
/**
|
||||
* A class to execute JavaScript scripts, with the possibility to inject context to the scripts.
|
||||
*/
|
||||
public class JsInterpreter implements Closeable {
|
||||
protected Logger logger = Logger.getLogger(JsInterpreter.class);
|
||||
|
||||
protected ScriptEngine interpreter;
|
||||
protected String interpreterName;
|
||||
private final String injectingLogMessage = "Injecting variable [%s] with value [%s] into the JS interpreter.";
|
||||
protected ExecutorService executor;
|
||||
private TimeUnit defaultTimeUnit = TimeUnit.MILLISECONDS;
|
||||
private long timeout;
|
||||
private String timeoutDefaultMessage;
|
||||
protected Map<String, String> variables = new LinkedHashMap<>();
|
||||
|
||||
public JsInterpreter(long timeout) {
|
||||
this.timeout = timeout;
|
||||
this.timeoutDefaultMessage = String.format("Timeout (in milliseconds) defined in the global setting [quota.activationrule.timeout]: [%s].", this.timeout);
|
||||
|
||||
executor = Executors.newSingleThreadExecutor();
|
||||
NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
|
||||
|
||||
this.interpreterName = factory.getEngineName();
|
||||
logger.trace(String.format("Initiating JS interpreter: %s.", interpreterName));
|
||||
|
||||
setScriptEngineDisablingJavaLanguage(factory);
|
||||
}
|
||||
|
||||
protected void setScriptEngineDisablingJavaLanguage(NashornScriptEngineFactory factory) {
|
||||
interpreter = factory.getScriptEngine("--no-java");
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards the current variables map and create a new one.
|
||||
*/
|
||||
public void discardCurrentVariables() {
|
||||
logger.trace("Discarding current variables map and creating a new one.");
|
||||
variables = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the parameters to a Map that will be converted to JS variables right before executing the scripts..
|
||||
* @param key The name of the variable.
|
||||
* @param value The value of the variable.
|
||||
*/
|
||||
public void injectVariable(String key, String value) {
|
||||
logger.trace(String.format(injectingLogMessage, key, value));
|
||||
variables.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the variables to the script and execute it.
|
||||
* @param script Code to be executed.
|
||||
* @return The result of the executed script.
|
||||
*/
|
||||
public Object executeScript(String script) {
|
||||
script = addVariablesToScript(script);
|
||||
|
||||
logger.debug(String.format("Executing script [%s].", script));
|
||||
|
||||
Object result = executeScriptInThread(script);
|
||||
|
||||
logger.debug(String.format("The script [%s] had the following result: [%s].", script, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Object executeScriptInThread(String script) {
|
||||
Callable<Object> task = () -> interpreter.eval(script);
|
||||
|
||||
Future<Object> future = executor.submit(task);
|
||||
|
||||
try {
|
||||
return future.get(this.timeout, defaultTimeUnit);
|
||||
} catch (TimeoutException | InterruptedException | ExecutionException e) {
|
||||
String message = String.format("Unable to execute script [%s] due to [%s]", script, e.getMessage());
|
||||
|
||||
if (e instanceof TimeoutException) {
|
||||
message = String.format("Execution of script [%s] took too long and timed out. %s", script, timeoutDefaultMessage);
|
||||
}
|
||||
|
||||
logger.error(message, e);
|
||||
throw new CloudRuntimeException(message, e);
|
||||
} finally {
|
||||
future.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected String addVariablesToScript(String script) {
|
||||
if (MapUtils.isEmpty(variables)) {
|
||||
logger.trace(String.format("There is no variables to add to script [%s]. Returning.", script));
|
||||
return script;
|
||||
}
|
||||
|
||||
String variablesToString = "";
|
||||
for (Map.Entry<String, String> variable : variables.entrySet()) {
|
||||
variablesToString = String.format("%s %s = %s;", variablesToString, variable.getKey(), variable.getValue());
|
||||
}
|
||||
|
||||
return String.format("%s %s", variablesToString, script);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
@ -129,6 +129,20 @@ public class ReflectionToStringBuilderUtils {
|
||||
.collect(Collectors.joining(multipleValuesSeparator == null ? DEFAULT_MULTIPLE_VALUES_SEPARATOR : multipleValuesSeparator)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Similar to {@link ReflectionToStringBuilderUtils#reflectOnlySelectedFields(Object, ToStringStyle, String, String...)}, but reflecting the whole collection.<br><br>
|
||||
* This method must be called only to {@link Collection}, as it will reflect the objects contained in it.<br>
|
||||
* To reflect the Collection itself or other objects, see {@link ReflectionToStringBuilder}.
|
||||
* @param object Collection to be reflected.
|
||||
* @return If <b>object</b> is null or is not a Collection, returns null.<br>
|
||||
* If <b>object</b> is a Collection, returns a <b>style</b> formatted string containing the not null elements, else, returns the object as the <b>style</b> parameter.<br>
|
||||
*/
|
||||
public static String reflectCollection(Object object){
|
||||
String[] excludeFields = null;
|
||||
return reflectCollection(object, DEFAULT_STYLE, DEFAULT_MULTIPLE_VALUES_SEPARATOR, excludeFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if object is a Collection.
|
||||
* @param object
|
||||
|
||||
@ -27,16 +27,26 @@ import org.junit.Test;
|
||||
public class UuidUtilsTest {
|
||||
|
||||
@Test
|
||||
public void isUuidTestPass() throws Exception {
|
||||
public void isUuidTestAllLowerCaseReturnTrue() {
|
||||
String serviceUuid = "f81a9aa3-1f7d-466f-b04b-f2b101486bae";
|
||||
|
||||
assertTrue(UuidUtils.isUuid(serviceUuid));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isUuidTestFail() throws Exception {
|
||||
String serviceUuid = "6fc6ce7-d503-4f95-9e68-c9cd281b13df";
|
||||
public void isUuidTestAllUpperCaseReturnTrue() {
|
||||
String serviceUuid = "F81A9AA3-1F7D-466F-B04B-F2B101486BAE";
|
||||
assertTrue(UuidUtils.isUuid(serviceUuid));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isUuidTestAlternatingCaseReturnTrue() {
|
||||
String serviceUuid = "f81A9Aa3-1f7d-466F-B04b-f2b101486BaE";
|
||||
assertTrue(UuidUtils.isUuid(serviceUuid));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isUuidTestNotUuidReturnFalse() {
|
||||
String serviceUuid = "6fc6ce7-d503-4f95-9e68-c9cd281b13df";
|
||||
assertFalse(UuidUtils.isUuid(serviceUuid));
|
||||
}
|
||||
}
|
||||
@ -31,11 +31,18 @@ public class ByteScaleUtilsTest extends TestCase {
|
||||
|
||||
@Test
|
||||
public void validateBytesToKib() {
|
||||
long kib = 1024L * 3000L;
|
||||
long kib = 3000L;
|
||||
long b = 1024 * kib;
|
||||
assertEquals(kib, ByteScaleUtils.bytesToKib(b));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateBytesToMib() {
|
||||
long mib = 3000L;
|
||||
long b = 1024L * 1024L * mib;
|
||||
assertEquals(mib, ByteScaleUtils.bytesToMib(b));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateMibToBytesIfIntTimesIntThenMustExtrapolateIntMaxValue() {
|
||||
int mib = 3000;
|
||||
|
||||
@ -0,0 +1,188 @@
|
||||
// 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.utils.jsinterpreter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PowerMockIgnore({"javax.xml.*", "org.apache.xerces.*", "org.xml.*", "org.w3c.*"})
|
||||
@PrepareForTest(JsInterpreter.class)
|
||||
public class JsInterpreterTest {
|
||||
private long timeout = 2000;
|
||||
|
||||
@InjectMocks
|
||||
@Spy
|
||||
JsInterpreter jsInterpreterSpy = new JsInterpreter(timeout);
|
||||
|
||||
@Mock
|
||||
ExecutorService executorMock;
|
||||
|
||||
@Mock
|
||||
Future<Object> futureObjectMock;
|
||||
|
||||
@Test
|
||||
public void closeTestShutdownExecutor() throws IOException {
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
jsInterpreterSpy.executor = executor;
|
||||
|
||||
jsInterpreterSpy.close();
|
||||
Assert.assertTrue(executor.isShutdown());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addVariablesToScriptTestVariablesMapIsEmptyReturnScript() {
|
||||
String script = "a + b";
|
||||
jsInterpreterSpy.variables = new LinkedHashMap<>();
|
||||
|
||||
String result = jsInterpreterSpy.addVariablesToScript(script);
|
||||
|
||||
Assert.assertEquals(script, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addVariablesToScriptTestVariablesMapIsNotEmptyInjectVariableToScript() {
|
||||
String script = "a + b";
|
||||
String var1 = "{test: \"test\"}";
|
||||
jsInterpreterSpy.injectVariable("var1", var1);
|
||||
jsInterpreterSpy.injectVariable("var2", var1);
|
||||
|
||||
String expected = String.format(" var1 = %s; var2 = %s; %s", var1, var1, script);
|
||||
|
||||
String result = jsInterpreterSpy.addVariablesToScript(script);
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeScriptTestReturnResultOfScriptExecution() {
|
||||
String script = "5";
|
||||
Object expected = new Object();
|
||||
Mockito.doReturn(script).when(jsInterpreterSpy).addVariablesToScript(Mockito.anyString());
|
||||
Mockito.doReturn(expected).when(jsInterpreterSpy).executeScript(Mockito.anyString());
|
||||
|
||||
Object result = jsInterpreterSpy.executeScript(script);
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void executeScriptInThreadTestThreadThrowInterruptedException() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
Mockito.doReturn(futureObjectMock).when(executorMock).submit(Mockito.<Callable<Object>>any());
|
||||
Mockito.doThrow(InterruptedException.class).when(futureObjectMock).get(Mockito.anyLong(), Mockito.any());
|
||||
|
||||
jsInterpreterSpy.executeScriptInThread("a");
|
||||
Mockito.verify(futureObjectMock).cancel(true);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void executeScriptInThreadTestThreadThrowExecutionException() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
Mockito.doReturn(futureObjectMock).when(executorMock).submit(Mockito.<Callable<Object>>any());
|
||||
Mockito.doThrow(ExecutionException.class).when(futureObjectMock).get(Mockito.anyLong(), Mockito.any());
|
||||
|
||||
jsInterpreterSpy.executeScriptInThread("b");
|
||||
Mockito.verify(futureObjectMock).cancel(true);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void executeScriptInThreadTestThreadThrowTimeoutException() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
Mockito.doReturn(futureObjectMock).when(executorMock).submit(Mockito.<Callable<Object>>any());
|
||||
Mockito.doThrow(TimeoutException.class).when(futureObjectMock).get(Mockito.anyLong(), Mockito.any());
|
||||
|
||||
jsInterpreterSpy.executeScriptInThread("c");
|
||||
Mockito.verify(futureObjectMock).cancel(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeScriptInThreadTestReturnResultOfScriptExecution() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
Object expected = new Object();
|
||||
|
||||
Mockito.doReturn(futureObjectMock).when(executorMock).submit(Mockito.<Callable<Object>>any());
|
||||
Mockito.doReturn(expected).when(futureObjectMock).get(Mockito.anyLong(), Mockito.any());
|
||||
|
||||
Object result = jsInterpreterSpy.executeScriptInThread("");
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
Mockito.verify(futureObjectMock).cancel(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void injectVariableTestAddVariableToMap() {
|
||||
Map<String, String> variables = new LinkedHashMap<>();
|
||||
variables.put("a", "b");
|
||||
variables.put("b", null);
|
||||
|
||||
jsInterpreterSpy.variables = new LinkedHashMap<>();
|
||||
|
||||
jsInterpreterSpy.injectVariable("a", "b");
|
||||
jsInterpreterSpy.injectVariable("b", null);
|
||||
|
||||
variables.forEach((key, value) -> {
|
||||
Assert.assertEquals(value, jsInterpreterSpy.variables.get(key));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discardCurrentVariablesTestInstantiateNewMap() {
|
||||
Map<String, String> variables = new LinkedHashMap<>();
|
||||
variables.put("a", "b");
|
||||
variables.put("b", null);
|
||||
|
||||
jsInterpreterSpy.variables = variables;
|
||||
|
||||
jsInterpreterSpy.discardCurrentVariables();
|
||||
|
||||
Assert.assertEquals(0, jsInterpreterSpy.variables.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@PrepareForTest(NashornScriptEngineFactory.class)
|
||||
public void setScriptEngineDisablingJavaLanguageTest() {
|
||||
NashornScriptEngineFactory nashornScriptEngineFactoryMock = Mockito.mock(NashornScriptEngineFactory.class);
|
||||
ScriptEngine scriptEngineMock = Mockito.mock(ScriptEngine.class);
|
||||
|
||||
Mockito.doReturn(scriptEngineMock).when(nashornScriptEngineFactoryMock).getScriptEngine(Mockito.anyString());
|
||||
|
||||
jsInterpreterSpy.setScriptEngineDisablingJavaLanguage(nashornScriptEngineFactoryMock);
|
||||
|
||||
Assert.assertEquals(scriptEngineMock, jsInterpreterSpy.interpreter);
|
||||
Mockito.verify(nashornScriptEngineFactoryMock).getScriptEngine("--no-java");
|
||||
}
|
||||
}
|
||||
@ -53,6 +53,9 @@ public class ReflectionToStringBuilderUtilsTest extends TestCase {
|
||||
private String classToReflectRemovedField;
|
||||
private String[] classToReflectFieldsNamesArray;
|
||||
|
||||
private static final ToStringStyle DEFAULT_STYLE = ToStringStyle.JSON_STYLE;
|
||||
private static final String DEFAULT_MULTIPLE_VALUES_SEPARATOR = ",";
|
||||
|
||||
@Before
|
||||
public void setup(){
|
||||
classToReflect = String.class;
|
||||
@ -329,4 +332,21 @@ public class ReflectionToStringBuilderUtilsTest extends TestCase {
|
||||
String result = ReflectionToStringBuilderUtils.reflectOnlySelectedFields(new Object());
|
||||
Assert.assertEquals(expectedResult, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reflectCollectionTestCallBaseReflectCollectionMethodWithDefaultParameters() {
|
||||
String expected = "test";
|
||||
|
||||
PowerMockito.spy(ReflectionToStringBuilderUtils.class);
|
||||
PowerMockito.when(ReflectionToStringBuilderUtils.reflectCollection(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.any())).thenReturn(expected);
|
||||
|
||||
Object object = Mockito.mock(Object.class);
|
||||
String result = ReflectionToStringBuilderUtils.reflectCollection(object);
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
|
||||
PowerMockito.verifyStatic(ReflectionToStringBuilderUtils.class);
|
||||
String[] excludeFields = null;
|
||||
ReflectionToStringBuilderUtils.reflectCollection(object, DEFAULT_STYLE, DEFAULT_MULTIPLE_VALUES_SEPARATOR, excludeFields);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user