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
|
===============================
Oslo.service migration examples
===============================
This example shows the same application with oslo.service and cotyledon.
It uses a wide range of API of oslo.service, but most applications don't
really uses all of this. In most case cotyledon.ServiceManager don't
need to inherited.
It doesn't show how to replace the periodic task API, if you use it
you should take a look to `futurist documentation`_
oslo.service typical application:
.. code-block:: python
import multiprocessing
from oslo.service import service
from oslo.config import cfg
class MyService(service.Service):
def __init__(self, conf):
# called before os.fork()
self.conf = conf
self.master_pid = os.getpid()
self.queue = multiprocessing.Queue()
def start(self):
# called when application start (parent process start)
# and
# called just after os.fork()
if self.master_pid == os.getpid():
do_master_process_start()
else:
task = self.queue.get()
do_child_process_start(task)
def stop(self):
# called when children process stop
# and
# called when application stop (parent process stop)
if self.master_pid == os.getpid():
do_master_process_stop()
else:
do_child_process_stop()
def restart(self):
# called on SIGHUP
if self.master_pid == os.getpid():
do_master_process_reload()
else:
# Can't be reach oslo.service currently prefers to
# kill the child process for safety purpose
do_child_process_reload()
class MyOtherService(service.Service):
pass
class MyThirdService(service.Service):
pass
def main():
conf = cfg.ConfigOpts()
service = MyService(conf)
launcher = service.launch(conf, service, workers=2, restart_method='reload')
launcher.launch_service(MyOtherService(), worker=conf.other_workers)
# Obviously not recommanded, because two objects will handle the
# lifetime of the masterp process but some application does this, so...
launcher2 = service.launch(conf, MyThirdService(), workers=2, restart_method='restart')
launcher.wait()
launcher2.wait()
# Here, we have no way to change the number of worker dynamically.
Cotyledon version of the typical application:
.. code-block:: python
import cotyledon
from cotyledon import oslo_config_glue
class MyService(cotyledon.Service):
name = "MyService fancy name that will showup in 'ps xaf'"
# Everything in this object will be called after os.fork()
def __init__(self, worker_id, conf, queue):
self.conf = conf
self.queue = queue
def run(self):
# Optional method to run the child mainloop or whatever
task = self.queue.get()
do_child_process_start(task)
def terminate(self):
do_child_process_stop()
def reload(self):
# Done on SIGHUP after the configuration file reloading
do_child_reload()
class MyOtherService(cotyledon.Service):
name = "Second Service"
class MyThirdService(cotyledon.Service):
pass
class MyServiceManager(cotyledon.ServiceManager):
def __init__(self, conf)
super(MetricdServiceManager, self).__init__()
self.conf = conf
oslo_config_glue.setup(self, self.conf, restart_method='reload')
self.queue = multiprocessing.Queue()
# the queue is explicitly passed to this child (it will live
# on all of them due to the usage of os.fork() to create children)
sm.add(MyService, workers=2, args=(self.conf, queue))
self.other_id = sm.add(MyOtherService, workers=conf.other_workers)
sm.add(MyThirdService, workers=2)
def run(self):
do_master_process_start()
super(MyServiceManager, self).run()
do_master_process_stop()
def reload(self):
# The cotyledon ServiceManager have already reloaded the oslo.config files
do_master_process_reload()
# Allow to change the number of worker for MyOtherService
self.reconfigure(self.other_id, workers=self.conf.other_workers)
def main():
conf = cfg.ConfigOpts()
MyServiceManager(conf).run()
Other examples can be found here:
* :doc:`examples`
* https://github.com/openstack/gnocchi/blob/master/gnocchi/cli.py#L287
* https://github.com/openstack/ceilometer/blob/master/ceilometer/cmd/collector.py
.. _futurist documentation: <http://docs.openstack.org/developer/futurist/api.html#periodics>`
|