source: lliurex-up/trunk/fuentes/lliurex-up-indicator/usr/bin/lliurex-up-indicator @ 5624

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

WIP in indicator. Add endession scritp

  • Property svn:executable set to *
File size: 10.0 KB
Line 
1#!/usr/bin/env python
2
3import gi
4gi.require_version('Gtk', '3.0')
5from gi.repository import Gtk, Pango, GdkPixbuf, Gdk, Gio, GObject, GLib
6gi.require_version('AppIndicator3', '0.1')
7from gi.repository import AppIndicator3 as appindicator
8
9import os
10import subprocess
11import threading
12import notify2
13import sys
14import grp
15import re
16import time
17import multiprocessing
18
19from aptdaemon import client
20
21import pyinotify
22from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
23
24import signal
25signal.signal(signal.SIGINT, signal.SIG_DFL)
26
27
28import gettext
29gettext.textdomain('lliurex-up')
30_ = gettext.gettext
31
32
33
34RSRC="/usr/share/lliurex-up/"
35SP1=RSRC+"rsrc/sp1.png"
36SP2=RSRC+"rsrc/sp2.png"
37SP3=RSRC+"rsrc/sp3.png"
38SP4=RSRC+"rsrc/sp4.png"
39SP5=RSRC+"rsrc/sp5.png"
40
41TARGET_FILE="/var/run/lliurexUp.lock"
42LOCK_PATH="~/.config/lliurex-up-indicator"
43LOCK_TOKEN=os.path.join(LOCK_PATH,'llxUP_Indicator.lock')
44
45DISABLE_INDICATOR_TOKEN="/etc/lliurex-up-indicator/disableIndicator.token"
46
47
48
49class UpgradeIndicator:
50
51        ID="net.lliurex.UpIndicator"
52        GROUPS=["admins","adm"]
53        WATCH_DIR=os.path.expanduser("/var/run")
54
55        def __init__(self,icon_name):
56
57                self.isindicator_running()
58                self.createLockToken()
59
60                self.sp_cont=0
61                self.sp_img=0
62
63                self.FREQUENCY=3600
64                self.updatedInfo=False
65                self.remoteUpdateInfo=False
66                self.is_working=False
67                self.is_cache_updated=True
68                self.last_check=0
69
70                if os.path.exists(TARGET_FILE):
71                        self.lliurexUp_running=True
72                else:
73                        self.lliurexUp_running=False
74
75                self.menuMode()         
76               
77                self.app_indicator=appindicator.Indicator.new(UpgradeIndicator.ID,icon_name,appindicator.IndicatorCategory.APPLICATION_STATUS)
78                self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
79                self.menu = Gtk.Menu()
80               
81                self.menu.add_events(Gdk.EventMask.ALL_EVENTS_MASK)
82                self.app_indicator.set_menu(self.menu)
83               
84
85                self.populate_menu()
86                self.start_inotify()
87
88                if self.updatedInfo:
89                        self.fcache=Gio.File.new_for_path("/var/cache/apt/pkgcache.bin")
90                        self.mcache=self.fcache.monitor_file(Gio.FileMonitorFlags.NONE,None)
91                        self.mcache.connect("changed",self.on_cache_changed)
92
93                GLib.timeout_add_seconds(5, self.worker)
94
95        #def __init__   
96                       
97
98
99        def menuMode(self):
100
101                flavours=self.get_flavour()
102                users_group=self.get_user_group()
103
104                if users_group and 'client' not in flavours:
105                        self.updatedInfo=True
106                else:
107                        self.updateInfo=False                   
108
109
110        def worker(self):
111                """ Timeout thread """
112               
113                if(self.is_working==False):
114                        if self.lliurexUp_running: 
115                                self.is_alive()
116
117                        if not os.path.exists(os.path.expanduser(DISABLE_INDICATOR_TOKEN)):
118                                if self.updatedInfo:
119                                        if not self.remoteUpdateInfo:
120                                                if(self.is_cache_updated==True):
121                                                        self.upgrade()
122                                                        self.last_check=0
123                                                else:
124                                                        self.last_check+=5
125                                                        if(self.last_check>self.FREQUENCY):
126                                                                self.last_check=0
127                                                                self.upgrade() 
128
129                return True     
130
131        #def worker     
132
133        def get_flavour(self):
134
135                cmd='lliurex-version -v'
136                p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
137                result=p.communicate()
138                flavours = [ x.strip() for x in result[0].split(',') ] 
139               
140                return flavours
141
142        #def get_flavour                       
143       
144
145        def get_user_group(self):
146               
147                #check if the user is in the enabled group, otherwise the indicator is closed
148                user=os.environ["USER"]
149                group_found=False
150               
151                for g in grp.getgrall():
152                        if(g.gr_name in UpgradeIndicator.GROUPS):
153                                for member in g.gr_mem:
154                                        if(member==user):
155                                                group_found=True
156                                               
157                return group_found                             
158
159        #def get_user_group                                     
160                                       
161        def populate_menu(self):
162       
163
164                label_item=_("LliureX-Up is being executed")
165                item=Gtk.ImageMenuItem()
166                item.set_label(label_item)
167                img=Gtk.Image.new_from_file(SP1)
168                item.set_image(img)
169                item.set_always_show_image(True)
170                item.remote=True
171                self.menu.insert(item,0)
172
173                if self.updatedInfo:
174                        item=Gtk.ImageMenuItem()
175                        label_item=_("Update the system now")
176                        item.set_label(label_item)
177                        img=Gtk.Image()
178                        #img.set_from_stock(Gtk.STOCK_PREFERENCES,Gtk.IconSize.MENU)
179                        img.set_from_icon_name("software-properties",Gtk.IconSize.MENU)
180                        item.set_image(img)
181                        item.set_always_show_image(True)
182                        item.connect("activate",self.open_gui)
183                        item.remote=False
184                        self.menu.insert(item,1)
185
186        #def populate_menu             
187
188        def start_inotify(self):
189
190                t=threading.Thread(target=self._inotify)
191                t.daemon=True
192                t.start()               
193
194        #def start_inotify     
195
196        def _inotify(self):
197               
198               
199                wm=WatchManager()
200                mask=pyinotify.IN_CREATE
201                       
202                class Process_handler(ProcessEvent):
203                               
204                        def __init__(self,main):
205                               
206                                self.main=main
207                               
208                        def process_IN_CREATE(self,event):
209
210                                if os.path.expanduser(event.pathname)=='/var/run/lliurexUp.lock':
211                                        self.main.lliurexUp_running=True
212                               
213       
214                notifier=Notifier(wm,Process_handler(self))
215                wdd=wm.add_watch(UpgradeIndicator.WATCH_DIR,mask,rec=True)
216                       
217                while True:
218                        try:
219                                       
220                                notifier.process_events()
221                                if notifier.check_events():
222                                        notifier.read_events()
223                               
224                        except Exception as e:
225                                notifier.stop()
226                                       
227                return False   
228
229        #def _inotify   
230
231        def remote_execute(self):
232
233                cont=0
234                remote_pts=[]
235                remote_users=[]
236                isrunning=[]
237                remote_executing=False
238
239                cmd='who | grep -v "(:0"'
240                p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
241                result=p.communicate()
242                remote_users=[ x.strip() for x in result[0].split('\n') ]
243                remote_users.pop()
244
245                for item in remote_users:
246                        tmp=re.search('(pts/\w)',item)
247                        try:
248                                remote_pts.append(tmp.group(1))
249                        except Exception as e:
250                                pass
251
252
253                cmd='ps -ef | grep "lliurex-upgrade" | grep -v "grep"'
254                p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
255                result=p.communicate()
256                isrunning= [ x.strip() for x in result[0].split('\n') ]
257                isrunning.pop()
258
259
260                for item in isrunning:
261                        if '?' in item:
262                                cont=cont+1
263                        for t in remote_pts:
264                                if t in item:
265                                        cont=cont+1
266
267                if cont>0:
268                        remote_executing=True
269
270                return remote_executing                         
271
272        #def remote_execute     
273
274        def is_alive(self):
275
276                #if os.path.exists(TARGET_FILE):
277                self.is_working=True
278
279                self.checkRemote=self.remote_execute()
280                self.remoteUpdateInfo=True
281
282                if self.checkRemote:
283                        self.menu.show_all()
284                        for item in self.menu.get_children():
285                                if not item.remote:
286                                        item.set_visible(False)
287                        self.app_indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
288                               
289                else:
290                        self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
291
292                GLib.timeout_add(100,self.check_status) 
293                               
294                return
295
296        #def is_alive   
297               
298        def check_status(self):
299
300                if os.path.exists(TARGET_FILE):
301                        if self.checkRemote:
302                                self.spinner_sync()
303                                for item in self.menu.get_children():
304                                        if item.remote:
305                                        #item=self.menu.get_children()[0]
306                                                item.set_image(self.sp_img)
307                                                self.sp_cont=self.sp_cont+1     
308                        return True
309                       
310                else:
311                        if self.checkRemote:
312                                img=Gtk.Image.new_from_file(SP1)
313                                for item in self.menu.get_children():
314                                        if item.remote:
315                                                item.set_image(img)
316                       
317                                message=_("The upgrade process has ended")
318                                self.show_message(message)
319                                self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
320                                time.sleep(2)
321
322                        self.remoteUpdateInfo=False
323                        self.lliurexUp_running=False
324                        self.is_working=False
325               
326                        return False           
327
328        #def check_status       
329       
330        def spinner_sync(self):
331       
332                if self.sp_cont>50:
333                        self.sp_cont=0
334                       
335                if self.sp_cont==0:
336                        img=Gtk.Image.new_from_file(SP1)
337                        self.sp_img=img
338                elif self.sp_cont==10:
339                        img=Gtk.Image.new_from_file(SP2)
340                        self.sp_img=img                 
341                elif self.sp_cont==20:
342                        img=Gtk.Image.new_from_file(SP3)
343                        self.sp_img=img
344                elif self.sp_cont==30:
345                        img=Gtk.Image.new_from_file(SP4)
346                        self.sp_img=img
347                elif self.sp_cont==40:
348                        img=Gtk.Image.new_from_file(SP5)
349                        self.sp_img=img
350                               
351        #def spinner_sync               
352
353
354
355        def on_cache_changed(self,monitor,file,other,type):
356                """Apt cache notification event"""
357       
358               
359                if(type==Gio.FileMonitorEvent.CHANGES_DONE_HINT and self.last_check>120): #ignore cache updates at intervals smaller than 2 minutes
360                        self.is_cache_updated=True
361                       
362       
363        #def on_cache_changed
364
365
366        def upgrade(self):
367                """
368                Performs an upgrade simulation.
369                Cache will be updated if needed.
370                """
371       
372                self.is_working=True
373
374               
375                apt_client=client.AptClient()
376               
377                if(self.is_cache_updated==False):
378                        apt_client.update_cache(wait=True)
379                        self.is_cache_updated=True
380                       
381                transaction=apt_client.upgrade_system()
382
383                transaction.simulate()
384                #this sync is needed in order to update transaction properties after simulation
385                #credits go to Lubuntu Team as this is completly undocumented :)
386                transaction.sync()
387
388
389                #transaction dependencies []
390                # install reinstall remove purge upgrade downgrade
391               
392                packages=[]
393               
394                for d in transaction.dependencies:
395                        for p in d:
396                                packages.append(d)
397               
398               
399               
400                if(len(packages)>0):
401                        self.menu.show_all()
402                        for item in self.menu.get_children():
403                                if item.remote:
404                                                item.set_visible(False)
405
406                        self.app_indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
407
408                        message=_("There are new packages ready to be updated or installed")
409                        self.show_message(message)
410                                               
411               
412                self.is_working=False
413                self.is_cache_updated=False
414       
415        #def upgrade
416
417        def show_message(self,message):
418
419                p=multiprocessing.Process(target=self._show_message,args=(message,))
420                p.daemon=True
421                p.start()
422
423        #def show_message
424
425        def _show_message(self,message):
426               
427                notify2.init(UpgradeIndicator.ID)
428
429                n=notify2.Notification("LliureX-Up",message,"lliurex-up")
430                n.show()
431
432                return
433
434        #def _show_message     
435
436        def open_gui(self,widget):
437               
438                if not os.path.exists(TARGET_FILE):
439                        self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
440                        cmd='gksu lliurex-up' + "&"
441                        os.system(cmd)
442
443        #def open_gui           
444
445        def isindicator_running(self):
446
447                lock_file=os.path.expanduser(LOCK_TOKEN)
448                if os.path.exists(lock_file):
449                        sys.exit(1)
450                       
451
452        def createLockToken(self):
453
454                lock_file=os.path.expanduser(LOCK_TOKEN)
455
456
457                if not os.path.exists(lock_file):
458                        lock_folder=os.path.expanduser(LOCK_PATH)
459                        if not os.path.exists(lock_folder):
460                                os.mkdir(lock_folder)
461
462                        f=open(lock_file,'w')
463                        f.close         
464
465
466        def launch_endsession(self):
467               
468                os.system("/usr/bin/lliurex-up-indicator-endsession")   
469               
470
471        def quit(self):
472
473                Gtk.main_quit() 
474
475        #def quit       
476       
477#class UpgradeIndicator
478
479if __name__=="__main__":
480
481
482        lliurexup=UpgradeIndicator("lliurex-up")
483        lliurexup.launch_endsession()
484        GObject.threads_init()
485        Gtk.main()
Note: See TracBrowser for help on using the repository browser.