Changeset 1508


Ignore:
Timestamp:
Feb 19, 2014 11:04:00 AM (8 years ago)
Author:
jemian
Message:

respond to changes in alive record server

File:
1 edited

Legend:

Unmodified
Added
Removed
  • topdoc/trunk/src/bcda/ask_alive.py

    r1507 r1508  
    2525
    2626class Ioc(object):
    27         '''describe the content of an IOC record in the alive database'''
    28 
    29         def __init__(self):
    30                 self.name = ''
    31                 self.address = ''
    32                 self.timer = 0
    33                 self.uptime = ''
    34                 self.downtime = ''
    35                 self.alive = False
    36                 self.env = dict(ARCH='', TOP='', EPICS_BASE='',
    37                                                 SUPPORT='', LOCATION='', ENGINEER='')
    38 
    39         def set_from_xml(self, node, version=UNVERSIONED_XML):
    40                 '''define the content from an XML node'''
    41                 if node is None:
    42                         return
    43                 if version in (UNVERSIONED_XML):
    44                         self.name = self.subnode_text(node, 'name')
    45                         self.address = self.subnode_text(node, 'address')
    46                         self.timer = int(self.subnode_text(node, 'timer'))
    47                         self.uptime = self.subnode_text(node, 'uptime')
    48                         self.downtime = self.subnode_text(node, 'downtime')
    49                         for subnode in node.xpath('env'):
    50                                 key = self.subnode_text(subnode, 'key')
    51                                 value = self.subnode_text(subnode, 'value')
    52                                 self.env[key] = value
    53 
    54                 self.alive = self.timer < TIMER_THRESHOLD_DEAD_IOC
    55 
    56         def subnode_text(self, node, subnode_tag):
    57                 '''return the text from the named subnode'''
    58                 subnode = node.find(subnode_tag)
    59                 if subnode is not None:
    60                         s = etree.tostring(subnode, method="text")
    61                         return s.strip()
    62                 else:
    63                         return None
     27    '''describe the content of an IOC record in the alive database'''
     28   
     29   
     30    def __init__(self):
     31        self.name = ''
     32        self.address = ''
     33        self.timer = 0
     34        self.boot_timer = 0
     35        self.clock = ''
     36        self.alive = False
     37        self.env = dict(ARCH='', TOP='', EPICS_BASE='',
     38                                        SUPPORT='', LOCATION='', ENGINEER='')
     39   
     40    def set_from_xml(self, node, version=UNVERSIONED_XML):
     41        '''define the content from an XML node'''
     42        if node is None:
     43                return
     44        if version in ("1.0"):
     45            self.name = node.get('name')
     46            self.address = subnode_text(node, 'address')
     47            self.timer = int(subnode_text(node, 'ping_timer'))
     48            self.boot_timer = int(subnode_text(node, 'boot_timer'))
     49            for subnode in node.xpath('env'):
     50                key = subnode.get('name')
     51                value = etree.tostring(subnode, method="text").strip()
     52                self.env[key] = value
     53            self.alive = self.timer < TIMER_THRESHOLD_DEAD_IOC
     54            secs = self.boot_timer
     55            clock = ' '.join([time_fmt(secs, base) for base in 'y w d h m s'.split()])
     56            # example: secs=446403, clock = '5d 4h 3s'
     57            self.clock = clock.strip()
    6458
    6559
     60# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     61
     62
     63def time_fmt(secs, base='s'):
     64    '''take secs and return a human-readable string: secs=72, base='m', return '1m' '''
     65    d = dict(s=1, m=60, h=60*60, d=24*60*60, w=7*24*60*60, y=52*7*24*60*60)[base]
     66    b = dict(s=60, m=60, h=24, d=7, w=52, y=100)[base]
     67    t = (secs/d) % b
     68    if t > 0:
     69        return str(t) + base
     70    else:
     71        return ''
     72
     73
     74def subnode_text(node, subnode_tag):
     75        '''return the text from the named subnode'''
     76        subnode = node.find(subnode_tag)
     77        if subnode is not None:
     78                s = etree.tostring(subnode, method="text")
     79                return s.strip()
     80        else:
     81                return None
     82   
     83   
    6684def identify_iocs(xml_source=ALIVE_URL):
    67         '''read all the IOCs from the XML document, return as {name:Ioc()}'''
    68         doc = etree.parse(xml_source)
    69         root = doc.getroot()
    70         version = root.get('version', UNVERSIONED_XML)
    71         if version not in (UNVERSIONED_XML):
    72                 raise RuntimeError, 'unexpected version: ' + version
     85    '''read all the IOCs from the XML document, return as report_time, {name:Ioc()}'''
     86    doc = etree.parse(xml_source)
     87    root = doc.getroot()
     88    version = root.get('version', UNVERSIONED_XML)
     89   
     90    # <time>2014-02-19 10:06:29</time>
     91    report_time = subnode_text(root, 'time')
     92   
     93    ioc_db = {}
     94    for node in doc.xpath('IOC'):
     95        ioc = Ioc()
     96        ioc.set_from_xml(node, version)
     97        if ioc.name in ioc_db:
     98                raise RuntimeError, 'duplicate IOC name: ' + ioc.name
     99        ioc_db[ioc.name] = ioc
     100    return report_time, ioc_db
    73101
    74         ioc_db = {}
    75         for node in doc.xpath('IOC'):
    76                 ioc = Ioc()
    77                 ioc.set_from_xml(node, version)
    78                 if ioc.name in ioc_db:
    79                         raise RuntimeError, 'duplicate IOC name: ' + ioc.name
    80                 ioc_db[ioc.name] = ioc
    81         return ioc_db
     102
     103# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    82104
    83105
    84106def main():
    85         '''print the list of IOCs in a table'''
    86         t = Table()
    87         t.labels = ['#', 'IOC', 'IP', 'uptime(downtime)', 'ENGINEER', 'LOCATION']
     107    '''print the list of IOCs in a table'''
     108    report_time, ioc_db = identify_iocs()
     109    t = Table()
     110    metalabels = ('ENGINEER', 'LOCATION', 'ARCH', 'TOP', 'EPICS_BASE', 'SUPPORT')
     111    metalabels = ('ENGINEER', 'LOCATION')
    88112
    89         c = 0
    90         for k, ioc in sorted(identify_iocs().items()):
    91                 c += 1
    92                 row = [c, k, ioc.address,]
    93                 if ioc.alive:
    94                         row.append(ioc.uptime)
    95                 else:
    96                         row.append('(' + ioc.downtime + ')')
    97                 for item in ('ENGINEER', 'LOCATION'):
    98                         row.append( ioc.env.get(item, '') )
    99                 t.rows += [row]
    100         print t.reST(fmt='complex')
     113    t.labels = ['#', 'IOC', 'IP', 'uptime(downtime)', ]
     114    t.labels += metalabels
     115   
     116    c = 0
     117    for k, ioc in sorted(ioc_db.items()):
     118        c += 1
     119        row = [c, k, ioc.address,]
     120        if ioc.alive:
     121                row.append(ioc.clock)
     122        else:
     123                row.append('(' + ioc.clock + ')')
     124        for item in metalabels:
     125                row.append( ioc.env.get(item, '') )
     126        t.rows += [row]
     127    print "report time: ", report_time
     128    print t.reST(fmt='complex')
    101129
    102130
Note: See TracChangeset for help on using the changeset viewer.