6.9 KiB
Usage
To use oslo.service in a project:
import oslo_service
Migrating to 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:
~oslo_service.eventlet_backdoor.initialize_if_enabled
- :py
oslo_service.periodic_task.PeriodicTasks
~oslo_service.service.launch
- :py
oslo_service.service.ProcessLauncher
- :py
oslo_service.service.ServiceLauncher
~oslo_service.sslutils.is_enabled
~oslo_service.sslutils.wrap
When using service from oslo-incubator
from foo.openstack.common import service
launcher = service.launch(service, workers=2)
When using oslo.service
from oslo_config import cfg
from oslo_service import service
CONF = cfg.CONF
launcher = service.launch(CONF, service, workers=2)
Using oslo.service with oslo-config-generator
The oslo.service
provides several entry points to
generate a configuration files.
oslo.service.service <oslo_service.service.list_opts>
-
The options from the service and eventlet_backdoor modules for the [DEFAULT] section.
oslo.service.periodic_task <oslo_service.periodic_task.list_opts>
-
The options from the periodic_task module for the [DEFAULT] section.
oslo.service.sslutils <oslo_service.sslutils.list_opts>
-
The options from the sslutils module for the [ssl] section.
oslo.service.wsgi <oslo_service.wsgi.list_opts>
-
The options from the wsgi module for the [DEFAULT] section.
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
Launching and controlling services
oslo_service.service module provides tools for launching OpenStack services and controlling their lifecycles.
A service is an instance of any class that subclasses :pyoslo_service.service.ServiceBase
. :pyServiceBase <oslo_service.service.ServiceBase>
is an abstract class that defines an interface every service should
implement. :pyoslo_service.service.Service
can serve as a base for
constructing new services.
Launchers
oslo_service.service module provides two launchers for running services:
- :py
oslo_service.service.ServiceLauncher
- used for running one or more service in a parent process. - :py
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
= cfg.CONF
CONF
= service.ServiceLauncher(CONF)
service_launcher
service_launcher.launch_service(service.Service())
= service.ProcessLauncher(CONF, wait_interval=1.0)
process_launcher =2) process_launcher.launch_service(service.Service(), workers
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
= cfg.CONF
CONF
= service.launch(CONF, service.Service(), workers=3) launcher
NOTE: Please be informed that it is highly recommended to use no more than one instance of ServiceLauncher and ProcessLauncher classes per process.
Signal handling
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.
The behavior on receiving SIGHUP varies based on how the service is
configured. If the launcher uses the reload
restart_method
(the default), then the service will reload its configuration and any
threads will be completely restarted. If the mutate
restart_method is used, then only the configuration options marked as
mutable will be reloaded and the service threads will not be
restarted.
See :pyoslo_service.service.Launcher
for more details on
the restart_method
parameter.
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
= cfg.CONF
CONF
= logging.getLogger(__name__)
LOG
class FooService(service.ServiceBase):
def start(self):
pass
def wait(self):
pass
def stop(self):
pass
def reset(self):
'foo') logging.setup(cfg.CONF,
Profiling
Processes spawned through oslo_service.service can be profiled (function calltrace) through eventlet_backdoor module. Service has to configure backdoor_port option to enable it's workers to listen on TCP ports. Then user can send "prof()" command to capture worker processes function calltrace.
- To start profiling send "prof()" command on processes listening port
- To stop profiling and capture "pstat" calltrace to a file, send prof command with filename as argument i.e "prof(filename)" on worker processes listening port. Stats file (in pstat format) with user provided filename by adding .prof as suffix will be generated in temp directory.
For example, to profile neutron server process (which is listening on port 8002 configured through backdoor_port option),
$ echo "prof()" | nc localhost 8002
$ neutron net-create n1; neutron port-create --name p1 n1;
$ neutron port-delete p1; neutron port-delete p1
$ echo "prof('neutron')" | nc localhost 8002
This will generate "/tmp/neutron.prof" as stats file. Later user can print the stats from the trace file like below
import pstats
= pstats.Stats('/tmp/neutron.prof')
stats stats.print_stats()