source: lliurex-up/trunk/fuentes/python-lliurex-up/lliurex/lliurexup/__init__.py @ 3542

Last change on this file since 3542 was 3542, checked in by jrpelegrina, 2 years ago

Add po files and fix some files

File size: 15.9 KB
Line 
1import xmlrpclib 
2import os
3import shutil
4import subprocess
5import socket
6import distutils.dir_util
7import urllib2
8
9class LliurexUpCore(object):
10        """docstring for LliurexUpCore"""
11        def __init__(self):
12                super(LliurexUpCore, self).__init__()
13                self.flavourReference=["lliurex-meta-server","lliurex-meta-client", "lliurex-meta-desktop", "lliurex-meta-music", "lliurex-meta-pyme", "lliurex-meta-infantil"] 
14                self.defaultMirror = 'llx16'
15                self.defaultVersion = 'xenial'
16                self.processPath = '/var/run/lliurex-up'
17                self.sourcesListPath='/etc/apt/'
18                self.changelogsPath = os.path.join(self.processPath,'changelogs')
19                self.processSourceslist = os.path.join(self.processPath,'sourceslist')
20                self.origsourcesfile=os.path.join(self.sourcesListPath,"sources.list")
21                self.origsourcesfileback=os.path.join(self.sourcesListPath,"lliurexup_sources.list")
22
23                self.targetMetapackagePath=os.path.join(self.processPath,"targetMetapackage")
24                self.previousflavourspath = os.path.join(self.processPath,'previousflavours')
25                self.errorpostaction_token=os.path.join(self.processPath,'errorpostaction_token')
26                self.errorupgrade_token=os.path.join(self.processPath,'errorupgrade_token')
27                self.finalupgrade_token=os.path.join(self.processPath,'finalupgrade_token')
28
29                self.initActionsPath='/usr/share/lliurex-up/initActions'
30                self.preActionsPath = '/usr/share/lliurex-up/preActions'
31                self.postActionsPath = '/usr/share/lliurex-up/postActions'
32
33                self.n4d = xmlrpclib.ServerProxy('https://localhost:9779')
34                self.haveLliurexMirror = False
35                self.metapackageRef=[]
36                self.previousFlavours = []
37                self.getTargetMetapackage()
38                self.flavours = []
39                self.getPreviousFlavours()
40                if len(self.n4d.get_methods('MirrorManager')) > 0:
41                        self.haveLliurexMirror = True
42                self.prepareEnvironment()
43
44        def getPreviousFlavours(self):
45               
46                if os.path.exists(self.previousflavourspath):
47                        aux = open(self.previousflavourspath,'r')
48                        lines = aux.readlines()
49                        for x in lines:
50                                self.previousFlavours.append(x.strip())
51                        aux.close()
52
53
54        def getTargetMetapackage(self):
55
56                if os.path.exists(self.targetMetapackagePath):
57                        aux = open(self.targetMetapackagePath,'r')
58                        lines = aux.readlines()
59                        for x in lines:
60                                self.metapackageRef.append(x.strip())
61                        aux.close()             
62
63        def saveTargetMetapackage(self,targetMetapackage):
64
65                aux=open(self.targetMetapackagePath,'w')
66                x=targetMetapackage.split("-")[2]
67                aux.write(x+"\n")
68                x="edu"
69                aux.write(x+"\n")
70                aux.close()
71
72
73        def checkInitialFlavour(self):
74
75                self.targetMetapackage=self.checkFlavour()
76                       
77                if len(self.metapackageRef)==0:
78                        self.getTargetMetapackage()
79               
80                self.metapackageRef=sorted(self.metapackageRef) 
81                         
82                if len(self.previousFlavours)==0:
83                        self.getPreviousFlavours()
84               
85                self.addSourcesListLliurex()
86
87                return self.targetMetapackage
88               
89
90        def updateFlavoursList(self):
91                self.flavours = [ x.strip() for x in self.n4d.lliurex_version('','LliurexVersion','-v')[1].split(',') ]
92                if len(self.flavours) > 0:
93                        aux = open(self.previousflavourspath,'w')
94                        for x in self.flavours:
95                                aux.write(x+"\n")
96                        aux.close()
97
98        def writeDefaultSourceslist(self):
99                f = open(os.path.join(self.processSourceslist,'default'),'w')
100                f.write('deb http://lliurex.net/{version} {version} main restricted universe multiverse\n'.format(version=self.defaultVersion))
101                f.write('deb http://lliurex.net/{version} {version}-updates main restricted universe multiverse\n'.format(version=self.defaultVersion))
102                f.write('deb http://lliurex.net/{version} {version}-security main restricted universe multiverse\n'.format(version=self.defaultVersion))
103                f.close()
104
105        def writeDefaultSourceslistMirror(self):
106                f = open(os.path.join(self.processSourceslist,'default_mirror'),'w')
107                f.write('deb http://mirror/{version_mirror} {version} main restricted universe multiverse\n'.format(version_mirror=self.defaultMirror,version=self.defaultVersion))
108                f.write('deb http://mirror/{version_mirror} {version}-updates main restricted universe multiverse\n'.format(version_mirror=self.defaultMirror,version=self.defaultVersion))
109                f.write('deb http://mirror/{version_mirror} {version}-security main restricted universe multiverse\n'.format(version_mirror=self.defaultMirror,version=self.defaultVersion))
110                f.close()       
111
112        def prepareEnvironment(self):
113                '''
114                        This funcion delete all environment and rebuild environment
115
116                '''
117                self.cleanEnvironment()
118                if not os.path.exists(self.processPath):
119                        os.mkdir(self.processPath)
120                if not os.path.exists(self.processSourceslist):
121                        os.mkdir(self.processSourceslist)
122                if not os.path.exists(self.changelogsPath):
123                        os.mkdir(self.changelogsPath)
124
125                self.writeDefaultSourceslist()
126                self.writeDefaultSourceslistMirror()
127
128        def addSourcesListLliurex(self):
129               
130                sourcesrefmirror=os.path.join(self.processSourceslist, 'default_mirror')
131
132                newsourcesfile=os.path.join(self.sourcesListPath,'sources.list')
133                extrasources=[]
134
135
136                if self.targetMetapackage=="lliurex-meta-client" or "client" in self.previousFlavours or "client" in self.metapackageRef:
137                        textsearch="/mirror/"+str(self.defaultMirror)
138                        sourcesref=os.path.join(self.processSourceslist, 'default_mirror')
139
140                else:
141                        textsearch="/lliurex.net/"+str(self.defaultVersion)
142                        sourcesref=os.path.join(self.processSourceslist, 'default')     
143
144                if os.path.exists(self.origsourcesfile):
145                        os.rename(self.origsourcesfile,self.origsourcesfileback)
146                        origsources=open(self.origsourcesfileback,'r')
147                        for line in origsources:
148                                if not textsearch in line:
149                                        extrasources.append(line.strip())
150                        origsources.close()
151                               
152                        if os.path.exists(sourcesref):
153                                shutil.copy(sourcesref,self.origsourcesfile)
154                                if len(extrasources)>0: 
155                                        newsourcesedit=open(newsourcesfile,'a')
156                                        for line in extrasources:
157                                                newsourcesedit.write(line+'\n')
158                                        newsourcesedit.close()
159                        else:
160                                os.rename(self.origsourcesfileback,self.origsourcesfile)                                       
161                       
162
163        def restoreOrigSourcesList(self):
164               
165                if os.path.exists(self.origsourcesfileback):
166                        os.rename(self.origsourcesfileback,self.origsourcesfile)
167
168
169        def cleanEnvironment(self):
170                if os.path.exists(self.processPath):
171                        shutil.rmtree(os.path.join(self.processPath))
172
173                self.restoreOrigSourcesList()   
174
175
176        def updateCacheApt(self,options=""):
177                command = "LANG=C LANGUAGE=en apt-get update {options}".format(options=options)
178                subprocess.Popen(command,shell=True).communicate()
179
180
181        def getPackageVersionAvailable(self,package,options=""):
182                '''
183                        Args :
184                                package String
185                                options String
186
187                        return dictionary => result
188                        result : {'installed':String,'candidate':String}
189
190                        Options are Apt options
191                '''
192                command = "LANG=C LANGUAGE=en apt-cache policy {package} {options}".format(package=package,options=options)
193                p = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE)
194                installed = None
195                candidate = None
196                for line in iter(p.stdout.readline,""):
197                        stripedline = line.strip()
198                        if stripedline.startswith("Installed"):
199                                installed = stripedline.replace("Installed: ","")
200                        if stripedline.startswith("Candidate"):
201                                candidate = stripedline.replace("Candidate: ","")
202                return {"installed":installed,"candidate":candidate}
203
204        def isLliurexUpIsUpdated(self):
205                '''
206                        return Boolean
207                '''
208                sourceslistDefaultPath = os.path.join(self.processSourceslist,'default')
209                options = ""
210                if self.canConnectToLliurexNet():
211                        options = "-o Dir::Etc::sourcelist={sourceslistOnlyLliurex} -o Dir::Etc::sourceparts=/dev/null".format(sourceslistOnlyLliurex=sourceslistDefaultPath)
212
213                self.updateCacheApt(options)
214                result = self.getPackageVersionAvailable('lliurex-up',options)
215
216                if result['installed'] != result['candidate']:
217                        return False
218                return True
219
220        def installLliurexUp(self,options=""):
221                '''
222                        Args :
223                                options String
224                        return dictionary => result
225                        result : {'returncode':Int,'stdout':String,'stderr':String}
226
227                        options are Apt options
228                       
229
230                        This function install lliurex-up
231                '''
232                command = "LANG=C LANGUAGE=en apt-get install --force-yes --yes lliurex-up {options}".format(options=options)
233                p = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE)
234                poutput,perror = p.communicate()
235                return {'returncode':p.returncode,'stdout':poutput,'stderrs':perror}
236
237        def lliurexMirrorIsUpdated(self):
238                '''
239                        return None | dictionary => result
240                        result : {'status':Boolean,'msg':String,'action':String}
241                        result.msg : message of status
242                        result.action : Action to launch
243                '''
244                if self.haveLliurexMirror and ('server' in self.flavours or 'lliurex-meta-server'==self.targetMetapackage):
245                        result = self.n4d.is_update_available('','MirrorManager',self.defaultMirror)
246                        return result
247                return None
248
249        def lliurexMirrorIsRunning(self):
250                '''
251                        return Boolean
252                '''
253                if self.haveLliurexMirror and ('server' in self.flavours or 'lliurex-meta-server'==self.targetMetapackage):
254                        result = self.n4d.is_alive('','MirrorManager')
255                        return result['status']
256                return False
257
258        def getPercentageLliurexMirror(self):
259                '''
260                        return int | None
261                '''
262                if self.haveLliurexMirror and ('server' in self.flavours or 'lliurex-meta-server'==self.targetMetapackage):
263                        result = self.n4d.get_percentage('','MirrorManager',self.defaultMirror)
264                        if result['status']:
265                                return result['msg']
266                return None
267       
268        def checkFlavour(self):
269                '''
270                        return None|String
271                        If metapackages has been uninstalled, this function return
272                        package to must install. If return None, you are ok and don't need
273                        install anything.
274                '''
275                self.updateFlavoursList()
276                targetMetapackage = None
277                if 'None' in self.flavours:
278                        # get last flavour
279                        result = self.n4d.lliurex_version('','LliurexVersion','--history')
280                        if result[0]:
281                                history = [ x.strip().split('\t')[0].strip() for x in result[1].split('\n') ]
282                                history = [ x for x in history if not 'lliurex-meta-live' in x ]
283                                for x in reversed(history):
284                                        if x.startswith('-'):
285                                                targetMetapackage = x[2:]
286                                                break
287
288                if targetMetapackage !=None:
289                        self.saveTargetMetapackage(targetMetapackage)                           
290                return targetMetapackage
291
292        def canConnectToLliurexNet(self):
293                '''
294                        return Boolean
295                '''
296                # s =  socket.socket(socket.AF_INET, socket.SOCK_STREAM)
297                # host = socket.gethostbyname('lliurex.net')
298                # result = s.connect_ex((host, 80))
299                # s.close()
300                # if result:
301                #       return False
302                # return True
303
304                try:
305                        req=urllib2.Request("http://lliurex.net/xenial")
306                        res=urllib2.urlopen(req)
307                        return True
308                except:
309                        return False
310                               
311        def getLliurexVersionLliurexNet(self):
312                '''
313                        return dictionary => result
314                        result : {'installed':String,'candidate':String}
315                '''
316                sourceslistDefaultPath = os.path.join(self.processSourceslist,'default')
317                options = ""
318                if self.canConnectToLliurexNet():
319                        options = "-o Dir::Etc::sourcelist={sourceslistOnlyLliurex} -o Dir::Etc::sourceparts=/dev/null".format(sourceslistOnlyLliurex=sourceslistDefaultPath)
320                self.updateCacheApt(options)
321                return self.getPackageVersionAvailable('lliurex-version-timestamp',options)
322
323        def getLliurexVersionLocal(self):
324                self.updateCacheApt('')
325                return self.getPackageVersionAvailable('lliurex-version-timestamp','')         
326
327        def initActionsScript(self,arg):
328                #return 'run-parts --arg="initActions" ' + self.initActionsPath
329                return 'run-parts --arg=' +str(arg) + ' ' + self.initActionsPath
330
331
332        def preActionsScript(self):
333                return 'run-parts --arg="preActions" ' + self.preActionsPath
334
335        def postActionsScript(self):
336                return 'run-parts --arg="postActions" ' + self.postActionsPath
337
338
339        # def requiresInstallFlavour(self):
340               
341        #       flavourToInstall=None
342               
343        #       if not 'None' in self.previuosFlavours:
344        #               if self.previuosFlavours !=self.flavours:
345        #                       flavourToInstall=self.parseFlavourToInstall(self.previousFlavours)
346                                                                               
347        #       else:
348                       
349        #               if self.metapackageRef != self.flavours:
350        #                       flavourToInstall=self.parseFlavourToInstall(self.metapackageRef)
351                                                       
352
353        #       return flavourToInstall                                 
354
355               
356        # def parseFlavourToInstall(self,flavours):
357       
358        #       parse_flavour=""
359
360        #       for item in flavours:
361        #               if item != "edu":
362        #                       parse_flavour=parse_flavour + " " + "lliurex-meta-" + item
363
364        #       return parse_flavour
365                       
366        #def parseFlavourToInstall(
367
368
369        def installInitialFlavour(self,flavourToInstall,options=""):
370                '''
371                        Args :
372                                flavourToInstall String
373                                options String
374                        return dictionary => result
375                        result : {'returncode':Int,'stdout':String,'stderr':String}
376
377                        options are Apt options
378                       
379
380                        This function install lliurex-up
381                '''
382                command = "LANG=C LANGUAGE=en apt-get install --force-yes --yes " + flavourToInstall + "{options} ".format(options=options)
383                p = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE)
384                poutput,perror = p.communicate()
385                return {'returncode':p.returncode,'stdout':poutput,'stderrs':perror}   
386
387        def getPackagesToUpdate(self):
388                '''
389                        packageInfo definition
390                        {
391                                'PACKAGENAME' : {
392                                                'install' : 'INSTALLEDVERSION',
393                                                'candidate' : 'CANDIDATEVERSION',
394                                                'icon' : 'ICONNAME',
395                                                'changelog' : 'CHANGELOGTEXT'
396                                }
397                        }
398                '''
399                self.packageInfo = {}
400                self.updateCacheApt("")
401                psimulate = subprocess.Popen('LANG=C LANGUAGE=en apt-get dist-upgrade -sV',shell=True,stdout=subprocess.PIPE)
402                rawoutputpsimulate = psimulate.stdout.readlines()
403                rawpackagestoinstall = [ aux.strip() for aux in rawoutputpsimulate if aux.startswith('Inst') ]
404                r = [ aux.replace('Inst ','') for aux in rawpackagestoinstall ]
405                for allinfo in r :
406                        self.packageInfo[allinfo.split(' ')[0]] = {}
407                        self.packageInfo[allinfo.split(' ')[0]]['raw'] = ' '.join(allinfo.split(' ')[1:])
408
409                for package in self.packageInfo:
410                        raw = self.packageInfo[package]['raw'].split(' ')
411                        if raw[0].startswith('['):
412                                self.packageInfo[package]['install'] = raw[0][1:-1]
413                                self.packageInfo[package]['candidate'] = raw[1][1:]
414                        elif raw[0].startswith('('):
415                                self.packageInfo[package]['install'] = None
416                                self.packageInfo[package]['candidate'] = raw[0][1:]
417                        self.packageInfo[package].pop('raw')
418                        #packageInfo[package]['changelog'] = os.path.join(self.changelogsPath,package)
419                        #os.system('LANG=C LANGUAGE=en apt-get changelog %s > %s%s'%(package,self.changelogsPath,package))
420                        #packageInfo[package]['icon'] =
421                return self.packageInfo
422
423
424        def checkIncorrectFlavours(self):
425               
426                self.incorrect_flavours=[]
427                count=0
428
429                for item in self.packageInfo:
430                        if item in self.flavourReference:
431                                self.incorrect_flavours.append(item)
432
433
434                if len(self.incorrect_flavours)>0:
435
436                        for item in self.incorrect_flavours:
437                                if self.targetMetapackage != None:
438                                        if item != self.targetMetapackage:
439                                                count=count+1
440                                else:
441                                        meta=item.split("-")[2]
442                                        if 'None' in self.previousFlavours:
443                                                if not meta in self.metapackageRef:
444                                                        count=count+1
445                                        else:           
446                                                if not meta in self.previousFlavours:
447                                                        count=count+1
448
449                if count>0:
450                        return True
451
452                else:
453                        return False   
454
455
456        def distUpgradeProcess(self):
457       
458                return 'apt-get dist-upgrade --yes --force-yes'
459
460
461
462        def checkErrorDistUpgrade(self):
463
464                count=0
465                error=False
466
467                if os.path.exists(self.errorpostaction_token):
468                        aux = open(self.errorpostaction_token,'r')
469                        lines = aux.readlines()
470                        for x in lines:
471                                if 'E: ' in x:
472                                        count=count+1
473                        aux.close()
474
475                if count==0:
476                        cmd='dpkg -l | grep "^i[^i]" >' + self.errorupgrade_token
477                        os.system(cmd)
478               
479                        if os.path.exists(self.errorupgrade_token):
480                                aux = open(self.errorupgrade_token,'r')
481                                lines = aux.readlines()
482                                aux.close()
483                       
484                                if len(lines)>0:
485                                        error=True
486                                        #log_msg="Dist-upgrade process ending with errors"
487                                        #self.log(log_msg)
488                                else:
489                                        j=0
490                                        cmd='apt-get dist-upgrade -sV >' + self.finalupgrade_token
491                                        os.system(cmd)
492                                        if os.path.exists(self.finalupgrade_token):
493                                                aux = open(self.finalupgrade_token,'r')
494                                                lines = aux.readlines()
495                                                aux.close()
496
497                                                for x in lines:
498                                                        if 'Inst' in x:
499                                                                j=j+1
500
501                                                if j>0:
502                                                        error=True             
503                else:
504                        error=True
505
506                return error   
507
508
509        def checkFinalFlavour(self):
510               
511                flavourToInstall=None
512               
513                self.targetMetapackage=self.checkFlavour()
514                if self.targetMetapackage!=None:
515                        #flavourToInstall=self.requiresInstallFlavour()
516                #else:
517                        flavourToInstall=self.targetMetapackage         
518
519                return flavourToInstall         
520
521
522        def installFinalFlavour(self,flavourToInstall):
523
524                return 'apt-get install ' + flavourToInstall + ' --yes --force-yes'
525               
526       
527
528if __name__ == '__main__':
529        x = LliurexUpCore()
Note: See TracBrowser for help on using the repository browser.