]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/controllers/_task.py
import ceph 16.2.7
[ceph.git] / ceph / src / pybind / mgr / dashboard / controllers / _task.py
1 from functools import wraps
2
3 import cherrypy
4
5 from ..tools import TaskManager
6 from ._helpers import _get_function_params
7
8
9 class Task:
10 def __init__(self, name, metadata, wait_for=5.0, exception_handler=None):
11 self.name = name
12 if isinstance(metadata, list):
13 self.metadata = {e[1:-1]: e for e in metadata}
14 else:
15 self.metadata = metadata
16 self.wait_for = wait_for
17 self.exception_handler = exception_handler
18
19 def _gen_arg_map(self, func, args, kwargs):
20 arg_map = {}
21 params = _get_function_params(func)
22
23 args = args[1:] # exclude self
24 for idx, param in enumerate(params):
25 if idx < len(args):
26 arg_map[param['name']] = args[idx]
27 else:
28 if param['name'] in kwargs:
29 arg_map[param['name']] = kwargs[param['name']]
30 else:
31 assert not param['required'], "{0} is required".format(param['name'])
32 arg_map[param['name']] = param['default']
33
34 if param['name'] in arg_map:
35 # This is not a type error. We are using the index here.
36 arg_map[idx+1] = arg_map[param['name']]
37
38 return arg_map
39
40 def __call__(self, func):
41 @wraps(func)
42 def wrapper(*args, **kwargs):
43 arg_map = self._gen_arg_map(func, args, kwargs)
44 metadata = {}
45 for k, v in self.metadata.items():
46 if isinstance(v, str) and v and v[0] == '{' and v[-1] == '}':
47 param = v[1:-1]
48 try:
49 pos = int(param)
50 metadata[k] = arg_map[pos]
51 except ValueError:
52 if param.find('.') == -1:
53 metadata[k] = arg_map[param]
54 else:
55 path = param.split('.')
56 metadata[k] = arg_map[path[0]]
57 for i in range(1, len(path)):
58 metadata[k] = metadata[k][path[i]]
59 else:
60 metadata[k] = v
61 task = TaskManager.run(self.name, metadata, func, args, kwargs,
62 exception_handler=self.exception_handler)
63 try:
64 status, value = task.wait(self.wait_for)
65 except Exception as ex:
66 if task.ret_value:
67 # exception was handled by task.exception_handler
68 if 'status' in task.ret_value:
69 status = task.ret_value['status']
70 else:
71 status = getattr(ex, 'status', 500)
72 cherrypy.response.status = status
73 return task.ret_value
74 raise ex
75 if status == TaskManager.VALUE_EXECUTING:
76 cherrypy.response.status = 202
77 return {'name': self.name, 'metadata': metadata}
78 return value
79 return wrapper