move files in from repo git.psi.ch/sinqdev/nicos-sinq
This commit is contained in:
150
devices.py
Normal file
150
devices.py
Normal file
@ -0,0 +1,150 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# *****************************************************************************
|
||||
# NICOS, the Networked Instrument Control System of the MLZ
|
||||
# Copyright (c) 2009-2018 by the NICOS contributors (see AUTHORS)
|
||||
#
|
||||
# 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>
|
||||
#
|
||||
# *****************************************************************************
|
||||
"""managing SECoP server and connections
|
||||
|
||||
SEC Node with added functionality for starting and stoping frappy servers
|
||||
connected to a SEC node
|
||||
"""
|
||||
|
||||
import os
|
||||
from os.path import expanduser
|
||||
|
||||
from nicos import config, session
|
||||
from nicos.core import Override, Param, Moveable, status
|
||||
from nicos.devices.secop import SecNodeDevice
|
||||
from nicos.utils.comparestrings import compare
|
||||
from servicemanager import FrappyManager
|
||||
|
||||
|
||||
def suggest(poi, allowed_keys):
|
||||
comp = {}
|
||||
for key in allowed_keys:
|
||||
comp[key] = compare(poi, key)
|
||||
comp = sorted(comp.items(), key=lambda t: t[1], reverse=True)
|
||||
return [m[0] for m in comp[:3] if m[1] > 2]
|
||||
|
||||
|
||||
class FrappyNode(SecNodeDevice, Moveable):
|
||||
"""SEC node device
|
||||
|
||||
with ability to start / restart / stop the frappy server
|
||||
"""
|
||||
|
||||
parameter_overrides = {
|
||||
'target': Override(description='configuration for the frappy server or host:port',
|
||||
type=str, default=''),
|
||||
}
|
||||
parameters = {
|
||||
'service': Param('frappy service name (main, stick or addons)', type=str, default=''),
|
||||
}
|
||||
|
||||
_service_manager = FrappyManager()
|
||||
_cfgvalue = None
|
||||
|
||||
def doStart(self, value):
|
||||
if value == 'None':
|
||||
value = None
|
||||
self.restart(value)
|
||||
|
||||
def doStop(self):
|
||||
"""never busy"""
|
||||
|
||||
def doRead(self, maxage=0):
|
||||
if self._cfgvalue is None and self._cache:
|
||||
self._cfgvalue = self._cache.get(self, 'value')
|
||||
return self._cfgvalue
|
||||
|
||||
@classmethod
|
||||
def config_dirs(cls, ins, service):
|
||||
sm = cls._service_manager
|
||||
sm.get_info()
|
||||
return sm.config_dirs(ins, service)
|
||||
|
||||
@classmethod
|
||||
def available_cfg(cls, service):
|
||||
ins = config.instrument
|
||||
available_cfg = set()
|
||||
for d in cls.config_dirs(ins, service):
|
||||
try:
|
||||
available_cfg |= set(c[:-4] for c in os.listdir(expanduser(d)) if c.endswith('.cfg'))
|
||||
except FileNotFoundError: # ignore missing directories
|
||||
pass
|
||||
return available_cfg
|
||||
|
||||
def disable(self):
|
||||
seaconn = session.devices.get('seaconn')
|
||||
if seaconn and seaconn._attached_secnode:
|
||||
seaconn.communicate('frappy_remove %s' % self.service)
|
||||
self._set_status(*self._status)
|
||||
|
||||
def _set_status(self, code, text):
|
||||
if self.uri == '':
|
||||
code, text = status.DISABLED, 'disabled'
|
||||
SecNodeDevice._set_status(self, code, text)
|
||||
|
||||
def restart(self, cfg=None):
|
||||
"""restart frappy server
|
||||
|
||||
if value is not given: restart with the same config
|
||||
else restart with given config
|
||||
"""
|
||||
was_cfg = self._cfgvalue and ':' not in self._cfgvalue
|
||||
if cfg is None: # do restart anyway
|
||||
cfg = self._cfgvalue
|
||||
elif cfg == self._cfgvalue: # probably called from doStart
|
||||
if cfg == '':
|
||||
self.disable()
|
||||
# do not restart in this case
|
||||
return
|
||||
is_cfg = cfg and ':' not in cfg
|
||||
ins = config.instrument
|
||||
info = self._service_manager.get_ins_info(ins)
|
||||
if is_cfg:
|
||||
available_cfg = self.available_cfg(self.service)
|
||||
failed = False
|
||||
for cfgitem in cfg.split(','):
|
||||
if cfgitem not in available_cfg:
|
||||
failed = True
|
||||
suggestions = suggest(cfgitem, available_cfg)
|
||||
if suggestions:
|
||||
session.log.error('%s unknown, did you mean: %s' % (cfgitem, ', '.join(suggestions)))
|
||||
if failed:
|
||||
raise ValueError('use "frappy_list()" to get a list of valid frappy configurations')
|
||||
uri = 'localhost:%d' % info[self.service]
|
||||
else:
|
||||
uri = cfg
|
||||
if uri != self.uri:
|
||||
self.uri = '' # disconnect
|
||||
if was_cfg:
|
||||
self._service_manager.do_stop(ins, self.service)
|
||||
if uri:
|
||||
if is_cfg:
|
||||
self._service_manager.do_restart(ins, self.service, cfg, self.log)
|
||||
self.uri = uri # connect
|
||||
else:
|
||||
self.disable()
|
||||
self._cfgvalue = cfg
|
||||
if self._cache:
|
||||
self._cache.put(self, 'value', cfg)
|
||||
self._setROParam('target', cfg)
|
Reference in New Issue
Block a user