diff --git a/magnum/cmd/api.py b/magnum/cmd/api.py index 394f67a5fe..eaad02f4ee 100644 --- a/magnum/cmd/api.py +++ b/magnum/cmd/api.py @@ -17,6 +17,7 @@ import os import sys +from oslo_concurrency import processutils from oslo_log import log as logging from oslo_reports import guru_meditation_report as gmr from werkzeug import serving @@ -79,5 +80,10 @@ def main(): LOG.info(_LI('Serving on %(proto)s://%(host)s:%(port)s'), dict(proto="https" if use_ssl else "http", host=host, port=port)) - serving.run_simple(host, port, app, + workers = CONF.api.workers + if not workers: + workers = processutils.get_worker_count() + LOG.info(_LI('Server will handle each request in a new process up to' + ' %s concurrent processes'), workers) + serving.run_simple(host, port, app, processes=workers, ssl_context=_get_ssl_configs(use_ssl)) diff --git a/magnum/conf/api.py b/magnum/conf/api.py index 11756c9191..0df0da88cb 100644 --- a/magnum/conf/api.py +++ b/magnum/conf/api.py @@ -39,7 +39,10 @@ api_service_opts = [ "effect. "), cfg.BoolOpt('enabled_ssl', default=False, - help='Enable SSL Magnum API service') + help='Enable SSL Magnum API service'), + cfg.IntOpt('workers', + help='The maximum number of magnum-api processes to ' + 'fork and run. Default to number of CPUs on the host.') ] diff --git a/magnum/tests/unit/cmd/test_api.py b/magnum/tests/unit/cmd/test_api.py index e6ce096902..ea55eadbf7 100644 --- a/magnum/tests/unit/cmd/test_api.py +++ b/magnum/tests/unit/cmd/test_api.py @@ -14,6 +14,8 @@ import mock +from oslo_concurrency import processutils + from magnum.cmd import api from magnum.tests import base @@ -32,9 +34,28 @@ class TestMagnumAPI(base.TestCase): app = mock_app.load_app.return_value mock_prep.assert_called_once_with(mock.ANY) mock_app.load_app.assert_called_once_with() + workers = processutils.get_worker_count() mock_run.assert_called_once_with(base.CONF.api.host, base.CONF.api.port, - app, ssl_context=None) + app, processes=workers, + ssl_context=None) + + @mock.patch('werkzeug.serving.run_simple') + @mock.patch.object(api, 'api_app') + @mock.patch('magnum.common.service.prepare_service') + def test_api_http_config_workers(self, mock_prep, mock_app, + mock_run, mock_base): + fake_workers = 8 + self.config(workers=fake_workers, group='api') + api.main() + + app = mock_app.load_app.return_value + mock_prep.assert_called_once_with(mock.ANY) + mock_app.load_app.assert_called_once_with() + mock_run.assert_called_once_with(base.CONF.api.host, + base.CONF.api.port, + app, processes=fake_workers, + ssl_context=None) @mock.patch('os.path.exists') @mock.patch('werkzeug.serving.run_simple') @@ -91,6 +112,8 @@ class TestMagnumAPI(base.TestCase): mock_app.load_app.assert_called_once_with() mock_exist.assert_has_calls([mock.call('tmp_crt'), mock.call('tmp_key')]) + workers = processutils.get_worker_count() mock_run.assert_called_once_with(base.CONF.api.host, base.CONF.api.port, app, + processes=workers, ssl_context=('tmp_crt', 'tmp_key'))