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:
Daniel Augusto Veronezi Salvador 2022-10-17 05:03:50 -03:00 committed by GitHub
parent 289a43f758
commit 2ca164ac96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
89 changed files with 5970 additions and 716 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,32 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package 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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();
QuotaBalanceVO lastRealBalanceEntry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), endDate);
Date lastBalanceDate = new Date(0);
if (lastRealBalanceEntry != null) {
lastBalanceDate = lastRealBalanceEntry.getUpdatedOn();
aggrUsage = aggrUsage.add(lastRealBalanceEntry.getCreditBalance());
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Getting Balance" + account.getAccountName() + ",Balance entry=" + aggrUsage + " on Date=" + endDate);
}
aggrUsage = aggrUsage.add(aggregateCreditBetweenDates(account, lastBalanceDate, endDate));
if (startDate.compareTo(quotaUsageStartDate) == 0) {
aggregatedUsage = aggregatedUsage.subtract(quotaUsed);
continue;
}
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
}
saveQuotaBalance(account, aggrUsage, endDate);
// update quota_balance
saveQuotaAccount(account, aggrUsage, 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();
aggregatedUsage = aggregatedUsage.add(lastRealBalanceEntry.getCreditBalance());
}
aggregatedUsage = aggregatedUsage.add(aggregateCreditBetweenDates(accountId, domainId, lastBalanceDate, endDate, accountToString));
aggregatedUsage = aggregatedUsage.subtract(quotaUsed);
}
_quotaBalanceDao.saveQuotaBalance(new QuotaBalanceVO(accountId, domainId, aggregatedUsage, endDate));
saveQuotaAccount(accountId, aggregatedUsage, endDate);
}
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);
}
protected BigDecimal getUsageValueAccordingToLastQuotaUsageEntryAndLastQuotaBalance(long accountId, long domainId, Date startDate, Date endDate, BigDecimal aggregatedUsage,
String accountToString) {
QuotaUsageVO lastQuotaUsage = _quotaUsageDao.findLastQuotaUsageEntry(accountId, domainId, startDate);
private boolean saveQuotaAccount(final AccountVO account, final BigDecimal aggrUsage, final Date endDate) {
// update quota_accounts
QuotaAccountVO quota_account = _quotaAcc.findByIdQuotaAccount(account.getAccountId());
if (lastQuotaUsage == null) {
aggregatedUsage = aggregatedUsage.add(aggregateCreditBetweenDates(accountId, domainId, new Date(0), startDate, accountToString));
QuotaBalanceVO firstBalance = new QuotaBalanceVO(accountId, domainId, aggregatedUsage, startDate);
if (quota_account == null) {
quota_account = new QuotaAccountVO(account.getAccountId());
quota_account.setQuotaBalance(aggrUsage);
quota_account.setQuotaBalanceDate(endDate);
if (s_logger.isDebugEnabled()) {
s_logger.debug(quota_account);
}
_quotaAcc.persistQuotaAccount(quota_account);
return true;
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);
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));
}
return _quotaAcc.updateQuotaAccount(account.getAccountId(), quota_account);
}
return aggregatedUsage;
}
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);
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;
}
if (creditsReceived != null) {
for (QuotaBalanceVO credit : creditsReceived) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Credit entry found " + credit);
s_logger.debug("Total = " + aggrUsage);
}
aggrUsage = aggrUsage.add(credit.getCreditBalance());
}
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) {
aggregatedUsage = aggregatedUsage.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);
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;
}
usageRecord.setQuotaCalculated(1);
_usageDao.persistUsage(usageRecord);
return quota_usage;
s_logger.debug(String.format("Retrieved [%s] pending usage records for account [%s].", usageRecords.second(), account.reflectionToString()));
return records;
}
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());
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));
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);
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;
}
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 quotalist;
return persistUsagesAndQuotaUsagesAndRetrievePersistedQuotaUsages(pairsUsageAndQuotaUsage);
}
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);
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 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 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;
}
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 PresetVariables getPresetVariables(boolean hasAnyQuotaTariffWithActivationRule, UsageVO usageRecord) {
if (hasAnyQuotaTariffWithActivationRule) {
return presetVariableHelper.getPresetVariables(usageRecord);
}
usageRecord.setQuotaCalculated(1);
_usageDao.persistUsage(usageRecord);
return quota_usage;
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());
}
}

View File

@ -0,0 +1,32 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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");
}
}

View File

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

View File

@ -0,0 +1,32 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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");
}
}

View File

@ -0,0 +1,56 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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);
}
}

View File

@ -0,0 +1,32 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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");
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,35 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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"));
}
}

View File

@ -0,0 +1,40 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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);
}
}

View File

@ -0,0 +1,35 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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"));
}
}

View File

@ -0,0 +1,73 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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);
}
}

View File

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

View File

@ -0,0 +1,40 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.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);
}
}

View File

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

View File

@ -0,0 +1,41 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
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"));
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,153 @@
//Licensed to the Apache Software Foundation (ASF) under one
//or more contributor license agreements. See the NOTICE file
//distributed with this work for additional information
//regarding copyright ownership. The ASF licenses this file
//to you under the Apache License, Version 2.0 (the
//"License"); you may not use this file except in compliance
//with the License. You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing,
//software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//KIND, either express or implied. See the License for the
//specific language governing permissions and limitations
//under the License.
package org.apache.cloudstack.api.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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
}
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"));
}
_quotaTariffDao.addQuotaTariff(result);
return result;
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);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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