variant with config as mixin
This commit is contained in:
+17
-17
@@ -17,20 +17,20 @@
|
||||
# Markus Zolliker <markus.zolliker@psi.ch>
|
||||
# *****************************************************************************
|
||||
|
||||
from configparser import ConfigParser
|
||||
|
||||
|
||||
def read_config(filename):
|
||||
parser = ConfigParser()
|
||||
parser.optxform = str
|
||||
parser.read([str(filename)])
|
||||
return {k: dict(parser[k].items()) for k in parser.sections()}
|
||||
|
||||
|
||||
def write_config(filename, newvalues):
|
||||
parser = ConfigParser()
|
||||
parser.optxform = str
|
||||
parser.read([str(filename)])
|
||||
parser.read_dict(newvalues)
|
||||
with open(filename, 'w') as f:
|
||||
parser.write(f)
|
||||
# from configparser import ConfigParser
|
||||
#
|
||||
#
|
||||
# def read_config(filename):
|
||||
# parser = ConfigParser()
|
||||
# parser.optxform = str
|
||||
# parser.read([str(filename)])
|
||||
# return {k: dict(parser[k].items()) for k in parser.sections()}
|
||||
#
|
||||
#
|
||||
# def write_config(filename, newvalues):
|
||||
# parser = ConfigParser()
|
||||
# parser.optxform = str
|
||||
# parser.read([str(filename)])
|
||||
# parser.read_dict(newvalues)
|
||||
# with open(filename, 'w') as f:
|
||||
# parser.write(f)
|
||||
|
||||
@@ -31,6 +31,7 @@ frappy_ports = 15000-15009
|
||||
MARCHESRC = ['/home/software/marche', '/home/l_samenv/marche']
|
||||
CFGDIRS = ['/home/linse/config', '/home/l_samenv/linse_config']
|
||||
|
||||
|
||||
def read_config(filename):
|
||||
parser = ConfigParser()
|
||||
parser.optxform = str
|
||||
@@ -94,12 +95,15 @@ class ArgError(ValueError):
|
||||
|
||||
|
||||
class Config:
|
||||
"""merge info from linsetools.cfg and instrument.cfg"""
|
||||
this = None
|
||||
single_instrument = None
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, instrument=None):
|
||||
configfile = Path('/sq_sw/linse/etc/linsetools.cfg')
|
||||
self.sections = read_config(configfile)
|
||||
if Path('/home/l_samenv').is_dir():
|
||||
# TODO: make it more elegant (this is a hack)
|
||||
for section_name, section in self.sections.items():
|
||||
for key, value in section.items():
|
||||
if value.startswith('/home/linse'):
|
||||
@@ -118,10 +122,23 @@ class Config:
|
||||
write_config(instconfig, self.instruments)
|
||||
except PermissionError:
|
||||
pass
|
||||
if len(self.instruments) == 1:
|
||||
self.single_instrument = list(self.instruments)[0]
|
||||
this = self.instruments.pop('this', None)
|
||||
if this:
|
||||
self.this = this['instrument']
|
||||
self.instruments[self.this] = this
|
||||
if not self.this:
|
||||
self.this = self.single_instrument
|
||||
|
||||
if instrument:
|
||||
self.instance = instrument or 'this'
|
||||
self.instrument = self.this if self.instance == 'this' else self.instance
|
||||
self.ins_config = self.instruments[self.instrument]
|
||||
self.init()
|
||||
|
||||
def init(self):
|
||||
pass
|
||||
|
||||
def parse_args(self, argmap, args, other=None):
|
||||
result = {}
|
||||
@@ -198,17 +215,14 @@ def wait_status(cl, service):
|
||||
return True
|
||||
|
||||
|
||||
class MarcheControl:
|
||||
class MarcheControl(Config):
|
||||
port = 8124
|
||||
otherarg = None
|
||||
argmap = {k: 'action' for k in ('start', 'restart', 'stop', 'gui', 'run', 'cli', 'list', 'listcfg')}
|
||||
argmap = {k: 'action' for k in ('start', 'restart', 'stop', 'gui', 'run', 'cli', 'list', 'listcfg', 'running')}
|
||||
|
||||
def __init__(self, instrument=None, host='localhost', port=None, user=None, config=None):
|
||||
self.config = config or Config()
|
||||
def __init__(self, instrument=None, host='localhost', port=None, user=None):
|
||||
super().__init__(instrument)
|
||||
self.host = host
|
||||
self.instance = instrument or 'this'
|
||||
self.instrument = self.config.this if self.instance == 'this' else self.instance
|
||||
self.ins_config = self.config.instruments[self.instrument]
|
||||
self.user = user or self.instrument # SINQ instruments
|
||||
if not (Path('/home') / self.user).is_dir():
|
||||
self.user = 'l_samenv'
|
||||
@@ -291,6 +305,5 @@ class MarcheControl:
|
||||
else:
|
||||
instruments = [instrument]
|
||||
for ins in instruments:
|
||||
print('---', ins)
|
||||
control = cls(ins, config=config)
|
||||
control.do(**argdict)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import re
|
||||
import os
|
||||
from pathlib import Path
|
||||
from .base import MarcheControl, Logger, ArgError, write_content
|
||||
from .base import MarcheControl, Logger, ArgError, write_content, Config
|
||||
|
||||
|
||||
WRAPPER_CFG = """interface = '{port}'
|
||||
@@ -11,12 +11,30 @@ overrideNode(interface=interface)
|
||||
WRAPPER_PAT = re.compile(r"interface\s=\s*'(\d*)'\s*\n")
|
||||
|
||||
|
||||
class FrappyConfig:
|
||||
class FrappyConfig(Config):
|
||||
log = None
|
||||
process_file = None
|
||||
|
||||
def init(self, host='localhost'):
|
||||
superconfig = self.sections['superfrappy']
|
||||
self.wrapperdir = superconfig.get('wrapperdir')
|
||||
if not Path(self.wrapperdir).is_dir():
|
||||
raise ValueError(f'{self.wrapperdir} does not exist')
|
||||
self.cfgdirs = superconfig.get('cfgdirs')
|
||||
frappy_ports = self.ins_config.get('frappy_ports', '0')
|
||||
ports = frappy_ports.split('-')
|
||||
self.frappy_ports = list(range(int(ports[0]), int(ports[-1])))
|
||||
self.frappy_servers = [f'{host}:{p}' for p in self.frappy_ports]
|
||||
|
||||
def service_from_uri(self, uri):
|
||||
try:
|
||||
idx = self.frappy_servers.index(uri)
|
||||
return {0: 'main', 1: 'stick'}.get(idx, 'addons')
|
||||
except ValueError:
|
||||
return ''
|
||||
|
||||
@classmethod
|
||||
def get(cls, cfgfile):
|
||||
def read_config(cls, cfgfile):
|
||||
if not cls.process_file:
|
||||
import logging
|
||||
from frappy.config import process_file
|
||||
@@ -32,30 +50,26 @@ class FrappyControl(MarcheControl):
|
||||
argmap = dict(MarcheControl.argmap, all='service', **services)
|
||||
otherarg = 'cfg'
|
||||
|
||||
def __init__(self, instance, host='localhost', port=None, user=None, config=None):
|
||||
super().__init__(instance, host, port, user, config)
|
||||
superconfig = self.config.sections['superfrappy']
|
||||
self.instance = instance
|
||||
|
||||
self.wrapperdir = superconfig.get('wrapperdir')
|
||||
self.cfgdirs = superconfig.get('cfgdirs')
|
||||
frappy_ports = self.ins_config.get('frappy_ports', '0')
|
||||
ports = frappy_ports.split('-')
|
||||
self.frappy_ports = list(range(int(ports[0]), int(ports[-1])))
|
||||
self.frappy_servers = [f'{host}:{p}' for p in self.frappy_ports]
|
||||
|
||||
if not Path(self.wrapperdir).is_dir():
|
||||
raise ValueError(f'{self.wrapperdir} does not exist')
|
||||
def __init__(self, instance, host='localhost', port=None, user=None):
|
||||
super().__init__(instance, host, port, user)
|
||||
FrappyConfig.init(self, host)
|
||||
self.get_cfg_info() # do we need to update this from time to time?
|
||||
|
||||
service_from_uri = FrappyConfig.service_from_uri
|
||||
|
||||
def get_service(self, instance):
|
||||
return f'frappy.{instance}' if self.instance == 'this' else f'frappy.{self.instrument}-{instance}'
|
||||
|
||||
def wrapper_file(self, cfg):
|
||||
prefix = "" if self.instrument == 'this' else f'{self.instrument}-'
|
||||
prefix = "" if self.single_instrument else f'{self.instrument}-'
|
||||
return Path(self.wrapperdir) / f'{prefix}{cfg}_cfg.py'
|
||||
|
||||
def cfg_file(self, cfgdirs, service, cfg):
|
||||
"""find config file
|
||||
|
||||
if service is empty, accept configuration files for all services
|
||||
return (the found or given service, Path(cfgfile))
|
||||
"""
|
||||
if '/' in cfg:
|
||||
return Path(cfg)
|
||||
cfgpy = f'{cfg}_cfg.py'
|
||||
@@ -86,12 +100,13 @@ class FrappyControl(MarcheControl):
|
||||
self.get_cfg_info()
|
||||
run_state = run_state or self.status('frappy')
|
||||
result = {}
|
||||
prefix = '' if self.single_instrument else f'{self.instrument}-'
|
||||
for host_port, cfg in self.cfg_info.items():
|
||||
host, port = host_port.split(':')
|
||||
if host == 'localhost':
|
||||
on, busy, _ = run_state.get(cfg, (0,0,0))
|
||||
on, busy, _ = run_state.get(prefix+cfg, (0,0,0))
|
||||
if on or busy:
|
||||
result.setdefault(int(port), []).append((on, busy, cfg))
|
||||
result.setdefault(int(port), []).append((on, busy, prefix+cfg))
|
||||
return {sorted(v)[-1][-1]: k for k, v in result.items()}
|
||||
|
||||
def get_port(self, service):
|
||||
@@ -110,18 +125,19 @@ class FrappyControl(MarcheControl):
|
||||
def add_frappy_service(self, service, cfg, port, log=None):
|
||||
if log is None:
|
||||
log = Logger('info')
|
||||
log.info('add %r port=%r', cfg, port)
|
||||
servicedir, cfgfile = self.cfg_file(self.cfgdirs, service, cfg)
|
||||
service, cfgfile = self.cfg_file(self.cfgdirs, service, cfg)
|
||||
if not port:
|
||||
if not service:
|
||||
raise ArgError('service is not given and can not be determined from cfg file location')
|
||||
port = self.get_port(service)
|
||||
log.info('add %r port=%r', cfg, port)
|
||||
wrapper_content = WRAPPER_CFG.format(cfg=str(cfgfile), port=port)
|
||||
cfgname = cfgfile.stem.removesuffix('_cfg')
|
||||
write_content(self.wrapper_file(cfgname), wrapper_content, group='+rw')
|
||||
wrapper_file = self.wrapper_file(cfgname)
|
||||
write_content(wrapper_file, wrapper_content, group='+rw')
|
||||
|
||||
self.get_cfg_info()
|
||||
log.info('wrapper %r %r', self.wrapper_file(cfgname), wrapper_content)
|
||||
log.info('wrapper %s %r', wrapper_file, wrapper_content)
|
||||
self.reload()
|
||||
log.info('registered %r', cfgname)
|
||||
return f'localhost:{port}'
|
||||
@@ -130,7 +146,10 @@ class FrappyControl(MarcheControl):
|
||||
"""get info from wrapper dir"""
|
||||
result = {}
|
||||
for cfgfile in Path(self.wrapperdir).glob('*_cfg.py'):
|
||||
cfg = cfgfile.stem[:-4]
|
||||
ins, _, cfg = cfgfile.stem[:-4].rpartition('-')
|
||||
ins = ins or self.single_instrument
|
||||
if ins != self.instrument:
|
||||
continue
|
||||
match = WRAPPER_PAT.match(cfgfile.read_text())
|
||||
if match:
|
||||
result[f'localhost:{match.group(1)}'] = cfg
|
||||
@@ -148,10 +167,11 @@ class FrappyControl(MarcheControl):
|
||||
run_state = self.status('frappy')
|
||||
ports = self.get_local_ports(run_state)
|
||||
result = {}
|
||||
for cfg, port in ports.items():
|
||||
on, busy, _ = run_state.pop(cfg)
|
||||
for ins_cfg, port in ports.items():
|
||||
cfg = ins_cfg.split('-')[-1]
|
||||
on, busy, _ = run_state.pop(ins_cfg)
|
||||
if on:
|
||||
port = ports.get(cfg)
|
||||
# port = ports.get(cfg)
|
||||
kind = (self.frappy_ports + [port]).index(port)
|
||||
result[cfg] = kind, f'localhost:{port}'
|
||||
return result
|
||||
@@ -188,7 +208,7 @@ class FrappyControl(MarcheControl):
|
||||
|
||||
@staticmethod
|
||||
def get_cfg_details(cfgfile):
|
||||
mods = FrappyConfig.get(cfgfile)
|
||||
mods = FrappyConfig.read_config(cfgfile)
|
||||
node = mods.pop('node') or {}
|
||||
sea_cfg = None
|
||||
for mod, config in mods.items():
|
||||
@@ -288,6 +308,10 @@ class FrappyControl(MarcheControl):
|
||||
self.list(service or 'frappy')
|
||||
elif action == 'listcfg':
|
||||
self.listcfg(service)
|
||||
elif action == 'running':
|
||||
kinds = ['main', 'stick', 'addons']
|
||||
for cfg, (kind, uri) in self.running().items():
|
||||
print(cfg, kinds[kind], uri)
|
||||
elif action == 'gui':
|
||||
self.gui()
|
||||
elif action in ('cli', None):
|
||||
|
||||
Reference in New Issue
Block a user