diff --git a/README.rst b/README.rst index 609efb2f..96fd5542 100644 --- a/README.rst +++ b/README.rst @@ -22,10 +22,19 @@ To run Mistral API server perform the following command in a shell: Note that an example configuration file can be found in etc/mistral.conf.example. ### Running Mistral Task Executors -To run Mistral Task Executor instance perform the following command in a shell: +To run Mistral Task Executor instance perform the following command in a shell:: *tox -evenv -- python mistral/cmd/task_executor.py --config-file path_to_config* Note that at least one Executor instance should be running so that workflow tasks are processed by Mistral. +### Debugging +To debug the engine, create etc/mistral.conf with the settings:: + [engine] + engine = mistral.engine.local.engine + [pecan] + auth_enable = False +and run in pdb, PyDev or PyCharm:: + + mistral/cmd/api --config-file etc/mistral.conf --use-debugger diff --git a/etc/mistral.conf.example b/etc/mistral.conf.example index 326f831e..1fbf3020 100644 --- a/etc/mistral.conf.example +++ b/etc/mistral.conf.example @@ -19,6 +19,10 @@ default_log_levels = mistral=INFO,mistral.cmd.api=INFO,mistral.api=DEBUG,wsme=DE host = 0.0.0.0 port = 8989 +[engine] +# Mistral engine class (string value) +#engine=mistral.engine.scalable.engine + [pecan] auth_enable = True diff --git a/mistral/api/app.py b/mistral/api/app.py index d55e319d..a37cca75 100644 --- a/mistral/api/app.py +++ b/mistral/api/app.py @@ -19,6 +19,7 @@ import pecan from oslo.config import cfg from mistral import context as ctx +from mistral.engine import engine from mistral.db import api as db_api from mistral.services import periodic from mistral.api import access_control @@ -47,6 +48,7 @@ def setup_app(config=None): app_conf = dict(config.app) db_api.setup_db() + engine.load_engine() ##TODO(akuznetsov) move this to event scheduling to separate process periodic.setup() diff --git a/mistral/cmd/api.py b/mistral/cmd/api.py index 7c79a804..5a89b984 100755 --- a/mistral/cmd/api.py +++ b/mistral/cmd/api.py @@ -29,9 +29,12 @@ from mistral.api import app from mistral import config from mistral.openstack.common import log as logging - eventlet.monkey_patch( - os=True, select=True, socket=True, thread=True, time=True) + os=True, + select=True, + socket=True, + thread=False if '--use-debugger' in sys.argv else True, + time=True) LOG = logging.getLogger('mistral.cmd.api') diff --git a/mistral/config.py b/mistral/config.py index d6c0f4b2..e6e47f49 100644 --- a/mistral/config.py +++ b/mistral/config.py @@ -24,12 +24,16 @@ from keystoneclient.middleware import auth_token from mistral.openstack.common import log from mistral import version - api_opts = [ cfg.StrOpt('host', default='0.0.0.0', help='Mistral API server host'), cfg.IntOpt('port', default=8989, help='Mistral API server port') ] +engine_opts = [ + cfg.StrOpt('engine', default='mistral.engine.scalable.engine', + help='Mistral engine class') +] + pecan_opts = [ cfg.StrOpt('root', default='mistral.api.controllers.root.RootController', help='Pecan root controller'), @@ -54,14 +58,25 @@ rabbit_opts = [ cfg.StrOpt('rabbit_password', default='guest', help='RabbitMQ password') ] +use_debugger = cfg.BoolOpt( + "use-debugger", + default=False, + help='Enables debugger. Note that using this option changes how the ' + 'eventlet library is used to support async IO. This could result ' + 'in failures that do not occur under normal operation. ' + 'Use at your own risk.' +) + CONF = cfg.CONF CONF.register_opts(api_opts, group='api') +CONF.register_opts(engine_opts, group='engine') CONF.register_opts(pecan_opts, group='pecan') CONF.register_opts(auth_token.opts, group='keystone') CONF.register_opts(db_opts, group='database') CONF.register_opts(rabbit_opts, group='rabbit') +CONF.register_cli_opt(use_debugger) CONF.import_opt('verbose', 'mistral.openstack.common.log') CONF.import_opt('debug', 'mistral.openstack.common.log') @@ -73,7 +88,6 @@ CONF.import_opt('log_date_format', 'mistral.openstack.common.log') CONF.import_opt('use_syslog', 'mistral.openstack.common.log') CONF.import_opt('syslog_log_facility', 'mistral.openstack.common.log') - cfg.set_defaults(log.log_opts, default_log_levels=['sqlalchemy=WARN', 'eventlet.wsgi.server=WARN']) diff --git a/mistral/engine/actions/action_factory.py b/mistral/engine/actions/action_factory.py index 4f76fe6f..b8bd384a 100644 --- a/mistral/engine/actions/action_factory.py +++ b/mistral/engine/actions/action_factory.py @@ -45,7 +45,7 @@ def _find_action_result_helper(task, action): try: return task['service_dsl']['actions'][action.name].get('output', {}) except (KeyError, AttributeError): - return None + return {} def get_rest_action(task): diff --git a/mistral/engine/engine.py b/mistral/engine/engine.py index d356f800..6c8c062e 100644 --- a/mistral/engine/engine.py +++ b/mistral/engine/engine.py @@ -20,15 +20,16 @@ of workflow executions. """ from mistral.openstack.common import importutils +from oslo.config import cfg + +_engine = None -# TODO(rakhmerov): make it configurable -module_name = "mistral.engine.scalable.engine" -try: +def load_engine(): + global _engine + module_name = cfg.CONF.engine.engine module = importutils.import_module(module_name) - IMPL = module.get_engine() -finally: - pass + _engine = module.get_engine() def start_workflow_execution(workbook_name, task_name, context=None): @@ -40,7 +41,7 @@ def start_workflow_execution(workbook_name, task_name, context=None): :param context: Execution context which defines a workflow input :return: Workflow execution. """ - return IMPL.start_workflow_execution(workbook_name, task_name, context) + return _engine.start_workflow_execution(workbook_name, task_name, context) def stop_workflow_execution(workbook_name, execution_id): @@ -50,7 +51,7 @@ def stop_workflow_execution(workbook_name, execution_id): :param execution_id: Workflow execution id. :return: Workflow execution. """ - return IMPL.stop_workflow_execution(workbook_name, execution_id) + return _engine.stop_workflow_execution(workbook_name, execution_id) def convey_task_result(workbook_name, execution_id, task_id, state, result): @@ -72,8 +73,8 @@ def convey_task_result(workbook_name, execution_id, task_id, state, result): :param result: Task result data. :return: Task. """ - return IMPL.convey_task_result(workbook_name, execution_id, task_id, - state, result) + return _engine.convey_task_result(workbook_name, execution_id, task_id, + state, result) def get_workflow_execution_state(workbook_name, execution_id): @@ -83,7 +84,7 @@ def get_workflow_execution_state(workbook_name, execution_id): :param execution_id: Workflow execution id. :return: Current workflow state. """ - return IMPL.get_workflow_execution_state(workbook_name, execution_id) + return _engine.get_workflow_execution_state(workbook_name, execution_id) def get_task_state(workbook_name, execution_id, task_id): @@ -94,4 +95,4 @@ def get_task_state(workbook_name, execution_id, task_id): :param task_id: Task id. :return: Current task state. """ - return IMPL.get_task_state(workbook_name, execution_id, task_id) + return _engine.get_task_state(workbook_name, execution_id, task_id)