# -*- 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]