diff options
Diffstat (limited to 'src/pybind/mgr/dashboard/plugins/motd.py')
-rw-r--r-- | src/pybind/mgr/dashboard/plugins/motd.py | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/plugins/motd.py b/src/pybind/mgr/dashboard/plugins/motd.py new file mode 100644 index 000000000..22d6a294a --- /dev/null +++ b/src/pybind/mgr/dashboard/plugins/motd.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- + +import hashlib +import json +from enum import Enum +from typing import Dict, NamedTuple, Optional + +from ceph.utils import datetime_now, datetime_to_str, parse_timedelta, str_to_datetime +from mgr_module import CLICommand + +from . import PLUGIN_MANAGER as PM +from .plugin import SimplePlugin as SP + + +class MotdSeverity(Enum): + INFO = 'info' + WARNING = 'warning' + DANGER = 'danger' + + +class MotdData(NamedTuple): + message: str + md5: str # The MD5 of the message. + severity: MotdSeverity + expires: str # The expiration date in ISO 8601. Does not expire if empty. + + +@PM.add_plugin # pylint: disable=too-many-ancestors +class Motd(SP): + NAME = 'motd' + + OPTIONS = [ + SP.Option( + name=NAME, + default='', + type='str', + desc='The message of the day' + ) + ] + + @PM.add_hook + def register_commands(self): + @CLICommand("dashboard {name} get".format(name=self.NAME)) + def _get(_): + stdout: str + value: str = self.get_option(self.NAME) + if not value: + stdout = 'No message of the day has been set.' + else: + data = json.loads(value) + if not data['expires']: + data['expires'] = "Never" + stdout = 'Message="{message}", severity="{severity}", ' \ + 'expires="{expires}"'.format(**data) + return 0, stdout, '' + + @CLICommand("dashboard {name} set".format(name=self.NAME)) + def _set(_, severity: MotdSeverity, expires: str, message: str): + if expires != '0': + delta = parse_timedelta(expires) + if not delta: + return 1, '', 'Invalid expires format, use "2h", "10d" or "30s"' + expires = datetime_to_str(datetime_now() + delta) + else: + expires = '' + value: str = json.dumps({ + 'message': message, + 'md5': hashlib.md5(message.encode()).hexdigest(), + 'severity': severity.value, + 'expires': expires + }) + self.set_option(self.NAME, value) + return 0, 'Message of the day has been set.', '' + + @CLICommand("dashboard {name} clear".format(name=self.NAME)) + def _clear(_): + self.set_option(self.NAME, '') + return 0, 'Message of the day has been cleared.', '' + + @PM.add_hook + def get_controllers(self): + from ..controllers import RESTController, UIRouter + + @UIRouter('/motd') + class MessageOfTheDay(RESTController): + def list(_) -> Optional[Dict]: # pylint: disable=no-self-argument + value: str = self.get_option(self.NAME) + if not value: + return None + data: MotdData = MotdData(**json.loads(value)) + # Check if the MOTD has been expired. + if data.expires: + expires = str_to_datetime(data.expires) + if expires < datetime_now(): + return None + return data._asdict() + + return [MessageOfTheDay] |