To use oslo.service in a project:
import oslo_service
The oslo.service library no longer assumes a global configuration object is available. Instead the following functions and classes have been changed to expect the consuming application to pass in an oslo.config configuration object:
from foo.openstack.common import service
launcher = service.launch(service, workers=2)
from oslo_config import cfg
from oslo_service import service
CONF = cfg.CONF
launcher = service.launch(CONF, service, workers=2)
The oslo.service provides several entry points to generate a configuration files.
ATTENTION: The library doesn’t provide an oslo.service entry point.
$ oslo-config-generator --namespace oslo.service.service \
--namespace oslo.service.periodic_task \
--namespace oslo.service.sslutils
oslo_service.service module provides tools for launching OpenStack services and controlling their lifecycles.
A service is an instance of any class that subclasses oslo_service.service.ServiceBase. ServiceBase is an abstract class that defines an interface every service should implement. oslo_service.service.Service can serve as a base for constructing new services.
oslo_service.service module provides two launchers for running services:
- oslo_service.service.ServiceLauncher - used for running one or more service in a parent process.
- oslo_service.service.ProcessLauncher - forks a given number of workers in which service(s) are then started.
It is possible to initialize whatever launcher is needed and then launch a service using it.
from oslo_config import cfg
from oslo_service import service
CONF = cfg.CONF
service_launcher = service.ServiceLauncher(CONF)
service_launcher.launch_service(service.Service())
process_launcher = service.ProcessLauncher(CONF, wait_interval=1.0)
process_launcher.launch_service(service.Service(), workers=2)
Or one can simply call oslo_service.service.launch() which will automatically pick an appropriate launcher based on a number of workers that are passed to it (ServiceLauncher in case workers=1 or None and ProcessLauncher in other case).
from oslo_config import cfg
from oslo_service import service
CONF = cfg.CONF
launcher = service.launch(CONF, service.Service(), workers=3)
NOTE: Please be informed that it is highly recommended to use no more than one instance of ServiceLauncher and ProcessLauncher classes per process.
oslo_service.service provides handlers for such signals as SIGTERM, SIGINT and SIGHUP.
SIGTERM is used for graceful termination of services. This can allow a server to wait for all clients to close connections while rejecting new incoming requests. Config option graceful_shutdown_timeout specifies how many seconds after receiving a SIGTERM signal, a server should continue to run, handling the existing connections. Setting graceful_shutdown_timeout to zero means that the server will wait indefinitely until all remaining requests have been fully served.
To force instantaneous termination SIGINT signal must be sent.
On receiving SIGHUP configuration files are reloaded and a service is being reset and started again. Then all child workers are gracefully stopped using SIGTERM and workers with new configuration are spawned. Thus, SIGHUP can be used for changing config options on the go.
NOTE: SIGHUP is not supported on Windows. NOTE: Config option graceful_shutdown_timeout is not supported on Windows.
Below is the example of a service with a reset method that allows reloading logging options by sending a SIGHUP.
from oslo_config import cfg
from oslo_log import log as logging
from oslo_service import service
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
class FooService(service.ServiceBase):
def start(self):
pass
def wait(self):
pass
def stop(self):
pass
def reset(self):
logging.setup(cfg.CONF, 'foo')