Oslo Service
oslo.service is a Python library that provides a robust framework for defining and running long-running services within the OpenStack ecosystem. It encapsulates patterns for service management, including handling concurrency, periodic operations, WSGI applications, and integration with systemd. The library is actively maintained as part of the OpenStack Oslo project, with version 4.5.1 being the latest as of February 2026, and receives regular updates.
Common errors
-
OSError: Server unexpectedly closed connection
cause Often indicates a dropped connection to the message broker (e.g., RabbitMQ) due to network issues, broker overload, or missed heartbeats.fixCheck network connectivity between the service and RabbitMQ. Review RabbitMQ logs for errors like 'missed heartbeats from client'. Consider increasing `rabbit_heartbeat_timeout_threshold` in `oslo.config` to tolerate brief network hiccups. -
oslo_messaging.exceptions.MessageUndeliverable
cause A message could not be delivered to its intended recipient, typically because the target queue does not exist or the connection was lost before delivery.fixEnsure the receiving service is running and its message queues are properly initialized. Verify that the routing keys and topics configured for message publication match the expected queue bindings on the consumer side. Check RabbitMQ management interface for queue existence.
Warnings
- breaking Future versions of oslo.service are removing the Eventlet dependency, which will significantly impact services heavily relying on Eventlet's green thread model for concurrency (e.g., `loopingcall`, `periodic task`, `wsgi`, `threadgroup`). This is a mandatory architectural shift within OpenStack.
- gotcha Encountering 'oslo_config.cfg.DuplicateOptError' when defining configuration options, especially in complex OpenStack deployments or when integrating multiple oslo libraries.
- gotcha Services using `oslo.messaging` may encounter `OSError: Server unexpectedly closed connection` or `oslo_messaging.exceptions.MessageUndeliverable` errors, often related to RabbitMQ issues or network instability.
Install
-
pip install oslo-service
Imports
- service
from oslo_service import service
- cfg
from oslo_config import cfg
Quickstart
import os
from oslo_config import cfg
from oslo_service import service
# Define a simple configuration option
service_opts = [
cfg.IntOpt('workers', default=1, min=1, help='Number of worker processes')
]
CONF = cfg.CONF
CONF.register_opts(service_opts, group='my_service')
class MyService(service.ServiceBase):
def __init__(self, conf):
super().__init__(conf)
self.conf = conf
self.should_stop = False
print(f"Service initialized with {self.conf.my_service.workers} workers.")
def start(self):
print(f"Service worker {os.getpid()} starting...")
# Simulate some work
# In a real service, this would be a long-running loop or event listener
def stop(self):
self.should_stop = True
print(f"Service worker {os.getpid()} stopping...")
def wait(self):
# In a real service, this would block until stop() is called
import time
while not self.should_stop:
time.sleep(0.1)
def main():
CONF(args=[], project='my_app') # Pass empty args to avoid argparse errors if not parsing CLI
# Instantiate your service
my_service_instance = MyService(CONF)
# Launch the service with workers
# Note: oslo.service's launch function creates a Launcher internally
# and manages worker processes if `workers` > 1.
# For a simple example, we often directly call the Service's methods.
# For multi-process, `service.launch` is key.
launcher = service.launch(CONF, my_service_instance, workers=CONF.my_service.workers)
print(f"Launcher started for PID {os.getpid()} with {CONF.my_service.workers} workers.")
# Wait for the service to complete (e.g., via signal handler or internal logic)
launcher.wait()
print("All services stopped.")
if __name__ == '__main__':
# To run this, you might need to install oslo.config and oslo.service
# and ideally run with python -m your_script_name
# This example demonstrates the basic structure, but running actual
# multi-worker services requires more robust signal handling and process management
# which oslo.service provides internally.
main()