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

Last change on this file since 2594 was 2594, checked in by kbut, 3 years ago

increment progress only download debs

File size: 20.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 re
12import json
13
14import BaseHTTPServer
15from SimpleHTTPServer import SimpleHTTPRequestHandler
16from multiprocessing import Process
17import socket
18from urllib2 import urlopen
19import string
20
21class MirrorManager:
22
23
24        def __init__(self):
25                #Default values
26                self.defaultpath = '/etc/lliurex-mirror/'
27                self.debmirrorconfpath = os.path.join(self.defaultpath,'debmirror')
28                self.configpath = os.path.join(self.defaultpath,'conf')
29                self.distro="llx16"
30                self.httpd = {}
31                self.debmirrorprocess = None
32
33                self.tpl_env = Environment(loader=FileSystemLoader('/usr/share/n4d/templates/lliurex-mirror'))
34                self.update_thread=threading.Thread()
35                self.get_mirror_thread = threading.Thread()
36                self.percentage=(0,None)
37                self.exportpercentage = 0
38                self.mirrorworking = None
39                self.webserverprocess = {}
40                self.defaultmirrorinfo = {"status_mirror":"New","last_mirror_date":None,"mirror_size":0,"progress":0}
41                self.valid_chars = "-_.%s%s" % (string.ascii_letters, string.digits)
42                self.default_mirror_config = '''
43{
44        "NAME": "",
45        "BANNER": "",
46        "ORIGS" : {"1":"lliruex.net/xenial","2":"","3":""},
47        "ARCHITECTURES": [ "amd64", "i386"],
48        "SECTIONS": ["main", "main/debian-installer", "universe", "restricted", "multiverse", "partner"],
49        "MIRROR_PATH": "/net/mirror/llx16",
50        "DISTROS": ["xenial","xenial-updates","xenial-security"],
51        "IGN_GPG":1,
52        "IGN_RELEASE":0,
53        "CHK_MD5":0,
54        "CURRENT_UPDATE_OPTION":"1"
55}'''
56               
57        #def init
58       
59        def startup(self,options):
60                self.n4d_vars=objects["VariablesManager"]
61                self.variable=objects["VariablesManager"].get_variable("LLIUREXMIRROR")
62               
63               
64                if self.variable==None:
65                        try:
66                                self.n4d_vars.add_variable("LLIUREXMIRROR",{},"","Lliurex Mirror info variable","n4d-lliurex-mirror")
67                        except Exception as e:
68                                pass
69                       
70                if type(self.variable)!=type({}):
71                        self.variable={}
72               
73                try:
74                        for repo in self.get_available_mirrors()['msg']:
75                                if self.variable.has_key(repo) and self.variable[repo].has_key("status_mirror") and self.variable[repo]["status_mirror"] == "Working":
76                                        if not self.update_thread.isAlive():
77                                                self.variable[repo]["status_mirror"] = "Error"
78                                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
79                                else:
80                                        if not self.variable.has_key(repo):
81                                                self.variable[repo] = self.defaultmirrorinfo
82                except Exception as e:
83                        pass
84        #def startup
85
86        def apt(self):
87                # executed after apt operations
88                pass
89               
90        #def apt
91       
92        # service test and backup functions #
93       
94        def test(self):
95
96                pass
97               
98        #def test
99       
100        def backup(self):
101
102                pass
103               
104        #def backup
105
106        def restore(self):
107                pass
108        #def restore
109
110        def set_cname(self):
111                #Get template
112                template = self.tpl_env.get_template("cname")
113                list_variables = {}
114               
115                list_variables = self.n4d_vars.get_variable_list(['INTERNAL_DOMAIN','HOSTNAME'])
116                for x in list_variables.keys():
117                        if list_variables[x] == None:
118                                return {'status':False,'msg':'Variable ' + x + ' not defined'}
119                       
120                #Encode vars to UTF-8
121                string_template = template.render(list_variables).encode('UTF-8')
122                #Open template file
123                fd, tmpfilepath = tempfile.mkstemp()
124                new_export_file = open(tmpfilepath,'w')
125                new_export_file.write(string_template)
126                new_export_file.close()
127                os.close(fd)
128                #Write template values
129                n4d_mv(tmpfilepath,'/var/lib/dnsmasq/config/cname-mirror',True,'root','root','0644',False )
130               
131                return {'status':True,'msg':'Set mirror cname'}
132        #def set_cname
133       
134        def update(self,ip,distro=None,callback_args=None):
135
136                if distro==None:
137                        distro=self.distro
138       
139                if self.update_thread.is_alive():
140                        return {'status':False,'msg':'Lliurex-mirror (n4d instance) is running'}
141               
142                self.percentage=(0,None)
143                self.update_thread=threading.Thread(target=self._update,args=(ip,distro,callback_args,))
144                self.update_thread.daemon=True
145                self.update_thread.start()
146               
147                return {'status':True,'msg':'running'}
148
149        #def update
150       
151        def _update(self,ip,distro,callback_args):
152                if not self.variable.has_key(distro):
153                        self.variable[distro]=self.defaultmirrorinfo
154                # link config debmirror to correct path with distro name
155                self.variable[distro]['status_mirror'] = "Working"
156                self.variable[distro]['progress'] = 0
157                self.variable[distro]['exception_msg'] = ""
158                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
159                self.build_debmirror_config(distro)
160                if os.path.lexists('/etc/debmirror.conf'):
161                        os.remove('/etc/debmirror.conf')
162                os.symlink(os.path.join(self.debmirrorconfpath,distro),'/etc/debmirror.conf')
163                self.mirrorworking = distro
164                fd = open('/var/log/lliurex-mirror.log','a')
165                import datetime
166                fd.write("************************* " + str(datetime.datetime.now())+ " ***********************************\n")
167                fd.flush()
168                errors_found = False   
169                self.debmirrorprocess=pexpect.spawn("/usr/bin/debmirror")
170                download_packages = False
171                emergency_counter = 0
172                try:
173                        objects["ZCenterVariables"].add_pulsating_color("lliurexmirror")
174                except:
175                        pass
176                while True:
177                        try:
178                                emergency_counter += 1
179                                if emergency_counter > 100:
180                                        download_packages = True
181                                self.debmirrorprocess.expect('\n',timeout=480)
182                                line =self.debmirrorprocess.before
183
184                                fd.write(line + "\n")
185                                fd.flush()
186                                if line.find("Files to download") >= 0 :
187                                        download_packages = True
188                                line1=line.strip("\n")
189                                if download_packages:
190                                        if line1.startswith("[") and line1[5] == "]":
191                                                self.percentage=(int(line1[1:4].strip()),self.debmirrorprocess.exitstatus)
192                                                self.variable[distro]['progress'] = self.percentage[0]
193                                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
194                                        if line1.startswith("Everything OK"):
195                                                self.percentage=(100,self.debmirrorprocess.exitstatus)
196                                                self.variable[distro]['progress'] = 100
197                                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
198                               
199                                if errors_found:
200                                        e=Exception(line1)
201                                        raise e
202                                if line1.startswith("Errors"):
203                                        errors_found = True
204       
205
206                        except pexpect.EOF:
207                                        line1 = self.debmirrorprocess.before
208                                        if line1 != "" and line1.startswith("[") and line1[5] == "]":
209                                                        self.percentage=(int(line1[1:4].strip()),self.debmirrorprocess.exitstatus)
210                                        self.debmirrorprocess.close()
211                                        status = self.debmirrorprocess.exitstatus
212                                        self.percentage=(self.percentage[0],status)
213                                        self.variable[distro]['progress'] = self.percentage[0]
214                                        self.variable[distro]['status_mirror'] = "Ok" if status == 0 else "Error"
215                                        self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
216                                        break
217                        except Exception as e:
218                                print e
219                                self.variable[distro]['status_mirror'] = "Error"
220                                self.variable[distro]["exception_msg"] = str(e)
221                                status = self.debmirrorprocess.exitstatus
222                                self.percentage=(self.percentage[0],str(e))
223                                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
224                                break
225                fd.close()
226                if type(callback_args) != type(None):
227                        if callback_args.has_key('port'):
228                                import xmlrpclib as x
229                                c = x.ServerProxy('https://' + ip + ':9779')
230                                c.stop_webserver('','MirrorManager',callback_args['port'])
231
232                self.download_time_file(distro)
233                self.set_mirror_info(distro)
234                self.mirrorworking = None
235                try:
236                        objects["ZCenterVariables"].remove_pulsating_color("lliurexmirror")
237                except:
238                        pass
239
240        #def _update
241       
242        def is_alive(self):
243
244                return {'status':self.update_thread.is_alive(),'msg':self.mirrorworking}
245        #def is_alive
246
247        def set_mirror_info(self,distro=None):
248               
249                if distro!=None:
250                        distro=distro
251                else:
252                        distro=self.distro
253               
254                configpath = os.path.join(self.configpath, distro + ".json")
255                config = json.load(open(configpath,'r'))
256
257                mirrorpath = config["MIRROR_PATH"]
258                #self.n4d_vars.set_variable("ZEROCENTERINTERNAL",self.internal_variable)
259               
260                MIRROR_DATE=datetime.date.today().strftime("%d/%m/%Y")
261                MIRROR_SIZE=self.get_size(mirrorpath)
262               
263                self.variable[distro]["last_mirror_date"]=MIRROR_DATE
264                self.variable[distro]["mirror_size"]=str(MIRROR_SIZE)
265                self.variable[distro]["progress"]=self.percentage[0]
266               
267                self.n4d_vars.set_variable("LLIUREXMIRROR",self.variable)
268               
269                #set_custom_text(self,app,text):
270                txt="Updated on: " + str(MIRROR_DATE)
271                txt+=" # Size: %.2fGB"%MIRROR_SIZE
272                try:
273                        objects["ZCenterVariables"].set_custom_text("lliurexmirror",txt)
274                        abstract=open('/var/log/lliurex/lliurex-mirror.log','w')
275                        abstract.write(txt+"\n")
276                        abstract.close()
277                except Exception as e:
278                        pass
279
280        #def set_mirror_info(self):
281
282        def get_size(self,start_path = '.'):
283       
284                total_size = 0
285                try:
286                        for dirpath, dirnames, filenames in os.walk(start_path):
287                                for f in filenames:
288                                        fp = os.path.join(dirpath, f)
289                                        total_size += os.path.getsize(fp)
290                                       
291                        total_size/=1024*1024*1024.0
292                        return total_size
293                except:
294                        return 0
295       
296        #def get_size(start_path = '.'):
297       
298        def search_field(self,filepath,fieldname):
299                try:
300                        f = open(filepath,'r')
301                        needle = None
302                        lines = f.readlines()
303                        for x in lines:
304                                        if re.match('\s*'+fieldname,x):
305                                                        needle = x.strip()
306                        return needle
307                except:
308                        return None
309        # def search_field
310       
311        def get_mirror_architecture(self,distro):
312
313                configpath = os.path.join(self.configpath,distro + ".json")
314                config = json.load(open(configpath,'r'))
315                if not os.path.lexists(configpath):
316                        return {'status':False,'msg':'not exists debmirror.conf to '+ distro }
317
318                if "ARCHITECTURES" in config.keys():
319                        return {'status':True,'msg':config["ARCHITECTURES"] }
320
321                return {'status':False,'msg':"debmirror.conf hasn't architecture variable" }
322        #def get_mirror_architecture
323       
324        def set_mirror_architecture(self,distro,archs):
325                configpath = os.path.join(self.configpath,distro + ".json")
326               
327                config = json.load(open(configpath,'r'))
328               
329                config['ARCHITECTURES'] = archs
330
331
332                f=open(configpath,"w")
333
334                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
335                f.write(data)
336                f.close()
337
338                self.build_debmirror_config(distro)
339                return {'status':True,'msg':'set architecture'}
340               
341        #def set_mirror_architecture
342       
343        def get_mirror_orig(self,distro,option):
344
345                configpath = os.path.join(self.configpath,distro + ".json")
346                config = json.load(open(configpath,'r'))
347                if not os.path.lexists(configpath):
348                        return {'status':False,'msg':'not exists debmirror.conf to '+ distro }
349
350                if "ORIGS" in config.keys():
351                        return {'status':True,'msg':config["ORIGS"][option] }
352                       
353                return {'status':False,'msg':"debmirror.conf hasn't orig variable" }   
354        #def get_mirror_from
355
356        def set_mirror_orig(self,distro,url,option):
357                if url == None:
358                        return {'status':False,'msg':'url is None'}
359                configpath = os.path.join(self.configpath, distro + ".json")
360                config = json.load(open(configpath,'r'))
361                config['ORIGS'][option] = url
362
363                f=open(configpath,"w")
364                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
365                f.write(data)
366                f.close()
367
368                self.build_debmirror_config(distro)
369                return {'status':True,'msg':'set orig'}
370        #def set_mirror_architecture
371
372        def get_option_update(self,distro):
373                configpath = os.path.join(self.configpath,distro + ".json")
374                config = json.load(open(configpath,'r'))
375                if not os.path.lexists(configpath):
376                        return {'status':False,'msg':'not exists debmirror.conf to '+ distro }
377
378                if "CURRENT_UPDATE_OPTION" in config.keys():
379                        return {'status':True,'msg':config["CURRENT_UPDATE_OPTION"] }
380                       
381                return {'status':False,'msg':"debmirror.conf hasn't option update variable" }
382        #def get_option_update
383
384        def set_option_update(self,distro,option):
385                configpath = os.path.join(self.configpath, distro + ".json")
386                config = json.load(open(configpath,'r'))
387                config['CURRENT_UPDATE_OPTION'] = str(option)
388
389                f=open(configpath,"w")
390                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
391                f.write(data)
392                f.close()
393
394                self.build_debmirror_config(distro)
395                return {'status':True,'msg':'set update option'}
396        #def set_option_update
397
398        def get_percentage(self,distro):
399                if self.variable.has_key(distro):
400                        return {'status':True,'msg':self.variable[distro]['progress']}
401                else:
402                        return {'status':False,'msg':'this repo nos has been configured'}
403        #def get_percentage
404
405
406        def build_debmirror_config(self,distro):
407                result = self.render_debmirror_config(distro)
408                string_template = result['msg']
409                f = open(os.path.join(self.debmirrorconfpath,distro),'w')
410                f.write(string_template)
411                f.close()
412        #def build_debmirror_config
413
414        def render_debmirror_config(self,arg):
415                if type(arg) == type(""):
416                        return self._render_debmirror_config_distro(arg)
417                if type(arg) == type({}):
418                        return self._render_debmirror_config_values(arg)
419        #def render_debmirror_config
420
421        def _render_debmirror_config_distro(self,distro):
422                template = self.tpl_env.get_template('debmirror.conf')
423                configpath = os.path.join(self.configpath,distro + ".json")
424                config = json.load(open(configpath,'r'))
425                return {'status':True,'msg':template.render(config).encode('utf-8')}
426        #def render_debmirror_config
427
428        def _render_debmirror_config_values(self,config):
429                template = self.tpl_env.get_template('debmirror.conf')
430                return {'status':True,'msg':template.render(config).encode('utf-8')}
431        #def _render_debmirror_config_values
432
433        def enable_webserver_into_folder(self,path):
434               
435                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
436                s.bind(('localhost', 0))
437                addr, port = s.getsockname()
438                s.close()
439                self.webserverprocess[str(port)] = Process(target=self._enable_webserver_into_folder,args=(port,path,))
440                self.webserverprocess[str(port)].start()
441                return {'status':True,'msg':port}
442        #enable_webserver_into_folder
443
444        def _enable_webserver_into_folder(self,port,path):
445                try:
446                        iface = '127.0.0.1'
447                        sock = (iface,port)
448                        proto = "HTTP/1.0"
449                        os.chdir(path)
450                        handler = SimpleHTTPRequestHandler
451                        handler.protocol_version = proto
452                        self.httpd[str(port)] = BaseHTTPServer.HTTPServer(sock,handler)
453                        self.httpd[str(port)].serve_forever()
454                except Exception, e:
455                        return None
456        #_enable_webserver_into_folder
457
458        def stop_webserver(self,port):
459                if self.webserverprocess.has_key(port):
460                        self.webserverprocess[port].terminate()
461                        self.webserverprocess.pop(port)
462                        return {'status':True,'msg':'Server stopped'}
463                return {'status':False,'msg':'Server not exists'}
464        #stop_webserver
465       
466        def set_checksum_validation(self,distro,status):
467                configpath = os.path.join(self.configpath, distro + ".json")
468                config = json.load(open(configpath,'r'))
469                config['CHK_MD5'] = status
470
471                f=open(configpath,"w")
472                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
473                f.write(data)
474                f.close()
475
476                self.build_debmirror_config(distro)
477                return {'status':True,'msg':'set checksum validation'}
478        #set_checksum_validation
479       
480        def get_checksum_validation(self,distro):
481
482                configpath = os.path.join(self.configpath,distro + ".json")
483                config = json.load(open(configpath,'r'))
484                if not os.path.lexists(configpath):
485                        return {'status':False,'msg':'not exists debmirror.conf to '+ distro }
486                if "IGN_GPG" in config.keys():
487                        return {'status':True,'msg':config["CHK_MD5"] }
488
489                return {'status':False,'msg':"debmirror.conf hasn't orig variable" }
490        #get_checksum_validation
491       
492        def get_available_mirrors(self):
493                versions = os.listdir(self.configpath)
494                versions = [ version.replace('.json','') for version in versions if version.endswith('.json')]
495                return {'status':True,'msg':versions}
496
497        def stopupdate(self):
498                try:
499                        self.debmirrorprocess.terminate()
500                        return {'status':True,'msg':'debmirror stopped'}
501                except Exception as e:
502                        return {'status':False,'msg':str(e)}
503
504        def stopgetmirror(self):
505                try:
506                        self.get_mirror_process.terminate()
507                        return {'status':True,'msg':'debmirror stopped'}
508                except Exception as e:
509                        return {'status':False,'msg':str(e)}
510
511        def download_time_file(self,distro):
512               
513                configpath = os.path.join(self.configpath,distro + ".json")
514                config = json.load(open(configpath,'r'))
515                path=config["MIRROR_PATH"]
516                f="time-of-last-update"
517                dest=os.path.join(path,f)
518
519                orig_mirror=self.get_mirror_orig(distro,"1")
520                url_mirror="http://"+os.path.join(orig_mirror['msg'],f)
521
522                return self.get_time_file(url_mirror,dest)
523
524        # # def download_time_file                     
525
526               
527        def get_time_file(self,url,dest):
528               
529                try:
530                        r=urlopen(url)
531                        f=open(dest,"wb")
532                        f.write(r.read())
533                        f.close()
534                        r.close()
535                        return {'status':True,'msg':dest + 'successfully downloaded.'}
536               
537                except Exception as e:
538                        return {'status':False,'msg':'Error downloading' + dest + ':' + str(e)}                 
539
540        # def get_time_file             
541
542        def is_update_available(self,distro):
543
544                configpath = os.path.join(self.configpath,distro + ".json")
545                config = json.load(open(configpath,'r'))
546                path = config["MIRROR_PATH"]
547                file_time_name = "time-of-last-update"
548                file_local_mirror = os.path.join(path,file_time_name)
549
550               
551                if os.path.isfile(file_local_mirror):
552                        url_pool = "http://"+os.path.join(config["ORIGS"]['1'],file_time_name)
553                        file_pool = os.path.join("/tmp",file_time_name)
554
555                        exist_file_pool = self.get_time_file(url_pool,file_pool)
556                        if exist_file_pool['status']:
557                                file_local_mirror_content=open(file_local_mirror,"r")
558                                file_local_miror_datetime=(file_local_mirror_content.readline().strip()).split("_")
559                                file_pool_content=open(file_pool,'r')
560                                file_pool_datetime=(file_pool_content.readline().strip()).split("_")
561                                file_local_mirror_content.close()
562                                file_pool_content.close()
563
564                                date_local_mirror=datetime.datetime.strptime(file_local_miror_datetime[0],"%Y/%m/%d")
565                                date_pool=datetime.datetime.strptime(file_pool_datetime[0],"%Y/%m/%d")
566
567                                if date_local_mirror==date_pool:
568                                        time_local_mirror=datetime.datetime.strptime(file_local_miror_datetime[1],"%H:%M")     
569                                        time_pool=datetime.datetime.strptime(file_pool_datetime[1],"%H:%M")
570
571                                        if time_local_mirror<time_pool:
572                                                return {'status':False,'msg':'Mirror not updated','action':'update'}
573                                        else:
574                                                return {'status':True,'msg':'Mirror is updated','action':'nothing'}
575
576                                elif date_local_mirror<date_pool:
577                                        return {'status':False,'msg':'Mirror not updated','action':'update'}
578                                else:
579                                        return {'status':True,'msg':'Mirror is updated','action':'nothing'}     
580                        else:
581                                return {'status':False,'msg':exist_file_pool['msg'],'action':'nothing'} 
582
583                else:
584                        return {'status':False,'msg':file_local_mirror + ' does not exist.','action':'nothing'}
585
586        # def is_update_available
587
588        def new_mirror_config(self,config):
589                name = config["NAME"].lower().strip()
590                name = ''.join(c for c in name if c in self.valid_chars)
591
592                # Checks
593                if name == "":
594                        return {'status':False,'msg':"Name can't void"}
595                while True:
596                        newconfigpath = os.path.join(self.configpath,name + '.json')
597                        if not os.path.lexists(newconfigpath):
598                                break
599                        name = name + "1"
600
601                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
602                f = open(newconfigpath,'w')
603                f.write(data)
604                f.close()
605                self.variable[name] = self.defaultmirrorinfo
606                return {'status':True,'msg':name}
607        #def new_mirror_config
608
609        def get_all_configs(self):
610                versions = os.listdir(self.configpath)
611                allconfigs = {}
612                for version in versions:
613                        configfile = os.path.join(self.configpath,version)
614                        f = open(configfile,'r')
615                        allconfigs[version.replace('.json','')] = json.load(f)
616                        f.close()
617                return {'status':True,'msg':allconfigs}
618        #def get_all_configs
619
620        def update_mirror_config(self,mirror,config):
621                configpath = os.path.join(self.configpath,mirror + ".json")
622
623                f=open(configpath,"w")
624
625                data=unicode(json.dumps(config,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
626                f.write(data)
627                f.close()
628
629                return {'status':True,'msg':'Updated config'}
630        #def update_mirror_config
631
632        def get_client_ip(self,ip):
633                return {'status':True,'msg':ip}
634        #def get_client_ip
635
636        def is_alive_get_mirror(self):
637                return {'status':self.get_mirror_thread.is_alive(),'msg':self.exportpercentage}
638        #def is_alive_get_mirror
639
640        def get_mirror(self,config_path,callback_args):
641                self.get_mirror_thread = threading.Thread(target=self._get_mirror,args=(config_path,callback_args,))
642                self.get_mirror_thread.daemon = True
643                self.get_mirror_thread.start()
644        #def get_mirror
645
646        def _get_mirror(self,config_path,callback_args):
647                self.get_mirror_process = pexpect.spawn("/usr/bin/debmirror --config-file="+config_path)
648                while True:
649                        try:
650                                self.get_mirror_process.expect('\n')
651                                line =self.get_mirror_process.before
652                                line1=line.strip("\n")
653                                if line1.startswith("[") and line1[5] == "]":
654                                        self.exportpercentage = (int(line1[1:4].strip()),self.get_mirror_process.exitstatus)
655                        except pexpect.EOF:
656                                        line1 = self.get_mirror_process.before
657                                        if line1 != "" and line1.startswith("[") and line1[5] == "]":
658                                                        self.exportpercentage=(int(line1[1:4].strip()),self.get_mirror_process.exitstatus)
659                                        self.get_mirror_process.close()
660                                        status = self.get_mirror_process.exitstatus
661                                        self.exportpercentage=(self.exportpercentage[0],status)
662                                        break
663                        except Exception as e:
664                                break
665                if callback_args.has_key('port') and callback_args.has_key('ip'):
666                        import xmlrpclib as x
667                        c = x.ServerProxy('https://' + callback_args['ip'] + ':9779')
668                        c.stop_webserver('','MirrorManager',callback_args['port'])
669        #def _get
Note: See TracBrowser for help on using the repository browser.