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