5
from twisted.application.service import Application, Service
6
from twisted.application.app import startApplication
8
from landscape.log import rotate_logs
9
from landscape.reactor import TwistedReactor
10
from landscape.deployment import get_versioned_persist, init_logging
11
from landscape.lib import bpickle_dbus
14
class LandscapeService(Service, object):
15
"""Utility superclass for defining Landscape services.
17
This sets up the reactor and L{Persist} object.
19
@cvar service_name: The lower-case name of the service. This is used to
20
generate the bpickle and the Unix socket filenames.
21
@ivar config: A L{Configuration} object.
22
@ivar reactor: A L{TwistedReactor} object.
23
@ivar persist: A L{Persist} object, if C{persist_filename} is defined.
24
@ivar factory: A L{LandscapeComponentProtocolFactory}, it must be provided
25
by instances of sub-classes.
27
reactor_factory = TwistedReactor
28
persist_filename = None
30
def __init__(self, config):
32
bpickle_dbus.install()
33
self.reactor = self.reactor_factory()
34
if self.persist_filename:
35
self.persist = get_versioned_persist(self)
36
if not (self.config is not None and self.config.ignore_sigusr1):
37
signal.signal(signal.SIGUSR1, lambda signal, frame: rotate_logs())
38
self.socket = os.path.join(self.config.sockets_path,
39
self.service_name + ".sock")
41
def startService(self):
42
Service.startService(self)
43
logging.info("%s started with config %s" % (
44
self.service_name.capitalize(), self.config.get_config_filename()))
45
self.port = self.reactor.listen_unix(self.socket, self.factory)
47
def stopService(self):
48
self.port.stopListening()
49
Service.stopService(self)
50
logging.info("%s stopped with config %s" % (
51
self.service_name.capitalize(), self.config.get_config_filename()))
54
def run_landscape_service(configuration_class, service_class, args):
55
"""Run a Landscape service.
57
This function instantiates the specified L{LandscapeService} subclass and
58
attaches the resulting service object to a Twisted C{Application}. After
59
that it starts the Twisted L{Application} and calls the
60
L{TwistedReactor.run} method of the L{LandscapeService}'s reactor.
62
@param configuration_class: The service-specific subclass of
63
L{Configuration} used to parse C{args} and build the C{service_class}
65
@param service_class: The L{LandscapeService} subclass to create and start.
66
@param args: Command line arguments used to initialize the configuration.
68
# Let's consider adding this:
69
# from twisted.python.log import (
70
# startLoggingWithObserver, PythonLoggingObserver)
71
# startLoggingWithObserver(PythonLoggingObserver().emit, setStdout=False)
73
configuration = configuration_class()
74
configuration.load(args)
75
init_logging(configuration, service_class.service_name)
76
application = Application("landscape-%s" % (service_class.service_name,))
77
service = service_class(configuration)
78
service.setServiceParent(application)
79
startApplication(application, False)
81
if configuration.ignore_sigint:
82
signal.signal(signal.SIGINT, signal.SIG_IGN)