summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaifeng Wang <kaifeng.w@gmail.com>2018-04-17 14:39:48 +0800
committerKaifeng Wang <kaifeng.w@gmail.com>2018-10-23 09:20:16 +0800
commitedd6810c3ddfa9b23febda7d6198bd1089ab3f2f (patch)
treeabfe561145a99b0563cbe35992dcddfde7362145
parenta228912827f0cda149fd8b79abbdccaf1c15d2b3 (diff)
Wrap Flask into oslo.service
This patch is part of inspector HA work, which wraps inspector api into oslo service. oslo.service has also provided support to signal processing like SIGHUP or SIGTERM, so these code were removed in this patch. Deprecated current SSL cert/key options used by ironic-inspector, code manually creates ssl context were removed. These options will be fed from [ssl] section. Change-Id: Ia5e16fcb9104556d62c90f5507f17b41f73a5208 Story: #2001842 Task: #12609
Notes
Notes (review): Code-Review+2: Dmitry Tantsur <divius.inside@gmail.com> Code-Review+1: Harald Jensås <hjensas@redhat.com> Code-Review+2: Julia Kreger <juliaashleykreger@gmail.com> Workflow+1: Julia Kreger <juliaashleykreger@gmail.com> Code-Review+1: Brin Zhang <zhangbailin@inspur.com> Code-Review+1: Leopard Ma <mabao@inspur.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Tue, 27 Nov 2018 03:38:15 +0000 Reviewed-on: https://review.openstack.org/561823 Project: openstack/ironic-inspector Branch: refs/heads/master
-rw-r--r--ironic_inspector/cmd/all.py12
-rw-r--r--ironic_inspector/common/service_utils.py6
-rw-r--r--ironic_inspector/conf/default.py8
-rw-r--r--ironic_inspector/test/unit/test_wsgi_service.py187
-rw-r--r--ironic_inspector/wsgi_service.py101
-rw-r--r--lower-constraints.txt2
-rw-r--r--releasenotes/notes/deprecate-ssl-opts-40ce8f4618c786ef.yaml7
-rw-r--r--requirements.txt1
-rw-r--r--tools/config-generator.conf5
9 files changed, 94 insertions, 235 deletions
diff --git a/ironic_inspector/cmd/all.py b/ironic_inspector/cmd/all.py
index c300cca..c88459b 100644
--- a/ironic_inspector/cmd/all.py
+++ b/ironic_inspector/cmd/all.py
@@ -14,16 +14,24 @@
14 14
15import sys 15import sys
16 16
17from oslo_config import cfg
18from oslo_service import service
19
20from ironic_inspector.common.rpc_service import RPCService
17from ironic_inspector.common import service_utils 21from ironic_inspector.common import service_utils
18from ironic_inspector import wsgi_service 22from ironic_inspector import wsgi_service
19 23
24CONF = cfg.CONF
25
20 26
21def main(args=sys.argv[1:]): 27def main(args=sys.argv[1:]):
22 # Parse config file and command line options, then start logging 28 # Parse config file and command line options, then start logging
23 service_utils.prepare_service(args) 29 service_utils.prepare_service(args)
24 30
25 server = wsgi_service.WSGIService() 31 launcher = service.ServiceLauncher(CONF, restart_method='mutate')
26 server.run() 32 launcher.launch_service(wsgi_service.WSGIService())
33 launcher.launch_service(RPCService(CONF.host))
34 launcher.wait()
27 35
28 36
29if __name__ == '__main__': 37if __name__ == '__main__':
diff --git a/ironic_inspector/common/service_utils.py b/ironic_inspector/common/service_utils.py
index ba09428..2f37cb9 100644
--- a/ironic_inspector/common/service_utils.py
+++ b/ironic_inspector/common/service_utils.py
@@ -12,6 +12,7 @@
12 12
13from oslo_config import cfg 13from oslo_config import cfg
14from oslo_log import log 14from oslo_log import log
15from oslo_service import sslutils
15 16
16from ironic_inspector.conf import opts 17from ironic_inspector.conf import opts
17 18
@@ -26,5 +27,10 @@ def prepare_service(args=None):
26 opts.parse_args(args) 27 opts.parse_args(args)
27 log.setup(CONF, 'ironic_inspector') 28 log.setup(CONF, 'ironic_inspector')
28 29
30 # TODO(kaifeng) Remove deprecated options at T* cycle.
31 sslutils.register_opts(CONF)
32 CONF.set_default('cert_file', CONF.ssl_cert_path, group='ssl')
33 CONF.set_default('key_file', CONF.ssl_key_path, group='ssl')
34
29 LOG.debug("Configuration:") 35 LOG.debug("Configuration:")
30 CONF.log_opt_values(LOG, log.DEBUG) 36 CONF.log_opt_values(LOG, log.DEBUG)
diff --git a/ironic_inspector/conf/default.py b/ironic_inspector/conf/default.py
index ef2b9c2..5567fb5 100644
--- a/ironic_inspector/conf/default.py
+++ b/ironic_inspector/conf/default.py
@@ -52,9 +52,15 @@ _OPTS = [
52 help=_('SSL Enabled/Disabled')), 52 help=_('SSL Enabled/Disabled')),
53 cfg.StrOpt('ssl_cert_path', 53 cfg.StrOpt('ssl_cert_path',
54 default='', 54 default='',
55 deprecated_for_removal=True,
56 deprecated_reason=_('This option will be superseded by '
57 '[ssl]cert_file.'),
55 help=_('Path to SSL certificate')), 58 help=_('Path to SSL certificate')),
56 cfg.StrOpt('ssl_key_path', 59 cfg.StrOpt('ssl_key_path',
57 default='', 60 default='',
61 deprecated_for_removal=True,
62 deprecated_reason=_('This option will be superseded by '
63 '[ssl]key_file.'),
58 help=_('Path to SSL key')), 64 help=_('Path to SSL key')),
59 cfg.IntOpt('max_concurrency', 65 cfg.IntOpt('max_concurrency',
60 default=1000, min=2, 66 default=1000, min=2,
@@ -78,7 +84,7 @@ _OPTS = [
78 help=_('Whether the current installation of ironic-inspector ' 84 help=_('Whether the current installation of ironic-inspector '
79 'can manage PXE booting of nodes. If set to False, ' 85 'can manage PXE booting of nodes. If set to False, '
80 'the API will reject introspection requests with ' 86 'the API will reject introspection requests with '
81 'manage_boot missing or set to True.')) 87 'manage_boot missing or set to True.')),
82] 88]
83 89
84 90
diff --git a/ironic_inspector/test/unit/test_wsgi_service.py b/ironic_inspector/test/unit/test_wsgi_service.py
index 3cb83db..7f39c55 100644
--- a/ironic_inspector/test/unit/test_wsgi_service.py
+++ b/ironic_inspector/test/unit/test_wsgi_service.py
@@ -11,15 +11,12 @@
11# See the License for the specific language governing permissions and 11# See the License for the specific language governing permissions and
12# limitations under the License. 12# limitations under the License.
13 13
14import ssl
15import sys
16import unittest
17
18import eventlet # noqa 14import eventlet # noqa
19import fixtures 15import fixtures
20import mock 16import mock
21from oslo_config import cfg 17from oslo_config import cfg
22 18
19from ironic_inspector.common import service_utils
23from ironic_inspector.test import base as test_base 20from ironic_inspector.test import base as test_base
24from ironic_inspector import wsgi_service 21from ironic_inspector import wsgi_service
25 22
@@ -32,9 +29,12 @@ class BaseWSGITest(test_base.BaseTest):
32 super(BaseWSGITest, self).setUp() 29 super(BaseWSGITest, self).setUp()
33 self.app = self.useFixture(fixtures.MockPatchObject( 30 self.app = self.useFixture(fixtures.MockPatchObject(
34 wsgi_service.app, 'app', autospec=True)).mock 31 wsgi_service.app, 'app', autospec=True)).mock
32 self.server = self.useFixture(fixtures.MockPatchObject(
33 wsgi_service.wsgi, 'Server', autospec=True)).mock
35 self.mock_log = self.useFixture(fixtures.MockPatchObject( 34 self.mock_log = self.useFixture(fixtures.MockPatchObject(
36 wsgi_service, 'LOG')).mock 35 wsgi_service, 'LOG')).mock
37 self.service = wsgi_service.WSGIService() 36 self.service = wsgi_service.WSGIService()
37 self.service.server = self.server
38 38
39 39
40class TestWSGIServiceInitMiddleware(BaseWSGITest): 40class TestWSGIServiceInitMiddleware(BaseWSGITest):
@@ -66,174 +66,55 @@ class TestWSGIServiceInitMiddleware(BaseWSGITest):
66 self.mock_add_cors_middleware.assert_called_once_with(self.app) 66 self.mock_add_cors_middleware.assert_called_once_with(self.app)
67 67
68 68
69class TestWSGIServiceRun(BaseWSGITest): 69class TestWSGIService(BaseWSGITest):
70 def setUp(self): 70 def setUp(self):
71 super(TestWSGIServiceRun, self).setUp() 71 super(TestWSGIService, self).setUp()
72 self.mock__init_middleware = self.useFixture(fixtures.MockPatchObject( 72 self.mock__init_middleware = self.useFixture(fixtures.MockPatchObject(
73 self.service, '_init_middleware')).mock 73 self.service, '_init_middleware')).mock
74 self.mock__create_ssl_context = self.useFixture(
75 fixtures.MockPatchObject(self.service, '_create_ssl_context')).mock
76 self.mock_shutdown = self.useFixture(fixtures.MockPatchObject(
77 self.service, 'shutdown')).mock
78 74
79 # 'positive' settings 75 # 'positive' settings
80 CONF.set_override('listen_address', '42.42.42.42') 76 CONF.set_override('listen_address', '42.42.42.42')
81 CONF.set_override('listen_port', 42) 77 CONF.set_override('listen_port', 42)
82 78
83 def test_run(self): 79 def test_start(self):
84 self.service.run() 80 self.service.start()
85 81
86 self.mock__create_ssl_context.assert_called_once_with()
87 self.mock__init_middleware.assert_called_once_with() 82 self.mock__init_middleware.assert_called_once_with()
88 self.app.run.assert_called_once_with( 83 self.server.start.assert_called_once_with()
89 host=CONF.listen_address, port=CONF.listen_port,
90 ssl_context=self.mock__create_ssl_context.return_value)
91 self.mock_shutdown.assert_called_once_with()
92 84
93 def test_run_no_ssl_context(self): 85 def test_stop(self):
94 self.mock__create_ssl_context.return_value = None 86 self.service.stop()
87 self.server.stop.assert_called_once_with()
95 88
96 self.service.run() 89 def test_wait(self):
97 self.mock__create_ssl_context.assert_called_once_with() 90 self.service.wait()
98 self.mock__init_middleware.assert_called_once_with() 91 self.server.wait.assert_called_once_with()
99 self.app.run.assert_called_once_with(
100 host=CONF.listen_address, port=CONF.listen_port)
101 self.mock_shutdown.assert_called_once_with()
102 92
103 def test_run_app_error(self): 93 def test_reset(self):
104 class MyError(Exception): 94 self.service.reset()
105 pass 95 self.server.reset.assert_called_once_with()
106 96
107 error = MyError('Oops!')
108 self.app.run.side_effect = error
109 self.service.run()
110 97
111 self.mock__create_ssl_context.assert_called_once_with() 98@mock.patch.object(service_utils.log, 'register_options', autospec=True)
112 self.mock__init_middleware.assert_called_once_with() 99class TestSSLOptions(test_base.BaseTest):
113 self.app.run.assert_called_once_with(
114 host=CONF.listen_address, port=CONF.listen_port,
115 ssl_context=self.mock__create_ssl_context.return_value)
116 self.mock_shutdown.assert_called_once_with(error=str(error))
117 100
101 def test_use_deprecated_options(self, mock_log):
102 CONF.set_override('ssl_cert_path', 'fake_cert_file')
103 CONF.set_override('ssl_key_path', 'fake_key_file')
118 104
119class TestWSGIServiceShutdown(BaseWSGITest): 105 service_utils.prepare_service()
120 def setUp(self):
121 super(TestWSGIServiceShutdown, self).setUp()
122 self.service = wsgi_service.WSGIService()
123 self.mock_rpc_service = mock.MagicMock()
124 self.service.rpc_service = self.mock_rpc_service
125 self.mock_exit = self.useFixture(fixtures.MockPatchObject(
126 wsgi_service.sys, 'exit')).mock
127 106
128 def test_shutdown(self): 107 self.assertEqual(CONF.ssl.cert_file, 'fake_cert_file')
129 class MyError(Exception): 108 self.assertEqual(CONF.ssl.key_file, 'fake_key_file')
130 pass
131 error = MyError('Oops!')
132 109
133 self.service.shutdown(error=error) 110 def test_use_ssl_options(self, mock_log):
134 self.mock_rpc_service.stop.assert_called_once_with() 111 CONF.set_override('ssl_cert_path', 'fake_cert_file')
135 self.mock_exit.assert_called_once_with(error) 112 CONF.set_override('ssl_key_path', 'fake_key_file')
136 113
114 service_utils.prepare_service()
137 115
138class TestCreateSSLContext(test_base.BaseTest): 116 CONF.set_override('cert_file', 'fake_new_cert', 'ssl')
139 def setUp(self): 117 CONF.set_override('key_file', 'fake_new_key', 'ssl')
140 super(TestCreateSSLContext, self).setUp()
141 self.app = mock.Mock()
142 self.service = wsgi_service.WSGIService()
143 118
144 def test_use_ssl_false(self): 119 self.assertEqual(CONF.ssl.cert_file, 'fake_new_cert')
145 CONF.set_override('use_ssl', False) 120 self.assertEqual(CONF.ssl.key_file, 'fake_new_key')
146 con = self.service._create_ssl_context()
147 self.assertIsNone(con)
148
149 @mock.patch.object(sys, 'version_info')
150 def test_old_python_returns_none(self, mock_version_info):
151 mock_version_info.__lt__.return_value = True
152 CONF.set_override('use_ssl', True)
153 con = self.service._create_ssl_context()
154 self.assertIsNone(con)
155
156 @unittest.skipIf(sys.version_info[:3] < (2, 7, 9),
157 'This feature is unsupported in this version of python '
158 'so the tests will be skipped')
159 @mock.patch.object(ssl, 'create_default_context', autospec=True)
160 def test_use_ssl_true(self, mock_cdc):
161 CONF.set_override('use_ssl', True)
162 m_con = mock_cdc()
163 con = self.service._create_ssl_context()
164 self.assertEqual(m_con, con)
165
166 @unittest.skipIf(sys.version_info[:3] < (2, 7, 9),
167 'This feature is unsupported in this version of python '
168 'so the tests will be skipped')
169 @mock.patch.object(ssl, 'create_default_context', autospec=True)
170 def test_only_key_path_provided(self, mock_cdc):
171 CONF.set_override('use_ssl', True)
172 CONF.set_override('ssl_key_path', '/some/fake/path')
173 mock_context = mock_cdc()
174 con = self.service._create_ssl_context()
175 self.assertEqual(mock_context, con)
176 self.assertFalse(mock_context.load_cert_chain.called)
177
178 @unittest.skipIf(sys.version_info[:3] < (2, 7, 9),
179 'This feature is unsupported in this version of python '
180 'so the tests will be skipped')
181 @mock.patch.object(ssl, 'create_default_context', autospec=True)
182 def test_only_cert_path_provided(self, mock_cdc):
183 CONF.set_override('use_ssl', True)
184 CONF.set_override('ssl_cert_path', '/some/fake/path')
185 mock_context = mock_cdc()
186 con = self.service._create_ssl_context()
187 self.assertEqual(mock_context, con)
188 self.assertFalse(mock_context.load_cert_chain.called)
189
190 @unittest.skipIf(sys.version_info[:3] < (2, 7, 9),
191 'This feature is unsupported in this version of python '
192 'so the tests will be skipped')
193 @mock.patch.object(ssl, 'create_default_context', autospec=True)
194 def test_both_paths_provided(self, mock_cdc):
195 key_path = '/some/fake/path/key'
196 cert_path = '/some/fake/path/cert'
197 CONF.set_override('use_ssl', True)
198 CONF.set_override('ssl_key_path', key_path)
199 CONF.set_override('ssl_cert_path', cert_path)
200 mock_context = mock_cdc()
201 con = self.service._create_ssl_context()
202 self.assertEqual(mock_context, con)
203 mock_context.load_cert_chain.assert_called_once_with(cert_path,
204 key_path)
205
206 @unittest.skipIf(sys.version_info[:3] < (2, 7, 9),
207 'This feature is unsupported in this version of python '
208 'so the tests will be skipped')
209 @mock.patch.object(ssl, 'create_default_context', autospec=True)
210 def test_load_cert_chain_fails(self, mock_cdc):
211 CONF.set_override('use_ssl', True)
212 key_path = '/some/fake/path/key'
213 cert_path = '/some/fake/path/cert'
214 CONF.set_override('use_ssl', True)
215 CONF.set_override('ssl_key_path', key_path)
216 CONF.set_override('ssl_cert_path', cert_path)
217 mock_context = mock_cdc()
218 mock_context.load_cert_chain.side_effect = IOError('Boom!')
219 con = self.service._create_ssl_context()
220 self.assertEqual(mock_context, con)
221 mock_context.load_cert_chain.assert_called_once_with(cert_path,
222 key_path)
223
224
225class TestWSGIServiceOnSigHup(BaseWSGITest):
226 def setUp(self):
227 super(TestWSGIServiceOnSigHup, self).setUp()
228 self.mock_spawn = self.useFixture(fixtures.MockPatchObject(
229 wsgi_service.eventlet, 'spawn')).mock
230 self.mock_mutate_conf = self.useFixture(fixtures.MockPatchObject(
231 wsgi_service.CONF, 'mutate_config_files')).mock
232
233 def test_on_sighup(self):
234 self.service._handle_sighup()
235 self.mock_spawn.assert_called_once_with(self.service._handle_sighup_bg)
236
237 def test_on_sighup_bg(self):
238 self.service._handle_sighup_bg()
239 self.mock_mutate_conf.assert_called_once_with()
diff --git a/ironic_inspector/wsgi_service.py b/ironic_inspector/wsgi_service.py
index 8513e16..b42e9c9 100644
--- a/ironic_inspector/wsgi_service.py
+++ b/ironic_inspector/wsgi_service.py
@@ -10,16 +10,11 @@
10# License for the specific language governing permissions and limitations 10# License for the specific language governing permissions and limitations
11# under the License. 11# under the License.
12 12
13import signal
14import ssl
15import sys
16
17import eventlet
18from oslo_config import cfg 13from oslo_config import cfg
19from oslo_log import log 14from oslo_log import log
20from oslo_service import service 15from oslo_service import service
16from oslo_service import wsgi
21 17
22from ironic_inspector.common.rpc_service import RPCService
23from ironic_inspector import main as app 18from ironic_inspector import main as app
24from ironic_inspector import utils 19from ironic_inspector import utils
25 20
@@ -27,21 +22,22 @@ LOG = log.getLogger(__name__)
27CONF = cfg.CONF 22CONF = cfg.CONF
28 23
29 24
30class WSGIService(object): 25class WSGIService(service.Service):
31 """Provides ability to launch API from wsgi app.""" 26 """Provides ability to launch API from wsgi app."""
32 27
33 def __init__(self): 28 def __init__(self):
34 self.app = app.app 29 self.app = app.app
35 signal.signal(signal.SIGHUP, self._handle_sighup) 30 self.server = wsgi.Server(CONF, 'ironic_inspector',
36 signal.signal(signal.SIGTERM, self._handle_sigterm) 31 self.app,
37 self.rpc_service = RPCService(CONF.host) 32 host=CONF.listen_address,
33 port=CONF.listen_port,
34 use_ssl=CONF.use_ssl)
38 35
39 def _init_middleware(self): 36 def _init_middleware(self):
40 """Initialize WSGI middleware. 37 """Initialize WSGI middleware.
41 38
42 :returns: None 39 :returns: None
43 """ 40 """
44
45 if CONF.auth_strategy != 'noauth': 41 if CONF.auth_strategy != 'noauth':
46 utils.add_auth_middleware(self.app) 42 utils.add_auth_middleware(self.app)
47 else: 43 else:
@@ -49,80 +45,31 @@ class WSGIService(object):
49 ' configuration') 45 ' configuration')
50 utils.add_cors_middleware(self.app) 46 utils.add_cors_middleware(self.app)
51 47
52 def _create_ssl_context(self): 48 def start(self):
53 if not CONF.use_ssl: 49 """Start serving this service using loaded configuration.
54 return
55
56 MIN_VERSION = (2, 7, 9)
57
58 if sys.version_info < MIN_VERSION:
59 LOG.warning(('Unable to use SSL in this version of Python: '
60 '%(current)s, please ensure your version of Python '
61 'is greater than %(min)s to enable this feature.'),
62 {'current': '.'.join(map(str, sys.version_info[:3])),
63 'min': '.'.join(map(str, MIN_VERSION))})
64 return
65
66 context = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
67 if CONF.ssl_cert_path and CONF.ssl_key_path:
68 try:
69 context.load_cert_chain(CONF.ssl_cert_path, CONF.ssl_key_path)
70 except IOError as exc:
71 LOG.warning('Failed to load certificate or key from defined '
72 'locations: %(cert)s and %(key)s, will continue '
73 'to run with the default settings: %(exc)s',
74 {'cert': CONF.ssl_cert_path,
75 'key': CONF.ssl_key_path,
76 'exc': exc})
77 except ssl.SSLError as exc:
78 LOG.warning('There was a problem with the loaded certificate '
79 'and key, will continue to run with the default '
80 'settings: %s', exc)
81 return context
82
83 def shutdown(self, error=None):
84 """Stop serving API.
85 50
86 :returns: None 51 :returns: None
87 """ 52 """
88 LOG.debug('Shutting down') 53 self._init_middleware()
89 self.rpc_service.stop() 54 self.server.start()
90 sys.exit(error)
91 55
92 def run(self): 56 def stop(self):
93 """Start serving this service using loaded application. 57 """Stop serving this API.
94 58
95 :returns: None 59 :returns: None
96 """ 60 """
97 app_kwargs = {'host': CONF.listen_address, 61 self.server.stop()
98 'port': CONF.listen_port}
99
100 context = self._create_ssl_context()
101 if context:
102 app_kwargs['ssl_context'] = context
103
104 self._init_middleware()
105 62
106 LOG.info('Spawning RPC service') 63 def wait(self):
107 service.launch(CONF, self.rpc_service, 64 """Wait for the service to stop serving this API.
108 restart_method='mutate')
109 65
110 try: 66 :returns: None
111 self.app.run(**app_kwargs) 67 """
112 except Exception as e: 68 self.server.wait()
113 self.shutdown(error=str(e))
114 else:
115 self.shutdown()
116
117 def _handle_sighup_bg(self, *args):
118 """Reload config on SIGHUP."""
119 CONF.mutate_config_files()
120 69
121 def _handle_sighup(self, *args): 70 def reset(self):
122 eventlet.spawn(self._handle_sighup_bg, *args) 71 """Reset server greenpool size to default.
123 72
124 def _handle_sigterm(self, *args): 73 :returns: None
125 # This is a workaround to ensure that shutdown() is done when recieving 74 """
126 # SIGTERM. Raising KeyboardIntrerrupt which won't be caught by any 75 self.server.reset()
127 # 'except Exception' clauses.
128 raise KeyboardInterrupt
diff --git a/lower-constraints.txt b/lower-constraints.txt
index dc3c40f..64a46e8 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -73,7 +73,7 @@ oslo.middleware==3.31.0
73oslo.policy==1.30.0 73oslo.policy==1.30.0
74oslo.rootwrap==5.8.0 74oslo.rootwrap==5.8.0
75oslo.serialization==2.18.0 75oslo.serialization==2.18.0
76oslo.service==1.30.0 76oslo.service==1.24.0
77oslo.utils==3.33.0 77oslo.utils==3.33.0
78oslotest==3.2.0 78oslotest==3.2.0
79packaging==17.1 79packaging==17.1
diff --git a/releasenotes/notes/deprecate-ssl-opts-40ce8f4618c786ef.yaml b/releasenotes/notes/deprecate-ssl-opts-40ce8f4618c786ef.yaml
new file mode 100644
index 0000000..9c456f7
--- /dev/null
+++ b/releasenotes/notes/deprecate-ssl-opts-40ce8f4618c786ef.yaml
@@ -0,0 +1,7 @@
1---
2deprecations:
3 - |
4 Configuration options ``[DEFAULT]ssl_cert_path`` and
5 ``[DEFAULT]ssl_key_path`` are deprecated for ironic-inspector now uses
6 oslo.service as underlying HTTP service instead of Werkzeug. Please use
7 ``[ssl]cert_file`` and ``[ssl]key_file``. \ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index ef6c055..c0f4edc 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -29,6 +29,7 @@ oslo.middleware>=3.31.0 # Apache-2.0
29oslo.policy>=1.30.0 # Apache-2.0 29oslo.policy>=1.30.0 # Apache-2.0
30oslo.rootwrap>=5.8.0 # Apache-2.0 30oslo.rootwrap>=5.8.0 # Apache-2.0
31oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 31oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
32oslo.service!=1.28.1,>=1.24.0 # Apache-2.0
32oslo.utils>=3.33.0 # Apache-2.0 33oslo.utils>=3.33.0 # Apache-2.0
33retrying!=1.3.0,>=1.2.3 # Apache-2.0 34retrying!=1.3.0,>=1.2.3 # Apache-2.0
34six>=1.10.0 # MIT 35six>=1.10.0 # MIT
diff --git a/tools/config-generator.conf b/tools/config-generator.conf
index 47fd222..b2663b9 100644
--- a/tools/config-generator.conf
+++ b/tools/config-generator.conf
@@ -4,6 +4,9 @@ namespace = ironic_inspector
4namespace = keystonemiddleware.auth_token 4namespace = keystonemiddleware.auth_token
5namespace = oslo.db 5namespace = oslo.db
6namespace = oslo.log 6namespace = oslo.log
7namespace = oslo.messaging
7namespace = oslo.middleware.cors 8namespace = oslo.middleware.cors
8namespace = oslo.policy 9namespace = oslo.policy
9namespace = oslo.messaging 10namespace = oslo.service.service
11namespace = oslo.service.sslutils
12namespace = oslo.service.wsgi \ No newline at end of file