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