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