diff --git a/__init__.py b/__init__.py index cf3212d..a7819a0 100644 --- a/__init__.py +++ b/__init__.py @@ -57,23 +57,24 @@ def run(group, arglist): defaults = parser['DEFAULT'] managers = {cls.group: cls() for cls in all if cls.group + '_command' in defaults} serv = managers[group] - arglist = arglist + [''] # add dummy argument - if arglist[0].endswith('help'): - serv.usage() - return - action = arglist.pop(0) if hasattr(serv, 'do_' + arglist[0]) else 'gui' - instance = arglist.pop(0) if arglist[0] and arglist[0] not in serv.services else None - if instance is None and serv.main_ins: - instance = serv.main_ins - if instance is not None: - arglist.insert(0, instance) - arglist.pop() # remove dummy argument + args = dict(action='gui', ins=serv.main_ins) + extra = [] + for arg in arglist: + if hasattr(serv, 'do_' + arg): + args['action'] = arg + elif arg in serv.services: + args['service'] = arg + elif arg in serv.info: + args['ins'] = arg + else: + extra.append(arg) + print(args, extra) try: - serv.action(action, *arglist) + serv.action(args['action'], *serv.treat_args(args, extra)) except AttributeError: raise except UsageError as e: - serv.usage() + serv.do_help() print('ERROR:', str(e)) diff --git a/base.py b/base.py index 28f0b4b..17d1fb0 100644 --- a/base.py +++ b/base.py @@ -251,7 +251,7 @@ class ServiceManager: if not self.stop(ins, service): print('nothing to stop') - def prepare_start(self, ins, service): + def prepare_start(self, ins, service, cfg=''): if ins not in self.env: self.get_info() gr = self.group.upper() @@ -300,12 +300,15 @@ class ServiceManager: if not cmd: if restart and service is None: continue # silently ignore missing cfg when restarting all services - raise ValueError('missing cfg for %s %s' % (ins, service_i)) + raise UsageError('missing cfg for %s %s' % (ins, service_i)) wd = os.getcwd() try: - start_dir, env = self.prepare_start(ins, service_i) + start_dir, env = self.prepare_start(ins, service_i, cfg) env = dict(os.environ, **env) os.chdir(start_dir) + if start_dir not in sys.path: + sys.path.insert(0, start_dir) + print('SYSPATH', sys.path) if wait: proc = subprocess.Popen(cmd.split(), env=env) proc.wait() @@ -353,7 +356,10 @@ class ServiceManager: def do_run(self, ins, service=None, cfg=None): """for tests: run and wait""" if not service: - service, = self.services + try: + service, = self.services + except ValueError: + raise UsageError('need service to start (one of %s)' % ', '.join(self.services)) self.do_start(ins, service, cfg, wait=True) def do_list(self, ins=None, *args): @@ -417,10 +423,19 @@ class ServiceManager: raise UsageError(errtxt) raise - def usage(self): + def do_help(self, *args): if self.main_ins: usage = self.USAGE.replace(' ', '').replace(' []', '') % '' else: usage = self.USAGE % (' is one of %s' % ', '.join(self.info)) print(usage) + def treat_args(self, argdict, unknown=(), extra=()): + if unknown: + raise UsageError('unknown argument: %s' % (' '.join(unknown))) + if extra: + return [argdict.get('ins'), argdict.get('service')] + extra + args = [argdict.get('ins'), argdict.get('service')] + while args and not args[-1]: + args.pop() + return args diff --git a/frappyman.py b/frappyman.py index 83cb0ee..b89dcaa 100644 --- a/frappyman.py +++ b/frappyman.py @@ -56,7 +56,12 @@ class FrappyManager(ServiceManager): cfgpaths.append(cfgpath) return cfgpaths - def prepare_start(self, ins, service): + def prepare_start(self, ins, service, cfg=''): + import os + import sys + print('CWD', os.getcwd()) + print('PYTHONPATH', sys.path) + start_dir, env = super().prepare_start(ins, service) his = env.get('FRAPPY_HISTORY') if his: @@ -67,6 +72,11 @@ class FrappyManager(ServiceManager): print(env['SECOP_CONFDIR']) return start_dir, env + def do_start(self, ins, service=None, cfg='', restart=False, wait=False, logger=None): + if cfg and not service and len(self.services) != 1: + raise UsageError('need service to start (one of %s)' % ', '.join(self.services)) + super().do_start(ins, service, cfg, restart, wait, logger) + def do_gui(self, ins='', service='main'): start_dir, env = self.prepare_start(ins, service) sys.path.insert(0, start_dir) @@ -95,23 +105,42 @@ class FrappyManager(ServiceManager): return app.exec_() + def all_cfg(self, ins, service, by_dir=False): + result = {} + all_cfg = {} + for ins in [ins] if ins else self.info: + for service in [service] if service else self.services: + for cfgdir in self.config_dirs(ins, service): + result.setdefault(cfgdir, {}) + cfgs = result[cfgdir] + for cfgfile in glob(join(cfgdir, '*.cfg')): + desc = '' + try: + parser = ConfigParser() + parser.read(cfgfile) + for s in parser.sections(): + if s == 'NODE' or s.startswith('node '): + desc = parser[s].get('description', '').split('\n')[0] + break + except Exception: + pass + cfg = basename(cfgfile)[:-4] + if cfg not in all_cfg: + all_cfg[cfg] = desc + cfgs[cfg] = desc + return result if by_dir else all_cfg + def do_listcfg(self, ins='', service='main'): - for cfgdir in self.config_dirs(ins, service): - table = [] - for cfgfile in glob(join(cfgdir, '*.cfg')): - desc = '' - try: - parser = ConfigParser() - parser.read(cfgfile) - for s in parser.sections(): - if s == 'NODE' or s.startswith('node '): - desc = parser[s].get('description', '').split('\n')[0] - break - except Exception: - pass - table.append((basename(cfgfile)[:-4], desc)) - if table: + for cfgdir, cfgs in self.all_cfg(ins, service, by_dir=True).items(): + if cfgs: print('\n--- %s:\n' % cfgdir) - lcol = max(len(c) for c, _ in table) - for cfg, desc in table: - print('%s %s' % (cfg.ljust(lcol), desc)) + keylen = max(len(k) for k in cfgs) + for cfg, desc in cfgs.items(): + print('%s %s' % (cfg.ljust(keylen), desc)) + + def treat_args(self, argdict, unknown=(), extra=()): + if len(unknown) == 1: + cfg = unknown[0] + if ',' in cfg or cfg in self.all_cfg(argdict.get('ins'), argdict.get('service')): + return super().treat_args(argdict, (), unknown) + return super().treat_args(argdict, unknown, extra) diff --git a/nicosman.py b/nicosman.py index b94cc05..2f65d6e 100644 --- a/nicosman.py +++ b/nicosman.py @@ -230,7 +230,7 @@ class NicosManager(ServiceManager): src = join(data, os.readlink(join(data, 'current'))) NicosManager.copy_linked(src) - def prepare_start(self, ins, service): + def prepare_start(self, ins, service, *args): start_dir, env = super().prepare_start(ins, service) instr = '%s.%s' % (env['NICOS_PACKAGE'], ins) env['INSTRUMENT'] = instr @@ -274,3 +274,8 @@ class NicosManager(ServiceManager): pass self.run_client(ins, main, 'nicos-gui') + def treat_args(self, argdict, unknown=(), extra=()): + if argdict['action'] == 'create' and len(unknown) == 1: + return super().treat_args(argdict, (), unknown) + return super().treat_args(argdict, unknown, extra) + diff --git a/seaman.py b/seaman.py index eda3ee3..790f977 100644 --- a/seaman.py +++ b/seaman.py @@ -24,6 +24,7 @@ import sys import time import termios import subprocess +import os from servicemanager.base import ServiceManager, ServiceDown from servicemanager.sicsclient import sics_client @@ -66,21 +67,21 @@ class SeaManager(ServiceManager): try: self.check_running(ins, 'sea') except ServiceDown as e: - self.usage() + self.do_help() print(str(e)) except KeyError: # running on an other machine? - self.usage() + self.do_help() run_command('six -sea %s' % ins, wait=True) def do_gui(self, ins=''): try: self.check_running(ins, 'sea') except ServiceDown as e: - self.usage() + self.do_help() print(str(e)) return except KeyError: # running on an other machine? - self.usage() + self.do_help() run_command('SeaClient %s' % ins) print('starting sea gui %s' % ins) time.sleep(5) @@ -97,3 +98,24 @@ class SeaManager(ServiceManager): except Exception as e: print(self.info) return repr(e) + + def treat_args(self, argdict, unknown=(), extra=()): + if len(unknown) == 1: + insts = set() + filename = os.environ.get('InstrumentHostList') + if filename: + with open(filename) as fil: + for line in fil: + inst = None + sea = False + for item in line.split(): + key, _, value = item.partition('=') + if key == 'instr': + inst = value + elif key == 'sea': + sea = True + if inst and sea: + insts.add(inst) + if unknown[0] in insts: + return super().treat_args(argdict, (), unknown) + return super().treat_args(argdict, unknown, extra)