source: lliurex-mirror/trunk/fuentes/n4d-lliurex-mirror.install/usr/share/n4d/python-plugins/MirrorManager.py @ 2261

Last change on this file since 2261 was 2261, checked in by jrpelegrina, 3 years ago

Adding download time_file and is_update functions

File size: 13.9 KB
Line 
1from jinja2 import Environment
2from jinja2.loaders import FileSystemLoader
3from jinja2 import Template
4
5import tempfile
6
7import os
8import threading
9import datetime
10import pexpect
11import re
12import json
13
14import BaseHTTPServer
15from SimpleHTTPServer import SimpleHTTPRequestHandler
16from multiprocessing import Process
17import socket
18from urllib2 import urlopen
19
20from datetime import datetime, date
21
22
23class MirrorManager:
24
25
26        def __init__(self):
27                #Default values
28                self.defaultpath = '/etc/lliurex-mirror/'
29                self.debmirrorconfpath = os.path.join(self.defaultpath,'debmirror')
30                self.configpath = os.path.join(self.defaultpath,'conf')
31                self.distro="llx16"
32                self.httpd = None
33                self.debmirrorprocess = None
34
35                self.tpl_env = Environment(loader=FileSystemLoader('/usr/share/n4d/templates/lliurex-mirror'))
36                self.update_thread=threading.Thread()
37                self.percentage=(0,None)
38                self.webserverprocess = None
39                self.defaultmirrorinfo = {"status_mirror":"New","last_mirror_date":None,"mirror_size":0,"progress":0}
40               
41        #def init
42       
43        def startup(self,options):
44                self.n4d_vars=objects["VariablesManager"]
45                self.variable=objects["VariablesManager"].get_variable("LLIUREXMIRROR")
46               
47               
48                if self.variable==None:
49                        try:
50                                self.n4d_vars.add_variable("LLIUREXMIRROR",{},"","Lliurex Mirror info variable","n4d-lliurex-mirror")
51                        except Exception as e:
52                                pass
53                       
54                if type(self.variable)!=type({}):
55                        self.variable={}
56               
57                try:
58                        for repo in self.get_available_mirrors()['msg']:
59                                if self.variable.has_key(repo) and self.variable[repo].has_key("status_mirror") and self.variable[repo]["status_mirror"] == "Working":
60                                        if not self.update_thread.isAlive():
61                                                self.variable[repo]["status_mirror"] = "Error"
62                                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
63                                else:
64                                        if not self.variable.has_key(repo):
65                                                self.variable[repo] = self.defaultmirrorinfo
66                except Exception as e:
67                        pass
68        #def startup
69
70        def apt(self):
71                # executed after apt operations
72                pass
73               
74        #def apt
75       
76        # service test and backup functions #
77       
78        def test(self):
79
80                pass
81               
82        #def test
83       
84        def backup(self):
85
86                pass
87               
88        #def backup
89
90        def restore(self):
91                pass
92        #def restore
93
94        def set_cname(self):
95                #Get template
96                template = self.tpl_env.get_template("cname")
97                list_variables = {}
98               
99                list_variables = self.n4d_vars.get_variable_list(['INTERNAL_DOMAIN','HOSTNAME'])
100                for x in list_variables.keys():
101                        if list_variables[x] == None:
102                                return {'status':False,'msg':'Variable ' + x + ' not defined'}
103                       
104                #Encode vars to UTF-8
105                string_template = template.render(list_variables).encode('UTF-8')
106                #Open template file
107                fd, tmpfilepath = tempfile.mkstemp()
108                new_export_file = open(tmpfilepath,'w')
109                new_export_file.write(string_template)
110                new_export_file.close()
111                os.close(fd)
112                #Write template values
113                n4d_mv(tmpfilepath,'/var/lib/dnsmasq/config/cname-mirror',True,'root','root','0644',False )
114               
115                return {'status':True,'msg':'Set mirror cname'}
116        #def set_cname
117       
118        def update(self,distro=None):
119
120                if distro==None:
121                        distro=self.distro
122       
123                if self.update_thread.is_alive():
124                        return {'status':False,'msg':'Lliurex-mirror (n4d instance) is running'}
125               
126                self.percentage=(0,None)
127                self.update_thread=threading.Thread(target=self._update,args=(distro,))
128                self.update_thread.daemon=True
129                self.update_thread.start()
130               
131                return {'status':True,'msg':'running'}
132
133        #def update
134       
135        def _update(self,distro):
136                if not self.variable.has_key(distro):
137                        self.variable[distro]=self.defaultmirrorinfo
138                # link config debmirror to correct path with distro name
139                self.variable[distro]['status_mirror'] = "Working"
140                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
141                filelog = open('/var/log/lliurex-mirror.log','w')
142                self.build_debmirror_config(distro)
143                os.remove('/etc/debmirror.conf')
144                os.symlink(os.path.join(self.debmirrorconfpath,distro),'/etc/debmirror.conf')
145                self.debmirrorprocess=pexpect.spawn("/usr/bin/debmirror")
146                try:
147                        objects["ZCenterVariables"].add_pulsating_color("lliurexmirror")
148                except:
149                        pass
150                while True:
151                        try:
152                                self.debmirrorprocess.expect('\n')
153                                line =self.debmirrorprocess.before
154                                filelog.write(line)
155                                line1=line.strip("\n")
156                                if line1.startswith("[") and line1[5] == "]":
157                                        self.percentage=(int(line1[1:4].strip()),self.debmirrorprocess.exitstatus)
158                                        self.variable[distro]['progress'] = self.percentage[0]
159                                        self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
160                        except pexpect.EOF:
161                                        line1 = self.debmirrorprocess.before
162                                        if line1 != "" and line1.startswith("[") and line1[5] == "]":
163                                                        self.percentage=(int(line1[1:4].strip()),self.debmirrorprocess.exitstatus)
164                                        filelog.write(line1)
165                                        self.debmirrorprocess.close()
166                                        status = self.debmirrorprocess.exitstatus
167                                        self.percentage=(self.percentage[0],status)
168                                        self.variable[distro]['progress'] = self.percentage[0]
169                                        self.variable[distro]['status_mirror'] = "Ok" if status == 0 else "Error"
170                                        self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
171                                        break
172                        except Exception as e:
173                                self.variable[distro]['status_mirror'] = "Error"
174                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
175                                break
176                filelog.close()
177
178                self.download_time_file(distro)
179
180                self.set_mirror_info(distro)
181
182                try:
183                        objects["ZCenterVariables"].remove_pulsating_color("lliurexmirror")
184                except:
185                        pass
186
187        #def _update
188       
189        def is_alive(self):
190                return {'status':self.update_thread.is_alive(),'msg':''}
191        #def is_alive
192
193        def set_mirror_info(self,distro=None):
194               
195                if distro!=None:
196                        distro=distro
197                else:
198                        distro=self.distro
199               
200                configpath = os.path.join(self.configpath, distro + ".json")
201                config = json.load(open(configpath,'r'))
202
203                mirrorpath = config["MIRRORPATH"]
204                #self.n4d_vars.set_variable("ZEROCENTERINTERNAL",self.internal_variable)
205               
206                MIRROR_DATE=datetime.date.today().strftime("%d/%m/%Y")
207                MIRROR_SIZE=self.get_size(mirrorpath)
208               
209                self.variable[distro]["last_mirror_date"]=MIRROR_DATE
210                self.variable[distro]["mirror_size"]=str(MIRROR_SIZE)
211                self.variable[distro]["progress"]=self.percentage[0]
212               
213                print self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
214               
215                #set_custom_text(self,app,text):
216                txt="Updated on: " + str(MIRROR_DATE)
217                txt+=" # Size: %.2fGB"%MIRROR_SIZE
218                try:
219                        objects["ZCenterVariables"].set_custom_text("lliurexmirror",txt)
220                        abstract=open('/var/log/lliurex/lliurex-mirror.log','w')
221                        abstract.write(txt+"\n")
222                        abstract.close()
223                except Exception as e:
224                        pass
225
226        #def set_mirror_info(self):
227
228        def get_size(self,start_path = '.'):
229       
230                total_size = 0
231                try:
232                        for dirpath, dirnames, filenames in os.walk(start_path):
233                                for f in filenames:
234                                        fp = os.path.join(dirpath, f)
235                                        total_size += os.path.getsize(fp)
236                                       
237                        total_size/=1024*1024*1024.0
238                        return total_size
239                except:
240                        return 0
241       
242        #def get_size(start_path = '.'):
243       
244        def search_field(self,filepath,fieldname):
245                try:
246                        f = open(filepath,'r')
247                        needle = None
248                        lines = f.readlines()
249                        for x in lines:
250                                        if re.match('\s*'+fieldname,x):
251                                                        needle = x.strip()
252                        return needle
253                except:
254                        return None
255        # def search_field
256       
257        def get_mirror_architecture(self,distro):
258
259                configpath = os.path.join(self.configpath,distro + ".json")
260                config = json.load(open(configpath,'r'))
261                if not os.path.exists(configpath):
262                        return {'status':False,'msg':'not exists debmirror.conf to '+ distro }
263
264                if "ARCHITECTURES" in config.keys():
265                        return {'status':True,'msg':config["ARCHITECTURES"] }
266
267                return {'status':False,'msg':"debmirror.conf hasn't architecture variable" }
268        #def get_mirror_architecture
269       
270        def set_mirror_architecture(self,distro,archs):
271                configpath = os.path.join(self.configpath,distro + ".json")
272               
273                config = json.load(open(configpath,'r'))
274               
275                config['ARCHITECTURES'] = archs
276
277
278                f=open(configpath,"w")
279
280                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
281                f.write(data)
282                f.close()
283
284                self.build_debmirror_config(distro)
285                return {'status':True,'msg':'set architecture'}
286               
287        #def set_mirror_architecture
288       
289        def get_mirror_orig(self,distro):
290
291                configpath = os.path.join(self.configpath,distro + ".json")
292                config = json.load(open(configpath,'r'))
293                if not os.path.exists(configpath):
294                        return {'status':False,'msg':'not exists debmirror.conf to '+ distro }
295
296                if "URL" in config.keys():
297                        return {'status':True,'msg':config["URL"] }
298                       
299                return {'status':False,'msg':"debmirror.conf hasn't orig variable" }           
300        #def get_mirror_from
301
302        def set_mirror_orig(self,distro,url):
303                configpath = os.path.join(self.configpath, distro + ".json")
304                config = json.load(open(configpath,'r'))
305                config['URL'] = url
306
307                f=open(configpath,"w")
308                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
309                f.write(data)
310                f.close()
311
312                self.build_debmirror_config(distro)
313                return {'status':True,'msg':'set orig'}
314        #def set_mirror_architecture
315
316        def get_percentage(self,distro):
317                if self.variable.has_key(distro):
318                        return {'status':True,'msg':self.variable[distro]['progress']}
319                else:
320                        return {'status':False,'msg':'this repo nos has been configured'}
321
322        def build_debmirror_config(self,distro):
323                template = self.tpl_env.get_template('debmirror.conf')
324                configpath = os.path.join(self.configpath,distro + ".json")
325                config = json.load(open(configpath,'r'))
326                string_template = template.render(config).encode('utf-8')
327                f = open(os.path.join(self.debmirrorconfpath,distro),'w')
328                f.write(string_template)
329                f.close()
330        #def build_debmirror_config
331       
332        def enable_webserver_into_folder(self,path):
333                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
334                s.bind(('localhost', 0))
335                addr, port = s.getsockname()
336                s.close()
337                self.webserverprocess = Process(target=self._enable_webserver_into_folder,args=(port,path,))
338                self.webserverprocess.start()
339                return {'status':True,'msg':port}
340        #enable_webserver_into_folder
341
342        def _enable_webserver_into_folder(self,port,path):
343                try:
344                        import os
345                        iface = '127.0.0.1'
346                        sock = (iface,port)
347                        proto = "HTTP/1.0"
348                        os.chdir(path)
349                        handler = SimpleHTTPRequestHandler
350                        handler.protocol_version = proto
351                        self.httpd = BaseHTTPServer.HTTPServer(sock,handler)
352                        self.httpd.serve_forever()
353                except Exception, e:
354                        return None
355        #_enable_webserver_into_folder
356
357        def stop_webserver(self):
358                if self.webserverprocess != None:
359                        self.webserverprocess.terminate()
360                return {'status':True,'msg':'Server stopped'}
361        #stop_webserver
362       
363        def set_checksum_validation(self,distro,status):
364                configpath = os.path.join(self.configpath, distro + ".json")
365                config = json.load(open(configpath,'r'))
366                config['CHK_MD5'] = status
367
368                f=open(configpath,"w")
369                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
370                f.write(data)
371                f.close()
372
373                self.build_debmirror_config(distro)
374                return {'status':True,'msg':'set checksum validation'}
375        #set_checksum_validation
376       
377        def get_checksum_validation(self,distro):
378
379                configpath = os.path.join(self.configpath,distro + ".json")
380                config = json.load(open(configpath,'r'))
381                if not os.path.exists(configpath):
382                        return {'status':False,'msg':'not exists debmirror.conf to '+ distro }
383                if "IGN_GPG" in config.keys():
384                        return {'status':True,'msg':config["CHK_MD5"] }
385
386                return {'status':False,'msg':"debmirror.conf hasn't orig variable" }
387        #get_checksum_validation
388       
389        def get_available_mirrors(self):
390                versions = os.listdir(self.configpath)
391                versions = [ version.replace('.json','') for version in versions if version.endswith('.json')]
392                return {'status':True,'msg':versions}
393
394        def stopupdate(self):
395                try:
396                        self.debmirrorprocess.terminate()
397                        return {'status':True,'msg':'debmirror stopped'}
398                except Exception as e:
399                        return {'status':False,'msg':str(e)}
400
401
402        def download_time_file(self,distro):
403               
404                configpath = os.path.join(self.configpath,distro + ".json")
405                config = json.load(open(configpath,'r'))
406                path=config["MIRRORPATH"]
407                file="time-of-last-update"
408                dest=os.path.join(path,file)
409
410                orig_mirror=self.get_mirror_orig(distro)
411                url_mirror="http://"+os.path.join(orig_mirror['msg'],file)
412
413                return self.get_time_file(url_mirror,dest)
414
415        # def download_time_file                       
416
417               
418        def get_time_file(self,url,dest):
419               
420                try:
421                        r=urlopen(url)
422                        f=open(dest,"wb")
423                        f.write(r.read())
424                        f.close()
425                        r.close()
426                        return {'status':True,'msg':dest + 'download sucessfull.'}
427               
428                except Exception as e:
429                        return {'status':False,'msg':'Error downloading' + dest + str(e)}                       
430
431        # def get_time_file             
432
433        def is_mirror_update(self,distro):
434
435                configpath = os.path.join(self.configpath,distro + ".json")
436                config = json.load(open(configpath,'r'))
437                path=config["MIRRORPATH"]
438                file_time_name="time-of-last-update"
439                file_local_mirror=os.path.join(path,file_time_name)
440
441               
442                if os.path.isfile(file_local_mirror):
443                        url_pool="http://"+os.path.join(config["LLIUREX_ORIG"],file_time_name)
444                        file_pool=os.path.join("/tmp",file_time_name)
445
446                        exist_file_pool=self.get_time_file(url_pool,file_pool)
447                        if exist_file_pool['status']:
448                                file_local_mirror_content=open(file_miror,"r")
449                                file_local_miror_datetime=(file_local_mirror_content.readline().strip()).split("_")
450                                file_pool_content=open(file_pool,'r')
451                                file_pool_datetime=(file_pool_content.readline().strip()).split("_")
452                                file_local_mirror_content.close()
453                                file_pool_content.close()
454
455                                date_local_mirror=datetime.strptime(file_local_miror_datetime[0],"%Y/%m/%d")
456                                date_pool=datetime.strptime(file_pool_datetime[0],"%Y/%m/%d")
457
458                                if date_local_mirror==date_pool:
459                                        time_local_mirror=datetime.strptime(file_local_miror_datetime[1],"%H:%M")       
460                                        time_pool=datetime.strptime(file_pool_datetime[1],"%H:%M")
461
462                                        if time_local_mirror<time_pool:
463                                                return {'status':False,'msg':'Mirror is not update','action': 'update'}
464                                        elif :
465                                                return {'status':True,'msg':'Mirror is update','action':'nothing'}
466
467                                elif date_local_mirror<date_pool:
468                                        return {'status':False,'msg':'Mirror is not update','action': 'update'}
469                                else:
470                                        return {'status':True,'msg':'Mirror is update','action':'nothing'}     
471                        else:
472                                return {'status':False,'msg':exist_file_pool['msg'],'action':'nothing'} 
473
474                else:
475                        return {'status':False,'msg':file_local_mirror + 'dont exists.','action':'nothing'}
476
477        # def is_mirror_update                 
Note: See TracBrowser for help on using the repository browser.