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

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

Fix indicator script

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