diff --git a/__init__.py b/__init__.py index 0b4deb3..d5eaa81 100644 --- a/__init__.py +++ b/__init__.py @@ -26,376 +26,8 @@ this code is currently used: - from NICOS to start and stop frappy servers - from a script allowing to start/stop/list (and more) multiple frappy and nicos servers """ -import json -import os -from os.path import expanduser -import subprocess -import time -import re -import socket -import psutil -from collections import OrderedDict, defaultdict -from configparser import ConfigParser - -class ServiceDown(Exception): - """the service is not running""" - - -class UsageError(Exception): - pass - - -def printTable(headers, items, printfunc, minlen=0, rjust=False): - """Print tabular information nicely formatted. - - accept less columns for some rows. The last item of such a row - may extend over columns. stolen from nicos.utils and modifed. - """ - if not headers and not items: - return - ncolumns = len(headers or items[0]) - rowlens = [minlen] * ncolumns - for row in [headers or []] + items: - # do not consider length of last column when row has less columns - cntrow = row if len(row) == ncolumns else row[:-1] - for i, item in enumerate(cntrow): - rowlens[i] = max(rowlens[i], len(item)) - rfmtstr = ('%%%ds ' * ncolumns) % tuple(rowlens) - lfmtstr = ('%%-%ds ' * ncolumns) % tuple(rowlens) - if headers: - printfunc(lfmtstr % tuple(headers)) - printfunc(lfmtstr % tuple('=' * n for n in rowlens)) - for row in items: - printfunc((rfmtstr if rjust else lfmtstr) % (tuple(row) + ('',) * (ncolumns - len(row)))) - - -def run(serv, arglist): - arglist = arglist + [''] # add dummy argument - 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 len(serv.info) == 1: - instance = list(serv.info)[0] - if instance is not None: - arglist.insert(0, instance) - arglist.pop() # remove dummy argument - try: - serv.action(action, *arglist) - except AttributeError as e: - raise - print(repr(e)) - raise ValueError("do not know '%s'" % ' '.join([serv.group, action] + arglist)) - - -class ServiceManager: - services = None - need_cfg = False - start_dir = None - group = None - all = {} # for the list command, we want to register all service managers - virtualenv = None - pkg = '' - revcmd = {} - - def __init__(self): - self.env = {} - self.commands = {} - # self.revcmd = {} - self.info = {} - self.all[self.group] = self - #prog, args = self.command.split(None, 1) - #self.cmdpat = re.compile('.* ' + # do not match prog, as it might be modified by the os - # (args % dict(ins=r'(?P\S*)', serv=r'(?P\S*)', - # cfg=r'(?P\S*)', port=r'\S*', pkg=r'\S*'))) - self.get_info() - self.stopped = defaultdict(dict) - - def get_services(self, section): - ports = {} - nr = '%02d' % int(section[self.group]) - gr = self.group.upper() - for service in self.services: - sv = '%s_%s' % (gr, service.upper()) - port = section.get('%s_PORT' % sv) - if port or json.loads(section.get(sv, '0').lower()): # e.g. NICOS_POLLER = True leads to port = 0 - ports[service] = int((port or '0').replace('nr', nr)) - return ports - - def get_info(self): - """returns port numbers,commands and environment variables - - the result is a dict[] of dict(ins=.., port= ..., cmd= ...) - if ins is omitted, return a list of above for all ins - """ - result = OrderedDict() - parser = ConfigParser(interpolation=None) - parser.optionxform = str - parser.read(expanduser('~/servman.cfg')) - defaults = parser['DEFAULT'] - self.commands = {} - # self.revcmd = {} - - for ins in parser.sections(): - section = dict(parser[ins]) - command = section.get('%s_command' % self.group) - self.revcmd[command] = self.group - if self.group in section: - self.commands[ins] = command - services = self.get_services(parser[ins]) - env = {k: expanduser(section.get(k) % dict(ins=ins)) - for k in defaults if k.isupper()} - result[ins] = services - self.env[ins] = env - self.info = result - - #def get_cmdpats(self, groups): - # return self.cmdpats - - def get_ins_info(self, ins): - self.get_info() - return self.info[ins] - - def get_cfg(self, ins, service): - """return cfg info about running programs, if relevant - - example for sea: return samenv name - """ - return '' - - def get_procs(self, groups=None, cfginfo=None): - """return processes - - result is a dict[ins] of dict[service] of list of tuples (process, cfg) - """ - - result = {} - cmdpatterns = [] - if groups is None: - groups = [self.group] - for cmd, group in self.revcmd.items(): - if group not in groups: - continue - args = cmd.split(None, 1)[1] - cmdpatterns.append( - re.compile('.* ' + # do not match prog, as it might be modified by the os - (args % dict(ins=r'(?P\S*)', - serv=r'(?P\S*)', - cfg=r'(?P\S*)', - port=r'\S*', - pkg=r'\S*')))) - for p in psutil.process_iter(attrs=['pid', 'cmdline']): - cmdline = p.info['cmdline'] - if cmdline: - cmd = ' '.join(cmdline) - for cmdpat in cmdpatterns: - match = cmdpat.match(cmd) - if match: - gdict = match.groupdict() - ins = gdict['ins'] - serv = gdict['serv'] - if cfginfo is not None and 'cfg' in gdict: - cfginfo[ins, serv] = gdict['cfg'] - result.setdefault(ins, {}).setdefault(serv, []).append(p) - return result - - def check_running(self, ins, service): - self.get_info() - if ins not in self.info: - raise KeyError("don't know %r" % ins) - if not self.get_procs().get(ins, {}).get(service): - raise ServiceDown('%s %s is not running' % (service, ins)) - - def stop(self, ins, service=None): - """stop service (or all services) of instance - - return a dict[][] of for all stopped processes - this information may be used for restarts - """ - procs = self.get_procs() - done = False - services = self.services if service is None else [service] - for service in reversed(services): - for p in procs.get(ins, {}).get(service, []): - print_wait = True - for action in ('terminate', 'kill'): - getattr(p, action)() # p.terminate or p.kill - for i in range(10): # total 0.1 * 10 * 9 / 2 = 4.5 sec - try: - p.wait(0.1 * i) - except psutil.TimeoutExpired: - if p.status() == psutil.STATUS_ZOMBIE: - break - if print_wait and i > 4: - print('wait for %s %s' % (ins, service)) - print_wait = False - continue - self.stopped[ins][service] = ' '.join(p.info['cmdline']) - done = True - break - else: - if action == 'kill': - action = 'kill fail' - break - continue - break - print('%s %s %s' % (ins, service, (action + 'ed').replace('eed', 'ed'))) - return done - - def do_stop(self, ins, service=None, *args): - self.get_info() - if not self.stop(ins, service): - print('nothing to stop') - - def prepare_start(self, ins): - if ins not in self.env: - self.get_info() - gr = self.group.upper() - env = self.env[ins] - return env.get('%s_ROOT' % gr, ''), env - - def do_start(self, ins, service=None, cfg='', restart=False, wait=False): - if ins is None: - print('nothing to start') - return - try: - service_ports = self.get_ins_info(ins) - except ValueError: - raise ValueError('do not know %r' % ins) - services = list(service_ports) if service is None else [service] - if restart: - self.stop(ins, service) - else: - procs = self.get_procs() - to_start = [] - for service in services: - n = len(procs.get(ins, {}).get(service, [])) - if n == 0: - to_start.append(service) - else: - count = '' if n == 1 else ' %sx' % n - print('%s %s is already running%s' % (ins, service, count)) - services = to_start - for service in services: - port = service_ports[service] - cmd = self.commands[ins] % dict(ins=ins, serv=service, port=port, cfg=cfg, pkg=self.pkg) - if '%(cfg)s' in self.commands[ins] and not cfg: - cmd = self.stopped[ins].get(service) - if not cmd: - raise ValueError('missing cfg for %s %s' % (ins, service)) - wd = os.getcwd() - try: - start_dir, env = self.prepare_start(ins) - env = dict(os.environ, **env) - os.chdir(start_dir) - if wait: - proc = subprocess.Popen(cmd.split(), env=env) - proc.wait() - return - process = subprocess.Popen(cmd.split(), env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - if not port: - print('%s %s started' % (ins, service)) - continue - - print_wait = True - for i in range(10): # total 10 * 9 / 2 = 4.5 sec - returnvalue = process.poll() - if returnvalue is not None: - print('started process finished with %r' % returnvalue) - process = subprocess.Popen(cmd.split(), env=env, stdout=subprocess.DEVNULL, - stderr=subprocess.PIPE) - try: - _, erroutput = process.communicate(timeout=10) - except subprocess.TimeoutExpired: - process.kill() - _, erroutput = process.communicate() - print(erroutput.decode()) - print('%s %s died' % (ins, service)) - break - try: - if print_wait and i > 4: - print('wait for port %s' % port) - print_wait = False - s = socket.create_connection(('localhost', port), timeout=5) - s.close() - except socket.error: - time.sleep(0.1 * i) - continue - if restart: - print('%s %s restarted' % (ins, service)) - else: - print('%s %s started' % (ins, service)) - break - else: - print(cmd) - print('starting %s %s failed' % (ins, service)) - finally: - os.chdir(wd) - - def do_restart(self, ins, service=None, cfg=None): - self.do_start(ins, service, cfg, True) - - def do_run(self, ins, service, cfg=None): - """for tests: run and wait""" - self.do_start(ins, service, cfg, wait=True) - - def do_list(self, ins=None, *args): - """info about running services""" - cfginfo = {} - procs = self.get_procs(self.all, cfginfo) - rows = [] - merged = OrderedDict() - show_unused = ins == 'all' - if show_unused: - ins = None - for group, sm in self.all.items(): - sm.get_info() - for ins_i, info_dict in sm.info.items(): - if ins is not None and ins != ins_i: - continue - for serv, port in info_dict.items(): - if ins_i not in merged: - merged[ins_i] = {g: {} for g in self.all} - merged[ins_i][group][serv] = port - for ins_i, info_dict in merged.items(): - show_ins = show_unused - run_info = [[''], [ins_i]] - procs_dict = procs.get(ins_i, {}) - for group, sm in self.all.items(): - info_grp = info_dict.get(group, {}) - for serv, port in info_grp.items(): - plist = procs_dict.get(serv) - if plist: - cfg = cfginfo.get((ins_i, serv), '') or sm.get_cfg(ins_i, serv) - if sm == self: - show_ins = True - gs = '%s %s' % (group, serv) - port = str(port or '') - run_info.append(('', gs, port, cfg)) - if len(plist) > 1: - rows.append(['', ' WARNING: multiple processes %s' - % ', '.join(str(p.pid) for p, _ in plist)]) - extra = sm.extra_info(ins_i) - if extra and show_ins: - run_info.append(['', extra]) - if show_ins: - rows.extend(run_info) - print('') - printTable(('inst', 'service', 'port', 'cfg'), rows, print) - - @staticmethod - def extra_info(ins): - """provide extra info or None""" - return None - - def action(self, action, *args): - method = getattr(self, 'do_' + action, None) - if not callable(method): - raise UsageError('%s is no valid action' % action) - try: - method(*args) - except TypeError as e: - raise - errtxt = str(e) - if ' do_%s(' % action in errtxt and 'argument' in errtxt: - raise UsageError(errtxt) - raise +from servman.base import ServiceManager, ServiceDown, run, UsageError +from servman.frappyman import FrappyManager +from servman.nicosman import NicosManager +from servman.seaman import SeaManager diff --git a/base.py b/base.py new file mode 100644 index 0000000..dd974f6 --- /dev/null +++ b/base.py @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +# ***************************************************************************** +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Module authors: +# Markus Zolliker +# +# ***************************************************************************** + + +import json +import os +from os.path import expanduser +import subprocess +import time +import re +import socket +import psutil +from collections import OrderedDict, defaultdict +from configparser import ConfigParser + + +class ServiceDown(Exception): + """the service is not running""" + + +class UsageError(Exception): + pass + + +def printTable(headers, items, printfunc, minlen=0, rjust=False): + """Print tabular information nicely formatted. + + accept less columns for some rows. The last item of such a row + may extend over columns. stolen from nicos.utils and modifed. + """ + if not headers and not items: + return + ncolumns = len(headers or items[0]) + rowlens = [minlen] * ncolumns + for row in [headers or []] + items: + # do not consider length of last column when row has less columns + cntrow = row if len(row) == ncolumns else row[:-1] + for i, item in enumerate(cntrow): + rowlens[i] = max(rowlens[i], len(item)) + rfmtstr = ('%%%ds ' * ncolumns) % tuple(rowlens) + lfmtstr = ('%%-%ds ' * ncolumns) % tuple(rowlens) + if headers: + printfunc(lfmtstr % tuple(headers)) + printfunc(lfmtstr % tuple('=' * n for n in rowlens)) + for row in items: + printfunc((rfmtstr if rjust else lfmtstr) % (tuple(row) + ('',) * (ncolumns - len(row)))) + + +def run(serv, arglist): + arglist = arglist + [''] # add dummy argument + 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 len(serv.info) == 1: + instance = list(serv.info)[0] + if instance is not None: + arglist.insert(0, instance) + arglist.pop() # remove dummy argument + try: + serv.action(action, *arglist) + except AttributeError as e: + raise + print(repr(e)) + raise ValueError("do not know '%s'" % ' '.join([serv.group, action] + arglist)) + + +class ServiceManager: + services = None + need_cfg = False + start_dir = None + group = None + all = {} # for the list command, we want to register all service managers + virtualenv = None + pkg = '' + revcmd = {} + + def __init__(self): + self.env = {} + self.commands = {} + # self.revcmd = {} + self.info = {} + self.all[self.group] = self + #prog, args = self.command.split(None, 1) + #self.cmdpat = re.compile('.* ' + # do not match prog, as it might be modified by the os + # (args % dict(ins=r'(?P\S*)', serv=r'(?P\S*)', + # cfg=r'(?P\S*)', port=r'\S*', pkg=r'\S*'))) + self.get_info() + self.stopped = defaultdict(dict) + + def get_services(self, section): + ports = {} + nr = '%02d' % int(section[self.group]) + gr = self.group.upper() + for service in self.services: + sv = '%s_%s' % (gr, service.upper()) + key = '%s_PORT' % sv + port = section.get(key) + if port or json.loads(section.get(sv, '0').lower()): + # e.g. NICOS_POLLER = True leads to port = 0 + port = (port or '0').replace('nr', nr) + ports[service] = int(port) + if key in section: # update replaced nr + section[key] = port + return ports + + def get_info(self): + """returns port numbers,commands and environment variables + + the result is a dict[] of dict(ins=.., port= ..., cmd= ...) + if ins is omitted, return a list of above for all ins + """ + result = OrderedDict() + parser = ConfigParser(interpolation=None) + parser.optionxform = str + parser.read(expanduser('~/servman.cfg')) + defaults = parser['DEFAULT'] + self.commands = {} + # self.revcmd = {} + + def expand_path(pathlist, ins): + return ':'.join(expanduser(p % dict(ins=ins)) for p in pathlist.split(':')) + + for ins in parser.sections(): + section = dict(parser[ins]) + command = section.get('%s_command' % self.group) + self.revcmd[command] = self.group + if self.group in section: + self.commands[ins] = command + services = self.get_services(section) + env = {k: expand_path(section.get(k), ins) for k in defaults if k.isupper()} + result[ins] = services + self.env[ins] = env + self.info = result + + #def get_cmdpats(self, groups): + # return self.cmdpats + + def get_ins_info(self, ins): + self.get_info() + return self.info[ins] + + def get_cfg(self, ins, service): + """return cfg info about running programs, if relevant + + example for sea: return samenv name + """ + return '' + + def get_procs(self, groups=None, cfginfo=None): + """return processes + + result is a dict[ins] of dict[service] of list of tuples (process, cfg) + """ + + result = {} + cmdpatterns = [] + if groups is None: + groups = [self.group] + for cmd, group in self.revcmd.items(): + if group not in groups: + continue + args = cmd.split(None, 1)[1] + cmdpatterns.append( + re.compile('.* ' + # do not match prog, as it might be modified by the os + (args % dict(ins=r'(?P\S*)', + serv=r'(?P\S*)', + cfg=r'(?P\S*)', + port=r'\S*', + pkg=r'\S*')))) + for p in psutil.process_iter(attrs=['pid', 'cmdline']): + cmdline = p.info['cmdline'] + if cmdline: + cmd = ' '.join(cmdline) + for cmdpat in cmdpatterns: + match = cmdpat.match(cmd) + if match: + gdict = match.groupdict() + ins = gdict['ins'] + serv = gdict['serv'] + if cfginfo is not None and 'cfg' in gdict: + cfginfo[ins, serv] = gdict['cfg'] + result.setdefault(ins, {}).setdefault(serv, []).append(p) + return result + + def check_running(self, ins, service): + self.get_info() + if ins not in self.info: + raise KeyError("don't know %r" % ins) + if not self.get_procs().get(ins, {}).get(service): + raise ServiceDown('%s %s is not running' % (service, ins)) + + def stop(self, ins, service=None): + """stop service (or all services) of instance + + return a dict[][] of for all stopped processes + this information may be used for restarts + """ + procs = self.get_procs() + done = False + services = self.services if service is None else [service] + for service in reversed(services): + for p in procs.get(ins, {}).get(service, []): + print_wait = True + for action in ('terminate', 'kill'): + getattr(p, action)() # p.terminate or p.kill + for i in range(10): # total 0.1 * 10 * 9 / 2 = 4.5 sec + try: + p.wait(0.1 * i) + except psutil.TimeoutExpired: + if p.status() == psutil.STATUS_ZOMBIE: + break + if print_wait and i > 4: + print('wait for %s %s' % (ins, service)) + print_wait = False + continue + self.stopped[ins][service] = ' '.join(p.info['cmdline']) + done = True + break + else: + if action == 'kill': + action = 'kill fail' + break + continue + break + print('%s %s %s' % (ins, service, (action + 'ed').replace('eed', 'ed'))) + return done + + def do_stop(self, ins, service=None, *args): + self.get_info() + if not self.stop(ins, service): + print('nothing to stop') + + def prepare_start(self, ins): + if ins not in self.env: + self.get_info() + gr = self.group.upper() + env = self.env[ins] + return env.get('%s_ROOT' % gr, ''), env + + def do_start(self, ins, service=None, cfg='', restart=False, wait=False): + if ins is None: + print('nothing to start') + return + try: + service_ports = self.get_ins_info(ins) + except ValueError: + raise ValueError('do not know %r' % ins) + services = list(service_ports) if service is None else [service] + if restart: + self.stop(ins, service) + else: + procs = self.get_procs() + to_start = [] + for service in services: + n = len(procs.get(ins, {}).get(service, [])) + if n == 0: + to_start.append(service) + else: + count = '' if n == 1 else ' %sx' % n + print('%s %s is already running%s' % (ins, service, count)) + services = to_start + for service_i in services: + port = service_ports[service_i] + cmd = self.commands[ins] % dict(ins=ins, serv=service_i, port=port, cfg=cfg, pkg=self.pkg) + if '%(cfg)s' in self.commands[ins] and not cfg: + cmd = self.stopped[ins].get(service_i) + if not cmd: + if restart and service is None: + continue # silently ignore missign cfg when restarting all services + raise ValueError('missing cfg for %s %s' % (ins, service_i)) + wd = os.getcwd() + try: + start_dir, env = self.prepare_start(ins) + env = dict(os.environ, **env) + os.chdir(start_dir) + if wait: + proc = subprocess.Popen(cmd.split(), env=env) + proc.wait() + return + process = subprocess.Popen(cmd.split(), env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + if not port: + print('%s %s started' % (ins, service_i)) + continue + + print_wait = True + for i in range(10): # total 10 * 9 / 2 = 4.5 sec + returnvalue = process.poll() + if returnvalue is not None: + print('started process finished with %r' % returnvalue) + process = subprocess.Popen(cmd.split(), env=env, stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE) + try: + _, erroutput = process.communicate(timeout=10) + except subprocess.TimeoutExpired: + process.kill() + _, erroutput = process.communicate() + print(erroutput.decode()) + print('%s %s died' % (ins, service_i)) + break + try: + if print_wait and i > 4: + print('wait for port %s' % port) + print_wait = False + s = socket.create_connection(('localhost', port), timeout=5) + s.close() + except socket.error: + time.sleep(0.1 * i) + continue + if restart: + print('%s %s restarted' % (ins, service_i)) + else: + print('%s %s started' % (ins, service_i)) + break + else: + print(cmd) + print('starting %s %s failed' % (ins, service_i)) + finally: + os.chdir(wd) + + def do_restart(self, ins, service=None, cfg=None): + self.do_start(ins, service, cfg, True) + + def do_run(self, ins, service, cfg=None): + """for tests: run and wait""" + self.do_start(ins, service, cfg, wait=True) + + def do_list(self, ins=None, *args): + """info about running services""" + cfginfo = {} + procs = self.get_procs(self.all, cfginfo) + rows = [] + merged = OrderedDict() + show_unused = ins == 'all' + if show_unused: + ins = None + for group, sm in self.all.items(): + sm.get_info() + for ins_i, info_dict in sm.info.items(): + if ins is not None and ins != ins_i: + continue + for serv, port in info_dict.items(): + if ins_i not in merged: + merged[ins_i] = {g: {} for g in self.all} + merged[ins_i][group][serv] = port + for ins_i, info_dict in merged.items(): + show_ins = show_unused + run_info = [[''], [ins_i]] + procs_dict = procs.get(ins_i, {}) + for group, sm in self.all.items(): + info_grp = info_dict.get(group, {}) + for serv, port in info_grp.items(): + plist = procs_dict.get(serv) + if plist: + cfg = cfginfo.get((ins_i, serv), '') or sm.get_cfg(ins_i, serv) + if sm == self: + show_ins = True + gs = '%s %s' % (group, serv) + port = str(port or '') + run_info.append(('', gs, port, cfg)) + if len(plist) > 1: + rows.append(['', ' WARNING: multiple processes %s' + % ', '.join(str(p.pid) for p, _ in plist)]) + extra = sm.extra_info(ins_i) + if extra and show_ins: + run_info.append(['', extra]) + if show_ins: + rows.extend(run_info) + print('') + printTable(('inst', 'service', 'port', 'cfg'), rows, print) + + @staticmethod + def extra_info(ins): + """provide extra info or None""" + return None + + def action(self, action, *args): + method = getattr(self, 'do_' + action, None) + if not callable(method): + raise UsageError('%s is no valid action' % action) + try: + method(*args) + except TypeError as e: + raise + errtxt = str(e) + if ' do_%s(' % action in errtxt and 'argument' in errtxt: + raise UsageError(errtxt) + raise diff --git a/bin/frappy b/bin/frappy index 4f529a2..34ea398 100755 --- a/bin/frappy +++ b/bin/frappy @@ -22,14 +22,13 @@ # ***************************************************************************** import sys -from os.path import join, abspath +from os.path import join, abspath, dirname -sys.path.insert(1, abspath(join(__file__, '../../..'))) +# above packages: servman, nicos, frappy, history +sys.path.insert(0, abspath(join(dirname(__file__), '../..'))) + +from servman import run, FrappyManager, NicosManager, SeaManager, UsageError -from servman.frappy import FrappyManager -from servman.nicos import NicosManager -from servman.sea import SeaManager -from servman import run NicosManager() serv = FrappyManager() @@ -50,6 +49,6 @@ Usage: try: run(serv, sys.argv[1:]) -except Exception as e: +except Exception as e: # TODO: change to UsageError print(repr(e)) print(''.join(USAGE)) diff --git a/bin/nicos b/bin/nicos index 0b9b42b..c94a174 100755 --- a/bin/nicos +++ b/bin/nicos @@ -21,20 +21,14 @@ # # ***************************************************************************** -import os -from os.path import join, abspath, expanduser import sys +from os.path import join, abspath, dirname -#nicos_root = os.environ.get('NICOS_ROOT', expanduser('~/nicos')) -#pkg_dir = abspath(join(nicos_root, 'nicos_linse')) -#sys.path.insert(1, join(pkg_dir, 'common')) +# above packages: servman, nicos, frappy, history +sys.path.insert(0, abspath(join(dirname(__file__), '../..'))) -sys.path.insert(1, abspath(join(__file__, '../../..'))) +from servman import run, FrappyManager, NicosManager, SeaManager, UsageError -from servman.frappy import FrappyManager -from servman.nicos import NicosManager -from servman.sea import SeaManager -from servman import run, UsageError serv = NicosManager() FrappyManager() diff --git a/bin/nicos-cache b/bin/nicos-cache index 46bbe2b..0ccc40d 100755 --- a/bin/nicos-cache +++ b/bin/nicos-cache @@ -24,13 +24,16 @@ # # ***************************************************************************** -from __future__ import absolute_import, division, print_function - import argparse import sys -from os import path, environ +from os import path, environ, chdir + +root = path.dirname(path.dirname(path.dirname(path.realpath(__file__)))) +nicos_root = path.join(root, 'nicos') +sys.path.insert(0, nicos_root) +# above packages: +sys.path.insert(1, root) -sys.path.insert(0, path.dirname(path.dirname(path.dirname(path.realpath(__file__))))) parser = argparse.ArgumentParser() parser.add_argument('-d', '--daemon', dest='daemon', action='store_true', diff --git a/bin/nicos-daemon b/bin/nicos-daemon index 6b918c1..f9edf24 100755 --- a/bin/nicos-daemon +++ b/bin/nicos-daemon @@ -25,13 +25,16 @@ # ***************************************************************************** -from __future__ import absolute_import, division, print_function - import argparse import sys -from os import path, environ +from os import path, environ, chdir + +root = path.dirname(path.dirname(path.dirname(path.realpath(__file__)))) +nicos_root = path.join(root, 'nicos') +sys.path.insert(0, nicos_root) +# above packages: +sys.path.insert(1, root) -sys.path.insert(0, path.dirname(path.dirname(path.dirname(path.realpath(__file__))))) parser = argparse.ArgumentParser() parser.add_argument('-d', '--daemon', dest='daemon', action='store_true', diff --git a/bin/nicos-poller b/bin/nicos-poller index 68be43b..878db1a 100755 --- a/bin/nicos-poller +++ b/bin/nicos-poller @@ -24,13 +24,16 @@ # # ***************************************************************************** -from __future__ import absolute_import, division, print_function - import argparse import sys -from os import path, environ +from os import path, environ, chdir + +root = path.dirname(path.dirname(path.dirname(path.realpath(__file__)))) +nicos_root = path.join(root, 'nicos') +sys.path.insert(0, nicos_root) +# above packages: +sys.path.insert(1, root) -sys.path.insert(0, path.dirname(path.dirname(path.dirname(path.realpath(__file__))))) parser = argparse.ArgumentParser() parser.add_argument('-d', '--daemon', dest='daemon', action='store_true', diff --git a/bin/sea b/bin/sea index d9e8e13..f4e1dc0 100755 --- a/bin/sea +++ b/bin/sea @@ -21,20 +21,14 @@ # # ***************************************************************************** -import os -from os.path import join, abspath, split, dirname, expanduser import sys +from os.path import join, abspath, dirname -#nicos_root = os.environ.get('NICOS_ROOT', expanduser('~/nicos')) -#pkg_dir = abspath(join(nicos_root, 'nicos_linse')) -#sys.path.insert(1, join(pkg_dir, 'common')) +# above packages: servman, nicos, frappy, history +sys.path.insert(0, abspath(join(dirname(__file__), '../..'))) -sys.path.insert(1, abspath(join(__file__, '../../..'))) +from servman import run, FrappyManager, NicosManager, SeaManager, UsageError -from servman import run -from servman.frappy import FrappyManager -from servman.nicos import NicosManager -from servman.sea import SeaManager NicosManager() FrappyManager() @@ -58,7 +52,7 @@ Usage: try: run(serv, sys.argv[1:]) -except Exception as e: +except Exception as e: # TODO: change to UsageError raise print(repr(e)) print(''.join(USAGE)) diff --git a/frappy.py b/frappyman.py similarity index 95% rename from frappy.py rename to frappyman.py index e690724..14ec5d8 100644 --- a/frappy.py +++ b/frappyman.py @@ -20,8 +20,7 @@ # # ***************************************************************************** -import re -from servman import ServiceManager +from servman.base import ServiceManager class FrappyManager(ServiceManager): diff --git a/nicos.py b/nicosman.py similarity index 82% rename from nicos.py rename to nicosman.py index eea4345..ab0c03d 100644 --- a/nicos.py +++ b/nicosman.py @@ -26,7 +26,7 @@ import shutil from glob import glob from os.path import join, abspath, dirname, expanduser, exists, islink from configparser import ConfigParser -from servman import ServiceManager +from servman.base import ServiceManager ENV_KEYS = { @@ -51,8 +51,7 @@ class NicosManager(ServiceManager): group = 'nicos' services = ('cache', 'daemon', 'poller') - def do_create(self, ins, nr=None, *args): - """TODO: redo""" + def do_create(self, ins, *args): self.get_info() if ins == 'all' or ins == 'check': inslist = list(self.info) @@ -76,7 +75,7 @@ class NicosManager(ServiceManager): cp = ConfigParser() cp.optionsxform = str cp.read(nicos_conf) - if set(cp.sections) != set(content): + if set(cp.sections()) != set(content): oldcontent = None else: oldcontent = {key: cp[key] for key in content} @@ -84,38 +83,13 @@ class NicosManager(ServiceManager): oldcontent = None if content != oldcontent: cp = ConfigParser() - cp.optionsxform = str + cp.optionxform = str + os.makedirs(base, exist_ok=True) for key, sdict in content.items(): cp[key] = sdict - cp.write(nicos_conf + 'x') - - # pdir = self.start_dir - # if ins is None or ins == 'common': - # raise ValueError("nothing to do") - # insdict = {info['cache']['port'] % 100: ins_i for ins_i, info in self.info.items()} - # nrdict = {v: k for k, v in insdict.items()} - # if nr is not None: - # nr = int(nr) - # if ins == 'all': - # if nr is not None: - # raise ValueError("'nicos create all' has no argument") - # action = 'update' - # else: - # if nr is None: - # nr = nrdict.get(ins) - # if nr is None: - # raise ValueError('%s not known, has to specified' % ins) - # if insdict.get(nr, ins) != ins: - # raise ValueError('%d conflicts with %s' % (nr, insdict[nr])) - # action = 'create' if ins in insdict.values() else 'update' - # insdict = {nr: ins} - # for nr, ins in insdict.items(): - # print('%s %3d %s %s' % (action, nr, ins, pdir)) - # os.makedirs(join(pdir, ins), exist_ok=True) - # with open(join(pdir, ins, 'nicos.conf'), 'w') as f: - # f.write(NICOS_CONF % dict(insnr='%02d' % nr, ins=ins, sea=8630 + nr, - # logroot=os.environ.get('NICOS_LOG'))) - # shutil.copyfile(join(pdir, 'common', 'guiconfig.py'), join(pdir, ins, 'guiconfig.py')) + with open(nicos_conf, 'w') as fd: + cp.write(fd) + shutil.copyfile(join(base, '..', 'common', 'guiconfig.py'), join(base, 'guiconfig.py')) @staticmethod def extra_info(ins): @@ -249,7 +223,6 @@ class NicosManager(ServiceManager): def do_gui(self, ins): self.prepare_client(ins) - print(os.getcwd()) from nicos.clients.gui.main import main userpath = expanduser('~/.config/nicos_%s' % ins) print('starting nicos gui %s' % ins, userpath) diff --git a/sea.py b/seaman.py similarity index 98% rename from sea.py rename to seaman.py index e9f1ff6..f29fa48 100644 --- a/sea.py +++ b/seaman.py @@ -24,7 +24,7 @@ import sys import time import termios import subprocess -from servman import ServiceManager, ServiceDown +from servman.base import ServiceManager from servman.sicsclient import sics_client