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()
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()
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
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
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()
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
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
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