From: Nizamudeen A Date: Wed, 8 Jul 2026 09:27:33 +0000 (+0530) Subject: mgr/dashboard: fix unncessary traceback when bucket not exist X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0ad33c0965dcd1ea325a70253c5ec8f8e2219936;p=ceph.git mgr/dashboard: fix unncessary traceback when bucket not exist UI has an async validator which calls the GET bucket API to make sure the bucket name doesn't exist, but the proxy was not properly handling the http_status_codes which results in raising a massive traceback in logs whenever you type things in the bucket name field. So handling that gracefully by capturing the proper status codes for both RequestException and DashboardException BEFORE ``` File "/usr/share/ceph/mgr/dashboard/services/exception.py", line 47, in dashboard_exception_handler return handler(*args, **kwargs) File "/lib/python3.9/site-packages/cherrypy/_cpdispatch.py", line 54, in _call_ return self.callable(*self.args, **self.kwargs) File "/usr/share/ceph/mgr/dashboard/controllers/_base_controller.py", line 263, in inner ret = func(*args, **kwargs) File "/usr/share/ceph/mgr/dashboard/controllers/_rest_controller.py", line 193, in wrapper return func(*vpath, **params) File "/usr/share/ceph/mgr/dashboard/controllers/rgw.py", line 357, in get result = self.proxy(daemon_name, 'GET', 'bucket', {'bucket': bucket}) File "/usr/share/ceph/mgr/dashboard/controllers/rgw.py", line 213, in proxy raise DashboardException(e, http_status_code=http_status_code, component='rgw') dashboard.exceptions.DashboardException: RGW REST API failed request with status code 404 (b'{"Code":"NoSuchBucket","Message":"","RequestId":"tx00000f14e08c1af0d5615-006' b'71f54a7-3bc6-default","HostId":"3bc6-default-default"}') 2024-10-28T09:08:55.990+0000 7f89e045b640 0 [dashboard INFO request] [::ffff:10.74.18.122:51853] [GET] [500] [0.007s] [admin] [200.0B] /api/rgw/bucket/bucket-das ``` AFTER ``` Jul 08 09:28:28 ceph-node-00 ceph-mgr[2243]: [dashboard ERROR dashboard.rest_client] RGW REST API failed GET req status: 404 Jul 08 09:28:28 ceph-node-00 ceph-mgr[2243]: [dashboard INFO dashboard.services.exception] Dashboard Exception: RGW REST API failed request with status code 404 (b'{"Code":"NoSuchBucket","Message":"","RequestId":"tx00000c029a81e5d154844-006' b'a4e183c-14251-default","HostId":"14251-default-default"}') Jul 08 09:28:28 ceph-node-00 ceph-mgr[2243]: [dashboard INFO dashboard.tools] [::ffff:192.168.100.1:60408] [GET] [404] [0.078s] [admin] [200.0B] /api/rgw/bucket/testsa ``` Fixes: https://tracker.ceph.com/issues/78038 Signed-off-by: Nizamudeen A --- diff --git a/qa/tasks/mgr/dashboard/test_rgw.py b/qa/tasks/mgr/dashboard/test_rgw.py index 3f385f79a27..40a294a80db 100644 --- a/qa/tasks/mgr/dashboard/test_rgw.py +++ b/qa/tasks/mgr/dashboard/test_rgw.py @@ -550,7 +550,7 @@ class RgwUserTest(RgwTestCase): self._delete('/api/rgw/user/teuth-test-user') self.assertStatus(204) self.get_rgw_user('teuth-test-user') - self.assertStatus(500) + self.assertStatus(404) resp = self.jsonBody() self.assertIn('detail', resp) self.assertIn('failed request with status code 404', resp['detail']) @@ -593,7 +593,7 @@ class RgwUserTest(RgwTestCase): self._delete('/api/rgw/user/test01$teuth-test-user') self.assertStatus(204) self.get_rgw_user('test01$teuth-test-user') - self.assertStatus(500) + self.assertStatus(404) resp = self.jsonBody() self.assertIn('detail', resp) self.assertIn('failed request with status code 404', resp['detail']) diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py index a0ef6965771..c7f22103bd7 100755 --- a/src/pybind/mgr/dashboard/controllers/rgw.py +++ b/src/pybind/mgr/dashboard/controllers/rgw.py @@ -394,7 +394,11 @@ class RgwRESTController(RESTController): result = json_str_to_object(result) return result except (DashboardException, RequestException) as e: - http_status_code = e.status if isinstance(e, DashboardException) else 500 + response = getattr(e, 'response', None) + if isinstance(e, RequestException) and response is not None: + http_status_code = getattr(response, 'status_code', 500) + else: + http_status_code = getattr(e, 'status_code', getattr(e, 'status', None)) or 500 raise DashboardException(e, http_status_code=http_status_code, component='rgw') diff --git a/src/pybind/mgr/dashboard/tests/test_rgw.py b/src/pybind/mgr/dashboard/tests/test_rgw.py index 609d5388fc4..a1e37e6110b 100644 --- a/src/pybind/mgr/dashboard/tests/test_rgw.py +++ b/src/pybind/mgr/dashboard/tests/test_rgw.py @@ -2,7 +2,7 @@ from unittest.mock import Mock, call, patch from .. import mgr -from ..controllers.rgw import Rgw, RgwDaemon, RgwTopic, RgwUser +from ..controllers.rgw import Rgw, RgwBucket, RgwDaemon, RgwTopic, RgwUser from ..rest_client import RequestException from ..services.rgw_client import RgwClient, RgwMultisite from ..tests import ControllerTestCase, RgwStub @@ -600,3 +600,51 @@ class TestRgwTopicController(ControllerTestCase): result = controller.delete(key='RGW22222222222222222:HttpTest') mock_delete_topic.assert_called_with(key='RGW22222222222222222:HttpTest') self.assertEqual(result, None) + + +class RgwBucketControllerTestCase(ControllerTestCase): + @classmethod + def setup_server(cls): + cls.setup_controllers([RgwBucket], '/test') + + @patch('dashboard.services.rgw_client.RgwClient.admin_instance') + def test_get_bucket_not_found(self, mock_admin_instance): + mock_instance = Mock() + mock_admin_instance.return_value = mock_instance + + mock_response = Mock() + mock_response.status_code = 404 + mock_exception = RequestException('RGW REST API failed request') + mock_exception.response = mock_response + mock_instance.proxy.side_effect = mock_exception + + self._get('/test/api/rgw/bucket/i-do-not-exist') + self.assertStatus(404) + + @patch('dashboard.services.rgw_client.RgwClient.admin_instance') + def test_get_bucket_not_found_with_fallback_attribute(self, mock_admin_instance): + + mock_instance = Mock() + mock_admin_instance.return_value = mock_instance + + # mock that lacks a .response but has a direct .status_code attribute. + mock_exception = RequestException('RGW REST API failed request') + mock_exception.status_code = 404 + + mock_instance.proxy.side_effect = mock_exception + + self._get('/test/api/rgw/bucket/i-do-not-exist') + self.assertStatus(404) + + @patch('dashboard.services.rgw_client.RgwClient.admin_instance') + def test_get_bucket_server_error(self, mock_admin_instance): + mock_instance = Mock() + mock_admin_instance.return_value = mock_instance + + mock_exception = RequestException('Internal Server Error') + mock_exception.status_code = 500 + + mock_instance.proxy.side_effect = mock_exception + + self._get('/test/api/rgw/bucket/i-do-not-exist') + self.assertStatus(500)