]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Add task info to exception result
authorSebastian Wagner <sebastian.wagner@suse.com>
Thu, 3 May 2018 14:41:34 +0000 (16:41 +0200)
committerSebastian Wagner <sebastian.wagner@suse.com>
Tue, 8 May 2018 14:38:59 +0000 (16:38 +0200)
Signed-off-by: Sebastian Wagner <sebastian.wagner@suse.com>
src/pybind/mgr/dashboard/services/exception.py
src/pybind/mgr/dashboard/tests/test_exceptions.py
src/pybind/mgr/dashboard/tests/test_task.py
src/pybind/mgr/dashboard/tools.py

index 93dff9a84cfb2be2104b869a9b5363611ef0056a..b5c0bd58a17f45a2c4875113e26e658337082bb3 100644 (file)
@@ -59,9 +59,12 @@ if sys.version_info < (3, 0):
         return helper
 
 
-def serialize_dashboard_exception(e):
+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
-    cherrypy.response.status = getattr(e, 'status', 400)
     if isinstance(e, ViewCacheNoDataException):
         return {'status': ViewCache.VALUE_NONE, 'value': None}
 
@@ -72,6 +75,10 @@ def serialize_dashboard_exception(e):
         pass
     component = getattr(e, 'component', None)
     out['component'] = component if component else None
+    if include_http_status:
+        out['status'] = getattr(e, 'status', 500)
+    if task:
+        out['task'] = dict(name=task.name, metadata=task.metadata)
     return out
 
 
@@ -83,6 +90,7 @@ def dashboard_exception_handler(handler, *args, **kwargs):
     except (ViewCacheNoDataException, DashboardException) as e:
         logger.exception('dashboard_exception_handler')
         cherrypy.response.headers['Content-Type'] = 'application/json'
+        cherrypy.response.status = getattr(e, 'status', 400)
         return json.dumps(serialize_dashboard_exception(e)).encode('utf-8')
 
 
index 78472022a4c18e74ffbdfd9608a3175eebe4da2e..a60ceaa7f09fb856dc6a5874d06f06f3c78a7e57 100644 (file)
@@ -73,7 +73,7 @@ class FooResource(RESTController):
 
     @cherrypy.expose
     @cherrypy.tools.json_out()
-    @Task('task_exceptions/task_exception', {}, 1.0,
+    @Task('task_exceptions/task_exception', {1: 2}, 1.0,
           exception_handler=serialize_dashboard_exception)
     @handle_rados_error('foo')
     def task_exception(self):
@@ -152,7 +152,8 @@ class RESTControllerTest(ControllerTestCase):
         self._get('/foo/task_exception')
         self.assertStatus(400)
         self.assertJsonBody(
-            {'detail': '[errno -42] hi', 'code': "42", 'component': 'foo'}
+            {'detail': '[errno -42] hi', 'code': "42", 'component': 'foo',
+             'task': {'name': 'task_exceptions/task_exception', 'metadata': {'1': 2}}}
         )
 
         self._get('/foo/wait_task_exception')
index 872deb6fa1ee38589b9d9a89549d1ccd094a8f64..c10af640bc2f52999164832e5cb6d23da5089cbd 100644 (file)
@@ -6,7 +6,9 @@ import unittest
 import threading
 import time
 from collections import defaultdict
+from functools import partial
 
+from ..services.exception import serialize_dashboard_exception
 from ..tools import NotificationQueue, TaskManager, TaskExecutor
 
 
@@ -41,13 +43,11 @@ class MyTask(object):
         self.handle_ex = handle_ex
         self._event = threading.Event()
 
-    def _handle_exception(self, ex):
-        return {'status': 409, 'detail': str(ex)}
-
     def run(self, ns, timeout=None):
         args = ['dummy arg']
         kwargs = {'dummy': 'arg'}
-        h_ex = self._handle_exception if self.handle_ex else None
+        h_ex = partial(serialize_dashboard_exception,
+                       include_http_status=True) if self.handle_ex else None
         if not self.is_async:
             task = TaskManager.run(
                 ns, self.metadata(), self.task_op, args, kwargs,
@@ -416,6 +416,18 @@ class TaskTest(unittest.TestCase):
         self.assertEqual(fn_t[0]['progress'], 50)
         self.assertFalse(fn_t[0]['success'])
         self.assertIsNotNone(fn_t[0]['exception'])
-        self.assertEqual(fn_t[0]['exception'],
-                         {"status": 409,
-                          "detail": "Task Unexpected Exception"})
+        self.assertEqual(fn_t[0]['exception'], {
+            'component': None,
+            'detail': 'Task Unexpected Exception',
+            'status': 500,
+            'task': {
+                'metadata': {
+                    'fail': True,
+                    'handle_ex': True,
+                    'is_async': False,
+                    'op_seconds': 1,
+                    'progress': 50,
+                    'wait': False},
+                'name': 'test15/task1'
+            }
+        })
index 8e8e536288e71fe8682e96ff2a9a51e313f1a40d..890a9c6129b75c26b4c118427c51588ff4d9260b 100644 (file)
@@ -602,7 +602,7 @@ class Task(object):
         if exception and self.ex_handler:
             # pylint: disable=broad-except
             try:
-                ret_value = self.ex_handler(exception)
+                ret_value = self.ex_handler(exception, task=self)
             except Exception as ex:
                 exception = ex
         with self.lock: