Merge "JSON RPC: add support for unix sockets and extract common code"

This commit is contained in:
Zuul 2023-12-06 18:18:44 +00:00 committed by Gerrit Code Review
commit a0e26d4f8e
4 changed files with 108 additions and 35 deletions

View File

@ -0,0 +1,22 @@
# 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.
from oslo_config import types
class Octal(types.Integer):
def __call__(self, value):
if isinstance(value, int):
return value
else:
return int(str(value), 8)

View File

@ -12,6 +12,7 @@
from oslo_config import cfg from oslo_config import cfg
from ironic_lib.common import config
from ironic_lib.common.i18n import _ from ironic_lib.common.i18n import _
from ironic_lib import keystone from ironic_lib import keystone
@ -54,6 +55,11 @@ opts = [
cfg.ListOpt('allowed_roles', cfg.ListOpt('allowed_roles',
default=['admin'], default=['admin'],
help=_("List of roles allowed to use JSON RPC")), help=_("List of roles allowed to use JSON RPC")),
cfg.StrOpt('unix_socket',
help=_('Unix socket to listen on. Disables host_ip and port.')),
cfg.Opt('unix_socket_mode', type=config.Octal(),
help=_('File mode (an octal number) of the unix socket to '
'listen on. Ignored if unix_socket is not set.')),
] ]

View File

@ -31,8 +31,6 @@ try:
import oslo_messaging import oslo_messaging
except ImportError: except ImportError:
oslo_messaging = None oslo_messaging = None
from oslo_service import service
from oslo_service import wsgi
from oslo_utils import strutils from oslo_utils import strutils
import webob import webob
@ -40,6 +38,7 @@ from ironic_lib import auth_basic
from ironic_lib.common.i18n import _ from ironic_lib.common.i18n import _
from ironic_lib import exception from ironic_lib import exception
from ironic_lib import json_rpc from ironic_lib import json_rpc
from ironic_lib import wsgi
CONF = cfg.CONF CONF = cfg.CONF
@ -100,7 +99,7 @@ class EmptyContext:
return self.__dict__.copy() return self.__dict__.copy()
class WSGIService(service.Service): class WSGIService(wsgi.WSGIService):
"""Provides ability to launch JSON RPC as a WSGI application.""" """Provides ability to launch JSON RPC as a WSGI application."""
def __init__(self, manager, serializer, context_class=EmptyContext): def __init__(self, manager, serializer, context_class=EmptyContext):
@ -130,10 +129,7 @@ class WSGIService(service.Service):
cfg.CONF.json_rpc.http_basic_auth_user_file) cfg.CONF.json_rpc.http_basic_auth_user_file)
else: else:
app = self._application app = self._application
self.server = wsgi.Server(CONF, 'ironic-json-rpc', app, super().__init__('ironic-json-rpc', app, CONF.json_rpc)
host=CONF.json_rpc.host_ip,
port=CONF.json_rpc.port,
use_ssl=CONF.json_rpc.use_ssl)
def _application(self, environment, start_response): def _application(self, environment, start_response):
"""WSGI application for conductor JSON RPC.""" """WSGI application for conductor JSON RPC."""
@ -294,31 +290,3 @@ class WSGIService(service.Service):
strutils.mask_dict_password(result) strutils.mask_dict_password(result)
if isinstance(result, dict) else result) if isinstance(result, dict) else result)
return result return result
def start(self):
"""Start serving this service using loaded configuration.
:returns: None
"""
self.server.start()
def stop(self):
"""Stop serving this API.
:returns: None
"""
self.server.stop()
def wait(self):
"""Wait for the service to stop serving this API.
:returns: None
"""
self.server.wait()
def reset(self):
"""Reset server greenpool size to default.
:returns: None
"""
self.server.reset()

77
ironic_lib/wsgi.py Normal file
View File

@ -0,0 +1,77 @@
# 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 socket
from oslo_config import cfg
from oslo_service import service
from oslo_service import wsgi
from ironic_lib import utils
CONF = cfg.CONF
class WSGIService(service.ServiceBase):
def __init__(self, name, app, conf):
"""Initialize, but do not start the WSGI server.
:param name: The name of the WSGI server given to the loader.
:param app: WSGI application to run.
:param conf: Object to load configuration from.
:returns: None
"""
self.name = name
self._conf = conf
if conf.unix_socket:
utils.unlink_without_raise(conf.unix_socket)
self.server = wsgi.Server(CONF, name, app,
socket_family=socket.AF_UNIX,
socket_file=conf.unix_socket,
socket_mode=conf.unix_socket_mode,
use_ssl=conf.use_ssl)
else:
self.server = wsgi.Server(CONF, name, app,
host=conf.host_ip,
port=conf.port,
use_ssl=conf.use_ssl)
def start(self):
"""Start serving this service using loaded configuration.
:returns: None
"""
self.server.start()
def stop(self):
"""Stop serving this API.
:returns: None
"""
self.server.stop()
if self._conf.unix_socket:
utils.unlink_without_raise(self._conf.unix_socket)
def wait(self):
"""Wait for the service to stop serving this API.
:returns: None
"""
self.server.wait()
def reset(self):
"""Reset server greenpool size to default.
:returns: None
"""
self.server.reset()