diff --git a/etc/marconi.conf-sample b/etc/marconi.conf-sample index 4e9be411a..b15ab8af4 100644 --- a/etc/marconi.conf-sample +++ b/etc/marconi.conf-sample @@ -5,7 +5,17 @@ transport = marconi.transport.wsgi storage = marconi.storage.mongodb [drivers:transport:wsgi] -port = 8888 +bind = 0.0.0.0:8888 +; workers = 4 +workers = 1 +; worker_class = sync, gevent, eventlet +worker_class = sync +; user = 1000 +; group = 1000 +; proc_name = marconi +; certfile = cert.crt +; keyfile = cert.key + ;[drivers:transport:zmq] ;port = 9999 diff --git a/marconi/tests/etc/wsgi_sqlite.conf b/marconi/tests/etc/wsgi_sqlite.conf index 552970918..ff11a5442 100644 --- a/marconi/tests/etc/wsgi_sqlite.conf +++ b/marconi/tests/etc/wsgi_sqlite.conf @@ -3,4 +3,5 @@ transport = marconi.transport.wsgi storage = marconi.storage.sqlite [drivers:transport:wsgi] -port = 8888 +bind = 0.0.0.0:8888 +workers = 20 diff --git a/marconi/tests/transport/wsgi/test_app.py b/marconi/tests/transport/wsgi/test_app.py new file mode 100644 index 000000000..b3dc1e39a --- /dev/null +++ b/marconi/tests/transport/wsgi/test_app.py @@ -0,0 +1,40 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import multiprocessing +import signal + +import marconi +from marconi.tests import util +from marconi.transport.wsgi import app + + +class TestApplication(util.TestBase): + + def setUp(self): + super(TestApplication, self).setUp() + + conf_file = self.conf_path('wsgi_sqlite.conf') + boot = marconi.Bootstrap(conf_file) + + self.app = app.Application(boot.transport.app) + + def test_run(self): + server = multiprocessing.Process(target=self.app.run) + server.start() + self.assertTrue(server.is_alive()) + server.terminate() + server.join() + self.assertEquals(server.exitcode, -signal.SIGTERM) diff --git a/marconi/transport/wsgi/app.py b/marconi/transport/wsgi/app.py new file mode 100644 index 000000000..9e39f894e --- /dev/null +++ b/marconi/transport/wsgi/app.py @@ -0,0 +1,57 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Gunicorn Application implementation for Marconi +""" + +import gunicorn.app.base as gunicorn +import gunicorn.config as gconfig + +from marconi.common import config + + +OPTIONS = { + # Process + "user": None, + "group": None, + "proc_name": "marconi", + + # SSL + "certfile": None, + "keyfile": None, + + # Network + "workers": 1, + "bind": "0.0.0.0:8888", + "worker_class": "sync" +} + +cfg = config.namespace('drivers:transport:wsgi').from_options(**OPTIONS) + + +class Application(gunicorn.Application): + + def __init__(self, wsgi_app, *args, **kwargs): + super(Application, self).__init__(*args, **kwargs) + self.app = wsgi_app + + def load(self): + return self.app + + def load_config(self): + self.cfg = gconfig.Config(self.usage, prog=self.prog) + + for key in OPTIONS: + self.cfg.set(key, getattr(cfg, key)) diff --git a/marconi/transport/wsgi/driver.py b/marconi/transport/wsgi/driver.py index 233b5f703..46741d8b3 100644 --- a/marconi/transport/wsgi/driver.py +++ b/marconi/transport/wsgi/driver.py @@ -15,11 +15,8 @@ import falcon -from marconi.common import config from marconi import transport - - -cfg = config.namespace('drivers:transport:wsgi').from_options(port=8888) +from marconi.transport.wsgi import app class Driver(transport.DriverBase): @@ -56,4 +53,4 @@ class Driver(transport.DriverBase): '/claims/{claim_id}', claim_item) def listen(self): - raise NotImplementedError + return app.Application(self.app).run() diff --git a/tools/pip-requires b/tools/pip-requires index 731fd3b5d..3dafcb3e0 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -6,4 +6,5 @@ PasteDeploy pymongo python-keystoneclient WebOb +gunicorn iso8601>=0.1.4