Add new masakari.wsgi module

We also update our devstack plugin to take advantage of it. The existing
masakari.wsgi module is moved to masakari.api.wsgi.

Change-Id: I374abe948f1be95cb68a524e04ab452809c5e854
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane
2025-05-08 11:47:23 +01:00
parent 01cf6692f3
commit 300fa732dc
14 changed files with 73 additions and 31 deletions

View File

@@ -158,7 +158,7 @@ function configure_masakari {
fi fi
if [ "$MASAKARI_USE_MOD_WSGI" == "True" ]; then if [ "$MASAKARI_USE_MOD_WSGI" == "True" ]; then
write_uwsgi_config "$MASAKARI_UWSGI_CONF" "$MASAKARI_UWSGI" "/instance-ha" write_uwsgi_config "$MASAKARI_UWSGI_CONF" "$MASAKARI_UWSGI" "/instance-ha" "" "masakari-api"
fi fi
} }

View File

@@ -45,7 +45,7 @@ MASAKARI_MANAGE=$MASAKARI_BIN_DIR/masakari-manage
MASAKARI_SERVICE_PORT=${MASAKARI_SERVICE_PORT:-15868} MASAKARI_SERVICE_PORT=${MASAKARI_SERVICE_PORT:-15868}
MASAKARI_SERVICE_PORT_INT=${MASAKARI_SERVICE_PORT_INT:-25868} MASAKARI_SERVICE_PORT_INT=${MASAKARI_SERVICE_PORT_INT:-25868}
MASAKARI_UWSGI=$MASAKARI_BIN_DIR/masakari-wsgi MASAKARI_UWSGI=masakari.wsgi.api:application
MASAKARI_UWSGI_CONF=$MASAKARI_CONF_DIR/masakari-api-uwsgi.ini MASAKARI_UWSGI_CONF=$MASAKARI_CONF_DIR/masakari-api-uwsgi.ini
enable_service masakari masakari-api masakari-engine enable_service masakari masakari-api masakari-engine

View File

@@ -13,7 +13,6 @@
# under the License. # under the License.
""" """
Common Auth Middleware. Common Auth Middleware.
""" """
from oslo_log import log as logging from oslo_log import log as logging
@@ -22,10 +21,10 @@ from oslo_serialization import jsonutils
import webob.dec import webob.dec
import webob.exc import webob.exc
from masakari.api import wsgi
import masakari.conf import masakari.conf
from masakari import context from masakari import context
from masakari.i18n import _ from masakari.i18n import _
from masakari import wsgi
CONF = masakari.conf.CONF CONF = masakari.conf.CONF

View File

@@ -23,10 +23,10 @@ import webob.dec
import webob.exc import webob.exc
from masakari.api.openstack import wsgi from masakari.api.openstack import wsgi
from masakari.api import wsgi as base_wsgi
import masakari.conf import masakari.conf
from masakari.i18n import translate from masakari.i18n import translate
from masakari import utils from masakari import utils
from masakari import wsgi as base_wsgi
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@@ -153,7 +153,7 @@ class APIRouterV1(base_wsgi.Router):
def factory(cls, global_config, **local_config): def factory(cls, global_config, **local_config):
"""Simple paste factory """Simple paste factory
:class:`masakari.wsgi.Router` doesn't have one. :class:`masakari.api.wsgi.Router` doesn't have one.
""" """
return cls() return cls()

View File

@@ -228,7 +228,7 @@ def get_sort_params(input_params, default_key='created_at',
The input parameters are not modified. The input parameters are not modified.
:param input_params: webob.multidict of request parameters (from :param input_params: webob.multidict of request parameters (from
masakari.wsgi.Request.params) masakari.api.wsgi.Request.params)
:param default_key: default sort key value, added to the list if no :param default_key: default sort key value, added to the list if no
'sort_key' parameters are supplied 'sort_key' parameters are supplied
:param default_dir: default sort dir value, added to the list if no :param default_dir: default sort dir value, added to the list if no

View File

@@ -25,10 +25,10 @@ import webob
from masakari.api import api_version_request as api_version from masakari.api import api_version_request as api_version
from masakari.api import versioned_method from masakari.api import versioned_method
from masakari.api import wsgi
from masakari import exception from masakari import exception
from masakari import i18n from masakari import i18n
from masakari.i18n import _ from masakari.i18n import _
from masakari import wsgi
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@@ -25,6 +25,7 @@ import oslo_messaging as messaging
from oslo_service import service from oslo_service import service
from oslo_utils import importutils from oslo_utils import importutils
from masakari.api import wsgi
import masakari.conf import masakari.conf
from masakari import context from masakari import context
from masakari import coordination as masakari_coordination from masakari import coordination as masakari_coordination
@@ -34,7 +35,6 @@ from masakari.objects import base as objects_base
from masakari import rpc from masakari import rpc
from masakari import utils from masakari import utils
from masakari import version from masakari import version
from masakari import wsgi
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@@ -24,9 +24,9 @@ from masakari.api.openstack import ha
from masakari.api.openstack.ha import versions from masakari.api.openstack.ha import versions
from masakari.api.openstack import wsgi as os_wsgi from masakari.api.openstack import wsgi as os_wsgi
from masakari.api import urlmap from masakari.api import urlmap
from masakari.api import wsgi
from masakari import context from masakari import context
from masakari.tests import uuidsentinel from masakari.tests import uuidsentinel
from masakari import wsgi
@webob.dec.wsgify @webob.dec.wsgify

View File

@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
"""Unit tests for `masakari.wsgi`.""" """Unit tests for `masakari.api.wsgi`."""
import os.path import os.path
import socket import socket
@@ -27,10 +27,10 @@ from oslo_config import cfg
import requests import requests
import testtools import testtools
from masakari.api import wsgi
import masakari.exception import masakari.exception
from masakari import test from masakari import test
from masakari.tests.unit import utils from masakari.tests.unit import utils
import masakari.wsgi
SSL_CERT_DIR = os.path.normpath(os.path.join( SSL_CERT_DIR = os.path.normpath(os.path.join(
os.path.dirname(os.path.abspath(__file__)), os.path.dirname(os.path.abspath(__file__)),
@@ -49,7 +49,7 @@ class TestLoaderNothingExists(test.NoDBTestCase):
self.flags(api_paste_config='api-paste.ini', group='wsgi') self.flags(api_paste_config='api-paste.ini', group='wsgi')
self.assertRaises( self.assertRaises(
masakari.exception.ConfigNotFound, masakari.exception.ConfigNotFound,
masakari.wsgi.Loader, wsgi.Loader,
) )
def test_asbpath_config_not_found(self): def test_asbpath_config_not_found(self):
@@ -57,7 +57,7 @@ class TestLoaderNothingExists(test.NoDBTestCase):
group='wsgi') group='wsgi')
self.assertRaises( self.assertRaises(
masakari.exception.ConfigNotFound, masakari.exception.ConfigNotFound,
masakari.wsgi.Loader, wsgi.Loader,
) )
@@ -76,7 +76,7 @@ document_root = /tmp
self.config.write(self._paste_config.lstrip()) self.config.write(self._paste_config.lstrip())
self.config.seek(0) self.config.seek(0)
self.config.flush() self.config.flush()
self.loader = masakari.wsgi.Loader(self.config.name) self.loader = wsgi.Loader(self.config.name)
def test_config_found(self): def test_config_found(self):
self.assertEqual(self.config.name, self.loader.config_path) self.assertEqual(self.config.name, self.loader.config_path)
@@ -101,18 +101,18 @@ class TestWSGIServer(test.NoDBTestCase):
"""WSGI server tests.""" """WSGI server tests."""
def test_no_app(self): def test_no_app(self):
server = masakari.wsgi.Server("test_app", None) server = wsgi.Server("test_app", None)
self.assertEqual("test_app", server.name) self.assertEqual("test_app", server.name)
def test_custom_max_header_line(self): def test_custom_max_header_line(self):
self.flags(max_header_line=4096, group='wsgi') # Default is 16384 self.flags(max_header_line=4096, group='wsgi') # Default is 16384
masakari.wsgi.Server("test_custom_max_header_line", None) wsgi.Server("test_custom_max_header_line", None)
self.assertEqual(CONF.wsgi.max_header_line, self.assertEqual(CONF.wsgi.max_header_line,
eventlet.wsgi.MAX_HEADER_LINE) eventlet.wsgi.MAX_HEADER_LINE)
def test_start_random_port(self): def test_start_random_port(self):
server = masakari.wsgi.Server("test_random_port", None, server = wsgi.Server("test_random_port", None, host="127.0.0.1",
host="127.0.0.1", port=0) port=0)
server.start() server.start()
self.assertNotEqual(0, server.port) self.assertNotEqual(0, server.port)
server.stop() server.stop()
@@ -120,8 +120,7 @@ class TestWSGIServer(test.NoDBTestCase):
@testtools.skipIf(not utils.is_ipv6_supported(), "no ipv6 support") @testtools.skipIf(not utils.is_ipv6_supported(), "no ipv6 support")
def test_start_random_port_with_ipv6(self): def test_start_random_port_with_ipv6(self):
server = masakari.wsgi.Server("test_random_port", None, server = wsgi.Server("test_random_port", None, host="::1", port=0)
host="::1", port=0)
server.start() server.start()
self.assertEqual("::1", server.host) self.assertEqual("::1", server.host)
self.assertNotEqual(0, server.port) self.assertNotEqual(0, server.port)
@@ -134,8 +133,8 @@ class TestWSGIServer(test.NoDBTestCase):
def test_socket_options_for_simple_server(self): def test_socket_options_for_simple_server(self):
# test normal socket options has set properly # test normal socket options has set properly
self.flags(tcp_keepidle=500, group='wsgi') self.flags(tcp_keepidle=500, group='wsgi')
server = masakari.wsgi.Server("test_socket_options", None, server = wsgi.Server(
host="127.0.0.1", port=0) "test_socket_options", None, host="127.0.0.1", port=0)
server.start() server.start()
sock = server._socket sock = server._socket
self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET, self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
@@ -151,7 +150,7 @@ class TestWSGIServer(test.NoDBTestCase):
def test_server_pool_waitall(self): def test_server_pool_waitall(self):
# test pools waitall method gets called while stopping server # test pools waitall method gets called while stopping server
server = masakari.wsgi.Server("test_server", None, server = wsgi.Server("test_server", None,
host="127.0.0.1") host="127.0.0.1")
server.start() server.start()
with mock.patch.object(server._pool, with mock.patch.object(server._pool,
@@ -161,7 +160,7 @@ class TestWSGIServer(test.NoDBTestCase):
mock_waitall.assert_called_once_with() mock_waitall.assert_called_once_with()
def test_uri_length_limit(self): def test_uri_length_limit(self):
server = masakari.wsgi.Server("test_uri_length_limit", None, server = wsgi.Server("test_uri_length_limit", None,
host="127.0.0.1", max_url_len=16384) host="127.0.0.1", max_url_len=16384)
server.start() server.start()
@@ -180,7 +179,7 @@ class TestWSGIServer(test.NoDBTestCase):
server.wait() server.wait()
def test_reset_pool_size_to_default(self): def test_reset_pool_size_to_default(self):
server = masakari.wsgi.Server("test_resize", None, server = wsgi.Server("test_resize", None,
host="127.0.0.1", max_url_len=16384) host="127.0.0.1", max_url_len=16384)
server.start() server.start()
@@ -200,8 +199,7 @@ class TestWSGIServer(test.NoDBTestCase):
# configured 'client_socket_timeout' value. # configured 'client_socket_timeout' value.
with mock.patch.object(eventlet, with mock.patch.object(eventlet,
'spawn') as mock_spawn: 'spawn') as mock_spawn:
server = masakari.wsgi.Server("test_app", None, server = wsgi.Server("test_app", None, host="127.0.0.1", port=0)
host="127.0.0.1", port=0)
server.start() server.start()
_, kwargs = mock_spawn.call_args _, kwargs = mock_spawn.call_args
self.assertEqual(CONF.wsgi.client_socket_timeout, self.assertEqual(CONF.wsgi.client_socket_timeout,
@@ -215,8 +213,7 @@ class TestWSGIServer(test.NoDBTestCase):
# configured 'keep_alive' value. # configured 'keep_alive' value.
with mock.patch.object(eventlet, with mock.patch.object(eventlet,
'spawn') as mock_spawn: 'spawn') as mock_spawn:
server = masakari.wsgi.Server("test_app", None, server = wsgi.Server("test_app", None, host="127.0.0.1", port=0)
host="127.0.0.1", port=0)
server.start() server.start()
_, kwargs = mock_spawn.call_args _, kwargs = mock_spawn.call_args
self.assertEqual(CONF.wsgi.keep_alive, self.assertEqual(CONF.wsgi.keep_alive,

View File

@@ -116,7 +116,7 @@ class TestWSGIService(test.NoDBTestCase):
def setUp(self): def setUp(self):
super(TestWSGIService, self).setUp() super(TestWSGIService, self).setUp()
self.stub_out('masakari.wsgi.Loader.load_app', mock.MagicMock()) self.stub_out('masakari.api.wsgi.Loader.load_app', mock.MagicMock())
def test_workers_set_default(self): def test_workers_set_default(self):
test_service = service.WSGIService("masakari_api") test_service = service.WSGIService("masakari_api")

View File

24
masakari/wsgi/api.py Normal file
View File

@@ -0,0 +1,24 @@
# 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.
"""WSGI application entry-point for Masakari API."""
import threading
from masakari.cmd import api
application = None
lock = threading.Lock()
with lock:
if application is None:
application = api.initialize_application()

View File

@@ -0,0 +1,22 @@
---
features:
- |
A new module, ``masakari.wsgi``, has been added as a place to gather WSGI
``application`` objects. This is intended to ease deployment by providing
a consistent location for these objects. For example, if using uWSGI then
instead of:
.. code-block:: ini
[uwsgi]
wsgi-file = /bin/masakari-wsgi
You can now use:
.. code-block:: ini
[uwsgi]
module = masakari.wsgi.api:application
This also simplifies deployment with other WSGI servers that expect module
paths such as gunicorn.