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