diff options
Diffstat (limited to '')
-rw-r--r-- | src/pybind/mgr/dashboard/settings.py | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/settings.py b/src/pybind/mgr/dashboard/settings.py new file mode 100644 index 00000000..95b1cdf4 --- /dev/null +++ b/src/pybind/mgr/dashboard/settings.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +import errno +import inspect +from six import add_metaclass + +from mgr_module import CLICheckNonemptyFileInput + +from . import mgr + + +class Options(object): + """ + If you need to store some configuration value please add the config option + name as a class attribute to this class. + + Example:: + + GRAFANA_API_HOST = ('localhost', str) + GRAFANA_API_PORT = (3000, int) + """ + ENABLE_BROWSABLE_API = (True, bool) + REST_REQUESTS_TIMEOUT = (45, int) + + # API auditing + AUDIT_API_ENABLED = (False, bool) + AUDIT_API_LOG_PAYLOAD = (True, bool) + + # RGW settings + RGW_API_HOST = ('', str) + RGW_API_PORT = (80, int) + RGW_API_ACCESS_KEY = ('', str) + RGW_API_SECRET_KEY = ('', str) + RGW_API_ADMIN_RESOURCE = ('admin', str) + RGW_API_SCHEME = ('http', str) + RGW_API_USER_ID = ('', str) + RGW_API_SSL_VERIFY = (True, bool) + + # Grafana settings + GRAFANA_API_URL = ('', str) + GRAFANA_FRONTEND_API_URL = ('', str) + GRAFANA_API_USERNAME = ('admin', str) + GRAFANA_API_PASSWORD = ('admin', str) + GRAFANA_API_SSL_VERIFY = (True, bool) + GRAFANA_UPDATE_DASHBOARDS = (False, bool) + + # NFS Ganesha settings + GANESHA_CLUSTERS_RADOS_POOL_NAMESPACE = ('', str) + + # Prometheus settings + PROMETHEUS_API_HOST = ('', str) + ALERTMANAGER_API_HOST = ('', str) + + # iSCSI management settings + ISCSI_API_SSL_VERIFICATION = (True, bool) + + @staticmethod + def has_default_value(name): + return getattr(Settings, name, None) is None or \ + getattr(Settings, name) == getattr(Options, name)[0] + + +class SettingsMeta(type): + def __getattr__(cls, attr): + default, stype = getattr(Options, attr) + if stype == bool and str(mgr.get_module_option( + attr, + default)).lower() == 'false': + value = False + else: + value = stype(mgr.get_module_option(attr, default)) + return value + + def __setattr__(cls, attr, value): + if not attr.startswith('_') and hasattr(Options, attr): + mgr.set_module_option(attr, str(value)) + else: + setattr(SettingsMeta, attr, value) + + def __delattr__(cls, attr): + if not attr.startswith('_') and hasattr(Options, attr): + mgr.set_module_option(attr, None) + + +# pylint: disable=no-init +@add_metaclass(SettingsMeta) +class Settings(object): + pass + + +def _options_command_map(): + def filter_attr(member): + return not inspect.isroutine(member) + + cmd_map = {} + for option, value in inspect.getmembers(Options, filter_attr): + if option.startswith('_'): + continue + key_get = 'dashboard get-{}'.format(option.lower().replace('_', '-')) + key_set = 'dashboard set-{}'.format(option.lower().replace('_', '-')) + key_reset = 'dashboard reset-{}'.format(option.lower().replace('_', '-')) + cmd_map[key_get] = {'name': option, 'type': None} + cmd_map[key_set] = {'name': option, 'type': value[1]} + cmd_map[key_reset] = {'name': option, 'type': None} + return cmd_map + + +_OPTIONS_COMMAND_MAP = _options_command_map() + + +def options_command_list(): + """ + This function generates a list of ``get`` and ``set`` commands + for each declared configuration option in class ``Options``. + """ + def py2ceph(pytype): + if pytype == str: + return 'CephString' + elif pytype == int: + return 'CephInt' + return 'CephString' + + cmd_list = [] + for cmd, opt in _OPTIONS_COMMAND_MAP.items(): + if cmd.startswith('dashboard get'): + cmd_list.append({ + 'cmd': '{}'.format(cmd), + 'desc': 'Get the {} option value'.format(opt['name']), + 'perm': 'r' + }) + elif cmd.startswith('dashboard set'): + cmd_entry = { + 'cmd': '{} name=value,type={}' + .format(cmd, py2ceph(opt['type'])), + 'desc': 'Set the {} option value'.format(opt['name']), + 'perm': 'w' + } + if handles_secret(cmd): + cmd_entry['cmd'] = cmd + cmd_entry['desc'] = '{} read from -i <file>'.format(cmd_entry['desc']) + cmd_list.append(cmd_entry) + elif cmd.startswith('dashboard reset'): + desc = 'Reset the {} option to its default value'.format( + opt['name']) + cmd_list.append({ + 'cmd': '{}'.format(cmd), + 'desc': desc, + 'perm': 'w' + }) + + return cmd_list + + +def options_schema_list(): + def filter_attr(member): + return not inspect.isroutine(member) + + result = [] + for option, value in inspect.getmembers(Options, filter_attr): + if option.startswith('_'): + continue + result.append({'name': option, 'default': value[0], + 'type': value[1].__name__}) + + return result + + +def handle_option_command(cmd, inbuf): + if cmd['prefix'] not in _OPTIONS_COMMAND_MAP: + return -errno.ENOSYS, '', "Command not found '{}'".format(cmd['prefix']) + + opt = _OPTIONS_COMMAND_MAP[cmd['prefix']] + + if cmd['prefix'].startswith('dashboard reset'): + delattr(Settings, opt['name']) + return 0, 'Option {} reset to default value "{}"'.format( + opt['name'], getattr(Settings, opt['name'])), '' + elif cmd['prefix'].startswith('dashboard get'): + return 0, str(getattr(Settings, opt['name'])), '' + elif cmd['prefix'].startswith('dashboard set'): + if handles_secret(cmd['prefix']): + value, stdout, stderr = get_secret(inbuf=inbuf) + if stderr: + return value, stdout, stderr + else: + value = cmd['value'] + value = opt['type'](value) + if opt['type'] == bool and cmd['value'].lower() == 'false': + value = False + setattr(Settings, opt['name'], value) + return 0, 'Option {} updated'.format(opt['name']), '' + + +def handles_secret(cmd): + return bool([cmd for secret_word in ['password', 'key'] if (secret_word in cmd)]) + + +@CLICheckNonemptyFileInput +def get_secret(inbuf=None): + return inbuf, None, None |