From f4067c0ba5cc910b6c99984c5f1e539e8d75583f Mon Sep 17 00:00:00 2001 From: OpenStack Proposal Bot Date: Thu, 8 Jan 2026 04:03:49 +0000 Subject: [PATCH 1/3] Imported Translations from Zanata For more information about this automatic import see: https://docs.openstack.org/i18n/latest/reviewing-translation-import.html Change-Id: I32d9a6e81c74d23811a54c88014ba52376f71d8d Signed-off-by: OpenStack Proposal Bot Generated-By: openstack/openstack-zuul-jobs:roles/prepare-zanata-client/files/common_translation_update.sh --- .../locale/en_GB/LC_MESSAGES/releasenotes.po | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po index 01ac7ba..160ae00 100644 --- a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po +++ b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po @@ -5,15 +5,16 @@ # Andi Chandler , 2022. #zanata # Andi Chandler , 2023. #zanata # Andi Chandler , 2024. #zanata +# Andi Chandler , 2026. #zanata msgid "" msgstr "" "Project-Id-Version: Cloudkitty Dashboard Release Notes\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-08-07 10:32+0000\n" +"POT-Creation-Date: 2025-11-26 12:19+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2024-04-18 12:35+0000\n" +"PO-Revision-Date: 2026-01-07 11:22+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: English (United Kingdom)\n" "Language: en_GB\n" @@ -29,6 +30,9 @@ msgstr "11.0.1" msgid "12.0.0" msgstr "12.0.0" +msgid "12.0.0-4" +msgstr "12.0.0-4" + msgid "13.0.0" msgstr "13.0.0" @@ -38,6 +42,9 @@ msgstr "14.0.1" msgid "15.0.0" msgstr "15.0.0" +msgid "19.0.0" +msgstr "19.0.0" + msgid "2023.1 Series Release Notes" msgstr "2023.1 Series Release Notes" @@ -47,6 +54,18 @@ msgstr "2023.2 Series Release Notes" msgid "2024.1 Series Release Notes" msgstr "2024.1 Series Release Notes" +msgid "2024.2 Series Release Notes" +msgstr "2024.2 Series Release Notes" + +msgid "2025.1 Series Release Notes" +msgstr "2025.1 Series Release Notes" + +msgid "2025.2 Series Release Notes" +msgstr "2025.2 Series Release Notes" + +msgid "21.0.0" +msgstr "21.0.0" + msgid "8.1.0" msgstr "8.1.0" @@ -136,6 +155,9 @@ msgstr "Rocky Series Release Notes" msgid "Stein Series Release Notes" msgstr "Stein Series Release Notes" +msgid "Support for Python 3.8 and 3.9 has been dropped." +msgstr "Support for Python 3.8 and 3.9 has been dropped." + msgid "" "The \"Cost Per Service Per Hour\" graph no longer stacks series on the Y " "axis." From 1d037c6d634f305aa3ebeba972bd03e31d10067e Mon Sep 17 00:00:00 2001 From: Juan Larriba Date: Tue, 13 Jan 2026 11:59:46 +0100 Subject: [PATCH 2/3] Fix exception handling in hashmap IndexView The IndexView.get_data() method catches exceptions.NotFound from keystoneauth1 when fetching metric info, but the CloudKitty client raises its own HttpError exception when a metric is not found. This causes the hashmap services list page to fail with an HTTP 500 error when any service is not registered as a metric in CloudKitty's info API. Change the exception handling to catch the broader Exception class to gracefully handle any error when fetching metric info, displaying "-" as the unit instead of crashing. Change-Id: I831f9d70492d377ec2508822f1ba8af967f0f8c7 Signed-off-by: Juan Larriba --- cloudkittydashboard/dashboards/admin/hashmap/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cloudkittydashboard/dashboards/admin/hashmap/views.py b/cloudkittydashboard/dashboards/admin/hashmap/views.py index f65c48a..b981def 100644 --- a/cloudkittydashboard/dashboards/admin/hashmap/views.py +++ b/cloudkittydashboard/dashboards/admin/hashmap/views.py @@ -13,6 +13,7 @@ # under the License. +from cloudkittyclient import exc as ck_exc from django.urls import reverse from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ @@ -41,7 +42,7 @@ def get_data(self): try: service = manager.info.get_metric(metric_name=s['name']) unit = service['unit'] - except exceptions.NotFound: + except (exceptions.NotFound, ck_exc.HTTPNotFound): unit = "-" list_services.append({ From 8af1dbba1ea1922f7481f29510bc9db72ec1b68e Mon Sep 17 00:00:00 2001 From: Leonie Chamberlin-Medd Date: Wed, 13 Aug 2025 14:44:45 +0000 Subject: [PATCH 3/3] Upgrade admin/rating panel to v2 of the CloudKitty API The admin/rating panel has been upgraded to use v2 of the CloudKitty API, matching the project/rating panel. Variable names have also been changed to match the project/rating panel format. This enables filtering in the API calls. Change-Id: I96f795ae9d8085ed92a9213a6e7571be5a702904 Signed-off-by: Leonie Chamberlin-Medd --- .../dashboards/admin/summary/tables.py | 5 +- .../dashboards/admin/summary/views.py | 57 ++++++++++--------- ...to-v2-cloudkitty-api-5de060caad561421.yaml | 5 ++ 3 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 releasenotes/notes/upgrade-admin-rating-panel-to-v2-cloudkitty-api-5de060caad561421.yaml diff --git a/cloudkittydashboard/dashboards/admin/summary/tables.py b/cloudkittydashboard/dashboards/admin/summary/tables.py index 3a1aca0..b41b47b 100644 --- a/cloudkittydashboard/dashboards/admin/summary/tables.py +++ b/cloudkittydashboard/dashboards/admin/summary/tables.py @@ -37,9 +37,12 @@ class Meta(object): class TenantSummaryTable(tables.DataTable): - res_type = tables.Column('res_type', verbose_name=_("Res Type")) + res_type = tables.Column('type', verbose_name=_("Resource Type")) rate = tables.Column('rate', verbose_name=_("Rate")) class Meta(object): name = "tenant_summary" verbose_name = _("Project Summary") + + def get_object_id(self, datum): + return datum.get('type') diff --git a/cloudkittydashboard/dashboards/admin/summary/views.py b/cloudkittydashboard/dashboards/admin/summary/views.py index 1ad29f6..bc4c813 100644 --- a/cloudkittydashboard/dashboards/admin/summary/views.py +++ b/cloudkittydashboard/dashboards/admin/summary/views.py @@ -33,23 +33,28 @@ class IndexView(tables.DataTableView): table_class = sum_tables.SummaryTable def get_data(self): - summary = api.cloudkittyclient(self.request).report.get_summary( - groupby=['tenant_id'], all_tenants=True)['summary'] + summary = api.cloudkittyclient( + self.request, version='2').summary.get_summary( + groupby=['project_id'], + response_format='object') - tenants, _ = api_keystone.tenant_list(self.request) + tenants, unused = api_keystone.tenant_list(self.request) tenants = {tenant.id: tenant.name for tenant in tenants} - summary.append({ - 'tenant_id': 'ALL', - 'rate': sum([float(item['rate']) for item in summary]), + data = summary.get('results') + + total = sum([r.get('rate') for r in data]) + data.append({ + 'project_id': 'ALL', + 'rate': total, }) - summary = api.identify(summary, key='tenant_id') - for tenant in summary: + data = api.identify(data, key='project_id') + for tenant in data: + tenant['tenant_id'] = tenant.get('project_id') tenant['name'] = tenants.get(tenant.id, '-') - summary[-1]['name'] = 'Cloud Total' - for tenant in summary: tenant['rate'] = utils.formatRate(tenant['rate'], rate_prefix, rate_postfix) - return summary + data[-1]['name'] = _('Cloud Total') + return data class TenantDetailsView(tables.DataTableView): @@ -57,25 +62,25 @@ class TenantDetailsView(tables.DataTableView): table_class = sum_tables.TenantSummaryTable page_title = _("Script details: {{ table.project_id }}") - def _get_cloud_total_summary(self): - return api.cloudkittyclient(self.request).report.get_summary( - groupby=['res_type'], all_tenants=True)['summary'] - def get_data(self): tenant_id = self.kwargs['project_id'] + if tenant_id == 'ALL': - summary = self._get_cloud_total_summary() + summary = api.cloudkittyclient( + self.request, version='2').summary.get_summary( + groupby=['type'], response_format='object') else: - summary = api.cloudkittyclient(self.request).report.get_summary( - groupby=['res_type'], tenant_id=tenant_id)['summary'] + summary = api.cloudkittyclient( + self.request, version='2').summary.get_summary( + filters={'project_id': tenant_id}, + groupby=['type'], response_format='object') - summary.append({ - 'tenant_id': tenant_id, - 'res_type': 'TOTAL', - 'rate': sum([float(item['rate']) for item in summary]), - }) - summary = api.identify(summary, key='res_type', name=True) - for item in summary: + data = summary.get('results') + total = sum([r.get('rate') for r in data]) + data.append({'type': 'TOTAL', 'rate': total}) + + for item in data: item['rate'] = utils.formatRate(item['rate'], rate_prefix, rate_postfix) - return summary + + return data diff --git a/releasenotes/notes/upgrade-admin-rating-panel-to-v2-cloudkitty-api-5de060caad561421.yaml b/releasenotes/notes/upgrade-admin-rating-panel-to-v2-cloudkitty-api-5de060caad561421.yaml new file mode 100644 index 0000000..b9d56ce --- /dev/null +++ b/releasenotes/notes/upgrade-admin-rating-panel-to-v2-cloudkitty-api-5de060caad561421.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - | + Upgrades the CloudKitty API from v1 to v2 in the admin/rating panel. +