Refactor service readiness notification
import and apply Oslo systemd module drop old keystone.common.systemd drop onready configuration parameter - systemd notification is no-op when not running inside systemd Oslo commit 53e1214c092f09e3851b1a1b55289a93a72b09ec Change-Id: I80f325c9be9c171c2dc8d5526570bf64f0f87c78
This commit is contained in:
parent
e954942d44
commit
c045ea108d
|
@ -48,7 +48,7 @@ from keystone.common import sql
|
||||||
from keystone.common import utils
|
from keystone.common import utils
|
||||||
from keystone import config
|
from keystone import config
|
||||||
from keystone.openstack.common.gettextutils import _
|
from keystone.openstack.common.gettextutils import _
|
||||||
from keystone.openstack.common import importutils
|
from keystone.openstack.common import systemd
|
||||||
|
|
||||||
|
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
|
@ -83,15 +83,7 @@ def serve(*servers):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# notify calling process we are ready to serve
|
# notify calling process we are ready to serve
|
||||||
if CONF.onready:
|
systemd.notify_once()
|
||||||
try:
|
|
||||||
notifier = importutils.import_module(CONF.onready)
|
|
||||||
notifier.notify()
|
|
||||||
except ImportError:
|
|
||||||
try:
|
|
||||||
utils.check_output(CONF.onready.split())
|
|
||||||
except Exception:
|
|
||||||
logging.exception('Failed to execute onready command')
|
|
||||||
|
|
||||||
for name, server in servers:
|
for name, server in servers:
|
||||||
server.wait()
|
server.wait()
|
||||||
|
|
|
@ -54,13 +54,6 @@
|
||||||
# server. (string value)
|
# server. (string value)
|
||||||
#admin_endpoint=<None>
|
#admin_endpoint=<None>
|
||||||
|
|
||||||
# onready allows you to send a notification when the process
|
|
||||||
# is ready to serve. For example, to have it notify using
|
|
||||||
# systemd, one could set shell command: "onready = systemd-
|
|
||||||
# notify --ready" or a module with notify() method: "onready =
|
|
||||||
# keystone.common.systemd". (string value)
|
|
||||||
#onready=<None>
|
|
||||||
|
|
||||||
# Enforced by optional sizelimit middleware
|
# Enforced by optional sizelimit middleware
|
||||||
# (keystone.middleware:RequestBodySizeLimiter). (integer
|
# (keystone.middleware:RequestBodySizeLimiter). (integer
|
||||||
# value)
|
# value)
|
||||||
|
|
|
@ -69,13 +69,6 @@ FILE_OPTIONS = {
|
||||||
'to set this value if the base URL contains a path '
|
'to set this value if the base URL contains a path '
|
||||||
'(e.g. /prefix/v2.0) or the endpoint should be found '
|
'(e.g. /prefix/v2.0) or the endpoint should be found '
|
||||||
'on a different server.'),
|
'on a different server.'),
|
||||||
cfg.StrOpt('onready',
|
|
||||||
help='onready allows you to send a notification when the '
|
|
||||||
'process is ready to serve. For example, to have it '
|
|
||||||
'notify using systemd, one could set shell command: '
|
|
||||||
'"onready = systemd-notify --ready" or a module '
|
|
||||||
'with notify() method: '
|
|
||||||
'"onready = keystone.common.systemd".'),
|
|
||||||
# default max request size is 112k
|
# default max request size is 112k
|
||||||
cfg.IntOpt('max_request_body_size', default=114688,
|
cfg.IntOpt('max_request_body_size', default=114688,
|
||||||
help='Enforced by optional sizelimit middleware '
|
help='Enforced by optional sizelimit middleware '
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
# Copyright 2012 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.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Helper module for systemd start-up completion notification.
|
|
||||||
Used for "onready" configuration parameter in keystone.conf
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import socket
|
|
||||||
|
|
||||||
|
|
||||||
def _sd_notify(msg):
|
|
||||||
sysd = os.getenv('NOTIFY_SOCKET')
|
|
||||||
if sysd:
|
|
||||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
|
||||||
if sysd.startswith('@'):
|
|
||||||
# abstract namespace socket
|
|
||||||
sysd = '\0%s' % sysd[1:]
|
|
||||||
sock.connect(sysd)
|
|
||||||
sock.sendall(msg)
|
|
||||||
sock.close()
|
|
||||||
|
|
||||||
|
|
||||||
def notify():
|
|
||||||
_sd_notify('READY=1')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
notify()
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
# Copyright 2012-2014 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Helper module for systemd service readiness notification.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from keystone.openstack.common import log as logging
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _abstractify(socket_name):
|
||||||
|
if socket_name.startswith('@'):
|
||||||
|
# abstract namespace socket
|
||||||
|
socket_name = '\0%s' % socket_name[1:]
|
||||||
|
return socket_name
|
||||||
|
|
||||||
|
|
||||||
|
def _sd_notify(unset_env, msg):
|
||||||
|
notify_socket = os.getenv('NOTIFY_SOCKET')
|
||||||
|
if notify_socket:
|
||||||
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
||||||
|
try:
|
||||||
|
sock.connect(_abstractify(notify_socket))
|
||||||
|
sock.sendall(msg)
|
||||||
|
if unset_env:
|
||||||
|
del os.environ['NOTIFY_SOCKET']
|
||||||
|
except EnvironmentError:
|
||||||
|
LOG.debug("Systemd notification failed", exc_info=True)
|
||||||
|
finally:
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
|
||||||
|
def notify():
|
||||||
|
"""Send notification to Systemd that service is ready.
|
||||||
|
For details see
|
||||||
|
http://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||||
|
"""
|
||||||
|
_sd_notify(False, 'READY=1')
|
||||||
|
|
||||||
|
|
||||||
|
def notify_once():
|
||||||
|
"""Send notification once to Systemd that service is ready.
|
||||||
|
Systemd sets NOTIFY_SOCKET environment variable with the name of the
|
||||||
|
socket listening for notifications from services.
|
||||||
|
This method removes the NOTIFY_SOCKET environment variable to ensure
|
||||||
|
notification is sent only once.
|
||||||
|
"""
|
||||||
|
_sd_notify(True, 'READY=1')
|
||||||
|
|
||||||
|
|
||||||
|
def onready(notify_socket, timeout):
|
||||||
|
"""Wait for systemd style notification on the socket.
|
||||||
|
|
||||||
|
:param notify_socket: local socket address
|
||||||
|
:type notify_socket: string
|
||||||
|
:param timeout: socket timeout
|
||||||
|
:type timeout: float
|
||||||
|
:returns: 0 service ready
|
||||||
|
1 service not ready
|
||||||
|
2 timeout occured
|
||||||
|
"""
|
||||||
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
||||||
|
sock.settimeout(timeout)
|
||||||
|
sock.bind(_abstractify(notify_socket))
|
||||||
|
try:
|
||||||
|
msg = sock.recv(512)
|
||||||
|
except socket.timeout:
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
sock.close()
|
||||||
|
if 'READY=1' in msg:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# simple CLI for testing
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
notify()
|
||||||
|
elif len(sys.argv) >= 2:
|
||||||
|
timeout = float(sys.argv[1])
|
||||||
|
notify_socket = os.getenv('NOTIFY_SOCKET')
|
||||||
|
if notify_socket:
|
||||||
|
retval = onready(notify_socket, timeout)
|
||||||
|
sys.exit(retval)
|
|
@ -13,6 +13,7 @@ module=jsonutils
|
||||||
module=log
|
module=log
|
||||||
module=policy
|
module=policy
|
||||||
module=strutils
|
module=strutils
|
||||||
|
module=systemd
|
||||||
module=timeutils
|
module=timeutils
|
||||||
module=versionutils
|
module=versionutils
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue