Esempio n. 1
0
class ProxiesDict(CaselessDefaultDict,Object): 
    ''' 
    Dictionary that stores PyTango.DeviceProxies/AttributeProxies
    
    It is like a normal dictionary but creates a new proxy each time 
        that the "get" method is called
        
    All keys translated to full tango URIs (fqdn=True by default)
        
    An earlier version is used in PyTangoArchiving.utils module
    
    Taurus3+ support is not tested
    '''
    def __init__(self,use_tau = False, tango_host = ''):
        self.log = Logger('ProxiesDict')
        self.log.setLogLevel('INFO')
        self.use_tau = TAU and use_tau
        self.tango_host = tango_host
        self.call__init__(CaselessDefaultDict,self.__default_factory__)
        
    def translate(self, dev):
        try:
            attr = get_attr_name(dev,False)
            if self.tango_host and ':' not in dev:
                dev = self.tango_host + '/' + dev            
            dev = get_dev_name(dev,full=True,fqdn=True).lower()
        except:
            dev = get_dev_name(dev,full=True,fqdn=False).lower()
        if attr:
            dev += '/'+attr
        return dev

    def __default_factory__(self,dev_name):
        '''
        Called by defaultdict_fromkey.__missing__ method
        If a key doesn't exists this method is called and 
        returns a proxy for a given device.
        If the proxy caused an exception (usually because device 
        doesn't exists) a None value is returned
        '''
        
        dev_name = self.translate(dev_name)
            
        if dev_name not in self.keys():
            self.log.debug( 'Getting a Proxy for %s'%dev_name)
            
            try:
                devklass,attrklass = (TAU.Device,TAU.Attribute) \
                    if self.use_tau else \
                    (PyTango.DeviceProxy,PyTango.AttributeProxy)
                klass = (devklass,attrklass)[get_attr_name(dev_name,False)]
                dev = klass(dev_name)
                
            except Exception,e:
                print('ProxiesDict: %s doesnt exist!'%dev_name)
                dev = None
        return dev
Esempio n. 2
0
    def __init__(self,
                 pattern='',
                 klass='',
                 devs_list='',
                 servers_list='',
                 hosts='',
                 loadAll=False,
                 log='WARNING',
                 logger=None,
                 tango_host='',
                 host='',
                 devices=''):
        ''' def __init__(self,pattern='', klass='',devs_list='',servers_list=''):
        The ServersDict can be initialized using any of the three argument lists or a wildcard for Database.get_server_list(pattern) 
        ServersDict('*') can be used to load all servers in database
        '''
        self.call__init__(CaselessDict, self)
        if logger is None:
            self.log = Logger('ServersDict')
            self.log.setLogLevel(log)
        else:
            self.log = logger
        self.log.debug('ServersDict(%s)' % ','.join(
            map(str, (pattern, klass, devs_list, servers_list, hosts, loadAll,
                      log, logger, tango_host))))

        ## proxies will keep a list of persistent device proxies
        self.proxies = ProxiesDict(tango_host=tango_host)
        ## db will keep a persistent link to PyTango database
        self.db = get_database() if not tango_host else get_database(
            *(tango_host.split(':')))
        self.server_names = self.keys
        self.servers = self.values

        if loadAll: self.load_all_servers()
        elif klass: self.load_by_class(klass)
        elif devs_list: self.load_from_devs_list(devs_list)
        elif devices: self.load_from_devs_list(devices)
        elif servers_list:
            self.load_from_servers_list(servers_list)
            #elif pattern: self.load_from_servers_list(self.db.get_server_list(pattern))
        elif hosts:
            hosts = type(hosts) is str and (',' in hosts and hosts.split(',')
                                            or [hosts]) or hosts
            for h in hosts:
                self.load_by_host(h)
        elif host:
            self.load_by_host(host)
        elif pattern:
            self.load_by_name(pattern)
Esempio n. 3
0
 def __init__(self,pattern='',klass='',devs_list='',servers_list='',hosts='',loadAll=False,log='WARNING',logger=None,tango_host=''):
     ''' def __init__(self,pattern='', klass='',devs_list='',servers_list=''):
     The ServersDict can be initialized using any of the three argument lists or a wildcard for Database.get_server_list(pattern) 
     ServersDict('*') can be used to load all servers in database
     '''
     self.call__init__(CaselessDict,self)
     if logger is None:
         self.log = Logger('ServersDict')
         self.log.setLogLevel(log)
     else: self.log=logger
     self.log.debug('ServersDict(%s)'%','.join(map(str,(pattern,klass,devs_list,servers_list,hosts,loadAll,log,logger,tango_host))))
     
     ## proxies will keep a list of persistent device proxies
     self.proxies = ProxiesDict()
     ## db will keep a persistent link to PyTango database
     self.db = get_database() if not tango_host else get_database(*(tango_host.split(':')))
     self.server_names = self.keys
     self.servers = self.values
             
     if loadAll: self.load_all_servers()
     elif klass: self.load_by_class(klass)
     elif devs_list: self.load_from_devs_list(devs_list)
     elif servers_list: self.load_from_servers_list(servers_list)
     #elif pattern: self.load_from_servers_list(self.db.get_server_list(pattern))
     elif hosts: 
         hosts = type(hosts) is str and (',' in hosts and hosts.split(',') or [hosts]) or hosts
         for h in hosts: self.load_by_host(h)
     elif pattern: self.load_by_name(pattern)
    def __init__(self,
                 schema,
                 host=None,
                 user='******',
                 passwd='browser',
                 classes=[],
                 LogLevel='info',
                 load=True,
                 logger=None):
        """
        """
        self.log = logger or Logger(
            'ArchivingAPI(%s)' % schema,
            format='%(levelname)-8s %(asctime)s %(name)s: %(message)s')
        self.log.setLogLevel(LogLevel)
        self.log.debug('Logger streams initialized (error,warning,info,debug)')

        self.tango = PyTango.Database()  #access to Tango database
        self.api = self  #hook used by legacy packages
        self.servers = None
        self.schema = str(schema).lower()
        self.user, self.passwd = user, passwd

        if host is None:
            prop = self.tango.get_class_property('%sArchiver' % schema,
                                                 ['DbHost'])['DbHost']
            if not prop:
                print('ERROR: %sArchiver.DbHost property not defined!' %
                      schema)
                self.host = None
            else:
                self.host = prop[0]
            #if 'TANGO_HOST' in os.environ:
            #    self.host=os.environ['TANGO_HOST'].split(':')[0]
        else:
            self.host = host

        self.dbs = {}  #pointers to Archiving databases

        self.ArchivingClasses = classes or self.get_archiving_classes()
        self.ArchiverClass = (k for k in self.ArchivingClasses
                              if 'Archiver' in k).next()
        self.ManagerClass = (k for k in self.ArchivingClasses
                             if 'Manager' in k).next()
        self.ExtractorClass = (k for k in self.ArchivingClasses
                               if 'Extractor' in k).next()
        try:
            self.WatcherClass = (k for k in self.ArchivingClasses
                                 if 'Watcher' in k).next()
        except:
            self.WatcherClass = None

        self.loads = CaselessDefaultDict(
            lambda k: 0)  #a dict with the archiving load for each device
        self.attributes = CaselessDict()  #a dict of ArchivedAttribute objects
        self.dedicated = CaselessDefaultDict(lambda k: set(
        ))  #Dictionary for keeping the attributes reserved for each archiver

        if load and self.host and self.ArchivingClasses:
            self.load_servers()
Esempio n. 5
0
 def __init__(self, name='', host='', parent=None):
     if not name or '/' not in name:
         raise Exception, 'TServer_WrongServerName_%s' % name
     self.info = None
     self.name = self.get_simple_name(name)
     self.update_level(host, 0)
     self.controlled = False
     self.level = 0
     self._classes = None
     self.state = None  #PyTango.DevState.UNKNOWN
     self.log = Logger('TServer-%s' % name)
     if parent and parent.log.getLogLevel():
         self.log.setLogLevel(parent.log.getLogLevel())
     else:
         self.log.setLogLevel('ERROR')
     self.state_lock = threading.Lock()
     if parent: self.proxies = parent.proxies
     else: self.proxies = ProxiesDict()
     pass
Esempio n. 6
0
class ProxiesDict(CaselessDefaultDict,Object): 
    ''' Dictionary that stores PyTango.DeviceProxies
    It is like a normal dictionary but creates a new proxy each time 
        that the "get" method is called
    An earlier version is used in PyTangoArchiving.utils module
    This class must be substituted by Tau.Core.TauManager().getFactory()()
    '''
    def __init__(self,use_tau = False, tango_host = ''):
        self.log = Logger('ProxiesDict')
        self.log.setLogLevel('INFO')
        self.use_tau = TAU and use_tau
        self.tango_host = tango_host
        self.call__init__(CaselessDefaultDict,self.__default_factory__)

    def __default_factory__(self,dev_name):
        '''
        Called by defaultdict_fromkey.__missing__ method
        If a key doesn't exists this method is called and 
        returns a proxy for a given device.
        If the proxy caused an exception (usually because device 
        doesn't exists) a None value is returned
        '''
        
        if self.tango_host and ':' not in dev_name:
            dev_name = self.tango_host + '/' + dev_name
            
        if dev_name not in self.keys():
            self.log.debug( 'Getting a Proxy for %s'%dev_name)
            
            try:
                devklass,attrklass = (TAU.Device,TAU.Attribute) \
                    if self.use_tau else \
                    (PyTango.DeviceProxy,PyTango.AttributeProxy)
                dev = (attrklass if 
                    str(dev_name).count('/')==(4 if ':' in dev_name else 3) 
                    else devklass)(dev_name)
            except Exception,e:
                print('ProxiesDict: %s doesnt exist!'%dev_name)
                dev = None
        return dev
Esempio n. 7
0
 def __init__(self,name='', host='', parent=None):
     if not name or '/' not in name: raise Exception,'TServer_WrongServerName_%s' % name
     self.info = None
     self.name=self.get_simple_name(name)
     self.update_level(host,0)
     self.controlled = False
     self.level = 0
     self._classes = None
     self.state=None #PyTango.DevState.UNKNOWN
     self.log = Logger('TServer-%s'%name)
     if parent and parent.log.getLogLevel(): self.log.setLogLevel(parent.log.getLogLevel())
     else: self.log.setLogLevel('ERROR')
     self.state_lock = threading.Lock()
     if parent: self.proxies=parent.proxies
     else: self.proxies=ProxiesDict()
     pass
Esempio n. 8
0
class TServer(Object):
    '''Class used by ServerDict to manage TangoDeviceServer admin devices.'''
    def __init__(self, name='', host='', parent=None):
        if not name or '/' not in name:
            raise Exception, 'TServer_WrongServerName_%s' % name
        self.info = None
        self.name = self.get_simple_name(name)
        self.update_level(host, 0)
        self.controlled = False
        self.level = 0
        self._classes = None
        self.state = None  #PyTango.DevState.UNKNOWN
        self.log = Logger('TServer-%s' % name)
        if parent and parent.log.getLogLevel():
            self.log.setLogLevel(parent.log.getLogLevel())
        else:
            self.log.setLogLevel('ERROR')
        self.state_lock = threading.Lock()
        if parent: self.proxies = parent.proxies
        else: self.proxies = ProxiesDict()
        pass

    def set_state(self, state):
        self.state_lock.acquire()
        self.state = state
        self.state_lock.release()

    def ping(self, dname=None):
        '''Executes .ping() and .state() methods of the admin device.'''
        name = dname or self.get_admin_name()
        wait = threading.Event().wait
        if not dname: self.set_state(None)
        try:
            proxy = self.get_proxy(name)
        except:
            self.log.error('%s.ping() ... %s not in database!!!' %
                           (self.name, name))
            return None
        wait(.01)  #this wait allows parallel threads
        try:
            proxy.ping()
        except:
            #self.log.debug( '%s.ping() ... Alive'%s_name)
            return None
        if not dname:
            self.set_state(
                PyTango.DevState.FAULT
            )  #Device pings but its state is not readable (ZOMBIE)
        wait(.01)  #this wait allows parallel threads
        try:
            result = proxy.state()
            if not dname: self.set_state(result)
            return result
        except:
            if not dname: return self.state
            else: return None

    def init_from_db(self, db=None, load_devices=False):
        """ Gets name, classes, devices, host, level information from Tango Database. """
        self._db = db or (self._db
                          if hasattr(self, '_db') else PyTango.Database())
        #print ('init_from_db(%s,%s,%s)'%(self.name,get_tango_host(self._db),load_devices))
        self.info = self._db.get_server_info(self.name)
        di = get_device_info(
            'dserver/' + self.name, db=self._db
        )  #get_server_info() must be combined with get_device_info to obtain the real name of the launcher
        self.name = di.server
        self.update_level(self.info.host, self.info.level)
        if load_devices: self.get_classes()

    def update_level(self, host, level=0):
        """ It only initializes the values, does not get values from database. """
        self.controlled = True if host or level else False
        if type(level) is str: level = level.strip()
        if self.controlled:
            self.host, self.level = host.split('.')[0].strip(), trial(
                int, args=level, excepts=0)
        else:
            self.host, self.level = '', 0

    def get_classes(self, load=False):
        if not load and self._classes is not None:
            return self._classes
        devs = self._db.get_device_class_list(self.name)
        self._classes = collections.defaultdict(list)
        #print 'loading from %s server:%s'%(s,str(devs))
        for i in range(0, len(devs), 2):
            klass = devs[i + 1]
            self._classes[klass].append(devs[i].lower())
        return self._classes

    classes = property(fget=get_classes)

    def get_server_level(self):
        """ It returns initialized values, does not get values from database. """
        if self.controlled and self.host: return self.host, self.level
        else: return '', 0

    def get_simple_name(self, name=''):
        '''Returns the name of the server in the Server/Instance format.'''
        name = name or self.name
        return name if name.count('/') == 1 else name.split('/', 1)[1]

    def get_tango_host(self):
        return get_tango_host(self._db)

    def get_admin_name(self):
        '''Returns the name of the server in the dserver/Server/Instance format.'''
        n = 'dserver/' + self.name if self.name.count('/') == 1 else self.name
        return self.get_tango_host() + '/' + n

    def get_starter_name(self):
        """Returns the starter on charge of controlling this server."""
        n = 'tango/admin/%s' % self.host if self.host else None
        return self.get_tango_host() + '/' + n

    def get_device_list(self):
        '''Returns a list of devices declared for this server.'''
        result = []
        [
            result.extend(v) for c, v in self.classes.items()
            if c.lower() != 'dserver'
        ]
        return result

    def get_proxy(self, device=''):
        '''Returns a proxy to the given device; or the admin device if no device name is provided.'''
        if device and ':' not in device:
            device = self.get_tango_host() + '/' + device
        device = device or self.get_admin_name()
        return self.proxies.get(device)

    def get_admin(self):
        return self.get_proxy()

    def get_device(self, device):
        return self.get_proxy(device)

    def get_all_states(self):
        """Returns a dictionary with the individual states of the inner devices."""
        result = {}
        for klass in self.classes:
            for device in self.classes[klass]:
                try:
                    result[device] = self.proxies[device].State()
                except Exception, e:
                    self.log.warning('Unable to read %s state: %s' %
                                     (device, str(e)[:100] + '...'))
                    result[device] = None  #PyTango.DevState.UNKNOWN
        return result
Esempio n. 9
0
class ServersDict(CaselessDict, Object):
    ''' 
    Dictionary of TServer classes indexed by server/instance names and loaded using wildcard expressions.
    Provides Jive/Astor functionality to a list of servers and allows to select/start/stop them by host, class or devices
    Its purpose is to allow generic start/stop of lists of Tango DeviceServers.
    This methods of selection provide new ways of search apart of Jive-like selection.
       
    @attention Dict keys are lower case, to get the real server name each key returns a TServer object with a .name attribute
    
    @par Usage:
    <pre>
    from fandango import Astor
    astor = Astor()
    astor.load_by_name('snap*')
    astor.keys()
      ['snapmanager/1', 'snaparchiver/1', 'snapextractor/1']
    server = astor['snaparchiver/1']
    server.get_device_list()
        ['dserver/snaparchiver/1', 'archiving/snaparchiver/1']
    astor.states()
    server.get_all_states()
        dserver/snaparchiver/1: ON
        archiving/snaparchiver/1: ON
     astor.get_device_host('archiving/snaparchiver/1')
        palantir01
     astor.stop_servers('snaparchiver/1')
     astor.stop_all_servers()
     astor.start_servers('snaparchiver/1','palantir01',wait=1000)
     astor.set_server_level('snaparchiver/1','palantir01',4)

     #Setting the polling of a device:
     server = astor['PySignalSimulator/bl11']
     for dev_name in server.get_device_list():
         dev = server.get_device(dev_name)
         attrs = dev.get_attribute_list()
         [dev.poll_attribute(attr,3000) for attr in attrs] 
     </pre>
    '''
    def __init__(self,
                 pattern='',
                 klass='',
                 devs_list='',
                 servers_list='',
                 hosts='',
                 loadAll=False,
                 log='WARNING',
                 logger=None,
                 tango_host=''):
        ''' def __init__(self,pattern='', klass='',devs_list='',servers_list=''):
        The ServersDict can be initialized using any of the three argument lists or a wildcard for Database.get_server_list(pattern) 
        ServersDict('*') can be used to load all servers in database
        '''
        self.call__init__(CaselessDict, self)
        if logger is None:
            self.log = Logger('ServersDict')
            self.log.setLogLevel(log)
        else:
            self.log = logger
        self.log.debug('ServersDict(%s)' % ','.join(
            map(str, (pattern, klass, devs_list, servers_list, hosts, loadAll,
                      log, logger, tango_host))))

        ## proxies will keep a list of persistent device proxies
        self.proxies = ProxiesDict(tango_host=tango_host)
        ## db will keep a persistent link to PyTango database
        self.db = get_database() if not tango_host else get_database(
            *(tango_host.split(':')))
        self.server_names = self.keys
        self.servers = self.values

        if loadAll: self.load_all_servers()
        elif klass: self.load_by_class(klass)
        elif devs_list: self.load_from_devs_list(devs_list)
        elif servers_list:
            self.load_from_servers_list(servers_list)
            #elif pattern: self.load_from_servers_list(self.db.get_server_list(pattern))
        elif hosts:
            hosts = type(hosts) is str and (',' in hosts and hosts.split(',')
                                            or [hosts]) or hosts
            for h in hosts:
                self.load_by_host(h)
        elif pattern:
            self.load_by_name(pattern)
        #dict.__init__(self)

    ## @name Dict methods
    # @{

    def __arranged_key(self, key):
        return key if key.count('/') <= 1 else key.split('/', 1)[1]

    #def __getitem__(self,key): dicts.CaselessDict.__getitem__(self,self.__arranged_key(key))
    #def __setitem__(self,key,value): dicts.CaselessDict.__setitem__(self,self.__arranged_key(key),value)
    #def __delitem__(self,key): dicts.CaselessDict.__delitem__(self,self.__arranged_key(key))
    #def __contains__(self,key): dicts.CaselessDict.__contains__(self,self.__arranged_key(key))
    #def has_key(self,key): dicts.CaselessDict.has_key(self,self.__arranged_key(key))
    #def get(self,key,def_val=None): dicts.CaselessDict.get(self,self.__arranged_key(key),def_val)
    #def pop(self,key,def_val=None): dicts.CaselessDict.pop(self,self.__arranged_key(key),def_val)
    #def setdefault(self,key,def_val=None): dicts.CaselessDict.pop(self,self.__arranged_key(key),def_val)

    def __repr__(self):
        return self.get_report()

    def __str__(self):
        return self.get_report()

    ## @}

    ## @name Database access
    # @{

    def load_all_servers(self):
        """ It loads all device servers declared in Tango database """
        #classes = self.db.get_device_family('dserver/*')
        #for c in classes:
        #    self.load_by_exec(c)
        print self.db
        self.load_from_servers_list(self.db.get_server_list())

    def load_by_name(self, name):
        ''' Initializes the dict with all the servers matching a given name (usually the executable name or class). A list of names is also possible.'''
        if type(name) in (list, set):
            for pattern in name:
                self.load_by_name(pattern)
        else:
            if name.count('/') >= 2 and not name.startswith('dserver/'):
                return self.load_from_devs_list([name])
            else:
                server_name = name.replace('dserver/', '')
                self.log.info('loading by %s server_name' % server_name)
                family = server_name.split(
                    '/')[0] if '/' in server_name else server_name
                member = server_name.split(
                    '/')[1] if '/' in server_name else '*'
                servers_list = self.get_devs_from_db('dserver/%s/%s' %
                                                     (family, member))
                #servers_list = [s for s in self.db.get_server_list() if fun.matchCl('%s/%s'%(family,member),s)]
                if servers_list:
                    self.load_from_servers_list(
                        [d.replace('dserver/', '') for d in servers_list],
                        check=False)
                    self.log.info('%d servers loaded' % len(servers_list))
                    return len(servers_list)
                else:
                    self.log.warning('No server matches with %s (family=%s).' %
                                     (server_name, family))
                    return 0
        return self

    def load_by_class(self, klass):
        """ Initializes the ServersDict using all the devices from a given class """
        self.load_from_devs_list(get_class_devices(klass))

    def load_by_host(self, host):
        """ Initializes the dict with all the servers assigned to a given host. """
        servers = self.get_db_device().DbGetHostServerList(host)
        self.log.warning("%d servers assigned in DB to host %s: %s" %
                         (len(servers), host, servers))
        if servers: self.load_from_servers_list(servers)
        return self

    def load_from_devs_list(self, devs_list):
        ''' Initializes the dict using a list of devices; a query to the database is used to identify the server for each device.  '''
        if type(devs_list) is str: devs_list = devs_list.split(',')
        if type(devs_list) not in [list, set, tuple]: devs_list = [devs_list]
        servers_list = set()
        for d in devs_list:
            devs = self.get_devs_from_db(d) if '*' in d else [d]
            devs = [get_normal_name(d) for d in devs]
            [
                servers_list.add(self.get_device_server(dev)) for dev in devs
                if dev
            ]
        self.log.info('Loading %d servers matching %s devices' %
                      (len(servers_list), len(devs_list)))
        self.load_from_servers_list([s for s in servers_list if s])
        return self

    def load_from_servers_list(self, servers_list, check=True):
        """ Initializes the dictionary using a list of server_names like ['Exec/Instance'] """
        t0 = time.time()
        if type(servers_list) is str: servers_list = servers_list.split(',')
        if check: self.check_servers_names(servers_list)
        for s in servers_list:
            try:
                self.log.debug('loading from %s/%s server' %
                               (get_tango_host(self.db), s))
                ss = TServer(name=s, parent=self)
                ss.init_from_db(self.db)
                self[s] = ss
            except Exception, e:
                self.log.warning('exception loading %s server: %s' %
                                 (s, str(e)[:100] + '...'))
                print traceback.format_exc()
        self.log.debug('load_from_servers_list(%d) took %f seconds' %
                       (len(servers_list), time.time() - t0))
        return self
Esempio n. 10
0
class TServer(Object):
    '''Class used by ServerDict to manage TangoDeviceServer admin devices.'''
    def __init__(self,name='', host='', parent=None):
        if not name or '/' not in name: raise Exception,'TServer_WrongServerName_%s' % name
        self.info = None
        self.name=self.get_simple_name(name)
        self.update_level(host,0)
        self.controlled = False
        self.level = 0
        self._classes = None
        self.state=None #PyTango.DevState.UNKNOWN
        self.log = Logger('TServer-%s'%name)
        if parent and parent.log.getLogLevel(): self.log.setLogLevel(parent.log.getLogLevel())
        else: self.log.setLogLevel('ERROR')
        self.state_lock = threading.Lock()
        if parent: self.proxies=parent.proxies
        else: self.proxies=ProxiesDict()
        pass
        
    def set_state(self,state):
        self.state_lock.acquire()
        self.state=state
        self.state_lock.release()
        
    def ping(self,dname=None):
        '''Executes .ping() and .state() methods of the admin device.'''
        name = dname or self.get_admin_name()
        wait = threading.Event().wait
        if not dname: self.set_state(None)
        try: proxy = self.get_proxy(name)
        except: 
            self.log.error('%s.ping() ... %s not in database!!!' % (self.name,name))
            return None
        wait(.01) #this wait allows parallel threads
        try: proxy.ping()
        except:
            #self.log.debug( '%s.ping() ... Alive'%s_name)
            return None
        if not dname: self.set_state(PyTango.DevState.FAULT) #Device pings but its state is not readable (ZOMBIE)
        wait(.01) #this wait allows parallel threads
        try: 
            result = proxy.state()
            if not dname: self.set_state(result)
            return result
        except:
            if not dname: return self.state
            else: return None
            
    def init_from_db(self,db=None,load_devices=False):
        """ Gets name, classes, devices, host, level information from Tango Database. """
        self._db = db or (self._db if hasattr(self,'_db') else PyTango.Database())
        #print ('init_from_db(%s,%s,%s)'%(self.name,get_tango_host(self._db),load_devices))
        self.info = self._db.get_server_info(self.name)
        di = get_device_info('dserver/'+self.name,db=self._db) #get_server_info() must be combined with get_device_info to obtain the real name of the launcher
        self.name = di.server
        self.update_level(self.info.host,self.info.level)
        if load_devices: self.get_classes()
    
    def update_level(self,host,level=0):
        """ It only initializes the values, does not get values from database. """
        self.controlled = True if host or level else False
        if type(level) is str: level=level.strip()
        if self.controlled: self.host,self.level = host.split('.')[0].strip(),trial(int,args=level,excepts=0)
        else: self.host,self.level = '',0
        
    def get_classes(self,load=False):
        if not load and self._classes is not None:
            return self._classes
        devs = self._db.get_device_class_list(self.name)
        self._classes = collections.defaultdict(list)
        #print 'loading from %s server:%s'%(s,str(devs))
        for i in range(0,len(devs),2):
            klass = devs[i+1]
            self._classes[klass].append(devs[i].lower())
        return self._classes
        
    classes = property(fget=get_classes)
        
    def get_server_level(self):
        """ It returns initialized values, does not get values from database. """
        if self.controlled and self.host: return self.host,self.level
        else: return '',0
    
    def get_simple_name(self,name=''): 
        '''Returns the name of the server in the Server/Instance format.'''
        name = name or self.name
        return name if name.count('/')==1 else name.split('/',1)[1]
      
    def get_tango_host(self):
        return get_tango_host(self._db)
    
    def get_admin_name(self): 
        '''Returns the name of the server in the dserver/Server/Instance format.'''
        n = 'dserver/'+self.name if self.name.count('/')==1 else self.name
        return self.get_tango_host()+'/'+n
    
    def get_starter_name(self):
        """Returns the starter on charge of controlling this server."""
        n = 'tango/admin/%s' % self.host if self.host else None
        return self.get_tango_host()+'/'+n
    
    def get_device_list(self): 
        '''Returns a list of devices declared for this server.'''
        result=[]
        [result.extend(v) for c,v in self.classes.items() if c.lower()!='dserver']
        return result
    
    def get_proxy(self,device=''): 
        '''Returns a proxy to the given device; or the admin device if no device name is provided.'''
        if device and ':' not in device:
          device = self.get_tango_host()+'/'+device
        device = device or self.get_admin_name()
        return self.proxies.get(device)
    
    def get_admin(self): return self.get_proxy()
    def get_device(self,device): return self.get_proxy(device)
    
    def get_all_states(self):
        """Returns a dictionary with the individual states of the inner devices."""
        result = {}
        for klass in self.classes:
            for device in self.classes[klass]:
                try:
                    result[device] = self.proxies[device].State()
                except Exception,e:
                    self.log.warning('Unable to read %s state: %s' % (device,str(e)[:100]+'...'))
                    result[device] = None #PyTango.DevState.UNKNOWN
        return result
Esempio n. 11
0
class ServersDict(CaselessDict,Object):
    ''' 
    Dictionary of TServer classes indexed by server/instance names and loaded using wildcard expressions.
    Provides Jive/Astor functionality to a list of servers and allows to select/start/stop them by host, class or devices
    Its purpose is to allow generic start/stop of lists of Tango DeviceServers.
    This methods of selection provide new ways of search apart of Jive-like selection.
       
    @attention Dict keys are lower case, to get the real server name each key returns a TServer object with a .name attribute
    
    @par Usage:
    <pre>
    from fandango import Astor
    astor = Astor()
    astor.load_by_name('snap*')
    astor.keys()
      ['snapmanager/1', 'snaparchiver/1', 'snapextractor/1']
    server = astor['snaparchiver/1']
    server.get_device_list()
        ['dserver/snaparchiver/1', 'archiving/snaparchiver/1']
    astor.states()
    server.get_all_states()
        dserver/snaparchiver/1: ON
        archiving/snaparchiver/1: ON
     astor.get_device_host('archiving/snaparchiver/1')
        palantir01
     astor.stop_servers('snaparchiver/1')
     astor.stop_all_servers()
     astor.start_servers('snaparchiver/1','palantir01',wait=1000)
     astor.set_server_level('snaparchiver/1','palantir01',4)

     #Setting the polling of a device:
     server = astor['PySignalSimulator/bl11']
     for dev_name in server.get_device_list():
         dev = server.get_device(dev_name)
         attrs = dev.get_attribute_list()
         [dev.poll_attribute(attr,3000) for attr in attrs] 
     </pre>
    '''
    def __init__(self,pattern='',klass='',devs_list='',servers_list='',hosts='',loadAll=False,log='WARNING',logger=None,tango_host=''):
        ''' def __init__(self,pattern='', klass='',devs_list='',servers_list=''):
        The ServersDict can be initialized using any of the three argument lists or a wildcard for Database.get_server_list(pattern) 
        ServersDict('*') can be used to load all servers in database
        '''
        self.call__init__(CaselessDict,self)
        if logger is None:
            self.log = Logger('ServersDict')
            self.log.setLogLevel(log)
        else: self.log=logger
        self.log.debug('ServersDict(%s)'%','.join(map(str,(pattern,klass,devs_list,servers_list,hosts,loadAll,log,logger,tango_host))))
        
        ## proxies will keep a list of persistent device proxies
        self.proxies = ProxiesDict()
        ## db will keep a persistent link to PyTango database
        self.db = get_database() if not tango_host else get_database(*(tango_host.split(':')))
        self.server_names = self.keys
        self.servers = self.values
                
        if loadAll: self.load_all_servers()
        elif klass: self.load_by_class(klass)
        elif devs_list: self.load_from_devs_list(devs_list)
        elif servers_list: self.load_from_servers_list(servers_list)
        #elif pattern: self.load_from_servers_list(self.db.get_server_list(pattern))
        elif hosts: 
            hosts = type(hosts) is str and (',' in hosts and hosts.split(',') or [hosts]) or hosts
            for h in hosts: self.load_by_host(h)
        elif pattern: self.load_by_name(pattern)
        #dict.__init__(self)
    
    ## @name Dict methods
    # @{
    
    def __arranged_key(self,key): return key if key.count('/')<=1 else key.split('/',1)[1]
    #def __getitem__(self,key): dicts.CaselessDict.__getitem__(self,self.__arranged_key(key))
    #def __setitem__(self,key,value): dicts.CaselessDict.__setitem__(self,self.__arranged_key(key),value)
    #def __delitem__(self,key): dicts.CaselessDict.__delitem__(self,self.__arranged_key(key))   
    #def __contains__(self,key): dicts.CaselessDict.__contains__(self,self.__arranged_key(key))
    #def has_key(self,key): dicts.CaselessDict.has_key(self,self.__arranged_key(key))
    #def get(self,key,def_val=None): dicts.CaselessDict.get(self,self.__arranged_key(key),def_val)
    #def pop(self,key,def_val=None): dicts.CaselessDict.pop(self,self.__arranged_key(key),def_val)
    #def setdefault(self,key,def_val=None): dicts.CaselessDict.pop(self,self.__arranged_key(key),def_val)   
    
    def __repr__(self): return self.get_report()
    def __str__(self): return self.get_report()
    
    ## @}
    
    ## @name Database access
    # @{
       
    def load_all_servers(self):
        """ It loads all device servers declared in Tango database """
        #classes = self.db.get_device_family('dserver/*')
        #for c in classes:
        #    self.load_by_exec(c)
        print self.db
        self.load_from_servers_list(self.db.get_server_list())
        
    def load_by_name(self,name):
        ''' Initializes the dict with all the servers matching a given name (usually the executable name or class). A list of names is also possible.'''
        if type(name) in (list,set):
            for pattern in name:
                self.load_by_name(pattern)
        else:
            if name.count('/')>=2 and not name.startswith('dserver/'):
                return self.load_from_devs_list([name])
            else:
                server_name = name.replace('dserver/','')
                self.log.info('loading by %s server_name'%server_name)
                family = server_name.split('/')[0] if '/' in server_name else server_name
                member = server_name.split('/')[1] if '/' in server_name else '*'
                servers_list = self.get_devs_from_db('dserver/%s/%s' % (family,member))
                #servers_list = [s for s in self.db.get_server_list() if fun.matchCl('%s/%s'%(family,member),s)]
                if servers_list:
                    self.load_from_servers_list([d.replace('dserver/','') for d in servers_list],check=False)
                    self.log.info('%d servers loaded'%len(servers_list))
                    return len(servers_list)
                else:
                    self.log.warning('No server matches with %s (family=%s).'%(server_name,family))
                    return 0
        return self
    
    def load_by_class(self,klass):
        """ Initializes the ServersDict using all the devices from a given class """
        self.load_from_devs_list(get_class_devices(klass))
        
    def load_by_host(self,host):
        """ Initializes the dict with all the servers assigned to a given host. """
        servers = self.get_db_device().DbGetHostServerList(host)
        self.log.warning("%d servers assigned in DB to host %s: %s" % (len(servers),host,servers))
        if servers: self.load_from_servers_list(servers)
        return self
    
    def load_from_devs_list(self,devs_list):
        ''' Initializes the dict using a list of devices; a query to the database is used to identify the server for each device.  '''
        if type(devs_list) is str: devs_list = devs_list.split(',')
        if type(devs_list) not in [list,set,tuple]: devs_list = [devs_list]
        servers_list=set()
        for d in devs_list:
            devs = self.get_devs_from_db(d) if '*' in d else [d] 
            [servers_list.add(self.get_device_server(dev)) for dev in devs if dev]
        self.log.info('Loading %d servers matching %s devices'%(len(servers_list),len(devs_list)))
        self.load_from_servers_list([s for s in servers_list if s])
        return self
    
    def load_from_servers_list(self,servers_list,check=True):
        """ Initializes the dictionary using a list of server_names like ['Exec/Instance'] """
        t0 = time.time()
        if type(servers_list) is str: servers_list = servers_list.split(',')
        if check: self.check_servers_names(servers_list)
        for s in servers_list:
            try:           
                self.log.debug('loading from %s/%s server'%(get_tango_host(self.db),s))
                ss=TServer(name=s,parent=self)
                ss.init_from_db(self.db)
                self[s] = ss
            except Exception,e:
                self.log.warning('exception loading %s server: %s' % (s,str(e)[:100]+'...'))
                print traceback.format_exc()
        self.log.debug('load_from_servers_list(%d) took %f seconds' % (len(servers_list),time.time()-t0))
        return self
Esempio n. 12
0
 def __init__(self,use_tau = False, tango_host = ''):
     self.log = Logger('ProxiesDict')
     self.log.setLogLevel('INFO')
     self.use_tau = TAU and use_tau
     self.tango_host = tango_host
     self.call__init__(CaselessDefaultDict,self.__default_factory__)