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

Last change on this file was 7258, checked in by mabarracus, 19 months ago

Avoid n4d exceptions throwing error messages when are called without proper parameters
Misc Fixes

File size: 29.6 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 signal
12import re
13import json
14
15import BaseHTTPServer
16from SimpleHTTPServer import SimpleHTTPRequestHandler
17from multiprocessing import Process
18import socket
19from urllib2 import urlopen
20import string
21import subprocess
22
23DEBUG = True
24
25class MirrorManager:
26
27        def __init__(self):
28                #Default values
29                self.defaultpath = '/etc/lliurex-mirror/'
30                self.debmirrorconfpath = os.path.join(self.defaultpath,'debmirror')
31                self.configpath = os.path.join(self.defaultpath,'conf')
32                self.distro="llx16"
33                self.httpd = {}
34                self.debmirrorprocess = None
35
36                self.tpl_env = Environment(loader=FileSystemLoader('/usr/share/n4d/templates/lliurex-mirror'))
37                self.update_thread=threading.Thread()
38                self.get_mirror_thread = threading.Thread()
39                self.percentage=(0,None)
40                self.exportpercentage = 0
41                self.mirrorworking = None
42                self.webserverprocess = {}
43                self.defaultmirrorinfo = {"status_mirror":"New","last_mirror_date":None,"mirror_size":0,"progress":0}
44                self.valid_chars = "-_.%s%s" % (string.ascii_letters, string.digits)
45                self.exitting = False
46                self.default_path_configs = {   'llx16':        '/usr/share/lliurex-mirror/conf/llx16.json',
47                                                'llx15':        '/usr/share/lliurex-mirror/templates/llx15.json',
48                                                'llx14':        '/usr/share/lliurex-mirror/templates/llx14.json',
49                                                'llx13':        '/usr/share/lliurex-mirror/templates/llx13.json',
50                                            }
51                self.default_mirror_config = '''
52{
53        "NAME": "",
54        "BANNER": "",
55        "ORIGS" : {"1":"lliurex.net/xenial","2":"","3":""}, # 1 ORIGINAL ; 2 LOCALFILESYSTEM; 3 REMOTEURL
56        "ARCHITECTURES": [ "amd64", "i386"],
57        "SECTIONS": ["main", "main/debian-installer", "universe", "restricted", "multiverse", "preschool"],
58        "MIRROR_PATH": "/net/mirror/llx16",
59        "DISTROS": ["xenial","xenial-updates","xenial-security"],
60        "IGN_GPG":1,
61        "IGN_RELEASE":0,
62        "CHK_MD5":0,
63        "CURRENT_UPDATE_OPTION":"1"
64}'''
65               
66        #def init
67       
68        def debug(self,*args,**kwargs):
69            if not DEBUG:
70                return None
71            try:
72                caller = sys._getframe().f_back.f_code.co_name
73            except:
74                caller = ""
75            with open('/var/log/lliurex-mirror.log','a') as fp:
76                for a in args:
77                    fp.write("{}:> {}\n".format(caller,a))
78                for kw in kwargs:
79                    fp.write("{}:> {}={}\n".format(caller,kw,kwargs.get(kw)))
80       
81        def startup(self,options):
82                self.n4d_vars=objects["VariablesManager"]
83                self.variable=objects["VariablesManager"].get_variable("LLIUREXMIRROR")
84               
85               
86                if self.variable==None:
87                        try:
88                                self.n4d_vars.add_variable("LLIUREXMIRROR",{},"","Lliurex Mirror info variable","n4d-lliurex-mirror")
89                        except Exception as e:
90                                pass
91                       
92                if type(self.variable)!=type({}):
93                        self.variable={}
94               
95                try:
96                        for repo in self.get_available_mirrors()['msg']:
97                                if self.variable.has_key(repo) and self.variable[repo].has_key("status_mirror") and self.variable[repo]["status_mirror"] == "Working":
98                                        if not self.update_thread.isAlive():
99                                                self.variable[repo]["status_mirror"] = "Error"
100                                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
101                                else:
102                                        if not self.variable.has_key(repo):
103                                                self.variable[repo] = self.defaultmirrorinfo
104                except Exception as e:
105                        pass
106        #def startup
107
108        def apt(self):
109                # executed after apt operations
110                pass
111               
112        #def apt
113       
114        # service test and backup functions #
115       
116        def test(self):
117
118                pass
119               
120        #def test
121       
122        def backup(self):
123
124                pass
125               
126        #def backup
127
128        def restore(self):
129                pass
130        #def restore
131       
132        def cancel_actions(self):
133            try:
134                self.exitting = True
135                time.sleep(3)
136                self.debmirrorprocess.kill(signal.SIGKILL)
137                self.debmirrorprocess.close(force=True)
138                return {'status':True,'msg':'Killed'}
139            except Exception as e:
140                return {'status':False,'msg':e}
141        #def cancel_actions(self)
142       
143        def set_cname(self):
144                #Get template
145                template = self.tpl_env.get_template("cname")
146                list_variables = {}
147               
148                list_variables = self.n4d_vars.get_variable_list(['INTERNAL_DOMAIN','HOSTNAME'])
149                for x in list_variables.keys():
150                        if list_variables[x] == None:
151                                return {'status':False,'msg':'Variable ' + x + ' not defined'}
152                       
153                #Encode vars to UTF-8
154                string_template = template.render(list_variables).encode('UTF-8')
155                #Open template file
156                fd, tmpfilepath = tempfile.mkstemp()
157                new_export_file = open(tmpfilepath,'w')
158                new_export_file.write(string_template)
159                new_export_file.close()
160                os.close(fd)
161                #Write template values
162                n4d_mv(tmpfilepath,'/var/lib/dnsmasq/config/cname-mirror',True,'root','root','0644',False )
163               
164                return {'status':True,'msg':'Set mirror cname'}
165        #def set_cname
166       
167        def _check_distro_param(self,distro):
168            try:
169                if not distro:
170                    distro = self.distro
171
172                filepath = os.path.join(self.configpath, distro + ".json")
173                if not os.path.isfile(filepath):
174                    filepath = None
175                return distro, filepath
176            except Exception as e:
177                return None,None
178        #def _check_distro_param(self,distro):
179       
180        def update(self,ip,distro=None,callback_args=None,restore_info={}):
181                distro,filepath = self._check_distro_param(distro)
182                if not filepath:
183                        return {'status':False,'msg':'Needed valid DISTRO parameter'}
184                if self.update_thread.is_alive():
185                        return {'status':False,'msg':'Lliurex-mirror (n4d instance) is running'}
186               
187                self.percentage=(0,None)
188                self.update_thread=threading.Thread(target=self._update,args=(ip,distro,callback_args,restore_info,))
189                self.update_thread.daemon=True
190                self.update_thread.start()
191               
192                return {'status':True,'msg':'running'}
193
194        #def update
195       
196        def _update(self,ip,distro,callback_args,restore_info):
197                if not self.variable.has_key(distro):
198                        self.variable[distro]=self.defaultmirrorinfo
199                # link config debmirror to correct path with distro name
200                self.variable[distro]['status_mirror'] = "Working"
201                self.variable[distro]['progress'] = 0
202                self.variable[distro]['exception_msg'] = ""
203                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
204                self.build_debmirror_config(distro)
205                if os.path.lexists('/etc/debmirror.conf'):
206                        os.remove('/etc/debmirror.conf')
207                os.symlink(os.path.join(self.debmirrorconfpath,distro),'/etc/debmirror.conf')
208                self.mirrorworking = distro
209                fd = open('/var/log/lliurex-mirror.log','a')
210                import datetime
211                fd.write("MIRROR START AT " + str(datetime.datetime.now())+ " \n")
212                fd.flush()
213                errors_found = False
214                self.debmirrorprocess=pexpect.spawn("/usr/bin/debmirror")
215                download_packages = False
216                emergency_counter = 0
217                try:
218                        objects["ZCenterVariables"].add_pulsating_color("lliurexmirror")
219                except:
220                        pass
221                fd.write('Starting Loop, reading debmirror process {}\n'.format(self.debmirrorprocess.pid))
222                fd.flush()
223                while True and not self.exitting:
224                        try:
225                                emergency_counter += 1
226                                if emergency_counter > 100:
227                                        download_packages = True
228                                self.debmirrorprocess.expect('\n',timeout=480)
229                                line =self.debmirrorprocess.before
230
231                                if line.find("Files to download") >= 0 :
232                                        download_packages = True
233                                line1=line.strip()
234                                if download_packages:
235                                        if line1.startswith("[") and line1[5] == "]":
236                                                self.percentage=(int(line1[1:4].strip()),self.debmirrorprocess.exitstatus)
237                                                self.variable[distro]['progress'] = self.percentage[0]
238                                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
239                                        if line1.startswith("Everything OK"):
240                                                self.percentage=(100,self.debmirrorprocess.exitstatus)
241                                                self.variable[distro]['progress'] = 100
242                                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
243                               
244                                if errors_found:
245                                        e=Exception(line1)
246                                        raise e
247
248                                if line1.startswith("Errors"):
249                                        errors_found = True
250                                        # error is printed on next line iteration
251
252                        except pexpect.EOF:
253                                        fd.write("Exception EOF line:'{}'\n".format(line1))
254                                        fd.flush()
255                                        line1 = self.debmirrorprocess.before
256                                        if line1 != "" and line1.startswith("[") and line1[5] == "]":
257                                                        self.percentage=(int(line1[1:4].strip()),self.debmirrorprocess.exitstatus)
258                                        self.debmirrorprocess.close()
259                                        status = self.debmirrorprocess.exitstatus
260                                        self.percentage=(self.percentage[0],status)
261                                        self.variable[distro]['progress'] = self.percentage[0]
262                                        self.variable[distro]['status_mirror'] = "Ok" if status == 0 else "Error"
263                                        self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
264                                        break
265                        except Exception as e:
266                                fd.write("Errors detected: '{}'\n".format(line1))
267                                fd.flush()
268                                self.debmirrorprocess.kill(signal.SIGKILL)
269                                self.debmirrorprocess.close(force=True)
270                                print e
271                                self.variable[distro]['status_mirror'] = "Error"
272                                self.variable[distro]["exception_msg"] = str(e)
273                                status = self.debmirrorprocess.exitstatus
274                                self.percentage=(self.percentage[0],str(e))
275                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
276                                break
277
278
279                fd.write("EXITTING LOOP errors_found={}\n".format(errors_found))
280                fd.flush()
281               
282                if restore_info and isinstance(restore_info,dict):
283                    if 'distro' in restore_info:
284                        self.debug(restore=restore_info)
285                        if 'mirrororig' in restore_info and 'optionorig' in restore_info:
286                            self.debug(msg='setting mirror orig')
287                            self.set_mirror_orig(restore_info['distro'],restore_info['mirrororig'],restore_info['optionused'])
288                        if 'optionorig' in restore_info:
289                            self.debug(msg='setting option orig')
290                            self.set_option_update(restore_info['distro'],restore_info['optionorig'])
291
292                if self.exitting:
293                        fd.write("Forced exit from update process!!!\n")
294                        fd.flush()
295                        self.percentage=(self.percentage[0],1)
296                        self.variable[distro]['progress'] = self.percentage[0]
297                        self.variable[distro]['status_mirror'] = "Cancelled"
298                        self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
299                        fd.close()
300                        self.exitting = False
301                        return 0
302                else:
303                    fd.close()
304
305                if not errors_found and type(callback_args) == type({}):
306                        if callback_args.has_key('port'):
307                                import xmlrpclib as x
308                                c = x.ServerProxy('https://' + ip + ':9779')
309                                c.stop_webserver('','MirrorManager',callback_args['port'])
310
311                self.download_time_file(distro)
312                self.set_mirror_info(distro)
313                self.mirrorworking = None
314                try:
315                        objects["ZCenterVariables"].remove_pulsating_color("lliurexmirror")
316                except:
317                        pass
318
319        #def _update
320       
321        def is_alive(self):
322                return {'status':self.update_thread.is_alive(),'msg':self.mirrorworking}
323        #def is_alive
324
325        def set_mirror_info(self,distro=None):
326                distro,configpath = self._check_distro_param(distro)
327                if not distro:
328                        return {'status':False, 'msg': 'Needed valid DISTRO parameter'}
329                if not configpath:
330                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
331                config = json.load(open(configpath,'r'))
332
333                mirrorpath = config["MIRROR_PATH"]
334                #self.n4d_vars.set_variable("ZEROCENTERINTERNAL",self.internal_variable)
335               
336                MIRROR_DATE=datetime.date.today().strftime("%d/%m/%Y")
337                MIRROR_SIZE=self.get_size(mirrorpath)
338               
339                self.variable[distro]["last_mirror_date"]=MIRROR_DATE
340                self.variable[distro]["mirror_size"]=str(MIRROR_SIZE)
341                self.variable[distro]["progress"]=self.percentage[0]
342               
343                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
344               
345                #set_custom_text(self,app,text):
346                txt="Updated on: " + str(MIRROR_DATE)
347                txt+=" # Size: %.2fGB"%MIRROR_SIZE
348                try:
349                        objects["ZCenterVariables"].set_custom_text("lliurexmirror",txt)
350                        abstract=open('/var/log/lliurex/lliurex-mirror.log','w')
351                        abstract.write(txt+"\n")
352                        abstract.close()
353                except Exception as e:
354                        pass
355
356        #def set_mirror_info(self):
357           
358        def get_distro_options(self,distro):
359                distro,configpath = self._check_distro_param(distro)
360                if not distro:
361                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
362                if not configpath:
363                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
364                try:
365                    config = json.load(open(configpath,'r'))
366                except Exception as e:
367                        return {'status':False,'msg': e }
368
369                if "ORIGS" in config.keys():
370                        return {'status':True,'msg':config["ORIGS"].keys() }
371
372                return {'status':False,'msg':' No options into configfile {}'.format(configpath)}
373
374        #def get_distro_options(self,distro)
375       
376        def update_size_info(self,distro):
377                distro,configpath = self._check_distro_param(distro)
378                if not distro:
379                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
380                if not configpath:
381                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
382                config = json.load(open(configpath,'r'))
383
384                mirrorpath = config["MIRROR_PATH"]
385                MIRROR_SIZE=self.get_size(mirrorpath)
386                self.variable[distro]["mirror_size"]=str(MIRROR_SIZE)
387                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
388                return {'status':True,'msg':MIRROR_SIZE}
389
390
391        def get_size(self,start_path = '.'):
392                total_size = 0
393                try:
394                        for dirpath, dirnames, filenames in os.walk(start_path):
395                                for f in filenames:
396                                        fp = os.path.join(dirpath, f)
397                                        total_size += os.path.getsize(fp)
398                                       
399                        total_size/=1024*1024*1024.0
400                        return total_size
401                except:
402                        return 0
403       
404        #def get_size(start_path = '.'):
405       
406        def search_field(self,filepath,fieldname):
407                try:
408                        f = open(filepath,'r')
409                        needle = None
410                        lines = f.readlines()
411                        for x in lines:
412                                        if re.match('\s*'+fieldname,x):
413                                                        needle = x.strip()
414                        return needle
415                except:
416                        return None
417        # def search_field
418       
419        def get_mirror_architecture(self,distro):
420                distro,configpath = self._check_distro_param(distro)
421                if not distro:
422                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
423                if not configpath:
424                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
425                config = json.load(open(configpath,'r'))
426
427                if "ARCHITECTURES" in config.keys():
428                        return {'status':True,'msg':config["ARCHITECTURES"] }
429
430                return {'status':False,'msg':"debmirror.conf hasn't architecture variable" }
431        #def get_mirror_architecture
432       
433        def set_mirror_architecture(self,distro,archs):
434                distro,configpath = self._check_distro_param(distro)
435                if not distro:
436                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
437                if not archs:
438                        return {'status':False,'msg': 'Needed ARCHS parameter','action':'nothing'}
439                if not configpath:
440                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
441                config = json.load(open(configpath,'r'))
442                config['ARCHITECTURES'] = archs
443                f=open(configpath,"w")
444                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
445                f.write(data)
446                f.close()
447                self.build_debmirror_config(distro)
448                return {'status':True,'msg':'set architecture'}
449               
450        #def set_mirror_architecture
451       
452        def get_mirror_orig(self,distro,option):
453                distro,configpath = self._check_distro_param(distro)
454                if not distro:
455                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
456                if not configpath:
457                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
458                config = json.load(open(configpath,'r'))
459                if "ORIGS" in config.keys():
460                        if option:
461                            if option in config['ORIGS']:
462                                return {'status':True,'msg':config["ORIGS"][option] }
463                            else:
464                                return {'status':False,'msg':'No such option available'}
465                        else:
466                            ret=[]
467                            for opt in config['ORIGS']:
468                                ret.append({opt:config['ORIGS'][opt]})
469                            return {'status':True,'msg':ret}
470                       
471                return {'status':False,'msg':"debmirror.conf hasn't orig variable" }   
472        #def get_mirror_from
473
474        def set_mirror_orig(self,distro,url,option):
475                distro,configpath = self._check_distro_param(distro)
476                if not distro:
477                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
478                if url == None:
479                        return {'status':False,'msg':'Needed URL parameter'}
480                if not configpath:
481                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
482                config = json.load(open(configpath,'r'))
483                config['ORIGS'][str(option)] = url
484                f=open(configpath,"w")
485                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
486                f.write(data)
487                f.close()
488                self.build_debmirror_config(distro)
489                return {'status':True,'msg':'set orig'}
490        #def set_mirror_architecture
491
492        def get_option_update(self,distro):
493                distro,configpath = self._check_distro_param(distro)
494                if not distro:
495                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
496                if not configpath:
497                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
498                config = json.load(open(configpath,'r'))
499                if not os.path.lexists(configpath):
500                        return {'status':False,'msg':' no configfile {} available'.format(configpath) }
501
502                if "CURRENT_UPDATE_OPTION" in config.keys():
503                        return {'status':True,'msg':config["CURRENT_UPDATE_OPTION"] }
504                       
505                return {'status':False,'msg':' No current_update_option into configfile {}'.format(configpath)}
506        #def get_option_update
507
508        def set_option_update(self,distro,option):
509                distro,configpath = self._check_distro_param(distro)
510                if not distro:
511                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
512                if not configpath:
513                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
514                config = json.load(open(configpath,'r'))
515                #Sanitize mirror url if it's a custom one
516                customMirror=config['ORIGS']['3']
517                if "http" in customMirror:
518                        customMirror=customMirror.split('//')[-1]
519                        config['ORIGS']['3']=customMirror
520                config['CURRENT_UPDATE_OPTION'] = str(option)
521
522                f=open(configpath,"w")
523                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
524                f.write(data)
525                f.close()
526                self.build_debmirror_config(distro)
527                return {'status':True,'msg':'set update option'}
528        #def set_option_update
529
530        def get_percentage(self,distro):
531                distro,configpath = self._check_distro_param(distro)
532                if not distro:
533                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
534                if not configpath:
535                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
536                if self.variable.has_key(distro):
537                        return {'status':True,'msg':self.variable[distro]['progress']}
538                else:
539                        return {'status':False,'msg':'this repo nos has been configured'}
540        #def get_percentage
541
542        def build_debmirror_config(self,distro):
543                distro,configpath = self._check_distro_param(distro)
544                if not distro:
545                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
546                if not configpath:
547                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
548                result = self.render_debmirror_config(distro)
549                string_template = result['msg']
550                conffile = os.path.join(self.debmirrorconfpath,distro)
551                f = open(conffile,'w')
552                f.write(string_template)
553                f.close()
554        #def build_debmirror_config
555
556        def reset_debmirror_config(self,distro):
557                distro,configpath = self._check_distro_param(distro)
558                if not distro:
559                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
560                if not configpath:
561                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
562                try:
563                    try:
564                        config=self.default_path_configs[distro]
565                        with open(config,'r') as fp_orig:
566                            with open(os.path.join(self.configpath,distro + ".json"),'w') as fp_dest:
567                                fp_dest.write(fp_orig.read())
568                    except:
569                        return {'status': False, 'msg': e}
570                    self.build_debmirror_config(distro)
571                    return {'status': True, 'msg': 'CONFIG RESET'}
572                except Exception as e:
573                    return {'status': False, 'msg': e}
574        #def reset_debmirror_config(self,distro)
575       
576        def render_debmirror_config(self,arg):
577                if type(arg) == type(""):
578                        return self._render_debmirror_config_distro(arg)
579                if type(arg) == type({}):
580                        return self._render_debmirror_config_values(arg)
581        #def render_debmirror_config
582
583        def _render_debmirror_config_distro(self,distro):
584                distro,configpath = self._check_distro_param(distro)
585                if not distro:
586                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
587                if not configpath:
588                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
589                template = self.tpl_env.get_template('debmirror.conf')
590                config = json.load(open(configpath,'r'))
591                return {'status':True,'msg':template.render(config).encode('utf-8')}
592        #def render_debmirror_config
593
594        def _render_debmirror_config_values(self,config):
595                template = self.tpl_env.get_template('debmirror.conf')
596                return {'status':True,'msg':template.render(config).encode('utf-8')}
597        #def _render_debmirror_config_values
598
599        def enable_webserver_into_folder(self,path):
600                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
601                s.bind(('localhost', 0))
602                addr, port = s.getsockname()
603                s.close()
604                self.webserverprocess[str(port)] = Process(target=self._enable_webserver_into_folder,args=(port,path,))
605                self.webserverprocess[str(port)].start()
606                return {'status':True,'msg':port}
607        #enable_webserver_into_folder
608
609        def _enable_webserver_into_folder(self,port,path):
610                try:
611                        iface = ''
612                        sock = (iface,port)
613                        proto = "HTTP/1.0"
614                        os.chdir(path)
615                        handler = SimpleHTTPRequestHandler
616                        handler.protocol_version = proto
617                        self.httpd[str(port)] = BaseHTTPServer.HTTPServer(sock,handler)
618                        self.httpd[str(port)].serve_forever()
619                except Exception, e:
620                        return None
621        #_enable_webserver_into_folder
622
623        def stop_webserver(self,port):
624                if self.webserverprocess.has_key(port):
625                        self.webserverprocess[port].terminate()
626                        self.webserverprocess.pop(port)
627                        return {'status':True,'msg':'Server stopped'}
628                return {'status':False,'msg':'Server not exists'}
629        #stop_webserver
630       
631        def set_checksum_validation(self,distro,status):
632                distro,configpath = self._check_distro_param(distro)
633                if not distro:
634                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
635                if not configpath:
636                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
637                config = json.load(open(configpath,'r'))
638                config['CHK_MD5'] = status
639
640                f=open(configpath,"w")
641                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
642                f.write(data)
643                f.close()
644
645                self.build_debmirror_config(distro)
646                return {'status':True,'msg':'set checksum validation'}
647        #set_checksum_validation
648       
649        def get_checksum_validation(self,distro):
650                distro,configpath = self._check_distro_param(distro)
651                if not distro:
652                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
653                if not configpath:
654                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
655                config = json.load(open(configpath,'r'))
656                if "IGN_GPG" in config.keys():
657                        return {'status':True,'msg':config["CHK_MD5"] }
658
659                return {'status':False,'msg':"debmirror.conf hasn't orig variable" }
660        #get_checksum_validation
661       
662        def get_available_mirrors(self):
663                versions = os.listdir(self.configpath)
664                versions = [ version.replace('.json','') for version in versions if version.endswith('.json')]
665                return {'status':True,'msg':versions}
666
667        def stopupdate(self):
668                try:
669                        self.debmirrorprocess.terminate()
670                        return {'status':True,'msg':'debmirror stopped'}
671                except Exception as e:
672                        return {'status':False,'msg':str(e)}
673
674        def stopgetmirror(self):
675                try:
676                        self.get_mirror_process.terminate()
677                        return {'status':True,'msg':'debmirror stopped'}
678                except Exception as e:
679                        return {'status':False,'msg':str(e)}
680
681        def download_time_file(self,distro):
682                distro,configpath = self._check_distro_param(distro)
683                if not distro:
684                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
685                if not configpath:
686                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
687                config = json.load(open(configpath,'r'))
688                path=config["MIRROR_PATH"]
689                f="time-of-last-update"
690                dest=os.path.join(path,f)
691
692                orig_mirror=self.get_mirror_orig(distro,"1")
693                url_mirror="http://"+os.path.join(orig_mirror['msg'],f)
694
695                return self.get_time_file(url_mirror,dest)
696
697        # # def download_time_file                     
698
699               
700        def get_time_file(self,url,dest):
701                if not url or not dest:
702                        return {'status':False,'msg': 'Needed URL and DEST parameter','action':'nothing'}
703                try:
704                        r=urlopen(url)
705                        f=open(dest,"wb")
706                        f.write(r.read())
707                        f.close()
708                        r.close()
709                        return {'status':True,'msg':dest + 'successfully downloaded.'}
710               
711                except Exception as e:
712                        return {'status':False,'msg':'Error downloading' + dest + ':' + str(e)}                 
713
714        # def get_time_file             
715
716        def is_update_available(self,distro):
717                distro, configpath = self._check_distro_param(distro)
718                if not distro:
719                        return {'status':False,'msg': 'Needed valid DISTRO parameter','action':'nothing'}
720                if not configpath:
721                        return {'status':False, 'msg': 'Wrong DISTRO parameter'}
722                config = json.load(open(configpath,'r'))
723                path = config["MIRROR_PATH"]
724                file_time_name = "time-of-last-update"
725                file_local_mirror = os.path.join(path,file_time_name)
726
727               
728                if os.path.isfile(file_local_mirror):
729                        url_pool = "http://"+os.path.join(config["ORIGS"]['1'],file_time_name)
730                        file_pool = os.path.join("/tmp",file_time_name)
731
732                        exist_file_pool = self.get_time_file(url_pool,file_pool)
733                        if exist_file_pool['status']:
734                                file_local_mirror_content=open(file_local_mirror,"r")
735                                file_local_miror_datetime=(file_local_mirror_content.readline().strip()).split("_")
736                                file_pool_content=open(file_pool,'r')
737                                file_pool_datetime=(file_pool_content.readline().strip()).split("_")
738                                file_local_mirror_content.close()
739                                file_pool_content.close()
740
741                                date_local_mirror=datetime.datetime.strptime(file_local_miror_datetime[0],"%Y/%m/%d")
742                                date_pool=datetime.datetime.strptime(file_pool_datetime[0],"%Y/%m/%d")
743
744                                if date_local_mirror==date_pool:
745                                        time_local_mirror=datetime.datetime.strptime(file_local_miror_datetime[1],"%H:%M")     
746                                        time_pool=datetime.datetime.strptime(file_pool_datetime[1],"%H:%M")
747
748                                        if time_local_mirror<time_pool:
749                                                return {'status':False,'msg':'Mirror not updated','action':'update'}
750                                        else:
751                                                return {'status':True,'msg':'Mirror is updated','action':'nothing'}
752
753                                elif date_local_mirror<date_pool:
754                                        return {'status':False,'msg':'Mirror not updated','action':'update'}
755                                else:
756                                        return {'status':True,'msg':'Mirror is updated','action':'nothing'}     
757                        else:
758                                return {'status':False,'msg':exist_file_pool['msg'],'action':'nothing'} 
759
760                else:
761                        return {'status':False,'msg':file_local_mirror + ' does not exist.','action':'nothing'}
762
763        # def is_update_available
764
765        def new_mirror_config(self,config):
766                name = config["NAME"].lower().strip()
767                name = ''.join(c for c in name if c in self.valid_chars)
768
769                # Checks
770                if name == "":
771                        return {'status':False,'msg':"Name can't void"}
772                while True:
773                        newconfigpath = os.path.join(self.configpath,name + '.json')
774                        if not os.path.lexists(newconfigpath):
775                                break
776                        name = name + "1"
777
778                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
779                f = open(newconfigpath,'w')
780                f.write(data)
781                f.close()
782                self.variable[name] = self.defaultmirrorinfo
783                return {'status':True,'msg':name}
784        #def new_mirror_config
785
786        def get_all_configs(self):
787                versions = os.listdir(self.configpath)
788                allconfigs = {}
789                for version in versions:
790                        configfile = os.path.join(self.configpath,version)
791                        f = open(configfile,'r')
792                        allconfigs[version.replace('.json','')] = json.load(f)
793                        f.close()
794                        #Sanitize mirror url if it's a custom one
795                        customMirror=allconfigs[version.replace('.json','')]['ORIGS']['3']
796                        if "http" in customMirror:
797                                customMirror=customMirror.split('//')[-1]
798                                allconfigs[version.replace('.json','')]['ORIGS']['3']=customMirror
799                return {'status':True,'msg':allconfigs}
800        #def get_all_configs
801
802        def update_mirror_config(self,mirror,config):
803                mirror,configpath = self._check_distro_param(mirror)
804                if not mirror:
805                        return {'status':False,'msg': 'Needed valid MIRROR parameter','action':'nothing'}
806                if not configpath:
807                        return {'status':False, 'msg': 'Wrong MIRROR parameter'}
808
809                #if not mirror:
810                #       return {'status':False,'msg': 'Needed MIRROR parameter','action':'nothing'}
811                #configpath = os.path.join(self.configpath,mirror + ".json")
812
813                f=open(configpath,"w")
814
815                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
816                f.write(data)
817                f.close()
818
819                return {'status':True,'msg':'Updated config'}
820        #def update_mirror_config
821
822        def get_client_ip(self,ip):
823                return {'status':True,'msg':ip}
824        #def get_client_ip
825
826        def is_alive_get_mirror(self):
827                return {'status':self.get_mirror_thread.is_alive(),'msg':self.exportpercentage}
828        #def is_alive_get_mirror
829
830        def get_mirror(self,config_path,callback_args):
831                self.get_mirror_thread = threading.Thread(target=self._get_mirror,args=(config_path,callback_args,))
832                self.get_mirror_thread.daemon = True
833                self.get_mirror_thread.start()
834        #def get_mirror
835
836        def _get_mirror(self,config_path,callback_args):
837                self.get_mirror_process = pexpect.spawn("/usr/bin/debmirror --config-file="+config_path)
838                while True:
839                        try:
840                                self.get_mirror_process.expect('\n')
841                                line =self.get_mirror_process.before
842                                line1=line.strip("\n")
843                                if line1.startswith("[") and line1[5] == "]":
844                                        self.exportpercentage = (int(line1[1:4].strip()),self.get_mirror_process.exitstatus)
845                        except pexpect.EOF:
846                                        line1 = self.get_mirror_process.before
847                                        if line1 != "" and line1.startswith("[") and line1[5] == "]":
848                                                        self.exportpercentage=(int(line1[1:4].strip()),self.get_mirror_process.exitstatus)
849                                        self.get_mirror_process.close()
850                                        status = self.get_mirror_process.exitstatus
851                                        self.exportpercentage=(self.exportpercentage[0],status)
852                                        break
853                        except Exception as e:
854                                break
855                if callback_args.has_key('port') and callback_args.has_key('ip'):
856                        import xmlrpclib as x
857                        c = x.ServerProxy('https://' + callback_args['ip'] + ':9779')
858                        c.stop_webserver('','MirrorManager',callback_args['port'])
859        #def _get
860
861        def get_last_log(self):
862                import base64
863                p = subprocess.Popen('lliurex-mirror-get-last-log',stdout=subprocess.PIPE)
864                path = p.communicate()[0].strip()
865                f = open(path,'r')
866                content = f.readlines()
867                onelinecontent = ''.join(content)
868                return {'status':True,'msg':base64.b64encode(onelinecontent)}
869        #def get_last_log(self):
870       
871        def is_mirror_available(self):
872            import fnmatch
873           
874            config=self.get_all_configs()
875            path=str(config['msg'][self.distro]['MIRROR_PATH'])
876           
877            found=False
878            for root,dirnames,filenames in os.walk(path+'/pool/main/l/lliurex-version-timestamp/'):
879                for filename in fnmatch.filter(filenames,'lliurex-version-timestamp_*.deb'):
880                    found=True
881            if found:
882                return {'status':True,'msg':'Mirror available'}
883            else:
884                return {'status':False,'msg':'Mirror unavailable'}
885        #def is_mirror_available(self):
886
887
Note: See TracBrowser for help on using the repository browser.