summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/dashboard/settings.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/pybind/mgr/dashboard/settings.py')
-rw-r--r--src/pybind/mgr/dashboard/settings.py201
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