From 567c9e76674f490cdb88f77545da197d54e5fe85 Mon Sep 17 00:00:00 2001 From: Pedro Gonzalez Gomez Date: Wed, 12 Feb 2025 20:24:57 +0100 Subject: [PATCH] mgr/dashboard: add xlmtodict import and fix lifecycle get request Fixes: https://tracker.ceph.com/issues/70128 Signed-off-by: Pedro Gonzalez Gomez --- ceph.spec.in | 1 + debian/control | 1 + .../rgw-bucket-details.component.html | 4 +- .../rgw-bucket-details.component.ts | 9 ++++- src/pybind/mgr/dashboard/requirements.txt | 1 + .../mgr/dashboard/services/rgw_client.py | 37 +++++++++++++------ src/pybind/mgr/tox.ini | 1 + 7 files changed, 38 insertions(+), 16 deletions(-) diff --git a/ceph.spec.in b/ceph.spec.in index d72b5abcc62..8c022125eba 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -695,6 +695,7 @@ Requires: ceph-prometheus-alerts = %{_epoch_prefix}%{version}-%{release} Requires: python%{python3_pkgversion}-grpcio Requires: python%{python3_pkgversion}-grpcio-tools Requires: python%{python3_pkgversion}-jmespath +Requires: python%{python3_pkgversion}-xmltodict %endif %if 0%{?fedora} || 0%{?rhel} || 0%{?openEuler} Requires: python%{python3_pkgversion}-cherrypy diff --git a/debian/control b/debian/control index 88c4c92238f..6d3fa326305 100644 --- a/debian/control +++ b/debian/control @@ -100,6 +100,7 @@ Build-Depends: automake, python3-dateutil , python3-grpcio , python3-jmespath (>=0.10) , + python3-xmltodict , python3-openssl , python3-prettytable , python3-requests , diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html index 2c22cf80c60..49d4f4255c7 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html @@ -152,13 +152,13 @@ diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts index b95faa3140e..fe8ab3e6a32 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges } from '@angular/core'; +import { ChangeDetectorRef, Component, Input, OnChanges } from '@angular/core'; import { RgwBucketService } from '~/app/shared/api/rgw-bucket.service'; @@ -24,7 +24,7 @@ export class RgwBucketDetailsComponent implements OnChanges { replicationStatus = $localize`Disabled`; bucketRateLimit: RgwRateLimitConfig; - constructor(private rgwBucketService: RgwBucketService) {} + constructor(private rgwBucketService: RgwBucketService, private cd: ChangeDetectorRef) {} ngOnChanges() { this.updateBucketDetails(this.extraxtDetailsfromResponse.bind(this)); @@ -102,4 +102,9 @@ export class RgwBucketDetailsComponent implements OnChanges { ); } } + + updateLifecycleFormatTo(format: 'json' | 'xml'): void { + this.lifecycleFormat = format; + this.cd.detectChanges(); + } } diff --git a/src/pybind/mgr/dashboard/requirements.txt b/src/pybind/mgr/dashboard/requirements.txt index be0bc1efb02..6f95477cb12 100644 --- a/src/pybind/mgr/dashboard/requirements.txt +++ b/src/pybind/mgr/dashboard/requirements.txt @@ -15,3 +15,4 @@ grpcio==1.46.5 grpcio-tools==1.46.5 jmespath lxml==4.8.0 # to fix https://github.com/xmlsec/python-xmlsec/issues/320 +xmltodict diff --git a/src/pybind/mgr/dashboard/services/rgw_client.py b/src/pybind/mgr/dashboard/services/rgw_client.py index f29e4766d61..f9423da564e 100755 --- a/src/pybind/mgr/dashboard/services/rgw_client.py +++ b/src/pybind/mgr/dashboard/services/rgw_client.py @@ -16,6 +16,12 @@ from subprocess import SubprocessError from urllib.parse import urlparse import requests + +try: + import xmltodict +except ModuleNotFoundError: + logging.error("Module 'xmltodict' is not installed.") + from mgr_util import build_url, name_to_config_section from .. import mgr @@ -715,23 +721,30 @@ class RgwClient(RestClient): @RestClient.api_get('/{bucket_name}?lifecycle') def get_lifecycle(self, bucket_name, request=None): # pylint: disable=unused-argument + + # xmltodict parser will prepend namespace to json keys as {ns0:key} + def remove_namespace(xml: str): + """Remove namespace in given xml string.""" + root = ET.fromstring(xml) + for elem in root.iter(): + tag_elements = elem.tag.split("}") # tag: {ns}tagname + # Removing namespaces and attributes + elem.tag = tag_elements[1] + elem.attrib.clear() + + return ET.tostring(root) + try: - decoded_request = request(raw_content=True).decode("utf-8") # type: ignore - result = { - 'LifecycleConfiguration': - json.loads( - decoded_request, - object_pairs_hook=RgwClient._handle_rules - ) - } + result = request( + raw_content=True, headers={'Accept': 'text/xml'}).decode() # type: ignore + return xmltodict.parse(remove_namespace(result), process_namespaces=False) except RequestException as e: if e.content: - content = json_str_to_object(e.content) - if content.get( - 'Code') == 'NoSuchLifecycleConfiguration': + root = ET.fromstring(e.content) + code = root.find('Code') + if code is not None and code.text == 'NoSuchLifecycleConfiguration': return None raise DashboardException(msg=str(e), component='rgw') - return result @staticmethod def dict_to_xml(data): diff --git a/src/pybind/mgr/tox.ini b/src/pybind/mgr/tox.ini index 366dc1ff871..c2deb627261 100644 --- a/src/pybind/mgr/tox.ini +++ b/src/pybind/mgr/tox.ini @@ -82,6 +82,7 @@ deps = types-PyYAML types-jwt types-jmespath + types-xmltodict commands = mypy --config-file=../../mypy.ini \ -m alerts \ -- 2.39.5