source: lliurex-up/trunk/fuentes/lliurex-up-cli/usr/sbin/lliurex-upgrade @ 4093

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

WIP in improve process to detect errors

  • Property svn:executable set to *
File size: 16.6 KB
Line 
1#!/usr/bin/env python
2
3from clint import arguments
4from clint.textui import puts, indent, colored
5import lliurex.lliurexup
6import os
7import subprocess
8import sys
9import commands
10import datetime
11import time
12import signal
13signal.signal(signal.SIGINT,signal.SIG_IGN)
14
15class LliurexUpCli(object):
16        def __init__(self):
17
18               
19                self.lliurexcore = lliurex.lliurexup.LliurexUpCore()
20                log_msg="------------------------------------------\n"+"LLIUREX-UP-CLI STARTING AT: " + datetime.datetime.today().strftime("%d/%m/%y %H:%M:%S") +"\n------------------------------------------"
21                self.log(log_msg)
22                signal.signal(signal.SIGINT,self.handler_signal)
23                self.checkInitialFlavour()
24       
25        #def __init__
26       
27        def checkInitialFlavour(self):
28
29                self.targetMetapackage=self.lliurexcore.checkInitialFlavour()
30                log_msg="Initial check metapackage. Metapackage to install: " + str(self.targetMetapackage)
31                self.log(log_msg)
32                log_msg="Get initial flavours: " + str(self.lliurexcore.previousFlavours)
33                self.log(log_msg)
34               
35        #def checkInitialFlavour       
36               
37
38        def canConnectToLliurexNet(self):
39
40                print("  [Lliurex-up]: Checking connection to lliurex.net")
41                can_connect=self.lliurexcore.canConnectToLliurexNet()
42                if can_connect:
43                                log_msg="Can connect to lliurex.net: True"
44                                self.log(log_msg)
45                                return True
46                else:
47                        log_msg="Can connect to lliurex.net: False"
48                        self.log(log_msg)
49
50                        if "lliurex-meta-server" == self.targetMetapackage or "server" in self.lliurexcore.previousFlavours:
51                                self.lliurexcore.cleanEnvironment()
52                                self.lliurexcore.cleanLliurexUpLock()
53                                return False
54                        else:
55                                return True
56                               
57        #def canConnectToLliurexNet                     
58                               
59        def clientCheckingMirrorIsRunning(self):
60               
61                is_mirror_running_inserver=self.lliurexcore.clientCheckingMirrorIsRunning()
62               
63                if is_mirror_running_inserver['ismirrorrunning'] ==None:
64                        log_msg="Checking if mirror in server is being updated. Error: " + str(is_mirror_running_inserver['exception'])
65                        self.log(log_msg)
66                else:
67                        if is_mirror_running_inserver['ismirrorrunning']:
68                                log_msg="Mirror is being udpated in server. Unable to update the system"
69                                self.log(log_msg)
70               
71                return is_mirror_running_inserver['ismirrorrunning']
72               
73                       
74        #def clientCheckingMirrorIsRunning             
75       
76        def initActionsScript(self,extra_args):
77
78                print("  [Lliurex-up]: Checking system")
79
80                if extra_args["unattendend_upgrade"]:
81                        command="DEBIAN_FRONTEND=noninteractive " + self.lliurexcore.initActionsScript(self.initActionsArg)
82               
83                else:
84                        command=self.lliurexcore.initActionsScript(self.initActionsArg)
85               
86                try:
87                       
88                        p=subprocess.Popen(command,shell=True,stderr=subprocess.PIPE)
89                        output=p.communicate()
90                        error=self.readErrorOutput(output[1])
91                        if error:
92                                log_msg="Exec Init-Actions. Error: %s"%output[1]
93                        else:
94                                log_msg="Exec Init-Actions. OK"
95                       
96                except Exception as e:
97                        log_msg="Exec Init-Actions.Error: " +str(e)
98                        print e
99                       
100                self.log(log_msg)       
101                       
102        #def initActionsScript
103       
104        def checkLliurexUp(self):
105
106                print("  [Lliurex-up]: Looking for new version of Lliurex Up")
107
108                is_lliurexup_updated=self.lliurexcore.isLliurexUpIsUpdated()
109
110
111                if not is_lliurexup_updated:
112                        print ("  [Lliurex-up]: Updating Lliurex Up")
113                        is_lliurexup_installed=self.lliurexcore.installLliurexUp()
114                        log_msg="Installing lliurex-up. Returncode: " + str(is_lliurexup_installed['returncode']) + ". Error: " + str(is_lliurexup_installed['stderrs'])
115                        self.log(log_msg)
116                        print ("  [Lliurex-up]: Lliurex Up is now udpate and will be reboot now" )
117                        time.sleep(3)
118                        self.lliurexcore.cleanLliurexUpLock()
119                        os.execv("/usr/sbin/lliurex-upgrade",sys.argv) 
120
121                else:
122                        log_msg="Checking lliurex-up. Is lliurex-up updated: "+ str(is_lliurexup_updated)
123                        self.log(log_msg)
124                        print ("  [Lliurex-up]: Lliurex Up is updated.Nothing to do")   
125                       
126        #def checkLliurexUp             
127
128        def checkMirror(self,extra_args=None):
129
130                print("  [Lliurex-up]: Checking if mirror is updated")
131
132                is_mirror_updated=self.lliurexcore.lliurexMirrorIsUpdated()
133
134                if is_mirror_updated !=None:
135                        is_mirror_running=self.lliurexcore.lliurexMirrorIsRunning()
136                        if is_mirror_running:
137                                print("  [Lliurex-up]: Updating mirror. Wait a moment please")
138                                command='lliurex-mirror update llx16'
139                                #os.system(command)
140                                subprocess.Popen(command,shell=True).communicate()
141
142                        else:
143                                if is_mirror_updated['action']=='update':
144                                        log_msg="Checking mirror. Is mirror update: False"
145                                        self.log(log_msg)
146                                        if not is_mirror_running:
147                                                if not extra_args["unattended_mirror"]:
148                                                        response=raw_input('  [LLiurex-up]: Do you want update mirror (yes/no): ').lower()
149                                                else:
150                                                        response="yes"
151
152                                                if response.startswith('y'):
153                                                        log_msg="Update lliurex-mirror: Yes"
154                                                        self.log(log_msg)
155                                                        print("  [Lliurex-up]: Updating mirror. Wait a moment please")
156                                                        command='lliurex-mirror update llx16'
157                                                        #os.system(command)
158                                                        subprocess.Popen(command,shell=True).communicate()
159
160                                                else:
161                                                        log_msg="Update lliurex-mirror: No"
162                                                        self.log(log_msg)
163                                                        print("  [Lliurex-up]: Mirror update.Nothing to do")           
164                else:
165                        log_msg="Checking mirror. Is mirror update: None"
166                        self.log(log_msg)
167                        print("  [Lliurex-up]: Nothing to do with mirror")
168                       
169        #def checkMirror               
170
171        def getLliurexVersionLocal(self):
172
173                print("  [Lliurex-up]: Looking for LliurexVersion from local repository")
174               
175                self.version_update=self.lliurexcore.getLliurexVersionLocal()
176                log_msg="Get LliurexVersion installed: " + str(self.version_update["installed"])
177                self.log(log_msg)
178                log_msg="Get LliurexVersion candidate from Local repository: " + str(self.version_update["candidate"])
179                self.log(log_msg)
180
181        #def getLliurexVersionLocal     
182       
183
184        def getLliurexVersionLliurexNet(self):
185       
186                print("  [Lliurex-up]: Looking for LliurexVersion from lliurex.net")
187
188                self.version_available=self.lliurexcore.getLliurexVersionLliurexNet()
189                log_msg="Get LliurexVersion candidate from Lliurex Net: " + str(self.version_available["candidate"])
190                self.log(log_msg)
191       
192        #def getLliurexVersionLliurexNet               
193
194        def checkingInitialFlavourToInstall(self):
195
196                print("  [Lliurex-up]: Checking if installation of metapackage is required")
197
198                self.returncode_initflavour=0
199
200                if self.targetMetapackage == None:
201                       
202                        print "  [Lliurex-up]: Installation of metapackage is not required"
203                       
204                else:
205                        print "  [Lliurex-up]: Installation of metapackage is required: " + str(self.targetMetapackage)
206                        is_flavour_installed=self.lliurexcore.installInitialFlavour(self.targetMetapackage)     
207                        self.returncode_initflavour=is_flavour_installed['returncode']
208                        error=is_flavour_installed['stderrs']
209                        log_msg="Install initial metapackage:" + self.targetMetapackage + ": Returncode: " + str(self.returncode_initflavour) + " Error: " + str(error)
210                        self.log(log_msg)
211                        print "  [Lliurex-up]: Metapackage is now installed: Returncode: " + str(self.returncode_initflavour) + " Error: " + str(error)
212                       
213        #def checkingInitialFlavourToInstall           
214       
215        def getPackagesToUpdate(self):
216
217                print("  [Lliurex-up]: Looking for new updates")
218                packages=self.lliurexcore.getPackagesToUpdate()
219                log_msg="Get packages to update. Number of packages: "+ str(len(packages))
220                self.log(log_msg)
221
222                self.newpackages=0
223                self.listpackages=""
224                if (len(packages))>0:
225                        for item in packages:
226                                if packages[item]["install"]==None:
227                                                self.newpackages=int(self.newpackages) + 1
228                                self.listpackages=str(self.listpackages) + item +" "           
229
230                return packages
231
232        #def getPackagesToUpdate               
233                       
234        def checkingIncorrectFlavours(self):
235               
236                incorrectFlavours=self.lliurexcore.checkIncorrectFlavours()
237                log_msg="Checking incorrect metapackages. Others metapackages detected: " + str(incorrectFlavours)
238                self.log(log_msg)
239
240                return incorrectFlavours
241       
242        #def checkingIncorrectFlavours         
243               
244        def checkPreviousUpgrade(self):
245               
246                error=False
247                if self.returncode_initflavour!=0:
248                        error=True
249
250                else:
251                        if self.version_update["candidate"]!=None:
252                                if self.version_update["installed"]!=self.version_update["candidate"]:
253                                        error=True
254                        else:
255                                if self.version_update["installed"]!=self.version_available["candidate"]:       
256                                        error=True
257
258                return error
259
260        #def checkPreviousUpgrade               
261
262        def preActionsScript(self,extra_args):
263
264                print("  [Lliurex-up]: Preparing system to update")
265
266                if extra_args["unattendend_upgrade"]:
267                        command="DEBIAN_FRONTEND=noninteractive " + self.lliurexcore.preActionsScript()
268                else:
269                        command=self.lliurexcore.preActionsScript()             
270               
271                try:
272                        #os.system(command)
273                        p=subprocess.Popen(command,shell=True,stderr=subprocess.PIPE)
274                        output=p.communicate()
275                        error=self.readErrorOutput(output[1])
276                        if error:
277                                log_msg="Exec Pre-Actions. Error: %s"%output[1]
278                        else:
279                                log_msg="Exec Pre-Actions. OK"
280
281                except Exception as e:
282                        log_msg="Exec Pre-Actions. Error " +str(e)
283                        print e
284
285                self.log(log_msg)       
286
287        #def preActionsScript                   
288
289        def distUpgrade(self,extra_args):
290
291                print("  [Lliurex-up]: Downloading and installing packages")
292
293                if extra_args["unattendend_upgrade"]:
294                        command="DEBIAN_FRONTEND=noninteractive " + self.lliurexcore.distUpgradeProcess()
295                else:
296                        command=self.lliurexcore.distUpgradeProcess()
297
298                try:
299                        #os.system(command)
300                        p=subprocess.Popen(command,shell=True,stderr=subprocess.PIPE)
301                        output=p.communicate()
302                        error=self.readErrorOutput(output[1])
303                        if error:
304                                log_msg="Exec Dist-upgrade. Error: %s"%output[1]
305                        else:
306                                log_msg="Exec Dist-upgrade. OK"
307               
308                except Exception as e:
309                        log_msg="Exec Dist-uggrade.Error : " +str(e)
310                        print e
311
312                self.log(log_msg)       
313                       
314        #def distUpgrade               
315
316        def postActionsScript(self,extra_args):
317
318                print("  [Lliurex-up]: Ending the update")
319
320                self.errorpostaction=False
321
322                if extra_args["unattendend_upgrade"]:
323                        command="DEBIAN_FRONTEND=noninteractive " + self.lliurexcore.postActionsScript() 
324                else:
325                        command=self.lliurexcore.postActionsScript()
326       
327                try:
328                        p=subprocess.Popen(command,shell=True,stderr=subprocess.PIPE)
329                        output=p.communicate()
330
331                        error=self.readErrorOutput(output[1])
332                        if error:
333                                self.errorpostaction=True
334                                log_msg="Exec Post-Actions. Error: %s"%output[1]
335                        else:
336                                log_msg="Exec Post-Actions.OK"
337
338                       
339                except Exception as e:
340                        self.errorpostaction=True
341                        log_msg="Exec Post-Actions.Error:%s"%e
342
343                self.log(log_msg)       
344
345        #def postActionsScript                 
346
347        def readErrorOutput(self,output):
348
349                cont=0
350                lines=output.split("\n")
351                for line in lines:
352                        if "E: " in line:
353                                cont=cont+1
354
355                if cont>0:
356                        return True
357                else:
358                        return False                   
359
360        #def readErrorOutput
361
362        def checkingFinalFlavourToInstall(self):
363               
364                print("  [Lliurex-up]: Checking final metapackage")
365                self.errorfinalmetapackage=False
366                #self.flavourToInstall=self.lliurexcore.checkFinalFlavour()
367                self.flavourToInstall=self.lliurexcore.checkFlavour()
368
369                log_msg="Final check metapackage. Metapackage to install:%s"%self.flavourToInstall
370                self.log(log_msg)
371               
372                if self.flavourToInstall!=None:
373                        print ("  [Lliurex-up]: Install of metapackage is required:%s"%self.flavourToInstall)
374                       
375                        if extra_args["unattendend_upgrade"]:
376                                command="DEBIAN_FRONTEND=noninteractive " + self.lliurexcore.installFinalFlavour(self.flavourToInstall)
377                        else:
378                                command=self.lliurexcore.installFinalFlavour(self.flavourToInstall)
379
380                        try:
381
382                                p=subprocess.Popen(command,shell=True,stderr=subprocess.PIPE)
383                                output=p.communicate()
384
385                                error=self.readErrorOutput(output[1])
386
387                                if error:
388                                        self.errorpostaction=True
389                                        log_msg="Final install metapackage. Error %s"%output[1]
390                                else:
391                                        log_msg="Final install metapackage.OK"
392
393
394                        except Exception as e:
395                                self.errorfinalmetapackage=True
396                                log_msg="Install of metapackage. Error:%s"%e
397
398                        self.log(log_msg)               
399                       
400                                       
401                else:
402                        print ("  [Lliurex-up]: Metapackage is correct. Nothing to do")
403                       
404        #def checkingFinalFlavourToInstall             
405                                       
406        def checkFinalUpgrade(self):
407
408                print("  [Lliurex-up]: Checking Dist-upgrade ")
409                error=self.lliurexcore.checkErrorDistUpgrade()
410
411                if error or self.errorfinalmetapackage or self.errorpostaction :
412                        print("  [Lliurex-up]: The updated process is endend with errors")
413                        log_msg="Dist-upgrade process ending with errors"
414               
415                else:                                   
416                        print("  [Lliurex-up]: The system is now update")       
417                        log_msg="Dist-upgrade process ending OK"
418               
419                self.log(log_msg)
420               
421        #def checkFinalUpgrade 
422
423        def handler_signal(self,signal,frame):
424               
425                print("\n  [Lliurex-up]: Cancel process with Ctr+c signal")
426                log_msg="Cancel process with Ctr+c signal"
427                self.log(log_msg)
428                self.lliurexcore.cleanEnvironment()
429                self.lliurexcore.cleanLliurexUpLock()
430                sys.exit(1)
431       
432        #def handler_signal
433
434        def log(self,msg):
435               
436                log_file="/var/log/lliurex-up.log"
437                f=open(log_file,"a+")
438                f.write(msg + '\n')
439                f.close()       
440       
441        #def log
442
443       
444        def main(self,mode,extra_args=None):
445
446                if mode=="sai":
447                        self.initActionsArg="initActionsSai"
448                       
449                else:
450                        mode="normal"
451                        self.initActionsArg="initActions"       
452
453                log_msg="Mode of execution: " + str(mode)
454                self.log(log_msg)
455                log_msg="Extra args: " + str(extra_args)
456                self.log(log_msg)
457                       
458                if not self.canConnectToLliurexNet():
459                        print("  [Lliurex-up]: Unable to connect to lliurex.net")
460                        self.lliurexcore.cleanEnvironment()
461                        self.lliurexcore.cleanLliurexUpLock()
462                        return 1
463                       
464                clientCheckingMirror=self.clientCheckingMirrorIsRunning()
465                if clientCheckingMirror!=False:
466                        if clientCheckingMirror:
467                                print("  [Lliurex-up]: Mirror is being udpated in server. Unable to update the system")
468                        else:
469                                print("  [Lliurex-up]: Unable to connect with server")
470
471                        self.lliurexcore.cleanEnvironment()
472                        self.lliurexcore.cleanLliurexUpLock()
473                        return 1
474                       
475                self.initActionsScript(extra_args)
476                self.checkLliurexUp()
477
478                if extra_args["mirror"]:
479                        self.checkMirror(extra_args)
480
481                self.getLliurexVersionLocal()
482                self.getLliurexVersionLliurexNet()
483                self.checkingInitialFlavourToInstall()
484                self.packages=self.getPackagesToUpdate()
485
486                if len(self.packages)>0:
487                        if not self.checkingIncorrectFlavours():
488                                print self.listpackages
489                                print("  [Lliurex-up]: Number of packages to update: " +  str(len(self.packages)) + " (" + str(self.newpackages) + " news)" )
490                                if not extra_args["unattendend_upgrade"]:
491                                        response=raw_input('  [LLiurex-up]: Do you want to update the system (yes/no)): ').lower()
492                                else:
493                                        response="yes"
494
495                                if response.startswith('y'):
496                                        self.preActionsScript(extra_args)
497                                        self.distUpgrade(extra_args)
498                                        self.postActionsScript(extra_args)
499                                        self.checkingFinalFlavourToInstall()   
500                                        self.checkFinalUpgrade()
501                                        self.lliurexcore.cleanEnvironment()
502                                        self.lliurexcore.cleanLliurexUpLock()
503
504
505                                else:
506                                        log_msg="Cancel the update"
507                                        self.log(log_msg)
508                                        print("  [Lliurex-up]: Cancel the update")
509                                        self.lliurexcore.cleanEnvironment()
510                                        self.lliurexcore.cleanLliurexUpLock()
511
512                                        return 0
513                        else:
514                                print("[Lliurex-up]: Updated abort for incorrect flavours detected in new update")
515                                self.lliurexcore.cleanEnvironment()
516                                self.lliurexcore.cleanLliurexUpLock()
517
518                                return 1                       
519                else:
520                        if not self.checkPreviousUpgrade():
521                                print("  [Lliurex-up]: Your system is updated. Nothing to do")
522                                self.lliurexcore.cleanEnvironment()
523                                self.lliurexcore.cleanLliurexUpLock()
524
525                                return 0
526                        else:
527                                print("  [Lliurex-up]: Updated abort. An error occurred checking new updates")
528                                self.lliurexcore.cleanEnvironment()
529                                self.lliurexcore.cleanLliurexUpLock()
530
531                                return 1
532        #def main                       
533                                       
534
535def     usage():
536        puts("Usage")
537        with indent(4):
538                puts("lliurex-upgrade [FLAGS...]")
539                puts("Flags")
540                with indent(4):
541                        puts("-h --help:                Show help")
542                        puts("-s --sai:         Update the system without pinning")     
543                        puts("-u --unattended:  Update the system in unattended mode. Does not require confirmation to update mirror and system")
544                        puts("-n --no-mirror:           Update the system without checking mirror")
545
546        sys.exit(1)             
547
548#def usage
549
550def free_space_check():
551               
552        if ((os.statvfs("/").f_bfree * os.statvfs("/").f_bsize) / (1024*1024*1024)) < 2: #less than 2GB available?
553                print "  [Lliurex-up]: There's not enough space on disk to upgrade (2 GB needed)"
554                       
555                sys.exit(1)
556
557#def free_space_check           
558
559def islliurexup_running():
560
561        if os.path.exists('/var/run/lliurexUp.lock'):
562                print "  [Lliurex-up]: Lliurex Up is now running "
563                sys.exit(1)
564
565#def isllliurexup_running
566
567
568if __name__ == '__main__':
569        if os.geteuid() != 0:
570                print "  [Lliurex-up]: You need be root!"
571                sys.exit(1)
572
573        islliurexup_running()
574        free_space_check()     
575        mode=None
576        options=0       
577        extra_args={}
578        extra_args["mirror"]=True
579        extra_args["unattended_mirror"]=False
580        extra_args["unattendend_upgrade"]=False
581
582        args=arguments.Args().copy
583       
584        if args.contains(["-h", "--help"]):
585                usage()
586       
587        if args.contains(["-s", "--sai"]):
588                mode="sai"
589                options=1
590
591        if args.contains(["-u", "--unattended"]):
592                extra_args["unattendend_upgrade"]=True
593                extra_args["unattended_mirror"]=True
594                options=1
595       
596        if args.contains(["-n", "--no-mirror"]):
597                extra_args["mirror"]=False
598                options=1
599        else:
600                if len(args)>0 and options==0:
601                        usage() 
602       
603        lliurexupcli = LliurexUpCli()   
604        sys.exit(lliurexupcli.main(mode,extra_args))
Note: See TracBrowser for help on using the repository browser.