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

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

WIP in added support to manage EULA

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