From dc616c7d724a2580927ff8fb1fbc070d83dd67ef Mon Sep 17 00:00:00 2001 From: Sebastian Wagner Date: Tue, 24 Apr 2018 18:20:59 +0200 Subject: [PATCH] mgr/dashboard: Applied Exception Handling * Minor changes to CephFS, OSD, Pool, RbdMirroring, Summary and RGW Signed-off-by: Sebastian Wagner --- qa/tasks/mgr/dashboard/test_cephfs.py | 11 ++++++++++ qa/tasks/mgr/dashboard/test_pool.py | 14 +++++++++--- .../mgr/dashboard/controllers/cephfs.py | 5 ++++- src/pybind/mgr/dashboard/controllers/osd.py | 22 ++++--------------- src/pybind/mgr/dashboard/controllers/pool.py | 8 ++++++- .../dashboard/controllers/rbd_mirroring.py | 7 +++--- src/pybind/mgr/dashboard/controllers/rgw.py | 2 +- .../mgr/dashboard/controllers/summary.py | 16 +++++++------- 8 files changed, 50 insertions(+), 35 deletions(-) diff --git a/qa/tasks/mgr/dashboard/test_cephfs.py b/qa/tasks/mgr/dashboard/test_cephfs.py index 5669e41e07ec4..351b8745ee189 100644 --- a/qa/tasks/mgr/dashboard/test_cephfs.py +++ b/qa/tasks/mgr/dashboard/test_cephfs.py @@ -37,3 +37,14 @@ class CephfsTest(DashboardTestCase): self.assertIsInstance(data, dict) self.assertIsNotNone(data) + + @authenticate + def test_cephfs_mds_counters_wrong(self): + data = self._get("/api/cephfs/mds_counters/baadbaad") + self.assertStatus(400) + self.assertJsonBody({ + "component": 'cephfs', + "code": "invalid_cephfs_id", + "detail": "Invalid cephfs id baadbaad" + }) + diff --git a/qa/tasks/mgr/dashboard/test_pool.py b/qa/tasks/mgr/dashboard/test_pool.py index 1330ed7e9c178..e884d2f1cd373 100644 --- a/qa/tasks/mgr/dashboard/test_pool.py +++ b/qa/tasks/mgr/dashboard/test_pool.py @@ -18,9 +18,6 @@ class PoolTest(DashboardTestCase): cls._ceph_cmd(['osd', 'pool', 'delete', name, name, '--yes-i-really-really-mean-it']) cls._ceph_cmd(['osd', 'erasure-code-profile', 'rm', 'ecprofile']) - - - @authenticate def test_pool_list(self): data = self._get("/api/pool") @@ -145,6 +142,17 @@ class PoolTest(DashboardTestCase): for data in pools: self._pool_create(data) + @authenticate + def test_pool_create_fail(self): + data = {'pool_type': u'replicated', 'rule_name': u'dnf', 'pg_num': u'8', 'pool': u'sadfs'} + self._post('/api/pool/', data) + self.assertStatus(400) + self.assertJsonBody({ + 'component': 'pool', + 'code': "2", + 'detail': "specified rule dnf doesn't exist" + }) + @authenticate def test_pool_info(self): info_data = self._get("/api/pool/_info") diff --git a/src/pybind/mgr/dashboard/controllers/cephfs.py b/src/pybind/mgr/dashboard/controllers/cephfs.py index 59b57174326be..22acf8d60fc2f 100644 --- a/src/pybind/mgr/dashboard/controllers/cephfs.py +++ b/src/pybind/mgr/dashboard/controllers/cephfs.py @@ -5,6 +5,7 @@ from collections import defaultdict import cherrypy +from ..exceptions import DashboardException from . import ApiController, AuthRequired, BaseController from .. import mgr from ..services.ceph_service import CephService @@ -80,7 +81,9 @@ class CephFS(BaseController): try: return int(fs_id) except ValueError: - raise cherrypy.HTTPError(400, "Invalid cephfs id {}".format(fs_id)) + raise DashboardException(code='invalid_cephfs_id', + msg="Invalid cephfs id {}".format(fs_id), + component='cephfs') def _get_mds_names(self, filesystem_id=None): names = [] diff --git a/src/pybind/mgr/dashboard/controllers/osd.py b/src/pybind/mgr/dashboard/controllers/osd.py index 4844ee9857e1d..d5a25e20c4bfe 100644 --- a/src/pybind/mgr/dashboard/controllers/osd.py +++ b/src/pybind/mgr/dashboard/controllers/osd.py @@ -1,13 +1,10 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import -import json - -from mgr_module import CommandResult - from . import ApiController, AuthRequired, RESTController -from .. import logger, mgr +from .. import mgr from ..services.ceph_service import CephService +from ..services.exception import handle_send_command_error @ApiController('osd') @@ -51,20 +48,9 @@ class Osd(RESTController): osds[str(osd['id'])] = osd return osds + @handle_send_command_error('osd') def get(self, svc_id): - result = CommandResult('') - mgr.send_command(result, 'osd', svc_id, - json.dumps({ - 'prefix': 'perf histogram dump', - }), - '') - r, outb, outs = result.wait() - if r != 0: - logger.warning('Failed to load histogram for OSD %s', svc_id) - logger.debug(outs) - histogram = outs - else: - histogram = json.loads(outb) + histogram = CephService.send_command('osd', srv_spec=svc_id, prefix='perf histogram dump') return { 'osd_map': self.get_osd_map()[svc_id], 'osd_metadata': mgr.get_metadata('osd', svc_id), diff --git a/src/pybind/mgr/dashboard/controllers/pool.py b/src/pybind/mgr/dashboard/controllers/pool.py index 8288165bc4996..b9719834347d8 100644 --- a/src/pybind/mgr/dashboard/controllers/pool.py +++ b/src/pybind/mgr/dashboard/controllers/pool.py @@ -6,6 +6,7 @@ import cherrypy from . import ApiController, RESTController, AuthRequired from .. import mgr from ..services.ceph_service import CephService +from ..services.exception import handle_send_command_error @ApiController('pool') @@ -55,12 +56,17 @@ class Pool(RESTController): def get(self, pool_name, attrs=None, stats=False): pools = self.list(attrs, stats) - return [pool for pool in pools if pool['pool_name'] == pool_name][0] + pool = [pool for pool in pools if pool['pool_name'] == pool_name] + if not pool: + return cherrypy.NotFound('No such pool') + return pool[0] + @handle_send_command_error('pool') def delete(self, pool_name): return CephService.send_command('mon', 'osd pool delete', pool=pool_name, pool2=pool_name, sure='--yes-i-really-really-mean-it') + @handle_send_command_error('pool') def create(self, pool, pg_num, pool_type, erasure_code_profile=None, flags=None, application_metadata=None, rule_name=None, **kwargs): ecp = erasure_code_profile if erasure_code_profile else None diff --git a/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py b/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py index b90401e188549..c218a518f82ff 100644 --- a/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py +++ b/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py @@ -13,6 +13,7 @@ from . import ApiController, AuthRequired, BaseController from .. import logger, mgr from ..services.ceph_service import CephService from ..tools import ViewCache +from ..services.exception import handle_rbd_error @ViewCache() @@ -94,6 +95,7 @@ def get_daemons_and_pools(): # pylint: disable=R0915 mirror_mode = rbdctx.mirror_mode_get(ioctx) except: # noqa pylint: disable=W0702 logger.exception("Failed to query mirror mode %s", pool_name) + mirror_mode = None stats = {} if mirror_mode == rbd.RBD_MIRROR_MODE_DISABLED: @@ -163,6 +165,7 @@ class RbdMirror(BaseController): @cherrypy.expose @cherrypy.tools.json_out() + @handle_rbd_error() def __call__(self): status, content_data = self._get_content_data() return {'status': status, 'content_data': content_data} @@ -233,6 +236,7 @@ class RbdMirror(BaseController): pass except: # noqa pylint: disable=W0702 logger.exception("Failed to list mirror image status %s", pool_name) + raise return data @@ -250,9 +254,6 @@ class RbdMirror(BaseController): pool_names = [pool['pool_name'] for pool in CephService.get_pool_list('rbd')] _, data = get_daemons_and_pools() - if isinstance(data, Exception): - logger.exception("Failed to get rbd-mirror daemons list") - raise type(data)(str(data)) daemons = data.get('daemons', []) pool_stats = data.get('pools', {}) diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py index 249df76addf71..ae0de6305b100 100644 --- a/src/pybind/mgr/dashboard/controllers/rgw.py +++ b/src/pybind/mgr/dashboard/controllers/rgw.py @@ -46,7 +46,7 @@ class RgwDaemon(RESTController): } service = CephService.get_service('rgw', svc_id) if not service: - return daemon + raise cherrypy.NotFound('Service rgw {} is not available'.format(svc_id)) metadata = service['metadata'] status = service['status'] diff --git a/src/pybind/mgr/dashboard/controllers/summary.py b/src/pybind/mgr/dashboard/controllers/summary.py index c2b7c4f601543..da570ceae1e49 100644 --- a/src/pybind/mgr/dashboard/controllers/summary.py +++ b/src/pybind/mgr/dashboard/controllers/summary.py @@ -5,9 +5,10 @@ import json import cherrypy +from .. import mgr from . import AuthRequired, ApiController, BaseController -from .. import logger, mgr from ..controllers.rbd_mirroring import get_daemons_and_pools +from ..tools import ViewCacheNoDataException from ..services.ceph_service import CephService from ..tools import TaskManager @@ -34,14 +35,13 @@ class Summary(BaseController): ] def _rbd_mirroring(self): - _, data = get_daemons_and_pools() + try: + _, data = get_daemons_and_pools() + except ViewCacheNoDataException: + return {} - if isinstance(data, Exception): - logger.exception("Failed to get rbd-mirror daemons and pools") - raise type(data)(str(data)) - else: - daemons = data.get('daemons', []) - pools = data.get('pools', {}) + daemons = data.get('daemons', []) + pools = data.get('pools', {}) warnings = 0 errors = 0 -- 2.39.5