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()
예제 #2
0
def read_alias_file(alias_file,trace=False):
    # Reading the Alias file
    # The format of the file will be:
    #   Alias                                   Attribute
    #   sr01/vc/eps-plc-01/sr01_vc_tc_s0112     sr01/vc/eps-plc-01/thermocouples[11]
    alias = CaselessDict()
    if alias_file:
        try:
            csv = fandango.arrays.CSVArray(alias_file)
            csv.setOffset(1)
            for i in range(csv.size()[0]):
                line = csv.getd(i)
                try: alias[line['Alias']] = line['Attribute']
                except: pass
            if trace: print('%d Attribute alias loaded from %s' % (len(alias),alias_file))
        except Exception,e:
            print('Unable to parse AliasFile: %s\n%s'%(alias_file,traceback.format_exc()))
            alias.clear()
예제 #3
0
def read_alias_file(alias_file,trace=False):
    # Reading the Alias file
    # The format of the file will be:
    #   Alias                                   Attribute
    #   sr01/vc/eps-plc-01/sr01_vc_tc_s0112     sr01/vc/eps-plc-01/thermocouples[11]
    alias = CaselessDict()
    if alias_file:
        try:
            csv = fandango.arrays.CSVArray(alias_file)
            csv.setOffset(1)
            for i in range(csv.size()[0]):
                line = csv.getd(i)
                try: alias[line['Alias']] = line['Attribute']
                except: pass
            if trace: print('%d Attribute alias loaded from %s' % (len(alias),alias_file))
        except Exception,e:
            print('Unable to parse AliasFile: %s\n%s'%(alias_file,traceback.format_exc()))
            alias.clear()
예제 #4
0
 def get_attributes(self, device=None, attribute=None):
     """Both device and attribute are regexps"""
     getattr(self, 'attributes', self.load_attributes())
     result = CaselessDict(
         (n, f) for n, f in self.attributes.items()
         if (not device
             or fun.matchCl(device, n.rsplit('/', 1)[0], terminate=True))
         and (not attribute or fun.matchCl(
             attribute, n.rsplit('/', 1)[-1], terminate=True)))
     return result
예제 #5
0
    def apply_filters(self, *args, **filters):
        """
        valid filters are:
        * device
        * active
        * severity
        * regexp (any place)
        * receiver
        * formula
        * attributes
        * has_history
        * failed
        * hierarchy top
        * hierarchy bottom
        """
        try:
            #self.lock.acquire()
            self.ordered = []
            self.filtered = []
            self.last_sort = 0
            filters = filters or (args and args[0])
            if filters and not isinstance(filters, FilterStack):
                filters = FilterStack(filters)
            else:
                filters = filters or self.filters

            self.debug('apply_filters(%s)' % repr(filters))
            self.filtered = [
                a.tag for a in filters.apply(self.api.values(), verbose=0)
            ]
            self.filters = filters

            objs = [self.api[f] for f in self.filtered]
            models = [(a.get_model().split('tango://')[-1], a) for a in objs]
            self.alarms = self.models = CaselessDict(models)
            self.info('apply_filters: %d -> %d\n' %
                      (len(self.api), len(self.filtered)))
        except:
            self.error(traceback.format_exc())
        finally:
            pass  #self.lock.release()

        return self.filtered
예제 #6
0
    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 = fandango.get_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()
예제 #7
0
class CommonAPI(Object,fn.SingletonMap):
    """ 
    This class provides common methods for managing a Soleil-like database 
    (for either archiving or snapshoting)
    The methods starting by "get" retrieve values using ArchivingDSs
    The methods starting by "load" access directly to MySQL database
    """
    #ArchivingTypes = ARCHIVING_TYPES
    #ArchivingClasses = ARCHIVING_CLASSES
    
    MAX_SERVERS_FOR_CLASS=5
    MIN_ARCHIVING_PERIOD=10
    
    def __init__(self,schema,host=None,user='******',passwd='browser',
                 classes=[],LogLevel='WARNING',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 = fn.get_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 = fn.first((k for k in self.ArchivingClasses if 'Archiver' in k),'')
        self.ManagerClass = fn.first((k for k in self.ArchivingClasses if 'Manager' in k),'')
        self.ExtractorClass = fn.first((k for k in self.ArchivingClasses if 'Extractor' in k),'')
        try: self.WatcherClass = fn.first((k for k in self.ArchivingClasses if 'Watcher' in k),'')
        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()
          
    ## The ArchivingAPI is an iterator through archived attributes
    def __getitem__(self,k): 
        k = k if k.count('/')<=3 else fn.tango.get_normal_name(k)
        return self.attributes.__getitem__(k)
    def __contains__(self,k): 
        k = k if k.count('/')<=3 else fn.tango.get_normal_name(k)
        return self.attributes.__contains__(k)
    def get(self,k): 
        k = k if k.count('/')<=3 else fn.tango.get_normal_name(k)
        return self.attributes.get(k)
    def has_key(self,k): 
        k = k if k.count('/')<=3 else fn.tango.get_normal_name(k)
        return self.attributes.has_key(k)
    #[setattr(self,method,lambda k,meth=method:getattr(self.attributes,meth)(k)) for method in ('__getitem__','__contains__','get','has_key')]
    def __iter__(self): return self.attributes.__iter__()
    def iteritems(self): return self.attributes.iteritems()
    def keys(self): return self.attributes.keys()
    def values(self): return self.attributes.values()
    def __len__(self): return len(self.attributes.keys())
    def items(self): return self.attributes.items()
    #[setattr(self,method,lambda meth=method:getattr(self.attributes,meth)()) for method in ('__iter__','iteritems','items','keys','values')]          
        
    def load_servers(self,filters=None):
        if getattr(self,'servers',None) is None:
            self.servers = ServersDict()
        [self.servers.load_by_name(k) for k in (filters or self.ArchivingClasses)]
        self.servers.refresh()
        self.proxies = self.servers.proxies
        return self.servers
        
    def get_servers(self):
        if not getattr(self,'servers',None): return self.load_servers()
        return self.servers
        
    def get_archiving_classes(self):        
        self.ArchivingClasses = [k for k in ARCHIVING_CLASSES if self.schema in k.lower()]
        if self.schema!='snap': self.ArchivingClasses.append('ArchivingManager')
        return self.ArchivingClasses

    def __del__(self):
        try:
            self.log.debug( 'Deleting ArchivingAPI ...')
            for p in self.proxies.values():
                del p
            del self.tango
            for d in self.dbs.values():
                del d
        except:
            pass #print('Unable to delete API object')
            
    def __repr__(self):
        '''The status of Archiving device servers '''
        return '%s(%s[%s])' % (type(self),self.schema,len(self))
        #if self.servers:
            #report='The status of %s Archiving device servers is:\n'%self.schema
            #for k,v in self.servers.items():
                #report+='%s:\t%s\n'%(k,v.state)
            #if self.WatcherClass:
                #try: report+=self.proxies(
                    #self.servers.get_class_devices(self.WatcherClass)[0]
                    #).command_inout('GetReportCurrent')+'\n'
                #except: pass
            #return report         

    ####################################################################################################

    def get_random_device(self,klass,timeout=300000):
        device = None
        if not getattr(self,'servers',None): 
          self.load_servers(filters=[klass])
        remaining = self.servers.get_class_devices(klass)
        if not remaining: 
          self.servers.load_by_name(klass)
          remaining = self.servers.get_class_devices(klass)
        while remaining: #for i in range(len(self.extractors)):
            next = randrange(len(remaining))
            devname = remaining.pop(next)
            device = self.servers.proxies[devname]
            print devname
            try:
                device.ping()
                device.set_timeout_millis(timeout)
                break
            except Exception,e: 
                self.log.info('%s unreachable: %s'%(devname,str(e)))
        return device
예제 #8
0
class AlarmView(EventListener):
    #ThreadedObject,

    _LOADED = False

    sources = CaselessDict()  #Dictionary for Alarm sources

    def __init__(self,
                 name='AlarmView',
                 filters={},
                 scope='*',
                 api=None,
                 refresh=3.,
                 events=False,
                 asynch=False,
                 verbose=False):

        self.t_init = now()
        self.lock = Lock()
        self.verbose = verbose if not isNumber(verbose) else (
            {
                verbose > 3: 'DEBUG',
                4 > verbose > 1: 'INFO',
                verbose <= 1: 'WARNING'
            }[True])

        if not AlarmView._LOADED:
            import panic.engine
            panic.engine.init_callbacks()
            AlarmView._LOADED = True

        EventListener.__init__(self, name)

        self.setLogLevel(self.verbose or 'WARNING')

        if isString(filters): filters = {'tag': filters}
        self.filters = FilterStack(filters)
        #if isString(filters):
        #if ',' in filters: filters = filters.split(',')
        #else: filters = {'regexp':filters}

        #if isSequence(filters):
        #filters = dict(iif('=' in k,k.split('=',1),(k,True))
        #for k in filters)

        ## default_filters should never change
        self.defaults = Struct(
            dict((k, '') for k in ('device', 'active', 'severity', 'regexp',
                                   'receivers', 'formula', 'attribute',
                                   'history', 'failed', 'hierarchy')))
        [self.defaults.update(**f) for f in self.filters.values()]
        self.filters.insert(0, 'default', self.defaults.dict())

        self.info('AlarmView(%s)' % str((filters, scope, refresh, asynch)))

        self.ordered = []  #Alarms list ordered
        self.last_sort = 0
        self.filtered = []  # vs alarms?
        self.values = CaselessDefaultDict(dict)

        self.timeSortingEnabled = None
        self.changed = True
        #self.info('parent init done, +%s'%(now()-self.t_init))

        if not isSequence(scope): scope = [scope]
        if api:
            self.apis = {scope[0]: api}
        else:
            self.apis = dict()
            for p in scope:
                if not p.split('#')[0]: continue
                k = p.split('@')
                t = first(k[1:] or (None, ))
                s = k[0] if ('/' in k[0] or isRegexp(k[0])) else '*%s*' % k[0]
                try:
                    self.info('creating AlarmAPI(%s,%s)' % (s, t))
                    self.apis[p] = panic.AlarmAPI(filters=s, tango_host=t)
                except:
                    traceback.print_exc()
                    self.apis[p] = None

        #@TODO: MULTIPLE APIS OBJECTS SHOULD BE MANAGED!!
        self.api = self.apis.values()[0]

        if not self.api.keys():
            self.warning('NO ALARMS FOUND IN DATABASE!?!?')

        self.apply_filters()
        self.info('view api init done, +%s' % (now() - self.t_init))
        self.info('%d sources : %s ...' %
                  (len(self.alarms), fd.log.pformat(self.alarms)[:80]))

        N = len(self.alarms)

        ## How often should the ordered list be renewed?
        if len(self.alarms) > 150:
            refresh = max((6., refresh))
            self.warning('%s alarms on display, polling set to %s' %
                         (len(self.alarms), refresh))

        self.__asynch = asynch  #Unmodifiable once started
        self.__events = events or False  #Unmodifiable once started
        self.__refresh = refresh  #Unmodifiable once started?
        self.__dead = 0  #deadtime caused by event hooks
        self.get_period = lambda s=self: refresh
        #ThreadedObject.__init__(self,target=self.sort,
        #period=refresh,start=False)
        #ThreadedObject.__init__(self,period=1.,nthreads=1,start=True,min_wait=1e-5,first=0)

        self.update_sources()
        self.info('event sources updated, +%s' % (now() - self.t_init))

        ######################################################################

        #self.start()
        self.info('view init done, +%s' % (now() - self.t_init))
        self.logPrint('info', '\n\n')

    def __del__(self):
        print('AlarmView(%s).__del__()' % self.name)
        self.disconnect()

    @staticmethod
    def __test__(*args):
        t0 = fd.now()
        args = args or ['*value*', '20']
        opts = dict.fromkeys(a.strip('-') for a in args if a.startswith('-'))
        args = [a for a in args if a not in opts]
        scope = args[0]
        tlimit = int((args[1:] or ['20'])[0])

        if opts:
            opts = dict(o.split('=') if '=' in o else (o, True) for o in opts)
            opts.update((o, fd.str2type(v)) for o, v in opts.items())

        print('AlarmView(Test,\t'
              '\tscope=%s,\n\ttlimit=%s,\n\t**%s)\n' % (scope, tlimit, opts))

        if opts.get('d', False):
            th = TangoAttribute.get_thread()
            th.set_period_ms(500)
            th.setLogLevel('DEBUG')

        verbose = opts.get('v', 2)

        view = AlarmView('Test', scope=scope, verbose=verbose, **opts)
        print('\n'.join('>' * 80 for i in range(4)))

        cols = 'sortkey', 'tag', 'state', 'active', 'time', 'severity'
        while fd.now() < (t0 + tlimit):
            fd.wait(3.)
            print('\n' + '<' * 80)
            l = view.sort(as_text={'cols': cols})
            print('\n'.join(l))

        print('AlarmView.__test__(%s) finished after %d seconds' %
              (args[0], fd.now() - t0))

    def get_alarm(self, alarm):
        #self.info('get_alarm(%s)'%alarm)
        alarm = getattr(alarm, 'tag', alarm)
        alarm = alarm.split('tango://')[-1]
        if not alarm: return None
        a = self.alarms.get(alarm, None)
        if a is None:
            alarm = alarm.split('/')[-1]
            #@KEEP, do not remove this first check
            if alarm in self.api:
                return self.api[alarm]
            else:
                m = self.api.get(alarm)
                assert len(m) <= 1, '%s_MultipleAlarmMatches!' % m
                assert m, '%s_AlarmNotFound!' % m
                a = m[0]
        return a

    def get_alarms(self, filters=None):
        """
        It returns a list with all alarm objects matching 
        the filter provided
        Alarms should be returned matching the current sortkey.
        """
        if not self.filtered and not filters:
            r = self.api.keys()[:]
        else:
            if filters:
                self.apply_filters(self, **filters)
            r = self.filtered

        self.debug('get_alarms(%s): %d alarms found' % (repr(filters), len(r)))
        return r

    def apply_filters(self, *args, **filters):
        """
        valid filters are:
        * device
        * active
        * severity
        * regexp (any place)
        * receiver
        * formula
        * attributes
        * has_history
        * failed
        * hierarchy top
        * hierarchy bottom
        """
        try:
            #self.lock.acquire()
            self.ordered = []
            self.filtered = []
            self.last_sort = 0
            filters = filters or (args and args[0])
            if filters and not isinstance(filters, FilterStack):
                filters = FilterStack(filters)
            else:
                filters = filters or self.filters

            self.debug('apply_filters(%s)' % repr(filters))
            self.filtered = [
                a.tag for a in filters.apply(self.api.values(), verbose=0)
            ]
            self.filters = filters

            objs = [self.api[f] for f in self.filtered]
            models = [(a.get_model().split('tango://')[-1], a) for a in objs]
            self.alarms = self.models = CaselessDict(models)
            self.info('apply_filters: %d -> %d\n' %
                      (len(self.api), len(self.filtered)))
        except:
            self.error(traceback.format_exc())
        finally:
            pass  #self.lock.release()

        return self.filtered

    @staticmethod
    def sortkey(alarm, priority=None):
        """
        Return alarms ordered from LEAST critical to MOST
        
        This is the REVERSE order of that shown in the GUI
        """
        r = []
        priority = priority or SORT_ORDER
        #print priority
        for p in priority:
            m, p = None, str(p).lower()

            if p == 'error':
                v = alarm.get_state() in ('ERROR', )
            elif p == 'active':
                v = alarm.is_active()
            else:
                if p in ('time', 'state'):
                    m = getattr(alarm, 'get_' + p, None)

                v = m() if m else getattr(alarm, p, None)

                if p in ('severity', 'priority'):
                    v = panic.SEVERITIES.get(str(v).upper(), 'UNKNOWN')

            r.append(v)

        setattr(alarm, 'sortkey', str(r))
        return r

    def sort(self, sortkey=None, as_text=False, filtered=True, keep=True):
        """
        Returns a sorted list of alarm models
        
        valid keys are:
        * name
        * device
        * active (time desc)
        * severity
        * receivers
        * hierarchy
        * failed
        """
        try:
            updated = [a for a in self.alarms.values() if a.updated]
            if len(updated) == len(self.alarms):
                [
                    a.get_active() for a in self.alarms.values()
                    if a.active in (1, True)
                ]
            else:
                self.info('sort(): %d alarms not updated yet' %
                          (len(self.alarms) - len(updated)))

            self.debug('%d alarms, %d filtered, %d updated' %
                       tuple(map(len, (self.alarms, updated, self.filtered))))

            #self.lock.acquire()
            ordered = self.ordered
            if not keep or not ordered \
                    or (now()-self.last_sort) > self.get_period():
                #self.last_keys = keys or self.last_keys
                sortkey = sortkey or self.sortkey
                if isSequence(sortkey):
                    sortkey = lambda a, p=sortkey: self.sortkey(a, priority=p)
                if filtered:
                    objs = [self.api[f] for f in self.filtered]
                else:
                    objs = self.alarms.values()

                ordered = sorted(objs, key=sortkey)
                if keep: self.ordered = ordered
                self.debug('sort([%d])' % (len(ordered)))

            if as_text:
                kw = fd.isMapping(as_text) and as_text or {}
                r = list(
                    reversed(
                        [self.get_alarm_as_text(a, **kw) for a in ordered]))
            else:
                r = list(reversed([a.get_model() for a in ordered]))

            self.last_sort = now()
            return r
        except:
            self.error(traceback.format_exc())
        finally:
            #self.lock.release()
            pass

    def export(self,
               keys=('active', 'severity', 'device', 'tag', 'description',
                     'formula'),
               to_type=list):
        objs = [self.alarms[a] for a in self.sort()]
        if to_type is list:
            return [[getattr(o, k) for k in keys] for o in objs]
        if to_type is str or isString(to_type):
            to_type = str
            sep = to_type if isString(to_type) else '\t'
            return [
                '\t'.join(to_type(getattr(o, k)) for k in keys) for o in objs
            ]

    def get_alarm_as_text(self,
                          alarm=None,
                          cols=None,
                          formatters=None,
                          lengths=[],
                          sep=' - '):
        alarm = self.get_alarm(alarm)
        cols = cols or VIEW_FIELDS
        formatters = formatters or FORMATTERS
        s = '  '
        try:
            for i, r in enumerate(cols):
                if s.strip(): s += sep
                v = getattr(alarm, r)
                args = [v() if fd.isCallable(v) else v]
                if lengths: args.append(lengths[i])
                s += formatters[r](*args)
            return s
        except:
            print traceback.format_exc()
            return s

    def get_alarm_from_text(self,
                            text,
                            cols=None,
                            formatters=None,
                            lengths=[],
                            sep=' - ',
                            obj=True):
        if hasattr(text, 'text'): text = text.text()
        cols = cols or ['tag', 'active', 'description']
        vals = [t.strip() for t in str(text).split(sep)]
        i = cols.index('tag') if 'tag' in cols else 0
        a = vals[i]
        return self.get_alarm(a) if obj else a

    def get_source(self, alarm):
        try:
            alarm = self.get_model(alarm)
        except:
            pass

        if alarm not in AlarmView.sources:
            alarm = alarm.replace('tango://', '')
            if '/' not in alarm: alarm = '/' + alarm
            match = [s for s in AlarmView.sources if s.endswith(alarm)]
            assert len(match) < 2, '%s_MultipleAlarmMatches' % alarm
            if not match:
                #self.debug('No alarm ends with %s'%alarm)
                return None
            alarm = match[0]

        return AlarmView.sources[alarm]

    def get_value(self, alarm):
        alarm = self.get_model(alarm)
        value = self.values.get(alarm, None)
        if value is None:
            try:
                alarm = self.get_source(alarm).full_name
                value = self.values.get(alarm, None)
            except Exception, e:
                self.warning('get_model(%s): %s' % (alarm, e))
        return value
예제 #9
0
class CommonAPI(Object,fandango.SingletonMap):
    """ 
    This class provides common methods for managing a Soleil-like database 
    (for either archiving or snapshoting)
    The methods starting by "get" retrieve values using ArchivingDSs
    The methods starting by "load" access directly to MySQL database
    """
    #ArchivingTypes = ARCHIVING_TYPES
    #ArchivingClasses = ARCHIVING_CLASSES
    
    MAX_SERVERS_FOR_CLASS=5
    MIN_ARCHIVING_PERIOD=10
    
    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 = fandango.get_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()
          
    ## The ArchivingAPI is an iterator through archived attributes
    def __getitem__(self,k): 
        k = k if k.count('/')<=3 else fandango.tango.get_normal_name(k)
        return self.attributes.__getitem__(k)
    def __contains__(self,k): 
        k = k if k.count('/')<=3 else fandango.tango.get_normal_name(k)
        return self.attributes.__contains__(k)
    def get(self,k): 
        k = k if k.count('/')<=3 else fandango.tango.get_normal_name(k)
        return self.attributes.get(k)
    def has_key(self,k): 
        k = k if k.count('/')<=3 else fandango.tango.get_normal_name(k)
        return self.attributes.has_key(k)
    #[setattr(self,method,lambda k,meth=method:getattr(self.attributes,meth)(k)) for method in ('__getitem__','__contains__','get','has_key')]
    def __iter__(self): return self.attributes.__iter__()
    def iteritems(self): return self.attributes.iteritems()
    def keys(self): return self.attributes.keys()
    def values(self): return self.attributes.values()
    def __len__(self): return len(self.attributes.keys())
    def items(self): return self.attributes.items()
    #[setattr(self,method,lambda meth=method:getattr(self.attributes,meth)()) for method in ('__iter__','iteritems','items','keys','values')]          
        
    def load_servers(self,filters=None):
        if getattr(self,'servers',None) is None:
            self.servers = ServersDict()
        [self.servers.load_by_name(k) for k in (filters or self.ArchivingClasses)]
        self.servers.refresh()
        self.proxies = self.servers.proxies
        return self.servers
        
    def get_servers(self):
        if not getattr(self,'servers',None): return self.load_servers()
        return self.servers
        
    def get_archiving_classes(self):        
        self.ArchivingClasses = [k for k in ARCHIVING_CLASSES if self.schema in k.lower()]
        if self.schema!='snap': self.ArchivingClasses.append('ArchivingManager')
        return self.ArchivingClasses

    def __del__(self):
        try:
            self.log.debug( 'Deleting ArchivingAPI ...')
            for p in self.proxies.values():
                del p
            del self.tango
            for d in self.dbs.values():
                del d
        except:
            pass #print('Unable to delete API object')
            
    def __repr__(self):
        '''The status of Archiving device servers '''
        return '%s(%s[%s])' % (type(self),self.schema,len(self))
        #if self.servers:
            #report='The status of %s Archiving device servers is:\n'%self.schema
            #for k,v in self.servers.items():
                #report+='%s:\t%s\n'%(k,v.state)
            #if self.WatcherClass:
                #try: report+=self.proxies(
                    #self.servers.get_class_devices(self.WatcherClass)[0]
                    #).command_inout('GetReportCurrent')+'\n'
                #except: pass
            #return report         

    ####################################################################################################

    def get_random_device(self,klass,timeout=300000):
        device = None
        if not getattr(self,'servers',None): 
          self.load_servers(filters=[klass])
        remaining = self.servers.get_class_devices(klass)
        if not remaining: 
          self.servers.load_by_name(klass)
          remaining = self.servers.get_class_devices(klass)
        while remaining: #for i in range(len(self.extractors)):
            next = randrange(len(remaining))
            devname = remaining.pop(next)
            device = self.servers.proxies[devname]
            print devname
            try:
                device.ping()
                device.set_timeout_millis(timeout)
                break
            except Exception,e: 
                self.log.info('%s unreachable: %s'%(devname,str(e)))
        return device