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()
Exemple #2
0
 def pop(self,dev_name):
     '''Removes a device from the dict'''
     if self.tango_host and ':' not in dev_name:
         dev_name = self.tango_host + '/' + dev_name
     if dev_name not in self.keys(): return
     self.log.debug( 'Deleting the Proxy for %s'%dev_name)
     return CaselessDefaultDict.pop(self,dev_name)
Exemple #3
0
 def __getitem__(self,key):
     if self.tango_host and ':' not in key:
         key = self.tango_host + '/' + key
     return CaselessDefaultDict.__getitem__(self,key)
Exemple #4
0
 def pop(self,dev_name):
     '''Removes a device from the dict'''
     dev_name = self.translate(dev_name)
     if dev_name not in self.keys(): return
     self.log.debug( 'Deleting the Proxy for %s'%dev_name)
     return CaselessDefaultDict.pop(self,dev_name)
Exemple #5
0
 def __getitem__(self,key):
     key = self.translate(key)
     return CaselessDefaultDict.__getitem__(self,key)
Exemple #6
0
    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')
Exemple #7
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