2019-06-10 13:35:09 +00:00
|
|
|
import logging
|
2018-05-26 20:53:02 +00:00
|
|
|
from ast import literal_eval
|
2018-06-29 20:08:05 +00:00
|
|
|
from functools import partial
|
2019-05-02 13:07:13 +00:00
|
|
|
from signal import signal, SIGTERM, SIGINT
|
2018-05-26 20:53:02 +00:00
|
|
|
|
2018-03-23 14:27:42 +00:00
|
|
|
from tornado.ioloop import IOLoop
|
|
|
|
|
2018-07-26 12:00:24 +00:00
|
|
|
from tfw.fsm import YamlFSM
|
2019-06-04 11:59:32 +00:00
|
|
|
from tfw.event_handlers import EventHandlerBase, FSMAwareEventHandler, TFWServerUplinkConnector
|
2018-06-04 19:56:59 +00:00
|
|
|
from tfw.components import IdeEventHandler, TerminalEventHandler
|
|
|
|
from tfw.components import ProcessManagingEventHandler, BashMonitor
|
2018-05-30 11:15:13 +00:00
|
|
|
from tfw.components import TerminalCommands, LogMonitoringEventHandler
|
2018-08-07 15:03:41 +00:00
|
|
|
from tfw.components import FSMManagingEventHandler, DirectorySnapshottingEventHandler
|
2019-06-04 11:59:32 +00:00
|
|
|
from tfw.components import FrontendEventHandler, MessageSender
|
2018-03-25 14:34:31 +00:00
|
|
|
from tfw.config import TFWENV
|
2018-04-12 09:08:58 +00:00
|
|
|
from tao.config import TAOENV
|
2018-03-31 22:45:15 +00:00
|
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
2019-06-10 13:35:09 +00:00
|
|
|
logging.basicConfig(level=logging.DEBUG)
|
2018-03-23 14:27:42 +00:00
|
|
|
|
|
|
|
|
2019-06-11 15:27:37 +00:00
|
|
|
class TerminalCallbackEventHandler(EventHandlerBase):
|
2018-05-31 12:19:47 +00:00
|
|
|
"""
|
2019-06-11 15:27:37 +00:00
|
|
|
Logs commands executed in terminal to messages and invokes an
|
|
|
|
additional callback function to handle special commands.
|
2018-05-31 12:19:47 +00:00
|
|
|
!! Please remove from production code. !!
|
|
|
|
"""
|
2019-06-11 15:27:37 +00:00
|
|
|
def __init__(self, key, callback):
|
|
|
|
self.callback = callback
|
|
|
|
super().__init__(key)
|
|
|
|
|
|
|
|
def handle_event(self, message):
|
|
|
|
command = message['value']
|
|
|
|
self.cenator(command)
|
|
|
|
self.callback(command)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def cenator(command):
|
|
|
|
LOG.debug('User executed command: "%s"', command)
|
|
|
|
MessageSender().send('JOHN CENA', f'You\'ve executed "{command}"')
|
2018-03-27 14:04:33 +00:00
|
|
|
|
|
|
|
|
2018-04-12 08:55:33 +00:00
|
|
|
class TestCommands(TerminalCommands):
|
2018-05-26 20:53:02 +00:00
|
|
|
"""
|
|
|
|
Some example commands useful for debugging.
|
2018-05-31 12:19:47 +00:00
|
|
|
!! Please remove from production code !! and inherit your own
|
2018-05-26 20:53:02 +00:00
|
|
|
class from TerminalCommands if you need to define custom
|
|
|
|
commands in your challenge.
|
|
|
|
"""
|
2018-04-18 18:45:17 +00:00
|
|
|
# pylint: disable=unused-argument, attribute-defined-outside-init, no-self-use
|
2018-05-26 20:53:02 +00:00
|
|
|
def command_sendmessage(self, *args):
|
|
|
|
"""
|
|
|
|
Insert TFW message template as first argument if executed without args.
|
2018-04-11 15:34:44 +00:00
|
|
|
|
2018-05-26 20:53:02 +00:00
|
|
|
Evaluate first argumen as a dict and send it to the frontend.
|
|
|
|
This is useful for playing around with frontend APIs.
|
|
|
|
"""
|
|
|
|
if not args:
|
|
|
|
message_template = """'{"key": "", "data": {"command": ""}}'"""
|
2019-06-04 11:59:32 +00:00
|
|
|
TFWServerUplinkConnector().send_message({
|
2018-05-26 20:53:02 +00:00
|
|
|
'key': 'shell',
|
|
|
|
'data': {
|
|
|
|
'command': 'write',
|
2018-05-31 12:20:08 +00:00
|
|
|
'value': f'sendmessage {message_template}'
|
2018-05-26 20:53:02 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
else:
|
2019-06-04 11:59:32 +00:00
|
|
|
TFWServerUplinkConnector().send_message(literal_eval(args[0]))
|
2018-03-27 14:04:33 +00:00
|
|
|
|
2018-04-19 14:23:46 +00:00
|
|
|
def command_seppuku_tfw(self, *args):
|
2018-05-26 20:53:02 +00:00
|
|
|
"""
|
|
|
|
Restart tfw_server.py and event_handler_main.py.
|
|
|
|
This can speed up development when combined with mounting
|
|
|
|
volumes from host to container.
|
|
|
|
"""
|
2018-06-04 19:56:59 +00:00
|
|
|
seppuku = (
|
|
|
|
'nohup sh -c "supervisorctl restart tfwserver event_handler_main" &> /dev/null & '
|
|
|
|
'clear && echo "Committed seppuku! :)" && sleep infinity'
|
|
|
|
)
|
2019-06-04 11:59:32 +00:00
|
|
|
uplink = TFWServerUplinkConnector()
|
2019-05-26 16:31:16 +00:00
|
|
|
uplink.send_message({
|
2018-05-26 20:53:02 +00:00
|
|
|
'key': 'shell',
|
|
|
|
'data': {
|
|
|
|
'command': 'write',
|
2018-05-31 12:20:08 +00:00
|
|
|
'value': f'{seppuku}\n'
|
2018-05-26 20:53:02 +00:00
|
|
|
}
|
|
|
|
})
|
2019-05-26 16:31:16 +00:00
|
|
|
uplink.send_message({
|
2018-05-26 20:53:02 +00:00
|
|
|
'key': 'dashboard',
|
|
|
|
'data': {
|
2018-05-31 12:20:08 +00:00
|
|
|
'command': 'reloadFrontend'
|
2018-05-26 20:53:02 +00:00
|
|
|
}
|
|
|
|
})
|
2018-04-20 12:42:32 +00:00
|
|
|
|
2018-03-27 14:04:33 +00:00
|
|
|
|
2018-07-20 11:37:22 +00:00
|
|
|
class MessageFSMStepsEventHandler(FSMAwareEventHandler):
|
|
|
|
"""
|
|
|
|
This example EventHandler is capable of detecting FSM state.
|
|
|
|
!! Please remove from production code !!
|
|
|
|
"""
|
|
|
|
def handle_event(self, message):
|
|
|
|
pass
|
|
|
|
|
2018-07-24 15:17:14 +00:00
|
|
|
def handle_fsm_step(self, **kwargs):
|
2018-07-20 11:37:22 +00:00
|
|
|
"""
|
|
|
|
When the FSM steps this method is invoked.
|
2018-07-24 15:17:14 +00:00
|
|
|
Receives a 'data' field from an fsm_update message as kwargs.
|
2018-07-20 11:37:22 +00:00
|
|
|
"""
|
|
|
|
MessageSender().send(
|
|
|
|
'FSM info',
|
2018-07-24 15:17:14 +00:00
|
|
|
f'FSM has stepped from state "{kwargs["last_event"]["from_state"]}" '
|
|
|
|
f'to state "{kwargs["current_state"]}" in response to trigger "{kwargs["last_event"]["trigger"]}"'
|
2018-07-20 11:37:22 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2018-08-07 15:01:58 +00:00
|
|
|
def main():
|
2019-05-15 15:26:02 +00:00
|
|
|
# pylint: disable=unused-variable
|
2018-08-07 15:01:58 +00:00
|
|
|
#
|
2018-07-20 11:37:22 +00:00
|
|
|
# TFW component EventHandlers (builtins, required for their respective functionalities)
|
2018-08-07 15:01:58 +00:00
|
|
|
fsm = FSMManagingEventHandler( # TFW FSM
|
2018-06-29 20:08:05 +00:00
|
|
|
key='fsm',
|
2018-07-27 11:59:14 +00:00
|
|
|
fsm_type=partial(
|
|
|
|
YamlFSM,
|
|
|
|
'test_fsm.yml',
|
|
|
|
{} # jinja2 variables, use empty dict to enable jinja2 parsing without any variables
|
|
|
|
)
|
2018-06-29 20:08:05 +00:00
|
|
|
)
|
2018-05-26 20:53:02 +00:00
|
|
|
ide = IdeEventHandler( # Web IDE backend
|
2018-05-30 13:58:19 +00:00
|
|
|
key='ide',
|
|
|
|
allowed_directories=[TFWENV.IDE_WD, TFWENV.WEBSERVICE_DIR],
|
|
|
|
directory=TFWENV.IDE_WD,
|
2018-06-04 19:48:54 +00:00
|
|
|
exclude=['*.pyc']
|
2018-05-26 20:53:02 +00:00
|
|
|
)
|
2018-05-29 16:00:57 +00:00
|
|
|
terminal = TerminalEventHandler( # Web shell backend
|
2018-05-26 20:53:02 +00:00
|
|
|
key='shell',
|
|
|
|
monitor=BashMonitor(TFWENV.HISTFILE)
|
|
|
|
)
|
2019-06-11 15:27:37 +00:00
|
|
|
commands = TerminalCallbackEventHandler( # Reacts to terminal commands
|
|
|
|
'history.bash',
|
|
|
|
TestCommands(bashrc=f'/home/{TAOENV.USER}/.bashrc').callback
|
|
|
|
)
|
2018-05-29 16:00:57 +00:00
|
|
|
processmanager = ProcessManagingEventHandler( # Handles 'deploy' button clicks
|
2018-05-26 20:53:02 +00:00
|
|
|
key='processmanager',
|
2018-05-29 16:00:57 +00:00
|
|
|
dirmonitor=ide.monitor,
|
|
|
|
log_tail=2000
|
2018-05-26 20:53:02 +00:00
|
|
|
)
|
2018-05-30 11:15:13 +00:00
|
|
|
logmonitor = LogMonitoringEventHandler( # Sends live logs of webservice process to frontend
|
2018-05-30 13:23:54 +00:00
|
|
|
key='logmonitor',
|
|
|
|
process_name='webservice',
|
2018-05-30 11:15:13 +00:00
|
|
|
log_tail=2000
|
|
|
|
)
|
2018-08-07 15:03:41 +00:00
|
|
|
snapshot = DirectorySnapshottingEventHandler( # Manages filesystem snapshots of directories
|
|
|
|
key='snapshot',
|
|
|
|
directories=[
|
|
|
|
TFWENV.IDE_WD,
|
|
|
|
TFWENV.WEBSERVICE_DIR
|
|
|
|
]
|
|
|
|
)
|
2019-05-26 16:31:16 +00:00
|
|
|
frontend = FrontendEventHandler() # Proxies frontend API calls to frontend
|
2018-05-26 20:53:02 +00:00
|
|
|
|
2018-07-20 11:37:22 +00:00
|
|
|
# Your custom event handlers
|
2018-08-07 15:01:58 +00:00
|
|
|
message_fsm_steps_eh = MessageFSMStepsEventHandler(
|
2018-07-20 11:37:22 +00:00
|
|
|
key='test'
|
|
|
|
)
|
|
|
|
|
2019-05-02 13:07:13 +00:00
|
|
|
event_handlers = EventHandlerBase.get_local_instances()
|
2019-05-20 09:09:27 +00:00
|
|
|
def stop(sig, frame):
|
2019-05-02 13:07:13 +00:00
|
|
|
for eh in event_handlers:
|
2019-05-20 09:09:27 +00:00
|
|
|
eh.stop()
|
2019-05-02 13:07:13 +00:00
|
|
|
exit(0)
|
2019-05-20 09:09:27 +00:00
|
|
|
signal(SIGTERM, stop)
|
|
|
|
signal(SIGINT, stop)
|
2019-05-02 13:07:13 +00:00
|
|
|
|
|
|
|
IOLoop.instance().start()
|
2018-08-07 15:01:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|