result from merge with gerrit

secop subdir only

Change-Id: I65ab7049719b374ae3ec0259483e7e7d16aafcd1
This commit is contained in:
2022-03-07 17:49:08 +01:00
parent dee3514065
commit bd246c5ca7
20 changed files with 760 additions and 583 deletions

View File

@ -27,14 +27,13 @@ import ast
import configparser
import os
import sys
import threading
import time
import traceback
from collections import OrderedDict
from secop.errors import ConfigError, SECoPError
from secop.lib import formatException, get_class, getGeneralConfig
from secop.modules import Attached
from secop.errors import ConfigError
from secop.lib import formatException, get_class, generalConfig
from secop.lib.multievent import MultiEvent
from secop.params import PREDEFINED_ACCESSIBLES
try:
from daemon import DaemonContext
@ -88,7 +87,6 @@ class Server:
...
"""
self._testonly = testonly
cfg = getGeneralConfig()
self.log = parent_logger.getChild(name, True)
if not cfgfiles:
@ -113,23 +111,21 @@ class Server:
if ambiguous_sections:
self.log.warning('ambiguous sections in %s: %r' % (cfgfiles, tuple(ambiguous_sections)))
self._cfgfiles = cfgfiles
self._pidfile = os.path.join(cfg['piddir'], name + '.pid')
self.close_callbacks = []
self._pidfile = os.path.join(generalConfig.piddir, name + '.pid')
def loadCfgFile(self, cfgfile):
if not cfgfile.endswith('.cfg'):
cfgfile += '.cfg'
cfg = getGeneralConfig()
if os.sep in cfgfile: # specified as full path
filename = cfgfile if os.path.exists(cfgfile) else None
else:
for filename in [os.path.join(d, cfgfile) for d in cfg['confdir'].split(os.pathsep)]:
for filename in [os.path.join(d, cfgfile) for d in generalConfig.confdir.split(os.pathsep)]:
if os.path.exists(filename):
break
else:
filename = None
if filename is None:
raise ConfigError("Couldn't find cfg file %r in %s" % (cfgfile, cfg['confdir']))
raise ConfigError("Couldn't find cfg file %r in %s" % (cfgfile, generalConfig.confdir))
self.log.debug('Parse config file %s ...' % filename)
result = OrderedDict()
parser = configparser.ConfigParser()
@ -207,11 +203,8 @@ class Server:
self.log.info('startup done, handling transport messages')
if systemd:
systemd.daemon.notify("READY=1\nSTATUS=accepting requests")
try:
self.interface.serve_forever()
except KeyboardInterrupt as e:
self._restart = False
self.close()
self.interface.serve_forever()
self.interface.server_close()
if self._restart:
self.restart_hook()
self.log.info('restart')
@ -227,12 +220,6 @@ class Server:
self._restart = False
self.interface.shutdown()
def close(self):
self.dispatcher.close()
self.interface.server_close()
for cb in self.close_callbacks:
cb()
def _processCfg(self):
errors = []
opts = dict(self.node_cfg)
@ -277,40 +264,41 @@ class Server:
failure_traceback = traceback.format_exc()
errors.append('error creating %s' % modname)
poll_table = dict()
missing_super = set()
# all objs created, now start them up and interconnect
for modname, modobj in self.modules.items():
self.log.info('registering module %r' % modname)
self.dispatcher.register_module(modobj, modname, modobj.export)
if modobj.pollerClass is not None:
# a module might be explicitly excluded from polling by setting pollerClass to None
modobj.pollerClass.add_to_table(poll_table, modobj)
# also call earlyInit on the modules
modobj.earlyInit()
if not modobj.earlyInitDone:
modobj.log.warning('missing supercall to earlyInit')
# handle attached modules
for modname, modobj in self.modules.items():
for propname, propobj in modobj.propertyDict.items():
if isinstance(propobj, Attached):
try:
setattr(modobj, propobj.attrname or '_' + propname,
self.dispatcher.get_module(getattr(modobj, propname)))
except SECoPError as e:
errors.append('module %s, attached %s: %s' % (modname, propname, str(e)))
missing_super.add('%s was not called, probably missing super call'
% modobj.earlyInit.__qualname__)
# call init on each module after registering all
for modname, modobj in self.modules.items():
try:
modobj.initModule()
if not modobj.initModuleDone:
modobj.log.warning('missing supercall to initModule')
missing_super.add('%s was not called, probably missing super call'
% modobj.initModule.__qualname__)
except Exception as e:
if failure_traceback is None:
failure_traceback = traceback.format_exc()
errors.append('error initializing %s: %r' % (modname, e))
if self._testonly:
return
start_events = MultiEvent(default_timeout=30)
for modname, modobj in self.modules.items():
# startModule must return either a timeout value or None (default 30 sec)
start_events.name = 'module %s' % modname
modobj.startModule(start_events)
if not modobj.startModuleDone:
missing_super.add('%s was not called, probably missing super call'
% modobj.startModule.__qualname__)
errors.extend(missing_super)
if errors:
for errtxt in errors:
for line in errtxt.split('\n'):
@ -322,35 +310,20 @@ class Server:
sys.stderr.write(failure_traceback)
sys.exit(1)
if self._testonly:
return
start_events = []
for modname, modobj in self.modules.items():
event = threading.Event()
# startModule must return either a timeout value or None (default 30 sec)
timeout = modobj.startModule(started_callback=event.set) or 30
if not modobj.startModuleDone:
modobj.log.warning('missing supercall to startModule')
start_events.append((time.time() + timeout, 'module %s' % modname, event))
for poller in poll_table.values():
event = threading.Event()
# poller.start must return either a timeout value or None (default 30 sec)
timeout = poller.start(started_callback=event.set) or 30
start_events.append((time.time() + timeout, repr(poller), event))
self.log.info('waiting for modules and pollers being started')
for deadline, name, event in sorted(start_events):
if not event.wait(timeout=max(0, deadline - time.time())):
self.log.info('WARNING: timeout when starting %s' % name)
self.log.info('all modules and pollers started')
self.log.info('waiting for modules being started')
start_events.name = None
if not start_events.wait():
# some timeout happened
for name in start_events.waiting_for():
self.log.warning('timeout when starting %s' % name)
self.log.info('all modules started')
history_path = os.environ.get('FRAPPY_HISTORY')
if history_path:
try:
from secop.historywriter import FrappyHistory # pylint: disable=import-outside-toplevel
history = FrappyHistory(history_path, self.modules, self.log.getChild('history'))
self.close_callbacks.append(history.close)
except ImportError:
raise
self.log.warning('FRAPPY_HISTORY is defined, but frappyhistory package not available')
from secop_psi.historywriter import FrappyHistoryWriter # pylint: disable=import-outside-toplevel
writer = FrappyHistoryWriter(history_path, PREDEFINED_ACCESSIBLES.keys(), self.dispatcher)
# treat writer as a connection
self.dispatcher.add_connection(writer)
writer.init(self.dispatcher.handle_describe(writer, None, None))
# TODO: if ever somebody wants to implement an other history writer:
# - a general config file /etc/secp/secop.conf or <frappy repo>/etc/secop.conf
# might be introduced, which contains the log, pid and cfg directory path and