import logging from tfw.networking import Scope from tfw.components import BashMonitor from tfw.components.terminado_mini_server import TerminadoMiniServer from tfw.config import TFWENV from tao.config import TAOENV from .event_handler import EventHandler LOG = logging.getLogger(__name__) class TerminalEventHandler(EventHandler): """ Event handler responsible for managing terminal sessions for frontend xterm sessions to connect to. You need to instanciate this in order for frontend terminals to work. This EventHandler accepts messages that have a data['command'] key specifying a command to be executed. The API of each command is documented in their respective handler. """ def __init__(self, key): """ :param key: key this EventHandler listens to :param monitor: tfw.components.HistoryMonitor instance to read command history from """ super().__init__(key, scope=Scope.WEBSOCKET) self._historymonitor = BashMonitor(self.server_connector, TFWENV.HISTFILE) bash_as_user_cmd = ['sudo', '-u', TAOENV.USER, 'bash'] self.terminado_server = TerminadoMiniServer( '/terminal', TFWENV.TERMINADO_PORT, TFWENV.TERMINADO_WD, bash_as_user_cmd ) self.commands = { 'write': self.write, 'read': self.read } self._historymonitor.start() self.terminado_server.listen() @property def historymonitor(self): return self._historymonitor def handle_event(self, message): try: data = message['data'] message['data'] = self.commands[data['command']](data) self.send_message(message) except KeyError: LOG.error('IGNORING MESSAGE: Invalid message received: %s', message) def write(self, data): """ Writes a string to the terminal session (on the pty level). Useful for pre-typing and executing commands for the user. :param data: TFW message data containing 'value' (command to be written to the pty) """ self.terminado_server.pty.write(data['value']) return data def read(self, data): """ Reads the history of commands executed. :param data: TFW message data containing 'count' (the number of history elements to return) :return dict: message with list of commands in data['history'] """ data['count'] = int(data.get('count', 1)) if self.historymonitor: data['history'] = self.historymonitor.history[-data['count']:] return data def cleanup(self): self.terminado_server.stop() self.historymonitor.stop()