1 | import json |
---|
2 | import os.path |
---|
3 | import os |
---|
4 | import time |
---|
5 | import xmlrpclib |
---|
6 | import socket |
---|
7 | import netifaces |
---|
8 | import re |
---|
9 | import importlib |
---|
10 | import sys |
---|
11 | import tarfile |
---|
12 | import threading |
---|
13 | import subprocess |
---|
14 | import time |
---|
15 | import string |
---|
16 | |
---|
17 | class VariablesManager: |
---|
18 | |
---|
19 | VARIABLES_FILE="/var/lib/n4d/variables" |
---|
20 | VARIABLES_DIR="/var/lib/n4d/variables-dir/" |
---|
21 | LOCK_FILE="/tmp/.llxvarlock" |
---|
22 | INBOX="/var/lib/n4d/variables-inbox/" |
---|
23 | TRASH="/var/lib/n4d/variables-trash/" |
---|
24 | CUSTOM_INSTALLATION_DIR="/usr/share/n4d/variablesmanager-funcs/" |
---|
25 | LOG="/var/log/n4d/variables-manager" |
---|
26 | |
---|
27 | def __init__(self): |
---|
28 | |
---|
29 | self.instance_id="".join(random.sample(string.letters+string.digits, 50)) |
---|
30 | self.server_instance_id=None |
---|
31 | self.variables={} |
---|
32 | self.variables_ok=False |
---|
33 | self.variables_clients={} |
---|
34 | self.variables_triggers={} |
---|
35 | self.failed_servers={} |
---|
36 | t=threading.Thread(target=self.check_clients,args=()) |
---|
37 | t.daemon=True |
---|
38 | t.start() |
---|
39 | |
---|
40 | if os.path.exists(VariablesManager.LOCK_FILE): |
---|
41 | os.remove(VariablesManager.LOCK_FILE) |
---|
42 | |
---|
43 | |
---|
44 | if os.path.exists(VariablesManager.VARIABLES_FILE): |
---|
45 | self.variables_ok,ret=self.load_json(VariablesManager.VARIABLES_FILE) |
---|
46 | try: |
---|
47 | os.remove(VariablesManager.VARIABLES_FILE) |
---|
48 | except: |
---|
49 | pass |
---|
50 | else: |
---|
51 | self.variables_ok,ret=self.load_json(None) |
---|
52 | |
---|
53 | if self.variables_ok: |
---|
54 | #print "\nVARIABLES FILE" |
---|
55 | #print "==============================" |
---|
56 | #self.listvars() |
---|
57 | self.read_inbox(False) |
---|
58 | #print "\nAFTER INBOX" |
---|
59 | #print "==============================" |
---|
60 | #print self.listvars(True) |
---|
61 | self.empty_trash(False) |
---|
62 | #print "\nAFTER TRASH" |
---|
63 | #print "==============================" |
---|
64 | #print self.listvars(True) |
---|
65 | self.add_volatile_info() |
---|
66 | self.write_file() |
---|
67 | else: |
---|
68 | print("[VariablesManager] Loading variables failed because: " + str(ret)) |
---|
69 | |
---|
70 | |
---|
71 | #def __init__ |
---|
72 | |
---|
73 | |
---|
74 | def startup(self,options): |
---|
75 | |
---|
76 | if "REMOTE_VARIABLES_SERVER" in self.variables: |
---|
77 | t=threading.Thread(target=self.register_n4d_instance_to_server) |
---|
78 | t.daemon=True |
---|
79 | t.start() |
---|
80 | |
---|
81 | #def startup |
---|
82 | |
---|
83 | |
---|
84 | def is_ip_in_range(self,ip,network): |
---|
85 | |
---|
86 | try: |
---|
87 | return netaddr.ip.IPAddress(ip) in netaddr.IPNetwork(network).iter_hosts() |
---|
88 | except: |
---|
89 | return False |
---|
90 | |
---|
91 | #def is_ip_in_range |
---|
92 | |
---|
93 | |
---|
94 | def get_net_size(self,netmask): |
---|
95 | |
---|
96 | netmask=netmask.split(".") |
---|
97 | binary_str="" |
---|
98 | for octet in netmask: |
---|
99 | binary_str += bin(int(octet))[2:].zfill(8) |
---|
100 | |
---|
101 | return str(len(binary_str.rstrip('0'))) |
---|
102 | |
---|
103 | #def get_net_size |
---|
104 | |
---|
105 | |
---|
106 | def get_ip(self): |
---|
107 | |
---|
108 | for item in netifaces.interfaces(): |
---|
109 | tmp=netifaces.ifaddresses(item) |
---|
110 | if tmp.has_key(netifaces.AF_INET): |
---|
111 | if tmp[netifaces.AF_INET][0].has_key("broadcast") and tmp[netifaces.AF_INET][0]["broadcast"]=="10.0.2.255": |
---|
112 | return tmp[netifaces.AF_INET][0]["addr"] |
---|
113 | return None |
---|
114 | |
---|
115 | #def get_ip |
---|
116 | |
---|
117 | |
---|
118 | def route_get_ip(self,ip): |
---|
119 | |
---|
120 | p=subprocess.Popen(["ip route get %s"%ip],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate() |
---|
121 | if "dev" in p[0]: |
---|
122 | dev=p[0].split("dev ")[1].split(" ")[0] |
---|
123 | else: |
---|
124 | dev=None |
---|
125 | return dev |
---|
126 | |
---|
127 | #def route_get_ip |
---|
128 | |
---|
129 | |
---|
130 | def get_mac_from_device(self,dev): |
---|
131 | |
---|
132 | for item in netifaces.interfaces(): |
---|
133 | |
---|
134 | try: |
---|
135 | i=netifaces.ifaddresses(item) |
---|
136 | mac=i[17][0]["addr"] |
---|
137 | broadcast=i[2][0]["broadcast"] |
---|
138 | network=broadcast |
---|
139 | netmask=i[2][0]["netmask"] |
---|
140 | network+="/%s"%self.get_net_size(netmask) |
---|
141 | ip=i[2][0]["addr"] |
---|
142 | except Exception as e: |
---|
143 | continue |
---|
144 | |
---|
145 | if dev=="lo": |
---|
146 | return mac |
---|
147 | |
---|
148 | if item==dev: |
---|
149 | return mac |
---|
150 | |
---|
151 | return None |
---|
152 | |
---|
153 | #def get_mac_from_device_in_server_network |
---|
154 | |
---|
155 | |
---|
156 | def register_instance(self,autocompleted_secured_ip,mac): |
---|
157 | |
---|
158 | client={} |
---|
159 | client["last_check"]=int(time.time()) |
---|
160 | client["missed_pings"]=0 |
---|
161 | client["ip"]=autocompleted_secured_ip |
---|
162 | self.variables_clients[mac]=client |
---|
163 | |
---|
164 | return self.instance_id |
---|
165 | |
---|
166 | #def register_instance |
---|
167 | |
---|
168 | |
---|
169 | def register_n4d_instance_to_server(self): |
---|
170 | |
---|
171 | while True: |
---|
172 | |
---|
173 | try: |
---|
174 | server_ip=socket.gethostbyname(self.variables["REMOTE_VARIABLES_SERVER"][u"value"]) |
---|
175 | if self.get_ip()!=server_ip: |
---|
176 | |
---|
177 | c=xmlrpclib.ServerProxy("https://%s:9779"%server_ip) |
---|
178 | mac=self.get_mac_from_device(self.route_get_ip(server_ip)) |
---|
179 | self.server_instance_id=c.register_instance("","VariablesManager","",mac) |
---|
180 | |
---|
181 | except Exception as e: |
---|
182 | |
---|
183 | self.server_instance_id=None |
---|
184 | return None |
---|
185 | |
---|
186 | time.sleep(60*3) |
---|
187 | |
---|
188 | #def register_n4d_instance_to_server |
---|
189 | |
---|
190 | |
---|
191 | def check_clients(self): |
---|
192 | |
---|
193 | while True: |
---|
194 | |
---|
195 | for mac in self.variables_clients: |
---|
196 | |
---|
197 | ip=self.variables_clients[mac]["ip"] |
---|
198 | t=threading.Thread(target=self.check_single_client,args=(mac,ip,)) |
---|
199 | t.daemon=True |
---|
200 | t.start() |
---|
201 | |
---|
202 | time.sleep(60*3) |
---|
203 | |
---|
204 | |
---|
205 | #def check_clients |
---|
206 | |
---|
207 | def manual_client_list_check(self): |
---|
208 | |
---|
209 | for mac in self.variables_clients: |
---|
210 | ip=self.variables_clients[mac]["ip"] |
---|
211 | t=threading.Thread(target=self.check_single_client,args=(mac,ip,)) |
---|
212 | t.daemon=True |
---|
213 | t.start() |
---|
214 | |
---|
215 | #def manual_client_list_check |
---|
216 | |
---|
217 | |
---|
218 | def check_single_client(self,mac,ip): |
---|
219 | |
---|
220 | max_pings=3 |
---|
221 | |
---|
222 | print("[VariablesManager] Checking client { MAC:%s IP:%s } ... "%(mac,ip)) |
---|
223 | c=xmlrpclib.ServerProxy("https://%s:9779"%ip) |
---|
224 | try: |
---|
225 | c.get_methods() |
---|
226 | self.variables_clients[mac]["last_check"]=time.time() |
---|
227 | self.variables_clients[mac]["missed_pings"]=0 |
---|
228 | except: |
---|
229 | if mac in self.variables_clients: |
---|
230 | self.variables_clients[mac]["missed_pings"]+=1 |
---|
231 | if self.variables_clients[mac]["missed_pings"] >=max_pings: |
---|
232 | print "[VariablesManager] Removing client %s:%s after %s missed pings."%(mac,ip,max_pings) |
---|
233 | self.variables_clients.pop(mac) |
---|
234 | |
---|
235 | #def check_single_client |
---|
236 | |
---|
237 | |
---|
238 | |
---|
239 | def get_client_list(self): |
---|
240 | |
---|
241 | return self.variables_clients |
---|
242 | |
---|
243 | #def get_client_list |
---|
244 | |
---|
245 | def notify_changes(self,variable): |
---|
246 | |
---|
247 | if len(self.variables_clients) > 0: |
---|
248 | |
---|
249 | print "[VariablesManager] Notifying changes... " |
---|
250 | for mac in self.variables_clients: |
---|
251 | |
---|
252 | ip=self.variables_clients[mac]["ip"] |
---|
253 | c=xmlrpclib.ServerProxy("https://%s:9779"%ip) |
---|
254 | try: |
---|
255 | c.server_changed("","VariablesManager","",self.instance_id,variable) |
---|
256 | |
---|
257 | except: |
---|
258 | self.variables_clients[mac]["missed_pings"]+=1 |
---|
259 | |
---|
260 | self.variables_clients[mac]["last_check"]=time.time() |
---|
261 | |
---|
262 | #def announce_changes |
---|
263 | |
---|
264 | |
---|
265 | def server_changed(self,autocompleted_server_ip,server_instance_id,variable_name): |
---|
266 | |
---|
267 | if server_instance_id==self.server_instance_id: |
---|
268 | |
---|
269 | print "[VariablesManager] Server instance ID validated" |
---|
270 | t=threading.Thread(target=self.execute_trigger,args=(variable_name,)) |
---|
271 | t.daemon=True |
---|
272 | t.start() |
---|
273 | |
---|
274 | return True |
---|
275 | |
---|
276 | else: |
---|
277 | |
---|
278 | if autocompleted_server_ip not in self.failed_servers: |
---|
279 | self.failed_servers[autocompleted_server_ip]={} |
---|
280 | self.failed_servers[autocompleted_server_ip]["failed_count"]=0 |
---|
281 | |
---|
282 | sleep_time=0.1 |
---|
283 | self.failed_servers[autocompleted_server_ip]["failed_count"]+=1 |
---|
284 | time.sleep(sleep_time*self.failed_servers[autocompleted_server_ip]["failed_count"]) |
---|
285 | return False |
---|
286 | |
---|
287 | #def server_changed |
---|
288 | |
---|
289 | |
---|
290 | def execute_trigger(self,variable_name): |
---|
291 | |
---|
292 | if variable_name in self.variables_triggers: |
---|
293 | for i in self.variables_triggers[variable_name]: |
---|
294 | class_name,function=i |
---|
295 | try: |
---|
296 | print "[VariablesManager] Executing %s.%s trigger..."%(class_name,function.im_func.func_name) |
---|
297 | function(self.get_variable(variable_name)) |
---|
298 | except Exception as e: |
---|
299 | print e |
---|
300 | |
---|
301 | #def execute_trigger |
---|
302 | |
---|
303 | |
---|
304 | def register_trigger(self,variable_name,class_name,function): |
---|
305 | |
---|
306 | if variable_name not in self.variables_triggers: |
---|
307 | self.variables_triggers[variable_name]=[] |
---|
308 | |
---|
309 | self.variables_triggers[variable_name].append((class_name,function)) |
---|
310 | |
---|
311 | #def register_trigger |
---|
312 | |
---|
313 | |
---|
314 | def backup(self,dir="/backup"): |
---|
315 | |
---|
316 | try: |
---|
317 | |
---|
318 | #file_path=dir+"/"+self.get_time()+"_VariablesManager.tar.gz" |
---|
319 | file_path=dir+"/"+get_backup_name("VariablesManager") |
---|
320 | tar=tarfile.open(file_path,"w:gz") |
---|
321 | tar.add(VariablesManager.VARIABLES_DIR) |
---|
322 | tar.close() |
---|
323 | |
---|
324 | return [True,file_path] |
---|
325 | |
---|
326 | except Exception as e: |
---|
327 | return [False,str(e)] |
---|
328 | |
---|
329 | #def backup |
---|
330 | |
---|
331 | |
---|
332 | def restore(self,file_path=None): |
---|
333 | |
---|
334 | |
---|
335 | if file_path==None: |
---|
336 | for f in sorted(os.listdir("/backup"),reverse=True): |
---|
337 | if "VariablesManager" in f: |
---|
338 | file_path="/backup/"+f |
---|
339 | break |
---|
340 | |
---|
341 | try: |
---|
342 | |
---|
343 | if os.path.exists(file_path): |
---|
344 | |
---|
345 | tmp_dir=tempfile.mkdtemp() |
---|
346 | tar=tarfile.open(file_path) |
---|
347 | tar.extractall(tmp_dir) |
---|
348 | tar.close() |
---|
349 | |
---|
350 | if not os.path.exists(VariablesManager.VARIABLES_DIR): |
---|
351 | os.mkdir(VariablesManager.VARIABLES_DIR) |
---|
352 | |
---|
353 | for f in os.listdir(tmp_dir+VariablesManager.VARIABLES_DIR): |
---|
354 | tmp_path=tmp_dir+VariablesManager.VARIABLES_DIR+f |
---|
355 | shutil.copy(tmp_path,VariablesManager.VARIABLES_DIR) |
---|
356 | |
---|
357 | self.load_json(None) |
---|
358 | |
---|
359 | return [True,""] |
---|
360 | |
---|
361 | except Exception as e: |
---|
362 | |
---|
363 | return [False,str(e)] |
---|
364 | |
---|
365 | #def restore |
---|
366 | |
---|
367 | def log(self,txt): |
---|
368 | |
---|
369 | try: |
---|
370 | f=open(VariablesManager.LOG,"a") |
---|
371 | txt=str(txt) |
---|
372 | f.write(txt+"\n") |
---|
373 | f.close() |
---|
374 | except Exception as e: |
---|
375 | pass |
---|
376 | |
---|
377 | #def log |
---|
378 | |
---|
379 | def listvars(self,extra_info=False,custom_dic=None): |
---|
380 | ret="" |
---|
381 | |
---|
382 | try: |
---|
383 | |
---|
384 | if custom_dic==None: |
---|
385 | custom_dic=self.variables |
---|
386 | for variable in custom_dic: |
---|
387 | if type(custom_dic[variable])==type({}) and "root_protected" in custom_dic[variable] and custom_dic[variable]["root_protected"]: |
---|
388 | continue |
---|
389 | value=self.get_variable(variable) |
---|
390 | if value==None: |
---|
391 | continue |
---|
392 | ret+=variable+ "='" + str(value).encode("utf-8") + "';\n" |
---|
393 | if extra_info: |
---|
394 | ret+= "\tDescription: " + self.variables[variable][u"description"] + "\n" |
---|
395 | ret+="\tUsed by:\n" |
---|
396 | for depend in self.variables[variable][u"packages"]: |
---|
397 | ret+= "\t\t" + depend.encode("utf-8") + "\n" |
---|
398 | |
---|
399 | return ret.strip("\n") |
---|
400 | except Exception as e: |
---|
401 | return str(e) |
---|
402 | |
---|
403 | #def listvars |
---|
404 | |
---|
405 | def calculate_variable(self,value): |
---|
406 | |
---|
407 | pattern="_@START@_.*?_@END@_" |
---|
408 | variables=[] |
---|
409 | |
---|
410 | ret=re.findall(pattern,value) |
---|
411 | |
---|
412 | for item in ret: |
---|
413 | tmp=item.replace("_@START@_","") |
---|
414 | tmp=tmp.replace("_@END@_","") |
---|
415 | variables.append(tmp) |
---|
416 | |
---|
417 | for var in variables: |
---|
418 | value=value.replace("_@START@_"+var+"_@END@_",self.get_variable(var)) |
---|
419 | |
---|
420 | return value |
---|
421 | |
---|
422 | #def remove_calculated_chars |
---|
423 | |
---|
424 | def add_volatile_info(self): |
---|
425 | |
---|
426 | for item in self.variables: |
---|
427 | |
---|
428 | if not self.variables[item].has_key("volatile"): |
---|
429 | self.variables[item]["volatile"]=False |
---|
430 | |
---|
431 | #def add_volatile_info |
---|
432 | |
---|
433 | |
---|
434 | def showvars(self,var_list,extra_info=False): |
---|
435 | |
---|
436 | ret="" |
---|
437 | |
---|
438 | for var in var_list: |
---|
439 | ret+=var+"='" |
---|
440 | if self.variables.has_key(var): |
---|
441 | try: |
---|
442 | ret+=self.variables[var][u'value'].encode("utf-8")+"';\n" |
---|
443 | except Exception as e: |
---|
444 | #it's probably something old showvars couldn't have stored anyway |
---|
445 | ret+="';\n" |
---|
446 | if extra_info: |
---|
447 | ret+= "\tDescription: " + self.variables[var][u"description"] + "\n" |
---|
448 | ret+="\tUsed by:\n" |
---|
449 | for depend in self.variables[var][u"packages"]: |
---|
450 | ret+= "\t\t" + depend.encode("utf-8") + "\n" |
---|
451 | else: |
---|
452 | ret+="'\n" |
---|
453 | |
---|
454 | return ret.strip("\n") |
---|
455 | |
---|
456 | #def showvars |
---|
457 | |
---|
458 | |
---|
459 | def get_variables(self): |
---|
460 | |
---|
461 | return self.variables |
---|
462 | |
---|
463 | #def get_variables |
---|
464 | |
---|
465 | |
---|
466 | def load_json(self, file=None): |
---|
467 | |
---|
468 | self.variables={} |
---|
469 | |
---|
470 | if file!=None: |
---|
471 | |
---|
472 | try: |
---|
473 | |
---|
474 | f=open(file,"r") |
---|
475 | data=json.load(f) |
---|
476 | f.close() |
---|
477 | self.variables=data |
---|
478 | #return [True,""] |
---|
479 | |
---|
480 | except Exception as e: |
---|
481 | print(str(e)) |
---|
482 | #return [False,e.message] |
---|
483 | |
---|
484 | for file in os.listdir(VariablesManager.VARIABLES_DIR): |
---|
485 | try: |
---|
486 | sys.stdout.write("\t[VariablesManager] Loading " + file + " ... ") |
---|
487 | f=open(VariablesManager.VARIABLES_DIR+file) |
---|
488 | data=json.load(f) |
---|
489 | f.close() |
---|
490 | self.variables[file]=data[file] |
---|
491 | print("OK") |
---|
492 | except Exception as e: |
---|
493 | print("FAILED ["+str(e)+"]") |
---|
494 | |
---|
495 | return [True,""] |
---|
496 | |
---|
497 | #def load_json |
---|
498 | |
---|
499 | def read_inbox(self, force_write=False): |
---|
500 | |
---|
501 | |
---|
502 | if self.variables_ok: |
---|
503 | |
---|
504 | if os.path.exists(VariablesManager.INBOX): |
---|
505 | |
---|
506 | for file in os.listdir(VariablesManager.INBOX): |
---|
507 | file_path=VariablesManager.INBOX+file |
---|
508 | print "[VariablesManager] Adding " + file_path + " info..." |
---|
509 | try: |
---|
510 | f=open(file_path,"r") |
---|
511 | data=json.load(f) |
---|
512 | f.close() |
---|
513 | |
---|
514 | for item in data: |
---|
515 | if self.variables.has_key(item): |
---|
516 | for key in data[item].keys(): |
---|
517 | if not self.variables[item].has_key(unicode(key)): |
---|
518 | self.variables[item][unicode(key)] = data[item][key] |
---|
519 | if data[item].has_key(unicode('function')): |
---|
520 | self.variables[item][unicode('function')] = data[item][u'function'] |
---|
521 | for depend in data[item][u'packages']: |
---|
522 | if depend not in self.variables[item][u'packages']: |
---|
523 | self.variables[item][u'packages'].append(depend) |
---|
524 | |
---|
525 | if "force_update" in data[item] and data[item]["force_update"]: |
---|
526 | self.variables[item][u'value']=data[item][u'value'] |
---|
527 | else: |
---|
528 | self.variables[item]=data[item] |
---|
529 | |
---|
530 | |
---|
531 | except Exception as e: |
---|
532 | print e |
---|
533 | #return [False,e.message] |
---|
534 | os.remove(file_path) |
---|
535 | |
---|
536 | if force_write: |
---|
537 | try: |
---|
538 | self.add_volatile_info() |
---|
539 | self.write_file() |
---|
540 | except Exception as e: |
---|
541 | print(e) |
---|
542 | |
---|
543 | |
---|
544 | return [True,""] |
---|
545 | |
---|
546 | #def read_inbox |
---|
547 | |
---|
548 | |
---|
549 | def empty_trash(self,force_write=False): |
---|
550 | |
---|
551 | |
---|
552 | if self.variables_ok: |
---|
553 | |
---|
554 | for file in os.listdir(VariablesManager.TRASH): |
---|
555 | file_path=VariablesManager.TRASH+file |
---|
556 | #print "[VariablesManager] Removing " + file_path + " info..." |
---|
557 | try: |
---|
558 | f=open(file_path,"r") |
---|
559 | data=json.load(f) |
---|
560 | f.close() |
---|
561 | |
---|
562 | for item in data: |
---|
563 | if self.variables.has_key(item): |
---|
564 | if data[item][u'packages'][0] in self.variables[item][u'packages']: |
---|
565 | count=0 |
---|
566 | for depend in self.variables[item][u'packages']: |
---|
567 | if depend==data[item][u'packages'][0]: |
---|
568 | self.variables[item][u'packages'].pop(count) |
---|
569 | if len(self.variables[item][u'packages'])==0: |
---|
570 | self.variables.pop(item) |
---|
571 | break |
---|
572 | else: |
---|
573 | count+=1 |
---|
574 | |
---|
575 | except Exception as e: |
---|
576 | print e |
---|
577 | #return [False,e.message] |
---|
578 | |
---|
579 | os.remove(file_path) |
---|
580 | |
---|
581 | if force_write: |
---|
582 | try: |
---|
583 | self.write_file() |
---|
584 | except Exception as e: |
---|
585 | print(e) |
---|
586 | |
---|
587 | return [True,''] |
---|
588 | |
---|
589 | |
---|
590 | #def empty_trash |
---|
591 | |
---|
592 | |
---|
593 | def get_variable_list(self,variable_list,store=False,full_info=False): |
---|
594 | |
---|
595 | ret={} |
---|
596 | if variable_list!=None: |
---|
597 | for item in variable_list: |
---|
598 | try: |
---|
599 | ret[item]=self.get_variable(item,store,full_info) |
---|
600 | except Exception as e: |
---|
601 | print e |
---|
602 | |
---|
603 | return ret |
---|
604 | |
---|
605 | #def get_variable_list |
---|
606 | |
---|
607 | |
---|
608 | def get_variable(self,name,store=False,full_info=False,key=None): |
---|
609 | |
---|
610 | global master_password |
---|
611 | |
---|
612 | if name in self.variables and self.variables[name].has_key("root_protected") and self.variables[name]["root_protected"] and key!=master_password: |
---|
613 | return None |
---|
614 | |
---|
615 | if name in self.variables and self.variables[name].has_key("function"): |
---|
616 | try: |
---|
617 | if not full_info: |
---|
618 | if (type(self.variables[name][u"value"])==type("") or type(self.variables[name][u"value"])==type(u"")) and self.variables[name][u"value"].find("_@START@_")!=-1: |
---|
619 | #print "I have to ask for " + name + " which has value: " + self.variables[name][u'value'] |
---|
620 | value=self.calculate_variable(self.variables[name][u"value"]) |
---|
621 | else: |
---|
622 | value=self.variables[name][u"value"] |
---|
623 | |
---|
624 | if type(value)==type(u""): |
---|
625 | try: |
---|
626 | ret=value.encode("utf-8") |
---|
627 | return ret |
---|
628 | except: |
---|
629 | return value |
---|
630 | else: |
---|
631 | return value |
---|
632 | else: |
---|
633 | variable=self.variables[name].copy() |
---|
634 | variable["remote"]=False |
---|
635 | if type(variable[u"value"])==type(""): |
---|
636 | if variable[u"value"].find("_@START@_")!=-1: |
---|
637 | variable["original_value"]=variable[u"value"] |
---|
638 | variable[u"value"]=self.calculate_variable(self.variables[name][u"value"]) |
---|
639 | variable["calculated"]=True |
---|
640 | return variable |
---|
641 | except: |
---|
642 | return None |
---|
643 | else: |
---|
644 | if self.variables.has_key("REMOTE_VARIABLES_SERVER") and self.variables["REMOTE_VARIABLES_SERVER"][u"value"]!="" and self.variables["REMOTE_VARIABLES_SERVER"][u"value"]!=None: |
---|
645 | try: |
---|
646 | server_ip=socket.gethostbyname(self.variables["REMOTE_VARIABLES_SERVER"][u"value"]) |
---|
647 | except: |
---|
648 | return None |
---|
649 | if self.get_ip()!=server_ip: |
---|
650 | for count in range(0,3): |
---|
651 | try: |
---|
652 | |
---|
653 | server=xmlrpclib.ServerProxy("https://"+server_ip+":9779",allow_none=True) |
---|
654 | var=server.get_variable("","VariablesManager",name,True,True) |
---|
655 | |
---|
656 | if var==None: |
---|
657 | return None |
---|
658 | if (var!="" or type(var)!=type("")) and store: |
---|
659 | |
---|
660 | self.add_variable(name,var[u"value"],var[u"function"],var[u"description"],var[u"packages"],False) |
---|
661 | return self.get_variable(name,store,full_info) |
---|
662 | else: |
---|
663 | if full_info: |
---|
664 | var["remote"]=True |
---|
665 | return var |
---|
666 | else: |
---|
667 | return var["value"] |
---|
668 | |
---|
669 | except Exception as e: |
---|
670 | time.sleep(1) |
---|
671 | |
---|
672 | return None |
---|
673 | else: |
---|
674 | return None |
---|
675 | else: |
---|
676 | |
---|
677 | return None |
---|
678 | |
---|
679 | #def get_variable |
---|
680 | |
---|
681 | |
---|
682 | def set_variable(self,name,value,depends=[],force_volatile_flag=False): |
---|
683 | |
---|
684 | if name in self.variables: |
---|
685 | |
---|
686 | if value == self.variables[name][u"value"]: |
---|
687 | return [True,"Variable already contained that value"] |
---|
688 | |
---|
689 | if type(value)==type(""): |
---|
690 | self.variables[name][u"value"]=unicode(value).encode("utf-8") |
---|
691 | else: |
---|
692 | self.variables[name][u"value"]=value |
---|
693 | |
---|
694 | if len(depends)>0: |
---|
695 | for depend in depends: |
---|
696 | self.variables[unicode(name).encode("utf-8")][u"packages"].append(depend) |
---|
697 | |
---|
698 | if not force_volatile_flag: |
---|
699 | self.write_file() |
---|
700 | else: |
---|
701 | |
---|
702 | self.variables[name]["volatile"]=True |
---|
703 | if "function" not in self.variables["name"]: |
---|
704 | self.variables[name]["function"]="" |
---|
705 | if "description" not in self.variables["name"]: |
---|
706 | self.variables[name]["description"]="" |
---|
707 | |
---|
708 | t=threading.Thread(target=self.notify_changes,args=(name,)) |
---|
709 | t.daemon=True |
---|
710 | t.start() |
---|
711 | |
---|
712 | # local trigger call |
---|
713 | self.execute_trigger(name) |
---|
714 | |
---|
715 | return [True,""] |
---|
716 | else: |
---|
717 | return [False,"Variable not found. Use add_variable"] |
---|
718 | |
---|
719 | |
---|
720 | #def set_variable |
---|
721 | |
---|
722 | |
---|
723 | def add_variable(self,name,value,function,description,depends,volatile=False,root_protected=False): |
---|
724 | |
---|
725 | if name not in self.variables: |
---|
726 | dic={} |
---|
727 | if type(value)==type(""): |
---|
728 | dic[u"value"]=unicode(value).encode("utf-8") |
---|
729 | else: |
---|
730 | dic[u"value"]=value |
---|
731 | dic[u"function"]=function |
---|
732 | dic[u"description"]=unicode(description).encode("utf-8") |
---|
733 | if type(depends)==type(""): |
---|
734 | dic[u"packages"]=[unicode(depends).encode("utf-8")] |
---|
735 | elif type(depends)==type([]): |
---|
736 | dic[u"packages"]=depends |
---|
737 | else: |
---|
738 | dic[u"packages"]=[] |
---|
739 | dic["volatile"]=volatile |
---|
740 | dic["root_protected"]=root_protected |
---|
741 | self.variables[unicode(name)]=dic |
---|
742 | if not volatile: |
---|
743 | self.write_file() |
---|
744 | return [True,""] |
---|
745 | else: |
---|
746 | return [False,"Variable already exists. Use set_variable"] |
---|
747 | |
---|
748 | #def add_variable |
---|
749 | |
---|
750 | |
---|
751 | def write_file(self,fname=None): |
---|
752 | |
---|
753 | try: |
---|
754 | while os.path.exists(VariablesManager.LOCK_FILE): |
---|
755 | time.sleep(2) |
---|
756 | |
---|
757 | f=open(VariablesManager.LOCK_FILE,"w") |
---|
758 | f.close() |
---|
759 | tmp_vars={} |
---|
760 | for item in self.variables: |
---|
761 | if self.variables[item].has_key("volatile") and self.variables[item]["volatile"]==False: |
---|
762 | tmp_vars[item]=self.variables[item] |
---|
763 | |
---|
764 | for item in tmp_vars: |
---|
765 | |
---|
766 | tmp={} |
---|
767 | tmp[item]=tmp_vars[item] |
---|
768 | f=open(VariablesManager.VARIABLES_DIR+item,"w") |
---|
769 | data=unicode(json.dumps(tmp,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8") |
---|
770 | f.write(data) |
---|
771 | f.close() |
---|
772 | |
---|
773 | if "root_protected" in tmp_vars[item]: |
---|
774 | if tmp_vars[item]["root_protected"]: |
---|
775 | self.chmod(VariablesManager.VARIABLES_DIR+item,0600) |
---|
776 | |
---|
777 | |
---|
778 | os.remove(VariablesManager.LOCK_FILE) |
---|
779 | return True |
---|
780 | |
---|
781 | |
---|
782 | except Exception as e: |
---|
783 | os.remove(VariablesManager.LOCK_FILE) |
---|
784 | print (e) |
---|
785 | return False |
---|
786 | |
---|
787 | #def write_file |
---|
788 | |
---|
789 | |
---|
790 | def chmod(self,file,mode): |
---|
791 | prevmask = os.umask(0) |
---|
792 | try: |
---|
793 | os.chmod(file,mode) |
---|
794 | os.umask(prevmask) |
---|
795 | return True |
---|
796 | except Exception as e: |
---|
797 | print e |
---|
798 | os.umask(prevmask) |
---|
799 | return False |
---|
800 | |
---|
801 | #def chmod |
---|
802 | |
---|
803 | |
---|
804 | def init_variable(self,variable,args={},force=False,full_info=False): |
---|
805 | |
---|
806 | try: |
---|
807 | funct=self.variables[variable]["function"] |
---|
808 | mod_name=funct[:funct.rfind(".")] |
---|
809 | funct_name=funct[funct.rfind(".")+1:] |
---|
810 | funct_name=funct_name.replace("(","") |
---|
811 | funct_name=funct_name.replace(")","") |
---|
812 | mod=importlib.import_module(mod_name) |
---|
813 | ret=getattr(mod,funct_name)(args) |
---|
814 | ok,exc=self.set_variable(variable,ret) |
---|
815 | if ok: |
---|
816 | return (True,ret) |
---|
817 | else: |
---|
818 | return (False,ret) |
---|
819 | except Exception as e: |
---|
820 | return (False,e) |
---|
821 | |
---|
822 | #def init_variable |
---|
823 | |
---|
824 | |
---|
825 | #class VariablesManager |
---|
826 | |
---|
827 | |
---|
828 | if __name__=="__main__": |
---|
829 | |
---|
830 | vm=VariablesManager() |
---|
831 | |
---|
832 | |
---|
833 | |
---|
834 | |
---|
835 | |
---|
836 | |
---|
837 | |
---|
838 | |
---|