]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | # -*- coding: utf-8 -*- |
11fdf7f2 TL |
2 | |
3 | import json | |
9f95a23c | 4 | import logging |
f67539c2 | 5 | from contextlib import contextmanager |
11fdf7f2 | 6 | |
20effc67 | 7 | import cephfs |
11fdf7f2 | 8 | import cherrypy |
11fdf7f2 | 9 | import rados |
f67539c2 TL |
10 | import rbd |
11 | from orchestrator import OrchestratorError | |
11fdf7f2 | 12 | |
f67539c2 | 13 | from ..exceptions import DashboardException, ViewCacheNoDataException |
20effc67 | 14 | from ..rest_client import RequestException |
11fdf7f2 | 15 | from ..services.ceph_service import SendCommandError |
9f95a23c TL |
16 | |
17 | logger = logging.getLogger('exception') | |
18 | ||
19 | ||
11fdf7f2 TL |
20 | def serialize_dashboard_exception(e, include_http_status=False, task=None): |
21 | """ | |
22 | :type e: Exception | |
23 | :param include_http_status: Used for Tasks, where the HTTP status code is not available. | |
24 | """ | |
25 | from ..tools import ViewCache | |
26 | if isinstance(e, ViewCacheNoDataException): | |
27 | return {'status': ViewCache.VALUE_NONE, 'value': None} | |
28 | ||
29 | out = dict(detail=str(e)) | |
30 | try: | |
31 | out['code'] = e.code | |
32 | except AttributeError: | |
33 | pass | |
34 | component = getattr(e, 'component', None) | |
35 | out['component'] = component if component else None | |
36 | if include_http_status: | |
1e59de90 | 37 | out['status'] = getattr(e, 'status', 500) # type: ignore |
11fdf7f2 | 38 | if task: |
9f95a23c | 39 | out['task'] = dict(name=task.name, metadata=task.metadata) # type: ignore |
11fdf7f2 TL |
40 | return out |
41 | ||
42 | ||
f67539c2 | 43 | # pylint: disable=broad-except |
11fdf7f2 TL |
44 | def dashboard_exception_handler(handler, *args, **kwargs): |
45 | try: | |
46 | with handle_rados_error(component=None): # make the None controller the fallback. | |
47 | return handler(*args, **kwargs) | |
2a845540 TL |
48 | # pylint: disable=try-except-raise |
49 | except (cherrypy.HTTPRedirect, cherrypy.NotFound, cherrypy.HTTPError): | |
50 | raise | |
f67539c2 | 51 | except (ViewCacheNoDataException, DashboardException) as error: |
9f95a23c | 52 | logger.exception('Dashboard Exception') |
11fdf7f2 | 53 | cherrypy.response.headers['Content-Type'] = 'application/json' |
f67539c2 TL |
54 | cherrypy.response.status = getattr(error, 'status', 400) |
55 | return json.dumps(serialize_dashboard_exception(error)).encode('utf-8') | |
56 | except Exception as error: | |
57 | logger.exception('Internal Server Error') | |
58 | raise error | |
11fdf7f2 TL |
59 | |
60 | ||
20effc67 TL |
61 | @contextmanager |
62 | def handle_cephfs_error(): | |
63 | try: | |
64 | yield | |
65 | except cephfs.OSError as e: | |
66 | raise DashboardException(e, component='cephfs') from e | |
67 | ||
68 | ||
11fdf7f2 TL |
69 | @contextmanager |
70 | def handle_rbd_error(): | |
71 | try: | |
72 | yield | |
73 | except rbd.OSError as e: | |
74 | raise DashboardException(e, component='rbd') | |
75 | except rbd.Error as e: | |
76 | raise DashboardException(e, component='rbd', code=e.__class__.__name__) | |
77 | ||
78 | ||
79 | @contextmanager | |
80 | def handle_rados_error(component): | |
81 | try: | |
82 | yield | |
83 | except rados.OSError as e: | |
84 | raise DashboardException(e, component=component) | |
85 | except rados.Error as e: | |
86 | raise DashboardException(e, component=component, code=e.__class__.__name__) | |
87 | ||
88 | ||
89 | @contextmanager | |
90 | def handle_send_command_error(component): | |
91 | try: | |
92 | yield | |
93 | except SendCommandError as e: | |
94 | raise DashboardException(e, component=component) | |
9f95a23c TL |
95 | |
96 | ||
97 | @contextmanager | |
98 | def handle_orchestrator_error(component): | |
99 | try: | |
100 | yield | |
101 | except OrchestratorError as e: | |
102 | raise DashboardException(e, component=component) | |
20effc67 TL |
103 | |
104 | ||
105 | @contextmanager | |
106 | def handle_request_error(component): | |
107 | try: | |
108 | yield | |
109 | except RequestException as e: | |
110 | if e.content: | |
111 | content = json.loads(e.content) | |
112 | content_message = content.get('message') | |
113 | if content_message: | |
114 | raise DashboardException( | |
115 | msg=content_message, component=component) | |
116 | raise DashboardException(e=e, component=component) | |
33c7a0ef TL |
117 | |
118 | ||
119 | @contextmanager | |
120 | def handle_error(component, http_status_code=None): | |
121 | try: | |
122 | yield | |
123 | except Exception as e: # pylint: disable=broad-except | |
124 | raise DashboardException(e, component=component, http_status_code=http_status_code) | |
2a845540 TL |
125 | |
126 | ||
127 | @contextmanager | |
128 | def handle_custom_error(component, http_status_code=None, exceptions=()): | |
129 | try: | |
130 | yield | |
131 | except exceptions as e: | |
132 | raise DashboardException(e, component=component, http_status_code=http_status_code) |