Merge "Introduce abstract base class for services"
This commit is contained in:
commit
e5c23386a8
@ -15,14 +15,27 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Generic Node base class for all workers that run on hosts."""
|
||||
"""Generic Node base class for all workers that run on hosts.
|
||||
|
||||
This module provides two launchers for running services:
|
||||
|
||||
* ServiceLauncher - used for running one or more service in
|
||||
a parent process.
|
||||
* ProcessLauncher - forks a given number of workers in which
|
||||
service(s) are then started.
|
||||
|
||||
Please be informed that it is highly recommended to use no more than
|
||||
one instance of ServiceLauncher and ProcessLauncher classes per process.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import errno
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import signal
|
||||
import six
|
||||
import sys
|
||||
import time
|
||||
|
||||
@ -87,6 +100,30 @@ def _set_signals_handler(handler):
|
||||
signal.signal(signal.SIGHUP, handler)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ServiceBase(object):
|
||||
"""Base class for all services."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def start(self):
|
||||
"""Start service."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def stop(self):
|
||||
"""Stop service."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def wait(self):
|
||||
"""Wait for service to complete."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def reset(self):
|
||||
"""Reset service.
|
||||
|
||||
Called in case service running in daemon mode receives SIGHUP.
|
||||
"""
|
||||
|
||||
|
||||
class Launcher(object):
|
||||
"""Launch one or more services and wait for them to complete."""
|
||||
|
||||
@ -421,7 +458,7 @@ class ProcessLauncher(object):
|
||||
self._wait_child()
|
||||
|
||||
|
||||
class Service(object):
|
||||
class Service(ServiceBase):
|
||||
"""Service object for binaries running on hosts."""
|
||||
|
||||
def __init__(self, threads=1000):
|
||||
@ -497,6 +534,9 @@ class Services(object):
|
||||
|
||||
|
||||
def launch(service, workers=1):
|
||||
if not isinstance(service, ServiceBase):
|
||||
raise TypeError("Service %(service)s must be subclass of %(base)s!"
|
||||
% {'service': service, 'base': ServiceBase})
|
||||
if workers is None or workers == 1:
|
||||
launcher = ServiceLauncher()
|
||||
launcher.launch_service(service)
|
||||
|
@ -373,6 +373,12 @@ class LauncherTest(test_base.BaseTestCase):
|
||||
service.launch(svc, workers=3)
|
||||
mock_launch.assert_called_with(svc, workers=3)
|
||||
|
||||
def test_launch_wrong_service_base_class(self):
|
||||
# check that services that do not subclass service.ServiceBase
|
||||
# can not be launched.
|
||||
svc = mock.Mock()
|
||||
self.assertRaises(TypeError, service.launch, svc)
|
||||
|
||||
|
||||
class ProcessLauncherTest(test_base.BaseTestCase):
|
||||
|
||||
|
@ -5,4 +5,5 @@
|
||||
Babel>=1.3
|
||||
eventlet>=0.17.3
|
||||
oslo.config>=1.11.0 # Apache-2.0
|
||||
six>=1.9.0
|
||||
oslo.i18n>=1.5.0 # Apache-2.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user