1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
# 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 copy
import functools
import logging
import os
import typing
from oslo_config import cfg
if typing.TYPE_CHECKING:
from cotyledon import Service
from cotyledon import ServiceManager
from cotyledon import types
LOG = logging.getLogger(__name__)
ReloadMethod: typing.TypeAlias = typing.Literal["reload", "mutate"]
service_opts = [
cfg.BoolOpt(
"log_options",
default=True,
mutable=True,
help="Enables or disables logging values of all "
"registered options when starting a service (at DEBUG "
"level).",
),
cfg.IntOpt(
"graceful_shutdown_timeout",
mutable=True,
default=60,
help="Specify a timeout after which a gracefully shutdown "
"server will exit. Zero value means endless wait.",
),
]
OsloConfigT: typing.TypeAlias = typing.Any
def _load_service_manager_options(
service_manager: "ServiceManager",
conf: OsloConfigT,
) -> None:
service_manager._graceful_shutdown_timeout = conf.graceful_shutdown_timeout # noqa: SLF001
if conf.log_options:
LOG.debug("Full set of CONF:")
conf.log_opt_values(LOG, logging.DEBUG)
def _load_service_options(service: "Service", conf: OsloConfigT) -> None:
if conf.log_options:
LOG.debug("Full set of CONF:")
conf.log_opt_values(LOG, logging.DEBUG)
def _configfile_reload(conf: OsloConfigT, reload_method: ReloadMethod) -> None:
if reload_method == "reload":
conf.reload_config_files()
elif reload_method == "mutate":
conf.mutate_config_files()
def _new_worker_hook(
conf: OsloConfigT,
reload_method: ReloadMethod,
service_id: "types.ServiceId",
worker_id: "types.WorkerId",
service: "Service",
) -> None:
def _service_reload(service: "Service") -> None:
_configfile_reload(conf, reload_method)
_load_service_options(service, conf)
real_reload = service.reload
def reload(self: "Service") -> None:
_service_reload(self)
real_reload()
_load_service_options(service, conf)
def register_opts(conf: OsloConfigT) -> None:
conf.register_opts(service_opts)
def unregister_opts(conf: OsloConfigT) -> None:
conf.unregister_opts(service_opts)
def link(
service_manager: "ServiceManager",
conf: OsloConfigT,
reload_method: ReloadMethod = "reload",
) -> None:
"""Link services configuration and hooks from oslo config object.
oslo_config_glue.register_opts() must be called first to register required options.
It reads ServiceManager and Service configuration options from an
oslo_config.ConfigOpts() object. Also It registers a ServiceManager hook to
reload the configuration file on reload in the master process and in all
children. And then when each child start or reload, the configuration
options are logged if the oslo config option 'log_options' is True.
On children, the configuration file is reloaded before the running the
application reload method.
Options currently supported on ServiceManager and Service:
* graceful_shutdown_timeout
:param service_manager: ServiceManager instance
:type service_manager: cotyledon.ServiceManager
:param conf: Oslo Config object
:type conf: oslo_config.ConfigOpts()
:param reload_method: reload or mutate the config files
:type reload_method: str "reload/mutate"
"""
# Set cotyledon options from oslo config options
_load_service_manager_options(service_manager, conf)
def _service_manager_reload() -> None:
_configfile_reload(conf, reload_method)
_load_service_manager_options(service_manager, conf)
if os.name != "posix":
# NOTE(sileht): reloading can't be supported oslo.config is not pickle
# But we don't care SIGHUP is not support on window
return
service_manager.register_hooks(
on_new_worker=functools.partial(_new_worker_hook, conf, reload_method),
on_reload=_service_manager_reload,
)
def setup(
service_manager: "ServiceManager",
conf: OsloConfigT,
reload_method: ReloadMethod = "reload",
) -> None:
"""Setup oslo config options registry and load services configuration from them
:param service_manager: ServiceManager instance
:type service_manager: cotyledon.ServiceManager
:param conf: Oslo Config object
:type conf: oslo_config.ConfigOpts()
:param reload_method: reload or mutate the config files
:type reload_method: str "reload/mutate"
"""
register_opts(conf)
link(service_manager, conf, reload_method)
def list_opts() -> list[typing.Any]:
"""Entry point for oslo-config-generator."""
return [(None, copy.deepcopy(service_opts))]
|