source: epi/trunk/fuentes/python3-epi/epimanager.py @ 7241

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

Improved the checking of the installation status of the packages

File size: 14.5 KB
Line 
1#!/usr/bin/env python3
2
3import os
4import subprocess
5import sys
6import json
7import platform
8#import socket
9import tempfile
10import time
11import datetime
12import urllib.request
13
14import lliurexstore.storeManager as StoreManager
15
16
17class EpiManager:
18       
19        def __init__(self):
20
21
22                self.storeManager=StoreManager.StoreManager()
23                self.reposPath="/etc/apt/sources.list.d/"
24                self.sources_list="epi.list"
25                self.epi_sources=os.path.join(self.reposPath,self.sources_list)
26                self.epi_keyring="/tmp/epi_keyring"
27                                               
28                self.order=0
29                self.epiFiles={}
30                self.arquitecture=False
31                self.update=False
32                self.zomando_name={}
33                self.epi_base={"repository":[],
34                                        "force32" : False,
35                                        "required_x" : False,
36                                        "script": {},
37                                        "depends":"",
38                                        "zomando":"",
39                                        "required_root":False
40                                        }
41
42                #self.read_conf(epi_file)
43       
44               
45        #def __init__   
46
47       
48        def check_connection(self):
49       
50                try:
51                        res=urllib.request.urlopen("http://lliurex.net")
52                        return True
53                       
54                except:
55                        return False   
56
57        #def check_connection   
58
59        def read_conf(self,epi_file):
60
61
62                if os.path.exists(epi_file):
63                        f=open(epi_file)
64                        epi_load=json.load(f)
65                        epi_conf=self.epi_base.copy()
66                        f.close()
67                        epi_conf.update(epi_load)
68                        self.epiFiles[self.order]=epi_conf
69                        self.zomando_name[self.order]=epi_conf["zomando"]
70                        try:
71                                if epi_conf["depends"]!="":
72                                        self.order=self.order+1
73                                        self.read_conf(epi_conf["depends"])
74                        except :
75                                pass           
76
77        #def read_conf         
78
79
80        def get_pkg_info(self):
81
82                pkg_list=[]
83                self.pkg_info={}
84                tmp_list=self.epiFiles.copy()
85
86                for item in tmp_list:
87                        pkg_list=[]
88                        pkg_list=tmp_list[item]["pkg_list"]
89                       
90                        info=self.get_store_info(pkg_list,item)
91
92                        cont=0
93
94                        for element in pkg_list:
95                                name=element["name"]
96                                if info[name]["status"]=="installed":
97                                        cont=cont+1
98
99                        if cont==len(pkg_list):
100                                if item>0:
101                                        self.epiFiles.pop(item)
102                                        self.zomando_name.pop(item)
103                                else:
104                                        self.epiFiles[item]["status"]="installed"
105                                        self.pkg_info.update(info)
106                        else:
107                                self.epiFiles[item]["status"]="availabled"
108                                self.pkg_info.update(info)     
109
110        #def get_pkg_info                               
111                                                       
112
113        def get_store_info(self,pkg_list,order):                       
114
115                        self.getStatus_byscript=False
116                        pkg_info={}
117                                               
118                        for item in pkg_list:
119                                app=item["name"]
120                                name=""
121                                summary=""
122                                status=""
123                                description=""
124                                icon=""
125                                debian_name=""
126                                component=""
127                                try:
128                                        pkg=item["key_store"]
129                                        action="info"
130                                        self.storeManager.execute_action(action,pkg)
131                                        while self.storeManager.is_action_running(action):
132                                                time.sleep(0.2)
133
134                                        ret=self.storeManager.get_status(action)
135
136                                        if ret["status"]==0:
137                                                data=self.storeManager.get_result(action)
138
139                                                if len(data)>0:
140
141                                                        description=data["info"][0]["description"]
142                                                        icon=data["info"][0]["icon"]
143                                                        name=data["info"][0]["name"]
144                                                        summary=data["info"][0]["summary"]
145                                                        debian_name=data["info"][0]["package"]
146                                                        component=data["info"][0]["component"]
147
148                                                        status=self.check_pkg_status(app,order)
149                                                        if not self.getStatus_byscript and status!="installed":
150                                                                if (data["info"][0]["state"]) !="":
151                                                                        status=data["info"][0]["state"]
152
153                                                else:
154                                                        status=self.check_pkg_status(app,order)         
155                                        else:
156                                                status=self.check_pkg_status(app,order) 
157                               
158                                except:
159                                        status=self.check_pkg_status(app,order) 
160                                                       
161                               
162                                pkg_info[app]={}
163                                pkg_info[app]["debian_name"]=debian_name
164                                pkg_info[app]["component"]=component
165                                pkg_info[app]["status"]=status
166                                pkg_info[app]["description"]=description
167                                pkg_info[app]["icon"]=icon
168                                pkg_info[app]["name"]=name
169                                pkg_info[app]["summary"]=summary
170
171                        return pkg_info
172
173        #def get_store_info                     
174
175        def check_pkg_status(self,pkg,order=None):
176       
177
178                try:
179                        if self.epiFiles[order]["script"]["getStatus"]:
180                                self.getStatus_byscript=True
181                except:
182                        pass
183
184                if self.getStatus_byscript:
185                        if order !=None:
186                                try:
187                                        script=self.epiFiles[order]["script"]["name"]
188                                        if os.path.exists(script):
189                                                cmd=script +' getStatus ' + pkg;
190                                                p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
191                                                poutput=p.communicate()
192                                                if len(poutput)>0:
193                                                        if poutput[0].decode("utf-8").split("\n")[0]=='0':
194                                                                return "installed"
195                                               
196                                except Exception as e:
197                                        self.getStatus_byscript=False
198                                        #print (str(e))
199                                        pass
200                else:                                   
201
202                        cmd='dpkg -l '+ pkg + '| grep "^i[i]"'
203                        p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
204                        poutput,perror=p.communicate()
205
206                        if len(poutput)>0:
207                                return "installed"
208               
209                               
210                return "available"     
211
212        #def check_pkg_status                                   
213               
214        def check_root(self):
215
216                self.root=False
217
218                try:
219                        f=open("/etc/epi.token","w")
220                        f.close()
221                        os.remove("/etc/epi.token")
222                        self.download_path="/var/cache/epi-downloads"
223                        self.root=True
224                except:
225                        if not os.path.exists(os.path.expanduser("~/.cache/epi-downloads/")):
226                                os.mkdir(os.path.expanduser("~/.cache/epi-downloads/"))
227                        self.download_path=os.path.expanduser("~/.cache/epi-downloads/")
228
229        #def check_root         
230
231
232        def required_root (self):
233
234                cont=0
235
236                if not self.root:
237                        for item in self.epiFiles:
238                                if self.epiFiles[item]["type"]!="file":
239                                        cont=cont+1
240
241                                else:
242                                        if self.epiFiles[item]["required_root"]:
243                                                cont=cont+1
244                                                       
245                        if cont>0:
246                                return True
247                        else:
248                                return False   
249
250                else:
251                        return False           
252
253        #def required_root             
254
255
256       
257        def check_update_repos(self):
258               
259                #Only update repos if needed
260                current_date=datetime.date.today().strftime('%y%m%d')
261                filename='/var/cache/apt/pkgcache.bin'
262                lastmod=os.path.getmtime(filename)
263                lastupdate=datetime.datetime.fromtimestamp(lastmod).strftime('%y%m%d')
264                cmd=""
265
266                if current_date !=lastupdate or self.update:
267                        cmd="LANG=C LANGUAGE=en apt-get update; "
268                else:
269                        for item in self.epi_conf["pkg_list"]:
270                                update_repo=False
271                                app=item["name"]
272                                command="LANG=C LANGUAGE=en apt-cache policy %s"%app
273                                p=subprocess.Popen(command,shell=True, stdout=subprocess.PIPE)
274                                output=p.communicate()
275                                if str(output[0]) != '':
276                                        tmp=str(output[0]).split("\\n")
277                                        if len(tmp)>1:
278                                                if tmp[2].split(":")[1]=="":
279                                                        update_repo=True
280                                                       
281                                        else:
282                                                update_repo=True
283                                               
284
285                                else:
286                                        update_repo=True
287
288                                if update_repo: 
289                                        cmd="LANG=C LANGUAGE=en apt-get update; "
290                                        return cmd             
291
292                return cmd
293               
294        #def check_update_repos
295
296        def check_arquitecture(self):
297
298                self.force32=self.epi_conf['force32']
299                cmd=""
300               
301                if self.force32:
302                        if platform.architecture()[0]=='64bit':
303                                cmd='dpkg --add-architecture i386; '
304                                                               
305                self.arquitecture=True
306                return cmd             
307
308        #def check_arquitecture
309       
310        def add_repository_keys(self,order):
311
312                self.epi_conf=self.epiFiles[order]
313
314                cmd=""
315                self.type=self.epi_conf["type"]
316
317                if self.type=="apt":
318
319                        repos_list=self.epi_conf["repository"]
320
321                        if len(repos_list)>0:
322                                f = open(self.epi_sources,'w')
323                                for item in repos_list:
324                                        if item["url"]!="":
325                                                lines=item["url"].split(";")
326                                                for line in lines:
327                                                        f.write(line+'\n')
328                                        try:
329                                                key_cmd=item["key_cmd"]
330                                                if key_cmd !="":
331                                                        cmd=cmd+key_cmd+';'     
332                                        except Exception as e:
333                                                if len(self.epi_conf["script"])>0:
334                                                        try:
335                                                                if self.epi_conf["script"]["addRepoKeys"]:
336                                                                        script=self.epi_conf["script"]["name"]
337                                                                        if os.path.exists(script):
338                                                                                command=script + ' addRepoKeys;'
339                                                                                cmd=cmd+command
340                                                        except Exception as e:
341                                                                #print (str(e))
342                                                                pass
343
344                                f.close()
345                                self.update=True
346
347                       
348                return cmd             
349
350        #def add_repository_keys       
351
352
353        def get_app_version(self,item=None):
354
355                self.force32=self.epi_conf["force32"]
356
357                if self.force32:
358                        version=item["version"]["32b"]
359                       
360                else:
361                        try:
362                                version=item["version"]["all"]
363                        except Exception as e:
364                                if platform.architecture()[0]=='64bit': 
365                                        version=item["version"]["64b"]
366                                else:
367                                        version=item["version"]["32b"]
368                       
369                return version
370
371        #def get_app_version   
372                                               
373        def download_app(self):
374
375                self.manage_download=True
376                self.download_folder={}
377                cmd=""
378
379                self.type=self.epi_conf["type"]
380                if self.type !='apt':
381
382                        self.token_result_download=tempfile.mkstemp("_result_download")
383                       
384                        if self.type=="file":
385                                if len(self.epi_conf["script"])>0:
386                                        try:
387                                                if self.epi_conf["script"]["download"]:
388                                                        script=self.epi_conf["script"]["name"]
389                                                        if os.path.exists(script):
390                                                                cmd=script +' download; echo $? >' + self.token_result_download[1] +';'
391                                                                self.manage_download=False
392                                        except:
393                                                pass                   
394
395                        if self.manage_download:
396
397                                for item in self.epi_conf["pkg_list"]:
398                                        version=self.get_app_version(item)
399                                        if self.type=="deb":
400                                                name=item["name"]+".deb"
401                                                tmp_file=os.path.join(self.download_path,name)
402                                        else:
403                                                try:
404                                                        tmp_file=os.path.join(self.download_path,item["alias_download"])
405                                                except Exception as e: 
406                                                        #name=item["name"]
407                                                        tmp_file=os.path.join(self.download_path,version)
408                               
409                                        url=item["url_download"]
410                                       
411                                        if os.path.exists(tmp_file):
412                                                cmd=cmd+'rm -f '+ tmp_file +';'
413                                        self.download_folder["name"]=tmp_file
414                                        cmd=cmd+'wget ' +url+version + ' --progress=bar:force -O ' + tmp_file +'; '
415
416                                cmd=cmd + ' echo $? >' + self.token_result_download[1] +';'     
417                       
418
419                return cmd                     
420                                       
421        #def download_app               
422
423
424        def check_download(self):
425
426               
427                result=True
428
429                if self.type !='apt':
430
431                       
432                        if os.path.exists(self.token_result_download[1]):
433                                file=open(self.token_result_download[1])
434                                content=file.readline()
435                                if '0' not in content:
436                                        result=False
437                                file.close()
438                                os.remove(self.token_result_download[1])
439
440                                if result:     
441                                        if self.manage_download:
442                                                pkgs_todownload=len(self.download_folder)
443                                                cont=0
444
445                                                for item in self.download_folder:
446                                                        if os.path.exists(self.download_folder[item]):
447                                                                cont=cont+1
448
449                                                if cont != pkgs_todownload:
450                                                        result=False
451
452                return result
453
454        #def check_download             
455
456        def preinstall_app(self):
457       
458
459                cmd=""
460
461                if len(self.epi_conf["script"])>0:
462                        self.token_result_preinstall=tempfile.mkstemp("_result_preinstall")
463                        script=self.epi_conf["script"]["name"]
464                        if os.path.exists(script):
465                                cmd=script +' preInstall; echo $? >' + self.token_result_preinstall[1] +';'
466
467                return cmd             
468
469        #def preinstall_app     
470       
471
472        def check_preinstall(self):
473               
474                result=True
475
476                try:
477                        if os.path.exists(self.token_result_preinstall[1]):
478                                file=open(self.token_result_preinstall[1])
479                                content=file.readline()
480                                if '0' not in content:
481                                        result=False
482                                file.close()
483                                os.remove(self.token_result_preinstall[1])
484
485                except:                 
486                        pass
487
488                return result
489
490
491        #def check_preinstall_app       
492
493        def install_app(self):
494       
495                add_i386=""
496               
497                if not self.arquitecture:
498                        add_i386=self.check_arquitecture()
499
500
501                cmd=""
502               
503                if self.type=="apt":
504
505                        update_repos=self.check_update_repos()
506                        cmd=update_repos+add_i386 + "LANG=C LANGUAGE=en DEBIAN_FRONTEND=noninteractive apt-get install --reinstall --allow-downgrades --allow-remove-essential --allow-change-held-packages --yes "
507                        for item in self.epi_conf["pkg_list"]:
508                                app=item["name"]
509                                cmd=cmd + app +" "
510
511       
512                       
513                elif self.type=="deb":
514                       
515                        cmd=add_i386 + "dpkg -i "
516                        for item in self.epi_conf["pkg_list"]:
517                                name=item["name"]+".deb"
518                                pkg=self.download_folder["name"]
519                                cmd=cmd+pkg +" "
520
521                       
522                else:
523                        self.token_result_install=tempfile.mkstemp("_result")
524                        script=self.epi_conf["script"]["name"]
525                        if os.path.exists(script):
526                                cmd=script + ' installPackage; echo $? >' + self.token_result_install[1]
527
528                cmd=cmd+";"
529                return cmd     
530
531        #def install_app       
532
533
534        def check_install_remove(self,action):
535
536                dpkg_status={}
537                cont=0
538                token=""
539               
540                if action=="install":
541                               
542                        if self.type !="file":
543                                pkgs=self.epi_conf["pkg_list"]
544                       
545                                for item in pkgs:
546                                        status=self.check_pkg_status(item["name"])
547                               
548                                        if status=="installed":
549                                                cont=cont+1
550                               
551                                        dpkg_status[item["name"]]=status
552
553                                if cont==len(pkgs):
554                                        result=True
555               
556                                else:
557                                        result=False
558
559                        else:
560                                token=self.token_result_install[1]     
561                                if os.path.exists(token):
562                                        file=open(token)
563                                        content=file.readline()
564                                        if '0' not in content:
565                                                result=False
566                                        else:
567                                                result=True     
568                                                                               
569                                        file.close()
570                                        os.remove(token)
571
572                else:
573               
574                        if self.epiFiles[0]["type"] !="file":
575                                        pkgs=self.epiFiles[0]["pkg_list"]                       
576                                        for item in pkgs:
577                                                status=self.check_pkg_status(item["name"])
578                                                if status!="installed":
579                                                        cont=cont+1
580                                                dpkg_status[item["name"]]=status
581
582               
583                        token=self.token_result_remove[1]
584                        if os.path.exists(token):
585                                        file=open(token)
586                                        content=file.readline()
587                                        if '0' not in content:
588                                                result=False
589                                        else:
590                                                result=True     
591                                                       
592                                        file.close()
593                                        os.remove(token)
594
595                return dpkg_status,result                       
596
597       
598               
599        #def check_install_remove       
600
601        def postinstall_app(self):
602       
603
604                cmd=""
605               
606                if len(self.epi_conf["script"])>0:
607                        self.token_result_postinstall=tempfile.mkstemp("_result_postinstall")
608                        script=self.epi_conf["script"]["name"]
609                        if os.path.exists(script):
610                                cmd=script + ' postInstall; echo $? >' + self.token_result_postinstall[1] +';'
611
612                return cmd     
613
614        #def postinstall_app   
615       
616        def check_postinstall(self):
617               
618                result=True
619
620                try:
621                        if os.path.exists(self.token_result_postinstall[1]):
622                                file=open(self.token_result_postinstall[1])
623                                content=file.readline()
624                                if '0' not in content:
625                                        result=False
626                                file.close()
627                                os.remove(self.token_result_postinstall[1])
628                except:
629                        pass                   
630
631                return result
632
633        #def check_postinstall 
634
635        def remove_repo_keys(self):
636       
637                if os.path.exists(self.epi_sources):
638                        os.remove(self.epi_sources)     
639
640                if os.path.exists(self.epi_keyring):
641                        os.remove(self.epi_keyring)     
642
643        #def remove_repo_keys   
644
645        def uninstall_app(self,order):
646
647                cmd=""
648
649                if self.epiFiles[order]["script"]["remove"]:
650                        self.token_result_remove=tempfile.mkstemp("_result_remove")
651                        script=self.epiFiles[order]["script"]["name"]
652                        if os.path.exists(script):
653                                cmd=script + ' remove; echo $? >' + self.token_result_remove[1] + ';'
654
655                return cmd
656
657        #def uninstall_app     
658
659        def zerocenter_feedback(self,order,action,result=None):
660
661                zomando_name=self.zomando_name[order]
662
663                if zomando_name!="":
664                        if action=="init":
665                                cmd="zero-center add-pulsating-color " +zomando_name
666                        elif action=="install":
667                                if result:
668                                        cmd="zero-center remove-pulsating-color "+zomando_name + " ;zero-center set-configured " +zomando_name
669                                       
670                                else:
671                                        cmd="zero-center remove-pulsating-color "+zomando_name + " ;zero-center set-failed " +zomando_name
672                        elif action=="uninstall":
673                                if result:
674                                        cmd="zero-center remove-pulsating-color "+zomando_name + " ;zero-center set-non-configured " +zomando_name
675                                else:
676                                        cmd="zero-center remove-pulsating-color "+zomando_name + " ;zero-center set-failed " +zomando_name
677
678                        os.system(cmd)         
679
680        #def zero-center_feedback       
681
682
683#class ApplicationInstallerManager
684
685
686if __name__=="__main__":
687       
688        epi=EpiManager()
Note: See TracBrowser for help on using the repository browser.