Files
frappy_sinq/commands.py
Markus Zolliker 91dbc9f086 improve frappy() command
- only informational effect without arguments
- consider also cfg from sea
- on nicos restart, frappy nodes look also for sea device
2023-09-20 17:33:27 +02:00

214 lines
7.4 KiB
Python

# *****************************************************************************
#
# 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 <markus.zolliker@psi.ch>
#
# *****************************************************************************
from nicos import session, config
from nicos.utils import printTable
from nicos.commands import helparglist, usercommand
from .devices import get_frappy_config, all_info
from servicemanager import FrappyManager, SeaManager
SERVICES = FrappyManager.services
def all_info(all_cfg, prefix='currently configured: '):
info = []
addkwd = False
for srv in SERVICES:
cfginfo = all_cfg.get(srv)
if cfginfo is None:
addkwd = True
elif addkwd:
info.append('%s=%r' % (srv, cfginfo))
else:
info.append(repr(cfginfo))
return f"{prefix}frappy({', '.join(info)})"
def frappy_start(**services):
"""start/stop frappy servers
for example: frappy_start(main='xy', stick='')
- restart main server with cfg='xy'
- stop stick server
- do not touch addons server
in addition, if a newly given cfg is already used on a running server,
this cfg is removed from the server (remark: cfg might be a comma separated list)
"""
frappy_config = session.devices.get('frappy_config')
for service in SERVICES:
if services.get(service) == '':
seaconn = session.devices.get(f'se_sea_{service}')
if seaconn and seaconn._attached_secnode:
seaconn.communicate('frappy_remove %s' % service)
used_cfg = {}
all_cfg = {}
new_cfg = []
remove_cfg = []
for service in reversed(SERVICES):
secnode = session.devices.get('se_' + service)
cfginfo = services.get(service)
if cfginfo is not None:
if cfginfo:
new_cfg.append((service, secnode, cfginfo))
else:
remove_cfg.append(secnode)
if secnode:
secnode('')
if secnode:
all_cfg[service] = secnode.get_info()
# check cfg is not used twice
for cfg in (cfginfo or '').split(','):
cfg = cfg.strip()
if cfg:
prev = used_cfg.get(cfg)
if prev:
raise ValueError('%r can not be used in both %s and %s' % (cfg, prev, service))
used_cfg[cfg] = service
if new_cfg:
for service, secnode, cfginfo in new_cfg:
nodename = 'se_' + service
if not secnode:
AddSetup('frappy_' + service)
secnode = session.devices[nodename]
secnode(cfginfo)
all_cfg[service] = secnode.get_info()
CreateDevice(nodename)
cleanup_defunct()
CreateAllDevices()
if frappy_config:
frappy_config.set_envlist()
else:
applyAliasConfig()
for secnode in remove_cfg:
secnode.disable()
return all_cfg
@usercommand
def set_se_list():
fc = get_frappy_config()
if fc:
fc.set_envlist()
@usercommand
@helparglist('main [, stick [, addons]]')
def frappy(*args, main=None, stick=None, addons=None, force=False):
"""(re)start frappy server(s) with given configs and load setup if needed
- without argument: list running frappy servers, restart failed frappy servers
- frappy('<cfg>'): if available, the standard stick is added too
- frappy(''): the stick is removed too
- addons are not changed when not given
- frappy(main='<cfg>') # main cfg is changed, but stick is kept
- frappy('restart') # restart all frappy servers
- frappy(stick='restart') # restart stick frappy server
"""
fc = get_frappy_config()
if not fc:
return
stickarg = stick
confirmed = SeaManager().get_cfg(config.instrument, 'sea', True).split('/', 1)[0]
if args:
if main is not None:
raise TypeError('got multiple values for main')
main = args[0]
if len(args) == 1: # special case: main given as single argument
if main == 'restart':
stick = 'restart'
addons = 'restart'
elif stick is None: # auto stick
if main == '':
stick = '' # remove stick with main
else:
stickcfg = main + 'stick'
if FrappyManager().is_cfg(config.instrument, 'stick', stickcfg):
# if a default stick is available, start this also
stick = stickcfg
else:
stick = '' # remove stick when main has changed
else:
if stick is not None:
raise TypeError('got multiple values for stick')
stick, *alist = args[1:]
if alist:
if addons is not None:
raise TypeError('got multiple values for addons')
addons = ','.join(alist)
elif main is None and stick is None and addons is None: # bare frappy() command
fc.show_config(fc.check_services())
return
if confirmed and confirmed != main and main not in (None, 'restart') and not force:
session.log.warning('%r is plugged to the cryostat control rack', confirmed)
cmd = all_info({'main': main, 'stick': stickarg, 'addons': addons}, '')[:-1] + ', force=True)'
session.log.warning(f'if you are sure, use: %s', cmd)
raise TypeError('refuse to override plugged device')
fc.show_config(fc.start_services(main, stick, addons))
@usercommand
def frappy_main(*args):
raise NameError('frappy_main(<cfg>) is no longer avaiable, use frappy(<cfg>) instead')
@usercommand
def frappy_stick(*args):
raise NameError('frappy_stick(<cfg>) is no longer avaiable, use frappy(stick=<cfg>) instead')
@usercommand
def frappy_addons(*args):
raise NameError('frappy_addons(<cfg>) is no longer avaiable, use frappy(addons=<cfg>) instead')
@usercommand
@helparglist('')
def frappy_list(service=None):
"""list available configuration files"""
content = []
def prt(line):
content.append(line)
if service is None:
prt('Available configuration files')
prt('')
prt('Hint: if no config file can be found which matches your needs exactly')
prt('make a copy of an existing one, and change the description accordingly')
prt('')
prt('Usage (default argument "main"):')
prt('')
printTable(['command'], [['frappy_list(%r)' % s] for s in SERVICES], prt)
FrappyManager().do_listcfg(config.instrument, service or 'main', prt)
session.log.info('\n%s', '\n'.join(content))
@usercommand
def frappy_changed():
fc = get_frappy_config()
if fc:
fc.changed()