diff --git a/daemon/core/service.py b/daemon/core/service.py index ccd19354..ddca4fc4 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -63,7 +63,8 @@ class CoreServices(ConfigurableManager): for path in paths.split(','): path = path.strip() self.importcustom(path) - + self.isStartupService = startup.Startup.isStartupService + def importcustom(self, path): ''' Import services from a myservices directory. ''' @@ -217,24 +218,25 @@ class CoreServices(ConfigurableManager): ''' services = sorted(node.services, key=lambda service: service._startindex) + useStartupService = any(map(self.isStartupService, services)) for s in services: if len(str(s._starttime)) > 0: try: t = float(s._starttime) if t > 0.0: fn = self.bootnodeservice - self.session.evq.add_event(t, fn, node, s, services) + self.session.evq.add_event(t, fn, node, s, services, False) continue except ValueError: pass - self.bootnodeservice(node, s, services) + self.bootnodeservice(node, s, services, useStartupService) - def bootnodeservice(self, node, s, services): + def bootnodeservice(self, node, s, services, useStartupService): ''' Start a service on a node. Create private dirs, generate config files, and execute startup commands. ''' if s._custom: - self.bootnodecustomservice(node, s, services) + self.bootnodecustomservice(node, s, services, useStartupService) return if node.verbose: node.info("starting service %s (%s)" % (s._name, s._startindex)) @@ -247,6 +249,8 @@ class CoreServices(ConfigurableManager): for filename in s.getconfigfilenames(node.objid, services): cfg = s.generateconfig(node, filename, services) node.nodefile(filename, cfg) + if useStartupService and not self.isStartupService(s): + return for cmd in s.getstartup(node, services): try: # NOTE: this wait=False can be problematic! @@ -254,7 +258,7 @@ class CoreServices(ConfigurableManager): except Exception, e: node.warn("error starting command %s: %s" % (cmd, e)) - def bootnodecustomservice(self, node, s, services): + def bootnodecustomservice(self, node, s, services, useStartupService): ''' Start a custom service on a node. Create private dirs, use supplied config files, and execute supplied startup commands. ''' @@ -284,6 +288,9 @@ class CoreServices(ConfigurableManager): continue node.nodefile(filename, cfg) + if useStartupService and not self.isStartupService(s): + return + for cmd in s._startup: try: # NOTE: this wait=False can be problematic! diff --git a/daemon/core/services/__init__.py b/daemon/core/services/__init__.py index 52ced896..b1117fe3 100644 --- a/daemon/core/services/__init__.py +++ b/daemon/core/services/__init__.py @@ -3,4 +3,4 @@ Services available to nodes can be put in this directory. Everything listed in __all__ is automatically loaded by the main core module. """ -__all__ = ["quagga", "nrl", "xorp", "bird", "utility", "security", "ucarp", "dockersvc"] +__all__ = ["quagga", "nrl", "xorp", "bird", "utility", "security", "ucarp", "dockersvc", 'startup'] diff --git a/daemon/core/services/startup.py b/daemon/core/services/startup.py new file mode 100644 index 00000000..8039ee62 --- /dev/null +++ b/daemon/core/services/startup.py @@ -0,0 +1,37 @@ +from core.service import CoreService, addservice +from sys import maxint +from inspect import isclass + +class Startup(CoreService): + 'A CORE service to start other services in order, serially' + _name = 'startup' + _group = 'Utility' + _depends = () + _dirs = () + _configs = ('startup.sh', ) + _startindex = maxint + _startup = ('sh startup.sh', ) + _shutdown = () + _validate = () + + @staticmethod + def isStartupService(s): + return isinstance(s, Startup) or \ + (isclass(s) and issubclass(s, Startup)) + + @classmethod + def generateconfig(cls, node, filename, services): + if filename != cls._configs[0]: + return '' + script = '#!/bin/sh\n' \ + '# auto-generated by Startup (startup.py)\n\n' \ + 'exec > startup.log 2>&1\n\n' + for s in sorted(services, key = lambda x: x._startindex): + if cls.isStartupService(s) or len(str(s._starttime)) > 0: + continue + start = '\n'.join(s.getstartup(node, services)) + if start: + script += start + '\n' + return script + +addservice(Startup)