From db27c0ad2a2a4d1e12368d32bbf248c1932d8c55 Mon Sep 17 00:00:00 2001 From: Stephan Krug Date: Fri, 17 Nov 2023 06:01:38 -0300 Subject: [PATCH] Set number of hours per month with actual number in Quota (#7210) Co-authored-by: Stephan Krug Co-authored-by: Gabriel --- .../apache/cloudstack/quota/QuotaManagerImpl.java | 12 +++++++++--- .../cloudstack/quota/QuotaManagerImplTest.java | 2 ++ utils/src/main/java/com/cloud/utils/DateUtil.java | 5 +++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java index d6499b91485..56a6edf5db4 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java @@ -89,11 +89,11 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { private TimeZone _usageTimezone; private int _aggregationDuration = 0; - - static final BigDecimal s_hoursInMonth = BigDecimal.valueOf(DateUtil.HOURS_IN_A_MONTH); static final BigDecimal GiB_DECIMAL = BigDecimal.valueOf(ByteScaleUtils.GiB); List lockablesAccountTypes = Arrays.asList(Account.Type.NORMAL, Account.Type.DOMAIN_ADMIN); + static BigDecimal hoursInCurrentMonth; + public QuotaManagerImpl() { super(); } @@ -533,7 +533,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { 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); + BigDecimal costPerHour = getCostPerHour(aggregatedQuotaTariffsValue, usageRecord.getStartDate()); switch (UsageUnitTypes.getByDescription(quotaUnit)) { case COMPUTE_MONTH: @@ -558,6 +558,12 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { } } + protected BigDecimal getCostPerHour(BigDecimal costPerMonth, Date date) { + BigDecimal hoursInCurrentMonth = BigDecimal.valueOf(DateUtil.getHoursInCurrentMonth(date)); + s_logger.trace(String.format("Dividing tariff cost per month [%s] by [%s] to get the tariffs cost per hour.", costPerMonth, hoursInCurrentMonth)); + return costPerMonth.divide(hoursInCurrentMonth, 8, RoundingMode.HALF_EVEN); + } + @Override public boolean isLockable(AccountVO account) { return lockablesAccountTypes.contains(account.getType()); diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java index e42e03dbe8e..e53051f2925 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java @@ -142,8 +142,10 @@ public class QuotaManagerImplTest { public void getUsageValueAccordingToUsageUnitTypeTestAllTypes() { Mockito.doReturn(10.0).when(usageVoMock).getRawUsage(); Mockito.doReturn(ByteScaleUtils.GiB).when(usageVoMock).getSize(); + Mockito.doReturn(new Date(0, 8, 10)).when(usageVoMock).getStartDate(); BigDecimal aggregatedQuotaTariffsValue = new BigDecimal(400); + Arrays.asList(UsageUnitTypes.values()).forEach(type -> { BigDecimal result = quotaManagerImplSpy.getUsageValueAccordingToUsageUnitType(usageVoMock, aggregatedQuotaTariffsValue, type.toString()); Double expected = null; diff --git a/utils/src/main/java/com/cloud/utils/DateUtil.java b/utils/src/main/java/com/cloud/utils/DateUtil.java index 41afcb1bab4..39ea60dae18 100644 --- a/utils/src/main/java/com/cloud/utils/DateUtil.java +++ b/utils/src/main/java/com/cloud/utils/DateUtil.java @@ -25,6 +25,7 @@ import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.time.YearMonth; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; @@ -336,4 +337,8 @@ public class DateUtil { .withSecond(localDateTime.getSecond()); return zonedDate; } + + public static int getHoursInCurrentMonth(Date date) { + return YearMonth.of(date.getYear(), date.getMonth() + 1).lengthOfMonth() * 24; + } }