zephir.monitor.agents.montages

Package zephir :: Package monitor :: Package agents :: Module montages |
[frames] | no frames]

# Source Code for Module zephir.monitor.agents.montages

      1  # -*- coding: UTF-8 -*-
      2  ###########################################################################
      3  # Eole NG - 2007
      4  # Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
      5  # Licence CeCill  cf /root/LicenceEole.txt
      6  # eole@ac-dijon.fr
      7  ###########################################################################
      8
      9  """
     10  Agent zephir pour afficher les partitions montées et leur utilisation
     11  """
     12
     13  from twisted.internet.utils import getProcessOutput
     14
     15  from zephir.monitor.agentmanager.agent import Agent
     16  from zephir.monitor.agentmanager import status
     17  from zephir.monitor.agentmanager.data import HTMLData, TableData
     18  from zephir.monitor.agentmanager.util import percent
     19
     20  # limites à partir des quelles on créé une alerte
     21  SOFT_LIMIT = 90
     22  HARD_LIMIT = 96
     23
     24 -def stat_format(x):
     25      return "%.1f" % x
     26
     27 -def perc2img(perc):
     28      p = int(perc[0:-1])
     29      if p >= HARD_LIMIT :
     30          color = 'red'
     31      elif p >= SOFT_LIMIT :
     32          color = 'orange'
     33      else:
     34          color = 'green'
     35
     36      return """<img src="/static/img/%spix.gif" height="16" width="%s">
     37  <img src="/static/img/whitepix.gif" height="16" width="%s">""" % (color,str(p),str(100-p))
     38
     39
     40 -class DiskSpace(Agent):
     41
     42 -    def __init__(self, name,
     43                   **params):
     44          Agent.__init__(self, name, **params)
     45          self.table = TableData([
     46              ('name', 'Montage', {'align':'right'}, None),
     47              ('device', 'Partition', {'align':'left'}, None),
     48              ('type', 'Type', {'align':'right'}, None),
     49              ('inodes', 'Inodes', {'align':'right'}, None),
     50              ('perc', 'Utilisation', {'align':'right'}, None),
     51              ('used', 'Utilisé (Mo)', {'align':'right'}, None),
     52              ('free', 'Libre (Mo)', {'align':'right'}, None),
     53              ('size', 'Taille (Mo)', {'align':'right'}, None),
     54              ('graph', 'Graphe', {'align':'left'}, None) ])
     55          self.data = [self.table]
     56
     57 -    def measure(self):
     58          cmd = getProcessOutput('/bin/mount',
     59                                 env = {'LC_ALL': 'C'})
     60          cmd.addCallback(self.measure_mounts)
     61          cmd.addErrback(self.measure_error)
     62          return cmd
     63
     64 -    def measure_mounts(self, output):
     65          # recherche des montages de type 'bind'
     66          mount_binds = []
     67          for mnt_line in output.split('\n'):
     68              try:
     69                  options = mnt_line.split('(')[1]
     70                  if 'bind' in options:
     71                      dev_name = mnt_line.split()[0]
     72                      mount_binds.append(dev_name)
     73              except:
     74                  # pas d'options affichées ?
     75                  pass
     76          cmd = getProcessOutput('df',
     77                                 args = ['-iP'],
     78                                 env = {'LC_ALL': 'C'})
     79          cmd.addCallback(self.measure_inodes, mount_binds)
     80          cmd.addErrback(self.measure_error)
     81          return cmd
     82
     83 -    def measure_inodes(self, mnt, mount_binds):
     84          # tableau du pourcentage d'inodes utilisés
     85          # récupération des lignes
     86          lmnt = mnt.splitlines()
     87          # traitement mnt
     88          inodes = {}
     89          for lmn in lmnt:
     90              try:
     91                  inodes[lmn.split()[0]] = lmn.split()[4]
     92                  # systèmes de fichiers sans inodes (#1829)
     93                  if inodes[lmn.split()[0]] == '-':
     94                      inodes[lmn.split()[0]] = '0%'
     95              except:
     96                  pass
     97          cmd = getProcessOutput('df',
     98                                 args = ['-kP','--print-type','--exclude-type=tmpfs','--exclude-type=usbfs'],
     99                                 env = {'LC_ALL': 'C'})
    100          cmd.addCallback(self.measure_process, mount_binds, inodes)
    101          cmd.addErrback(self.measure_error)
    102          return cmd
    103
    104 -    def measure_process(self, mnt, mount_binds, inodes):
    105          # récupération des lignes
    106          lmnt = mnt.splitlines()
    107          # traitement mnt
    108          lmnt = lmnt[1:]
    109          liste=[]
    110          for lmn in lmnt :
    111              try:
    112                  l = {}
    113                  l['name'] = lmn.split()[6] # montage
    114                  l['device'] = lmn.split()[0] # partition
    115                  l['type'] = lmn.split()[1] # jointure sur le type
    116                  l['perc'] = lmn.split()[5] # utilisation (%)
    117                  l['free'] = int(lmn.split()[4])/1024 # dispo
    118                  l['used'] = int(lmn.split()[3])/1024 # utilisé
    119                  l['size'] = int(lmn.split()[2])/1024 # taille
    120                  l['graph'] = perc2img(l['perc'])
    121                  l['inodes'] = inodes[l['device']]
    122              except:
    123                  pass
    124              if l['device'] not in mount_binds:
    125                  liste.append(l)
    126                  self.measure_data[l['name']] = (int(l['perc'][:-1]), int(l['size']), int(l['used']), int(l['free']), l['type'])
    127
    128          return {'statistics': liste}
    129
    130 -    def measure_error(self, res):
    131          """ la commande df ne retourne rien ?"""
    132          return {'statistics': [{'name':'---', 'device':'---', 'type':'---',
    133                                  'inodes':'---', 'perc':'---', 'free':'---',
    134                                  'used':'---', 'size':'---', 'graph':'---'}]}
    135
    136 -    def check_status(self):
    137          err = 0
    138          warn = 0
    139          err_nodes = 0
    140          warn_nodes = 0
    141          if self.last_measure is not None:
    142              if self.last_measure.value['statistics'][0]['name'] == '---':
    143                  return status.Unknown()
    144              # Alerte si une partition est remplie à plus de "LIMIT" (%)
    145              for device in self.last_measure.value['statistics']:
    146                  # on ignore les cdroms pour les alertes
    147                  if not device['type'] in ['iso9660', 'supermount', 'cifs']:
    148                      if int(device['perc'][:-1]) >= HARD_LIMIT:
    149                          err += 1
    150                      if int(device['inodes'][:-1]) >= HARD_LIMIT:
    151                          err_nodes += 1
    152                      if int(device['perc'][:-1]) >= SOFT_LIMIT:
    153                          warn += 1
    154                      if int(device['inodes'][:-1]) >= SOFT_LIMIT:
    155                          warn_nodes += 1
    156          if err == 1:
    157              return status.Error("%d partition remplie à plus de %d %%"%(err,HARD_LIMIT))
    158          if err > 1:
    159              return status.Error("%d partitions remplies à plus de %d %%"%(err,HARD_LIMIT))
    160          if err_nodes == 1:
    161              return status.Error("%d partition utilise plus de %d %% des Inodes"%(err_nodes,HARD_LIMIT))
    162          if err_nodes > 1:
    163              return status.Error("%d partitions utilisent plus de %d %% des Inodes"%(err_nodes,HARD_LIMIT))
    164          if warn == 1:
    165              return status.Warn("%d partition remplie à plus de %d %%"%(warn,SOFT_LIMIT))
    166          if warn > 1:
    167              return status.Warn("%d partitions remplies à plus de %d %%"%(warn,SOFT_LIMIT))
    168          if warn_nodes == 1:
    169              return status.Warn("%d partition utilise plus de %d %% des Inodes"%(warn_nodes,SOFT_LIMIT))
    170          if warn_nodes > 1:
    171              return status.Warn("%d partitions utilisent plus de %d %% des Inodes"%(warn_nodes,SOFT_LIMIT))
    172          return status.OK()
    173
    174 -    def write_data(self):
    175          Agent.write_data(self)
    176          if self.last_measure is not None:
    177              self.table.table_data = self.last_measure.value['statistics']
    178