]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | # -*- coding: utf-8 -*- |
2 | from __future__ import absolute_import | |
3 | ||
f91f0fd5 TL |
4 | from . import ApiController, RESTController, \ |
5 | allow_empty_body | |
11fdf7f2 TL |
6 | from .. import mgr |
7 | from ..security import Scope | |
8 | from ..services.ceph_service import CephService | |
9 | from ..services.exception import handle_send_command_error | |
10 | from ..tools import find_object_in_list, str_to_bool | |
11 | ||
12 | ||
13 | @ApiController('/mgr/module', Scope.CONFIG_OPT) | |
14 | class MgrModules(RESTController): | |
15 | ignore_modules = ['selftest'] | |
16 | ||
17 | def list(self): | |
18 | """ | |
19 | Get the list of managed modules. | |
20 | :return: A list of objects with the fields 'enabled', 'name' and 'options'. | |
21 | :rtype: list | |
22 | """ | |
23 | result = [] | |
24 | mgr_map = mgr.get('mgr_map') | |
9f95a23c | 25 | always_on_modules = mgr_map['always_on_modules'].get(mgr.release_name, []) |
11fdf7f2 | 26 | for module_config in mgr_map['available_modules']: |
92f5a8d4 TL |
27 | module_name = module_config['name'] |
28 | if module_name not in self.ignore_modules: | |
29 | always_on = module_name in always_on_modules | |
30 | enabled = module_name in mgr_map['modules'] or always_on | |
11fdf7f2 | 31 | result.append({ |
92f5a8d4 TL |
32 | 'name': module_name, |
33 | 'enabled': enabled, | |
34 | 'always_on': always_on, | |
11fdf7f2 TL |
35 | 'options': self._convert_module_options( |
36 | module_config['module_options']) | |
37 | }) | |
11fdf7f2 TL |
38 | return result |
39 | ||
40 | def get(self, module_name): | |
41 | """ | |
42 | Retrieve the values of the persistent configuration settings. | |
43 | :param module_name: The name of the Ceph Mgr module. | |
44 | :type module_name: str | |
45 | :return: The values of the module options. | |
46 | :rtype: dict | |
47 | """ | |
48 | assert self._is_module_managed(module_name) | |
49 | options = self._get_module_options(module_name) | |
50 | result = {} | |
51 | for name, option in options.items(): | |
52 | result[name] = mgr.get_module_option_ex(module_name, name, | |
53 | option['default_value']) | |
54 | return result | |
55 | ||
56 | @RESTController.Resource('PUT') | |
57 | def set(self, module_name, config): | |
58 | """ | |
59 | Set the values of the persistent configuration settings. | |
60 | :param module_name: The name of the Ceph Mgr module. | |
61 | :type module_name: str | |
62 | :param config: The values of the module options to be stored. | |
63 | :type config: dict | |
64 | """ | |
65 | assert self._is_module_managed(module_name) | |
66 | options = self._get_module_options(module_name) | |
67 | for name in options.keys(): | |
68 | if name in config: | |
69 | mgr.set_module_option_ex(module_name, name, config[name]) | |
70 | ||
71 | @RESTController.Resource('POST') | |
72 | @handle_send_command_error('mgr_modules') | |
f91f0fd5 | 73 | @allow_empty_body |
11fdf7f2 TL |
74 | def enable(self, module_name): |
75 | """ | |
76 | Enable the specified Ceph Mgr module. | |
77 | :param module_name: The name of the Ceph Mgr module. | |
78 | :type module_name: str | |
79 | """ | |
80 | assert self._is_module_managed(module_name) | |
81 | CephService.send_command( | |
82 | 'mon', 'mgr module enable', module=module_name) | |
83 | ||
84 | @RESTController.Resource('POST') | |
85 | @handle_send_command_error('mgr_modules') | |
f91f0fd5 | 86 | @allow_empty_body |
11fdf7f2 TL |
87 | def disable(self, module_name): |
88 | """ | |
89 | Disable the specified Ceph Mgr module. | |
90 | :param module_name: The name of the Ceph Mgr module. | |
91 | :type module_name: str | |
92 | """ | |
93 | assert self._is_module_managed(module_name) | |
94 | CephService.send_command( | |
95 | 'mon', 'mgr module disable', module=module_name) | |
96 | ||
97 | @RESTController.Resource('GET') | |
98 | def options(self, module_name): | |
99 | """ | |
100 | Get the module options of the specified Ceph Mgr module. | |
101 | :param module_name: The name of the Ceph Mgr module. | |
102 | :type module_name: str | |
103 | :return: The module options as list of dicts. | |
104 | :rtype: list | |
105 | """ | |
106 | assert self._is_module_managed(module_name) | |
107 | return self._get_module_options(module_name) | |
108 | ||
109 | def _is_module_managed(self, module_name): | |
110 | """ | |
111 | Check if the specified Ceph Mgr module is managed by this service. | |
112 | :param module_name: The name of the Ceph Mgr module. | |
113 | :type module_name: str | |
114 | :return: Returns ``true`` if the Ceph Mgr module is managed by | |
115 | this service, otherwise ``false``. | |
116 | :rtype: bool | |
117 | """ | |
118 | if module_name in self.ignore_modules: | |
119 | return False | |
120 | mgr_map = mgr.get('mgr_map') | |
121 | for module_config in mgr_map['available_modules']: | |
122 | if module_name == module_config['name']: | |
123 | return True | |
124 | return False | |
125 | ||
126 | def _get_module_config(self, module_name): | |
127 | """ | |
128 | Helper function to get detailed module configuration. | |
129 | :param module_name: The name of the Ceph Mgr module. | |
130 | :type module_name: str | |
131 | :return: The module information, e.g. module name, can run, | |
132 | error string and available module options. | |
133 | :rtype: dict or None | |
134 | """ | |
135 | mgr_map = mgr.get('mgr_map') | |
136 | return find_object_in_list('name', module_name, | |
137 | mgr_map['available_modules']) | |
138 | ||
139 | def _get_module_options(self, module_name): | |
140 | """ | |
141 | Helper function to get the module options. | |
142 | :param module_name: The name of the Ceph Mgr module. | |
143 | :type module_name: str | |
144 | :return: The module options. | |
145 | :rtype: dict | |
146 | """ | |
147 | options = self._get_module_config(module_name)['module_options'] | |
148 | return self._convert_module_options(options) | |
149 | ||
150 | def _convert_module_options(self, options): | |
151 | # Workaround a possible bug in the Ceph Mgr implementation. | |
152 | # Various fields (e.g. default_value, min, max) are always | |
153 | # returned as a string. | |
154 | for option in options.values(): | |
155 | if option['type'] == 'str': | |
156 | if option['default_value'] == 'None': # This is Python None | |
157 | option['default_value'] = '' | |
158 | elif option['type'] == 'bool': | |
159 | if option['default_value'] == '': | |
160 | option['default_value'] = False | |
161 | else: | |
162 | option['default_value'] = str_to_bool( | |
163 | option['default_value']) | |
f6b5b4d7 TL |
164 | elif option['type'] in ['float', 'uint', 'int', 'size', 'secs']: |
165 | cls = { | |
166 | 'float': float | |
167 | }.get(option['type'], int) | |
11fdf7f2 | 168 | for name in ['default_value', 'min', 'max']: |
f6b5b4d7 TL |
169 | if option[name] == 'None': # This is Python None |
170 | option[name] = None | |
171 | elif option[name]: # Skip empty entries | |
172 | option[name] = cls(option[name]) | |
11fdf7f2 | 173 | return options |