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