renamed to 'servicemanager'
the PYTHONPATH should be set to the directory above servicemanager
This commit is contained in:
parent
632beda430
commit
ff71f10ce5
@ -1,5 +1,5 @@
|
||||
# servman
|
||||
# servicemanager
|
||||
|
||||
A manager for starting, stopping and listing services/servers like frappy, nicos and sea.
|
||||
|
||||
Several instances of nicos, frappy and sea might run on the same machine.
|
||||
Several instances of nicos, frappy, sea and seweb might run on the same machine.
|
||||
|
66
__init__.py
66
__init__.py
@ -27,7 +27,65 @@ this code is currently used:
|
||||
- from a script allowing to start/stop/list (and more) multiple frappy and nicos servers
|
||||
"""
|
||||
|
||||
from servman.base import ServiceManager, ServiceDown, run, UsageError
|
||||
from servman.frappyman import FrappyManager
|
||||
from servman.nicosman import NicosManager
|
||||
from servman.seaman import SeaManager
|
||||
from servicemanager.base import ServiceManager, ServiceDown, UsageError, get_config
|
||||
from servicemanager.nicosman import NicosManager
|
||||
from servicemanager.seaman import SeaManager
|
||||
|
||||
|
||||
class FrappyManager(ServiceManager):
|
||||
group = 'frappy'
|
||||
services = ('main', 'stick', 'addons')
|
||||
USAGE = """
|
||||
Usage:
|
||||
|
||||
frappy list [<instance>]
|
||||
frappy start <instance> <service> <cfgfiles>
|
||||
frappy restart <instance> [<service>] [<cfgfiles>]
|
||||
frappy stop <instance> [<service>]
|
||||
|
||||
<service> is one of main, stick, addons
|
||||
<instance> is one of %s
|
||||
"""
|
||||
|
||||
|
||||
class SewebManager(ServiceManager):
|
||||
group = 'seweb'
|
||||
services = ('',)
|
||||
USAGE = """
|
||||
Usage:
|
||||
|
||||
seaweb list [<instance>]
|
||||
seaweb start <instance>
|
||||
seaweb restart <instance>
|
||||
seaweb stop <instance>
|
||||
|
||||
<instance> is one of %s
|
||||
"""
|
||||
|
||||
|
||||
all = NicosManager, FrappyManager, SeaManager, SewebManager
|
||||
|
||||
|
||||
def run(group, arglist):
|
||||
try:
|
||||
parser = get_config()
|
||||
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
|
||||
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:
|
||||
raise UsageError("do not know '%s'" % ' '.join([serv.group, action] + arglist))
|
||||
except UsageError as e:
|
||||
print(repr(e))
|
||||
print(serv.usage())
|
||||
|
||||
|
||||
|
59
base.py
59
base.py
@ -21,6 +21,7 @@
|
||||
# *****************************************************************************
|
||||
|
||||
|
||||
import sys
|
||||
import json
|
||||
import os
|
||||
from os.path import expanduser
|
||||
@ -65,25 +66,15 @@ def printTable(headers, items, printfunc, minlen=0, rjust=False):
|
||||
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))
|
||||
def get_config():
|
||||
parser = ConfigParser(interpolation=None)
|
||||
parser.optionxform = str
|
||||
parser.read(expanduser('~/servicemanager.cfg'))
|
||||
return parser
|
||||
|
||||
|
||||
class ServiceManager:
|
||||
services = None
|
||||
services = ['SINGLE']
|
||||
need_cfg = False
|
||||
start_dir = None
|
||||
group = None
|
||||
@ -91,6 +82,7 @@ class ServiceManager:
|
||||
virtualenv = None
|
||||
pkg = ''
|
||||
revcmd = {}
|
||||
USAGE = None
|
||||
|
||||
def __init__(self):
|
||||
self.env = {}
|
||||
@ -109,10 +101,11 @@ class ServiceManager:
|
||||
ports = {}
|
||||
nr = '%02d' % int(section[self.group])
|
||||
gr = self.group.upper()
|
||||
singlekey = gr + '_PORT'
|
||||
for service in self.services:
|
||||
sv = '%s_%s' % (gr, service.upper())
|
||||
sv = gr + '_' + service.upper()
|
||||
key = '%s_PORT' % sv
|
||||
port = section.get(key)
|
||||
port = section.get(key) or section.get(singlekey)
|
||||
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)
|
||||
@ -128,24 +121,28 @@ class ServiceManager:
|
||||
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'))
|
||||
parser = get_config()
|
||||
defaults = parser['DEFAULT']
|
||||
self.commands = {}
|
||||
# self.revcmd = {}
|
||||
|
||||
def expand_path(pathlist, ins):
|
||||
return ':'.join(expanduser(p % dict(ins=ins)) for p in pathlist.split(':'))
|
||||
def get_subs(section, key, ins, nr):
|
||||
"""get item <key> from section and substitute nr or expand filename"""
|
||||
value = section.get(key)
|
||||
if key.endswith('_PORT'):
|
||||
return value.replace('nr', nr)
|
||||
return ':'.join(expanduser(p % dict(ins=ins)) for p in value.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:
|
||||
nr = section.get(self.group)
|
||||
if nr is not None:
|
||||
nr = '%02d' % int(nr)
|
||||
self.commands[ins] = command
|
||||
services = self.get_services(section)
|
||||
env = {k: expand_path(section.get(k), ins) for k in defaults if k.isupper()}
|
||||
env = {k: get_subs(section, k, ins, nr) for k in defaults if k.isupper()}
|
||||
result[ins] = services
|
||||
self.env[ins] = env
|
||||
self.info = result
|
||||
@ -194,7 +191,7 @@ class ServiceManager:
|
||||
if match:
|
||||
gdict = match.groupdict()
|
||||
ins = gdict['ins']
|
||||
serv = gdict['serv']
|
||||
serv = gdict.get('serv', '')
|
||||
if cfginfo is not None and 'cfg' in gdict:
|
||||
cfginfo[ins, serv] = gdict['cfg']
|
||||
result.setdefault(ins, {}).setdefault(serv, []).append(p)
|
||||
@ -264,6 +261,7 @@ class ServiceManager:
|
||||
except ValueError:
|
||||
raise ValueError('do not know %r' % ins)
|
||||
services = list(service_ports) if service is None else [service]
|
||||
print('start', services, service_ports)
|
||||
if restart:
|
||||
self.stop(ins, service)
|
||||
else:
|
||||
@ -280,6 +278,7 @@ class ServiceManager:
|
||||
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)
|
||||
print('COMMAND', cmd)
|
||||
if '%(cfg)s' in self.commands[ins] and not cfg:
|
||||
cmd = self.stopped[ins].get(service_i)
|
||||
if not cmd:
|
||||
@ -338,8 +337,10 @@ class ServiceManager:
|
||||
def do_restart(self, ins, service=None, cfg=None):
|
||||
self.do_start(ins, service, cfg, True)
|
||||
|
||||
def do_run(self, ins, service, cfg=None):
|
||||
def do_run(self, ins, service=None, cfg=None):
|
||||
"""for tests: run and wait"""
|
||||
if not service:
|
||||
service, = self.services
|
||||
self.do_start(ins, service, cfg, wait=True)
|
||||
|
||||
def do_list(self, ins=None, *args):
|
||||
@ -403,3 +404,7 @@ class ServiceManager:
|
||||
if ' do_%s(' % action in errtxt and 'argument' in errtxt:
|
||||
raise UsageError(errtxt)
|
||||
raise
|
||||
|
||||
def usage(self):
|
||||
print(self.USAGE % ', '.join(self.info))
|
||||
|
||||
|
30
bin/frappy
30
bin/frappy
@ -24,31 +24,11 @@
|
||||
import sys
|
||||
from os.path import join, abspath, dirname
|
||||
|
||||
# above packages: servman, nicos, frappy, history
|
||||
# for packages: servicemanager, frappyhistory
|
||||
sys.path.insert(0, abspath(join(dirname(__file__), '../..')))
|
||||
# for frappy:
|
||||
sys.path.insert(0, abspath(join(dirname(__file__), '../../frappy')))
|
||||
|
||||
from servman import run, FrappyManager, NicosManager, SeaManager, UsageError
|
||||
from servicemanager import run
|
||||
|
||||
|
||||
NicosManager()
|
||||
serv = FrappyManager()
|
||||
SeaManager()
|
||||
|
||||
USAGE = """
|
||||
Usage:
|
||||
|
||||
frappy list [<instance>]
|
||||
frappy start <instance> <service> <cfgfiles>
|
||||
frappy restart <instance> [<service>] [<cfgfiles>]
|
||||
frappy stop <instance> [<service>]
|
||||
|
||||
<service> is one of main, stick, addons
|
||||
<instance> is one of %s
|
||||
""" % ', '.join(serv.info)
|
||||
|
||||
try:
|
||||
run(serv, sys.argv[1:])
|
||||
|
||||
except Exception as e: # TODO: change to UsageError
|
||||
print(repr(e))
|
||||
print(''.join(USAGE))
|
||||
run('frappy', sys.argv[1:])
|
||||
|
41
bin/nicos
41
bin/nicos
@ -24,42 +24,11 @@
|
||||
import sys
|
||||
from os.path import join, abspath, dirname
|
||||
|
||||
# above packages: servman, nicos, frappy, history
|
||||
# for packages: servicemanager, frappyhistory
|
||||
sys.path.insert(0, abspath(join(dirname(__file__), '../..')))
|
||||
# for nicos:
|
||||
sys.path.insert(0, abspath(join(dirname(__file__), '../../nicos')))
|
||||
|
||||
from servman import run, FrappyManager, NicosManager, SeaManager, UsageError
|
||||
from servicemanager import run
|
||||
|
||||
|
||||
serv = NicosManager()
|
||||
FrappyManager()
|
||||
SeaManager()
|
||||
|
||||
|
||||
USAGE = """
|
||||
Usage:
|
||||
|
||||
nicos gui <instance>
|
||||
nicos <instance> (the same as above)
|
||||
nicos list [<instance>]
|
||||
nicos start <instance> [<service>]
|
||||
nicos restart <instance> [<service>]
|
||||
nicos stop <instance> [<service>]
|
||||
nicos create <instance> <nr>
|
||||
nicos create all
|
||||
nicos link <instance> (create links to nicos data and scripts)
|
||||
|
||||
<service> is one of main, stick, addons
|
||||
<instance> is one of %s
|
||||
|
||||
to be done after the experiment:
|
||||
nicos copy (copy data and scripts from link)
|
||||
nicos copy [<instance> [<year>/<proposal>]] (copy specific data)
|
||||
|
||||
""" % ', '.join(serv.info)
|
||||
|
||||
try:
|
||||
run(serv, sys.argv[1:])
|
||||
|
||||
except UsageError as e:
|
||||
print(repr(e))
|
||||
print(''.join(USAGE))
|
||||
run('nicos', sys.argv[1:])
|
||||
|
32
bin/sea
32
bin/sea
@ -24,35 +24,9 @@
|
||||
import sys
|
||||
from os.path import join, abspath, dirname
|
||||
|
||||
# above packages: servman, nicos, frappy, history
|
||||
# for packages: servicemanager, frappyhistory
|
||||
sys.path.insert(0, abspath(join(dirname(__file__), '../..')))
|
||||
|
||||
from servman import run, FrappyManager, NicosManager, SeaManager, UsageError
|
||||
from servicemanager import run
|
||||
|
||||
|
||||
NicosManager()
|
||||
FrappyManager()
|
||||
serv = SeaManager()
|
||||
|
||||
USAGE = """
|
||||
Usage:
|
||||
|
||||
sea gui <instance>
|
||||
sea <instance> # the same as sea gui <instance>
|
||||
sea cli <instance> (the same as old seacmd)
|
||||
sea start <instance> <service>
|
||||
sea restart <instance> [<service>]
|
||||
sea stop <instance> [<service>]
|
||||
sea list [<instance>]
|
||||
|
||||
<service> is one of main, stick, addons
|
||||
<instance> is one of %s
|
||||
""" % ', '.join(serv.info)
|
||||
|
||||
try:
|
||||
run(serv, sys.argv[1:])
|
||||
|
||||
except Exception as e: # TODO: change to UsageError
|
||||
raise
|
||||
print(repr(e))
|
||||
print(''.join(USAGE))
|
||||
run('sea', sys.argv[1:])
|
||||
|
12
frappyman.py → bin/seweb
Normal file → Executable file
12
frappyman.py → bin/seweb
Normal file → Executable file
@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# *****************************************************************************
|
||||
#
|
||||
@ -20,9 +21,12 @@
|
||||
#
|
||||
# *****************************************************************************
|
||||
|
||||
from servman.base import ServiceManager
|
||||
import sys
|
||||
from os.path import join, abspath, dirname
|
||||
|
||||
# for packages: servicemanager, frappyhistory
|
||||
sys.path.insert(0, abspath(join(dirname(__file__), '../..')))
|
||||
|
||||
class FrappyManager(ServiceManager):
|
||||
group = 'frappy'
|
||||
services = ('main', 'stick', 'addons')
|
||||
from servicemanager import run
|
||||
|
||||
run('seweb', sys.argv[1:])
|
23
nicosman.py
23
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.base import ServiceManager
|
||||
from servicsmanager.base import ServiceManager
|
||||
|
||||
|
||||
ENV_KEYS = {
|
||||
@ -50,6 +50,27 @@ def copy_all(srcdir, dstdir):
|
||||
class NicosManager(ServiceManager):
|
||||
group = 'nicos'
|
||||
services = ('cache', 'daemon', 'poller')
|
||||
USAGE = """
|
||||
Usage:
|
||||
|
||||
nicos gui <instance>
|
||||
nicos <instance> (the same as above)
|
||||
nicos list [<instance>]
|
||||
nicos start <instance> [<service>]
|
||||
nicos restart <instance> [<service>]
|
||||
nicos stop <instance> [<service>]
|
||||
nicos create <instance> <nr>
|
||||
nicos create all
|
||||
nicos link <instance> (create links to nicos data and scripts)
|
||||
|
||||
<service> is one of main, stick, addons
|
||||
<instance> is one of %s
|
||||
|
||||
to be done after the experiment:
|
||||
nicos copy (copy data and scripts from link)
|
||||
nicos copy [<instance> [<year>/<proposal>]] (copy specific data)
|
||||
|
||||
"""
|
||||
|
||||
def do_create(self, ins, *args):
|
||||
self.get_info()
|
||||
|
25
seaman.py
25
seaman.py
@ -24,15 +24,15 @@ import sys
|
||||
import time
|
||||
import termios
|
||||
import subprocess
|
||||
from servman.base import ServiceManager
|
||||
from servman.sicsclient import sics_client
|
||||
from servicemanager.base import ServiceManager, ServiceDown
|
||||
from servicemanager.sicsclient import sics_client
|
||||
|
||||
|
||||
def run_command(cmd, wait=False):
|
||||
if wait:
|
||||
old = termios.tcgetattr(sys.stdin)
|
||||
proc = subprocess.Popen(cmd.split())
|
||||
try:
|
||||
proc = subprocess.Popen(cmd.split())
|
||||
proc.wait()
|
||||
except KeyboardInterrupt:
|
||||
proc.terminate()
|
||||
@ -47,6 +47,20 @@ def run_command(cmd, wait=False):
|
||||
class SeaManager(ServiceManager):
|
||||
group = 'sea'
|
||||
services = ('sea', 'graph')
|
||||
USAGE = """
|
||||
Usage:
|
||||
|
||||
sea gui <instance>
|
||||
sea <instance> # the same as sea gui <instance>
|
||||
sea cli <instance> (the same as old seacmd)
|
||||
sea start <instance> <service>
|
||||
sea restart <instance> [<service>]
|
||||
sea stop <instance> [<service>]
|
||||
sea list [<instance>]
|
||||
|
||||
<service> is one of main, stick, addons
|
||||
<instance> is one of %s
|
||||
"""
|
||||
|
||||
def do_cli(self, ins):
|
||||
try:
|
||||
@ -55,7 +69,7 @@ class SeaManager(ServiceManager):
|
||||
print('%s, try to start...' % e)
|
||||
self.do_start(ins)
|
||||
time.sleep(1) # make sure caller did read the message
|
||||
except KeyError as e: # running on an other machine?
|
||||
except KeyError: # running on an other machine?
|
||||
pass
|
||||
run_command('six -sea %s' % ins, wait=True)
|
||||
|
||||
@ -66,13 +80,12 @@ class SeaManager(ServiceManager):
|
||||
print('%s, try to start...' % e)
|
||||
self.do_start(ins)
|
||||
time.sleep(1) # make sure caller did read the message
|
||||
except KeyError as e: # running on an other machine?
|
||||
except KeyError: # running on an other machine?
|
||||
pass
|
||||
run_command('SeaClient %s' % ins)
|
||||
print('starting sea gui %s' % ins)
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
def get_cfg(self, ins, service):
|
||||
"""return cfg info about running programs, if relevant
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user