zephir.monitor.agentmanager.agentdatamanager

Package zephir :: Package monitor :: Package agentmanager :: Module agentdatamanager |
[frames] | no frames]

# Source Code for Module zephir.monitor.agentmanager.agentdatamanager

      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
     11  """
     12
     13  try: _ # localized string fetch function
     14  except NameError: _ = str
     15
     16  import os, dircache
     17
     18  from zephir.monitor.agentmanager import config as cfg
     19  from zephir.monitor.agentmanager.agent import AgentData
     20
     21
     22
     23
     24 -class AgentManager:
     25      """Structure d'accès aux agents d'un poste client donné (classe
     26      abstraite).
     27
     28      Se comporte comme un dictionnaire C{{nom: agent}}.
     29
     30      TODO: utiliser UserDict.DictMixin
     31      """
     32
     33 -    def __init__(self, config, client_name):
     34          """
     35          @param config: dictionnaire des options de configuration de
     36            l'application
     37
     38          @param client_name: nom du client qui possède les agents
     39          """
     40          self.config = config
     41          self.client_name = client_name
     42          self.structure = self.load_structure()
     43
     44 -    def _sort_struct(self, liste, order_list):
     45          done = []
     46          # elements ordonnés
     47          for item in order_list:
     48              if item in liste:
     49                  done.append(item)
     50          # autres éléments (non présents dans site.cfg) ->  tri alphabétique
     51          liste.sort()
     52          for item in liste:
     53              if item not in done:
     54                  done.append(item)
     55          return done
     56
     57 -    def update_structure(self):
     58          """Recharge le classement en sections des agents.
     59          utile si un nouvel agent est remonté dans un datamanager"""
     60          self.structure = self.load_structure()
     61
     62 -    def load_structure(self):
     63          """Charge le classement en sections des agents.
     64
     65          Charge le fichier C{site.cfg} du répertoire de données
     66          correspondant au poste client. Ce fichier doit déclarer une
     67          variable C{SITE}. Cette variable doit contenir une liste de
     68          couples C{('titre de section': liste d'agents)}, qui définit
     69          le classement des agents dans la page du client.
     70
     71          Une structuration par défaut est créée si le C{site.cfg}
     72          n'existe pas.
     73          """
     74          h = { 'SITE': None }
     75          structure_file = os.path.join(
     76              cfg.client_data_dir(self.config, self.client_name),
     77              "site.cfg")
     78          self.order_section = []
     79          self.order_agent = {}
     80          try:
     81              execfile(structure_file, globals(), h)
     82              assert h['SITE'] is not None and type(h['SITE']) is list
     83              structure = h['SITE']
     84              for sct, ag in structure:
     85                  self.order_section.append(sct)
     86                  self.order_agent[sct] = ag
     87          except IOError:
     88              pass
     89
     90          unclassified_agents = [] # how does this update when agents get uploaded?
     91          struct = {}
     92          for name, agent in self.items():
     93              if hasattr(agent, 'section'):
     94                  section = agent.section
     95              else:
     96                  section = None
     97                  # ancienne version, on prend la section de site.cfg
     98                  for sct, agents in self.order_agent.items():
     99                      if name in agents:
    100                          section = sct
    101              if section is None:
    102                  unclassified_agents.append(name)
    103              elif struct.has_key(section):
    104                  struct[section].append(name)
    105              else:
    106                  struct[section] = [name]
    107
    108          final_struct = []
    109          for section in self._sort_struct(struct.keys(), self.order_section):
    110              agents = struct[section]
    111              final_struct.append((section, self._sort_struct(agents, self.order_agent[section])))
    112
    113          if len(final_struct) == 0 and len(unclassified_agents) != 0:
    114              final_struct.append((None, unclassified_agents))
    115
    116          return final_struct
    117
    118 -    def keys(self):
    119          raise NotImplemented # abstract method
    120
    121 -    def get_measure(self):
    122          """Renvoie les données stockées à la dernière mesure (sentinelle)
    123          """
    124          result = {}
    125          for agent_name,data in self.items():
    126              if hasattr(data, 'measure_data'):
    127                  result[agent_name] = data.measure_data
    128              else:
    129                  result[agent_name] = {}
    130          return result
    131
    132 -    def items(self):
    133
    134          result = []
    135          for k in self.keys():
    136              result.append([k, self[k]])
    137          return result
    138
    139 -    def reset_max_status(agent_name):
    140          raise NotImplemented # abstract method
    141
    142
    143
    144
    145 -class AgentDataManager(AgentManager):
    146      """Implémentation de C{L{AgentManager}} chargeant les données des
    147      agents depuis leurs archives sur disque exclusivement.
    148
    149      Le chargement des données se fait à travers un cache.
    150      """
    151
    152
    153 -    def __init__(self, config, client_name):
    154          self.cache = {} # agent_name => (modif. date, agent)
    155          AgentManager.__init__(self, config, client_name)
    156
    157 -    def __getitem__(self, agent_name):
    158          """Accès par nom aux agents (opérateur [] d'un dictionnaire).
    159          """
    160          # check has_key then empty cache if data removed ?
    161          agent_dir = cfg.agent_data_dir(self.config, self.client_name, agent_name)
    162          # get a lock on agent_dir ?
    163          needs_refresh = False
    164          try:
    165              (mtime, agent) = self.cache[agent_name]
    166          except KeyError: needs_refresh = True
    167          disk_mtime = os.path.getmtime(os.path.join(agent_dir, 'agent.xml'))
    168          if needs_refresh or (disk_mtime > mtime):
    169              agent = AgentData.from_archive(agent_dir)
    170              self.cache[agent_name] = (disk_mtime, agent)
    171          return agent
    172
    173
    174 -    def __setitem__(self, agent_name, agent):
    175          """Affectation par nom aux agents (opérateur []= d'un
    176          dictionnaire).
    177          """
    178          assert false, "Can't assign agent archives"
    179
    180
    181 -    def has_key(self, agent_name):
    182          d = cfg.agent_data_dir(self.config, self.client_name, agent_name)
    183          agent_data_dir_exists = os.path.isdir(d)
    184          agent_metadata_exists = os.path.isfile(os.path.join(d, 'agent.xml'))
    185          return agent_data_dir_exists and agent_metadata_exists
    186
    187
    188 -    def keys(self):
    189          d = cfg.client_data_dir(self.config, self.client_name)
    190          result = []
    191          for k in dircache.listdir(d):
    192              if self.has_key(k): result.append(k)
    193          return result
    194
    195 -    def global_status(self):
    196          """Méthode de compatibilité avec l'ancien système d'agents.
    197          """
    198          # liste des agents à prendre en compte
    199          real_agents = []
    200          # lecture de la liste des agents à ignorer
    201          ignore_list = []
    202          # liste globale
    203          fic_override = os.path.normpath(os.path.join(cfg.client_data_dir(self.config, self.client_name),'../ignore_list'))
    204          if os.path.exists(fic_override):
    205              f = open(fic_override)
    206              ignore_list.extend(f.read().strip().split('\n'))
    207              f.close()
    208          # liste par serveur
    209          fic_override = os.path.join(cfg.client_data_dir(self.config, self.client_name),'ignore_list')
    210          if os.path.exists(fic_override):
    211              f = open(fic_override)
    212              ignore_list.extend(f.read().strip().split('\n'))
    213              f.close()
    214          for fam in self.structure:
    215              real_agents.extend(fam[1])
    216          # on les supprime de la liste
    217          for agent in ignore_list:
    218              if agent in real_agents:
    219                  real_agents.remove(agent)
    220          for agent_name in self.keys():
    221              if self[agent_name].last_status.level() in ['Error']:
    222                  if agent_name in real_agents:
    223                      return 0
    224          return 1
    225
    226 -    def agents_status(self):
    227          """Méthode de compatibilité avec l'ancien système d'agents.
    228
    229          @return: dictionnaire C{{'nom agent': (description, status, date de dernière mesure)}}.
    230          """
    231          result = {}
    232          for agent_name,data in self.items():
    233              if data.last_status.level() in ['Error']:
    234                  status=0
    235              else:
    236                  status=1
    237              # on retourne le libellé de l'agent, l'etat et la date de mesure
    238              libelle = data.description
    239              if libelle == '':
    240                  libelle=agent_name
    241              result[agent_name]=[libelle,status,data.last_measure_date]
    242          return result
    243
    244 -    def reset_max_status(self, agent_name):
    245          # do xmlrpc call to updater on client... impossible since the client may be hidden by a firewall
    246          pass
    247          # rpc = xmlrpclib.Server('http://localhost:%d/xmlrpc/' % cfg.DEFAULT_CONFIG['webserver_port'])
    248          # rpc.reset_max_status_for_agents([agent_name])
    249          # check if it worked, display errors
    250
    251
    252
    253
    254 -class LiveAgentsManager(AgentManager):
    255      """Implémentation de C{L{AgentManager}} donnant accès direct aux
    256      agents en mémoire.
    257
    258      Utile pour les agents chargés sur la même machine. La page web
    259      sera mise à jour en temps réel plutôt qu'au rythme des envois de
    260      données au serveur Zephir.
    261      """
    262
    263 -    def __init__(self, config, client_name, agents):
    264          self.agents = agents
    265          AgentManager.__init__(self, config, client_name) # needs keys(), thus self.agents defined
    266
    267
    268 -    def __getitem__(self, agent_name):
    269          agent = self.agents[agent_name]
    270          agent.ensure_data_uptodate()
    271          return AgentData.from_agent(agent)
    272
    273
    274 -    def __setitem__(self, agent_name, agent):
    275          self.agents[agent_name] = agent
    276
    277 -    def has_key(self, agent_name): return self.agents.has_key(agent_name)
    278 -    def keys(self): return self.agents.keys()
    279
    280 -    def reset_max_status(self, agent_name):
    281          self.agents[agent_name].reset_max_status()
    282