Skip to content

Commit e52d771

Browse files
authored
[COST-7114] Distribute GPU unallocated at start of month (#5846)
1 parent 322b963 commit e52d771

File tree

13 files changed

+385
-128
lines changed

13 files changed

+385
-128
lines changed

koku/masu/database/ocp_report_db_accessor.py

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from masu.processor import OCP_GPU_COST_MODEL_UNLEASH_FLAG
3636
from masu.util.common import filter_dictionary
3737
from masu.util.common import source_in_trino_table
38+
from masu.util.common import SummaryRangeConfig
3839
from masu.util.common import trino_table_exists
3940
from masu.util.ocp.common import DistributionConfig
4041
from masu.util.ocp.common import get_cluster_alias_from_cluster_id
@@ -468,7 +469,9 @@ def populate_markup_cost(self, markup, start_date, end_date, cluster_id):
468469
),
469470
)
470471

471-
def populate_distributed_cost_sql(self, start_date, end_date, provider_uuid, distribution_info):
472+
def populate_distributed_cost_sql(
473+
self, summary_range: SummaryRangeConfig, provider_uuid: uuid.UUID, distribution_info: dict
474+
) -> None:
472475
"""
473476
Populate the distribution cost model options.
474477
@@ -503,27 +506,50 @@ def populate_distributed_cost_sql(self, start_date, end_date, provider_uuid, dis
503506
cost_model_rate_type="gpu_distributed",
504507
query_type="trino",
505508
required_table="openshift_gpu_usage_line_items_daily",
509+
requires_full_month=True,
506510
),
507511
}
508512

509513
table_name = self._table_map["line_item_daily_summary"]
510-
report_period = self.report_periods_for_provider_uuid(provider_uuid, start_date)
511-
if not report_period:
512-
msg = "no report period for OCP provider, skipping distribution update"
513-
context = {"schema": self.schema, "provider_uuid": provider_uuid, "start_date": start_date}
514-
LOG.info(log_json(msg=msg, context=context))
515-
return
516-
517-
report_period_id = report_period.id
514+
dh = DateHelper()
518515
for cost_model_key, config in distribution_configs.items():
519516
sql_params = {
520-
"start_date": start_date,
521-
"end_date": end_date,
517+
"start_date": summary_range.start_date,
518+
"end_date": summary_range.end_date,
522519
"schema": self.schema,
523-
"report_period_id": report_period_id,
524520
"source_uuid": provider_uuid,
525521
"cost_model_rate_type": config.cost_model_rate_type,
526522
}
523+
# Handle distributions that require full month data
524+
if config.requires_full_month:
525+
# Skip full-month distributions on subsequent days when iterating day-by-day
526+
if summary_range.skip_full_month:
527+
continue
528+
sql_params["start_date"] = summary_range.start_of_month
529+
sql_params["end_date"] = summary_range.end_of_month
530+
if summary_range.is_current_month:
531+
# Trigger distribution for previous month during a window of the current
532+
# month
533+
if dh.now_utc.day in [1, 2, 3]:
534+
sql_params["start_date"] = summary_range.start_of_previous_month
535+
sql_params["end_date"] = summary_range.end_of_previous_month
536+
else:
537+
msg = f"Skipping {cost_model_key} distribution requires full month"
538+
LOG.info(log_json(msg=msg, context={"schema": self.schema, "cost_model_key": cost_model_key}))
539+
continue
540+
541+
report_period = self.report_periods_for_provider_uuid(provider_uuid, sql_params["start_date"])
542+
if not report_period:
543+
msg = f"no report period for OCP provider, skipping {cost_model_key} distribution update"
544+
context = {
545+
"schema": self.schema,
546+
"provider_uuid": provider_uuid,
547+
"start_date": sql_params["start_date"],
548+
}
549+
LOG.info(log_json(msg=msg, context=context))
550+
continue
551+
sql_params["report_period_id"] = report_period.id
552+
527553
self._delete_monthly_cost_model_rate_type_data(sql_params, cost_model_key)
528554
populate = distribution_info.get(cost_model_key, config.distribute_by_default)
529555
if not populate:
@@ -551,6 +577,8 @@ def populate_distributed_cost_sql(self, start_date, end_date, provider_uuid, dis
551577
else:
552578
self._prepare_and_execute_raw_sql_query(table_name, sql, sql_params, operation=f"INSERT: {log_msg}")
553579

580+
return summary_range
581+
554582
def _delete_monthly_cost_model_rate_type_data(self, sql_params, cost_model_key):
555583
delete_sql = pkgutil.get_data(
556584
"masu.database", "sql/openshift/cost_model/delete_monthly_cost_model_rate_type.sql"

koku/masu/database/trino_sql/openshift/cost_model/monthly_cost_gpu.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ WITH cte_unutilized_uptime_hours AS (
117117
ON gpu.node = node_ut.node
118118
AND gpu.interval_date = DATE(node_ut.interval_start)
119119
where node_labels like '%"nvidia_com_gpu_present": "True"%'
120+
AND date(node_ut.interval_start) >= DATE({{start_date}})
121+
AND date(node_ut.interval_start) <= DATE({{end_date}})
120122
AND node_ut.month = {{month}}
121123
AND node_ut.year = {{year}}
122124
AND node_ut.source = {{source_uuid}}

koku/masu/processor/aws/aws_cost_model_cost_updater.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from masu.database.aws_report_db_accessor import AWSReportDBAccessor
1414
from masu.database.cost_model_db_accessor import CostModelDBAccessor
1515
from masu.util.aws.common import get_bills_from_provider
16+
from masu.util.common import SummaryRangeConfig
1617
from reporting.provider.aws.models import UI_SUMMARY_TABLES_MARKUP_SUBSET
1718

1819

@@ -54,12 +55,11 @@ def _update_markup_cost(self, start_date, end_date):
5455
exc_info=error,
5556
)
5657

57-
def update_summary_cost_model_costs(self, start_date=None, end_date=None):
58+
def update_summary_cost_model_costs(self, summary_range: SummaryRangeConfig) -> None:
5859
"""Update the AWS summary table with the charge information.
5960
6061
Args:
61-
start_date (str, Optional) - Start date of range to update derived cost.
62-
end_date (str, Optional) - End date of range to update derived cost.
62+
summary_range (SummaryRangeConfig) - Date range configuration for cost model updates.
6363
6464
Returns
6565
None
@@ -69,28 +69,31 @@ def update_summary_cost_model_costs(self, start_date=None, end_date=None):
6969
log_json(
7070
msg="starting charge calculation updates",
7171
schema=self._schema,
72-
start_date=start_date,
73-
end_date=end_date,
72+
start_date=summary_range.start_date,
73+
end_date=summary_range.end_date,
7474
provider_uuid=self._provider.uuid,
7575
)
7676
)
7777

78-
self._update_markup_cost(start_date, end_date)
78+
self._update_markup_cost(summary_range.start_date, summary_range.end_date)
7979

8080
with AWSReportDBAccessor(self._schema) as accessor:
8181
LOG.debug(
8282
log_json(
8383
msg="updating AWS derived cost summary",
8484
schema=self._schema,
8585
provider_uuid=self._provider.uuid,
86-
start_date=start_date,
87-
end_date=end_date,
86+
start_date=summary_range.start_date,
87+
end_date=summary_range.end_date,
8888
)
8989
)
9090
accessor.populate_ui_summary_tables(
91-
start_date, end_date, self._provider.uuid, UI_SUMMARY_TABLES_MARKUP_SUBSET
91+
summary_range.start_date,
92+
summary_range.end_date,
93+
self._provider.uuid,
94+
UI_SUMMARY_TABLES_MARKUP_SUBSET,
9295
)
93-
bills = accessor.bills_for_provider_uuid(self._provider.uuid, start_date)
96+
bills = accessor.bills_for_provider_uuid(self._provider.uuid, summary_range.start_date)
9497
with schema_context(self._schema):
9598
for bill in bills:
9699
bill.derived_cost_datetime = timezone.now()

koku/masu/processor/azure/azure_cost_model_cost_updater.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from masu.database.azure_report_db_accessor import AzureReportDBAccessor
1414
from masu.database.cost_model_db_accessor import CostModelDBAccessor
1515
from masu.util.azure.common import get_bills_from_provider
16+
from masu.util.common import SummaryRangeConfig
1617

1718

1819
LOG = logging.getLogger(__name__)
@@ -54,12 +55,11 @@ def _update_markup_cost(self, start_date, end_date):
5455
except AzureCostModelCostUpdaterError as error:
5556
LOG.error(log_json(msg="unable to update markup costs", context=self._context), exc_info=error)
5657

57-
def update_summary_cost_model_costs(self, start_date=None, end_date=None):
58+
def update_summary_cost_model_costs(self, summary_range: SummaryRangeConfig) -> None:
5859
"""Update the Azure summary table with the charge information.
5960
6061
Args:
61-
start_date (str, Optional) - Start date of range to update derived cost.
62-
end_date (str, Optional) - End date of range to update derived cost.
62+
summary_range (SummaryRangeConfig) - Date range configuration for cost model updates.
6363
6464
Returns
6565
None
@@ -69,17 +69,17 @@ def update_summary_cost_model_costs(self, start_date=None, end_date=None):
6969
log_json(
7070
msg="starting charge calculation updates",
7171
context=self._context,
72-
start_date=start_date,
73-
end_date=end_date,
72+
start_date=summary_range.start_date,
73+
end_date=summary_range.end_date,
7474
)
7575
)
7676

77-
self._update_markup_cost(start_date, end_date)
77+
self._update_markup_cost(summary_range.start_date, summary_range.end_date)
7878

7979
with AzureReportDBAccessor(self._schema) as accessor:
8080
LOG.debug(log_json(msg="updating Azure derived cost summary", context=self._context))
81-
accessor.populate_ui_summary_tables(start_date, end_date, self._provider.uuid)
82-
bills = accessor.bills_for_provider_uuid(self._provider.uuid, start_date)
81+
accessor.populate_ui_summary_tables(summary_range.start_date, summary_range.end_date, self._provider.uuid)
82+
bills = accessor.bills_for_provider_uuid(self._provider.uuid, summary_range.start_date)
8383
with schema_context(self._schema):
8484
for bill in bills:
8585
bill.derived_cost_datetime = timezone.now()

koku/masu/processor/cost_model_cost_updater.py

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
# SPDX-License-Identifier: Apache-2.0
44
#
55
"""Update Cost Model Cost info for report summary tables."""
6-
import datetime
76
import logging
87

9-
import ciso8601
10-
118
from api.models import Provider
129
from api.utils import DateHelper
1310
from koku.cache import invalidate_cache_for_tenant_and_cache_key
@@ -18,6 +15,7 @@
1815
from masu.processor.azure.azure_cost_model_cost_updater import AzureCostModelCostUpdater
1916
from masu.processor.gcp.gcp_cost_model_cost_updater import GCPCostModelCostUpdater
2017
from masu.processor.ocp.ocp_cost_model_cost_updater import OCPCostModelCostUpdater
18+
from masu.util.common import SummaryRangeConfig
2119

2220
LOG = logging.getLogger(__name__)
2321

@@ -76,18 +74,6 @@ def _set_updater(self):
7674
if self._provider.type in (Provider.PROVIDER_GCP, Provider.PROVIDER_GCP_LOCAL):
7775
return GCPCostModelCostUpdater(self._schema, self._provider)
7876

79-
def _format_dates(self, start_date, end_date):
80-
"""Convert dates to strings for use in the updater."""
81-
if isinstance(start_date, datetime.date):
82-
start_date = start_date.strftime("%Y-%m-%d")
83-
elif isinstance(start_date, str):
84-
start_date = ciso8601.parse_datetime(start_date).date()
85-
if isinstance(end_date, datetime.date):
86-
end_date = end_date.strftime("%Y-%m-%d")
87-
elif isinstance(end_date, str):
88-
end_date = ciso8601.parse_datetime(end_date).date()
89-
return start_date, end_date
90-
9177
def update_cost_model_costs(self, start_date=None, end_date=None):
9278
"""
9379
Update usage charge information.
@@ -100,14 +86,18 @@ def update_cost_model_costs(self, start_date=None, end_date=None):
10086
None
10187
10288
"""
89+
dh = DateHelper()
90+
if start_date is None:
91+
start_date = dh.this_month_start.date()
92+
if end_date is None:
93+
end_date = dh.today.date()
94+
summary_range = SummaryRangeConfig(start_date=start_date, end_date=end_date)
10395
if self._updater:
10496
if is_customer_cost_model_large(self._schema):
105-
for day_date in DateHelper().list_days(start_date, end_date):
106-
start, end = self._format_dates(day_date, day_date)
107-
self._updater.update_summary_cost_model_costs(start, end)
97+
for day_range in summary_range.iter_days():
98+
self._updater.update_summary_cost_model_costs(day_range)
10899
else:
109-
start_date, end_date = self._format_dates(start_date, end_date)
110-
self._updater.update_summary_cost_model_costs(start_date, end_date)
100+
self._updater.update_summary_cost_model_costs(summary_range)
111101
invalidate_view_cache_for_tenant_and_source_type(self._schema, self._provider.type)
112102
# Invalidate the tag_rate_map for tag mapping
113103
invalidate_cache_for_tenant_and_cache_key(self._schema, TAG_MAPPING_PREFIX)

koku/masu/processor/gcp/gcp_cost_model_cost_updater.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from api.common import log_json
1313
from masu.database.cost_model_db_accessor import CostModelDBAccessor
1414
from masu.database.gcp_report_db_accessor import GCPReportDBAccessor
15+
from masu.util.common import SummaryRangeConfig
1516
from masu.util.gcp.common import get_bills_from_provider
1617
from reporting.provider.gcp.models import UI_SUMMARY_TABLES
1718

@@ -50,12 +51,11 @@ def _update_markup_cost(self, start_date, end_date):
5051
except GCPCostModelCostUpdaterError as error:
5152
LOG.error(log_json(msg="unable to update markup costs"), exc_info=error)
5253

53-
def update_summary_cost_model_costs(self, start_date=None, end_date=None):
54+
def update_summary_cost_model_costs(self, summary_range: SummaryRangeConfig) -> None:
5455
"""Update the GCP summary table with the charge information.
5556
5657
Args:
57-
start_date (str, Optional) - Start date of range to update derived cost.
58-
end_date (str, Optional) - End date of range to update derived cost.
58+
summary_range (SummaryRangeConfig) - Date range configuration for cost model updates.
5959
6060
Returns
6161
None
@@ -66,12 +66,12 @@ def update_summary_cost_model_costs(self, start_date=None, end_date=None):
6666
msg="starting charge calculation updates",
6767
schema=self._schema,
6868
provider_uuid=self._provider.uuid,
69-
start_date=start_date,
70-
end_date=end_date,
69+
start_date=summary_range.start_date,
70+
end_date=summary_range.end_date,
7171
)
7272
)
7373

74-
self._update_markup_cost(start_date, end_date)
74+
self._update_markup_cost(summary_range.start_date, summary_range.end_date)
7575

7676
with GCPReportDBAccessor(self._schema) as accessor:
7777
LOG.debug(
@@ -81,9 +81,9 @@ def update_summary_cost_model_costs(self, start_date=None, end_date=None):
8181
provider_uuid=self._provider.uuid,
8282
)
8383
)
84-
invoice_month = start_date.strftime("%Y%m")
84+
invoice_month = summary_range.start_date.strftime("%Y%m")
8585
invoice_dates = accessor.fetch_invoice_month_dates(
86-
start_date, end_date, invoice_month, self._provider.uuid
86+
summary_range.start_date, summary_range.end_date, invoice_month, self._provider.uuid
8787
)
8888
invoice_start, invoice_end = invoice_dates[0]
8989
accessor.populate_ui_summary_tables(

0 commit comments

Comments
 (0)