summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/dashboard/controllers/mgr_modules.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/pybind/mgr/dashboard/controllers/mgr_modules.py
parentInitial commit. (diff)
downloadceph-upstream/18.2.2.tar.xz
ceph-upstream/18.2.2.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/pybind/mgr/dashboard/controllers/mgr_modules.py')
-rw-r--r--src/pybind/mgr/dashboard/controllers/mgr_modules.py196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/controllers/mgr_modules.py b/src/pybind/mgr/dashboard/controllers/mgr_modules.py
new file mode 100644
index 000000000..57bb9b5ff
--- /dev/null
+++ b/src/pybind/mgr/dashboard/controllers/mgr_modules.py
@@ -0,0 +1,196 @@
+# -*- coding: utf-8 -*-
+
+from .. import mgr
+from ..security import Scope
+from ..services.ceph_service import CephService
+from ..services.exception import handle_send_command_error
+from ..tools import find_object_in_list, str_to_bool
+from . import APIDoc, APIRouter, EndpointDoc, RESTController, allow_empty_body
+
+MGR_MODULE_SCHEMA = ([{
+ "name": (str, "Module Name"),
+ "enabled": (bool, "Is Module Enabled"),
+ "always_on": (bool, "Is it an always on module?"),
+ "options": ({
+ "Option_name": ({
+ "name": (str, "Name of the option"),
+ "type": (str, "Type of the option"),
+ "level": (str, "Option level"),
+ "flags": (int, "List of flags associated"),
+ "default_value": (int, "Default value for the option"),
+ "min": (str, "Minimum value"),
+ "max": (str, "Maximum value"),
+ "enum_allowed": ([str], ""),
+ "desc": (str, "Description of the option"),
+ "long_desc": (str, "Elaborated description"),
+ "tags": ([str], "Tags associated with the option"),
+ "see_also": ([str], "Related options")
+ }, "Options")
+ }, "Module Options")
+}])
+
+
+@APIRouter('/mgr/module', Scope.CONFIG_OPT)
+@APIDoc("Get details of MGR Module", "MgrModule")
+class MgrModules(RESTController):
+ ignore_modules = ['selftest']
+
+ @EndpointDoc("List Mgr modules",
+ responses={200: MGR_MODULE_SCHEMA})
+ def list(self):
+ """
+ Get the list of managed modules.
+ :return: A list of objects with the fields 'enabled', 'name' and 'options'.
+ :rtype: list
+ """
+ result = []
+ mgr_map = mgr.get('mgr_map')
+ always_on_modules = mgr_map['always_on_modules'].get(mgr.release_name, [])
+ for module_config in mgr_map['available_modules']:
+ module_name = module_config['name']
+ if module_name not in self.ignore_modules:
+ always_on = module_name in always_on_modules
+ enabled = module_name in mgr_map['modules'] or always_on
+ result.append({
+ 'name': module_name,
+ 'enabled': enabled,
+ 'always_on': always_on,
+ 'options': self._convert_module_options(
+ module_config['module_options'])
+ })
+ return result
+
+ def get(self, module_name):
+ """
+ Retrieve the values of the persistent configuration settings.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: The values of the module options.
+ :rtype: dict
+ """
+ assert self._is_module_managed(module_name)
+ options = self._get_module_options(module_name)
+ result = {}
+ for name, option in options.items():
+ result[name] = mgr.get_module_option_ex(module_name, name,
+ option['default_value'])
+ return result
+
+ @RESTController.Resource('PUT')
+ def set(self, module_name, config):
+ """
+ Set the values of the persistent configuration settings.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :param config: The values of the module options to be stored.
+ :type config: dict
+ """
+ assert self._is_module_managed(module_name)
+ options = self._get_module_options(module_name)
+ for name in options.keys():
+ if name in config:
+ mgr.set_module_option_ex(module_name, name, config[name])
+
+ @RESTController.Resource('POST')
+ @handle_send_command_error('mgr_modules')
+ @allow_empty_body
+ def enable(self, module_name):
+ """
+ Enable the specified Ceph Mgr module.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ """
+ assert self._is_module_managed(module_name)
+ CephService.send_command(
+ 'mon', 'mgr module enable', module=module_name)
+
+ @RESTController.Resource('POST')
+ @handle_send_command_error('mgr_modules')
+ @allow_empty_body
+ def disable(self, module_name):
+ """
+ Disable the specified Ceph Mgr module.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ """
+ assert self._is_module_managed(module_name)
+ CephService.send_command(
+ 'mon', 'mgr module disable', module=module_name)
+
+ @RESTController.Resource('GET')
+ def options(self, module_name):
+ """
+ Get the module options of the specified Ceph Mgr module.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: The module options as list of dicts.
+ :rtype: list
+ """
+ assert self._is_module_managed(module_name)
+ return self._get_module_options(module_name)
+
+ def _is_module_managed(self, module_name):
+ """
+ Check if the specified Ceph Mgr module is managed by this service.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: Returns ``true`` if the Ceph Mgr module is managed by
+ this service, otherwise ``false``.
+ :rtype: bool
+ """
+ if module_name in self.ignore_modules:
+ return False
+ mgr_map = mgr.get('mgr_map')
+ for module_config in mgr_map['available_modules']:
+ if module_name == module_config['name']:
+ return True
+ return False
+
+ def _get_module_config(self, module_name):
+ """
+ Helper function to get detailed module configuration.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: The module information, e.g. module name, can run,
+ error string and available module options.
+ :rtype: dict or None
+ """
+ mgr_map = mgr.get('mgr_map')
+ return find_object_in_list('name', module_name,
+ mgr_map['available_modules'])
+
+ def _get_module_options(self, module_name):
+ """
+ Helper function to get the module options.
+ :param module_name: The name of the Ceph Mgr module.
+ :type module_name: str
+ :return: The module options.
+ :rtype: dict
+ """
+ options = self._get_module_config(module_name)['module_options']
+ return self._convert_module_options(options)
+
+ def _convert_module_options(self, options):
+ # Workaround a possible bug in the Ceph Mgr implementation.
+ # Various fields (e.g. default_value, min, max) are always
+ # returned as a string.
+ for option in options.values():
+ if option['type'] == 'str':
+ if option['default_value'] == 'None': # This is Python None
+ option['default_value'] = ''
+ elif option['type'] == 'bool':
+ if option['default_value'] == '':
+ option['default_value'] = False
+ else:
+ option['default_value'] = str_to_bool(
+ option['default_value'])
+ elif option['type'] in ['float', 'uint', 'int', 'size', 'secs']:
+ cls = {
+ 'float': float
+ }.get(option['type'], int)
+ for name in ['default_value', 'min', 'max']:
+ if option[name] == 'None': # This is Python None
+ option[name] = None
+ elif option[name]: # Skip empty entries
+ option[name] = cls(option[name])
+ return options