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, 2 years ago

Fix indicator script

  • Property svn:executable set to *
File size: 11.6 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 syslog
22import dbus
23from dbus.mainloop.glib import DBusGMainLoop
24
25
26import pyinotify
27from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
28
29import signal
30signal.signal(signal.SIGINT, signal.SIG_DFL)
31
32
33import gettext
34gettext.textdomain('lliurex-up')
35_ = gettext.gettext
36
37
38
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"
47LOCK_PATH="~/.config/lliurex-up-indicator"
48LOCK_TOKEN=os.path.join(LOCK_PATH,'llxUP_Indicator.lock')
49
50DISABLE_INDICATOR_TOKEN="/etc/lliurex-up-indicator/disableIndicator.token"
51
52
53
54class UpgradeIndicator:
55
56        ID="net.lliurex.UpIndicator"
57        GROUPS=["admins","adm"]
58        WATCH_DIR=os.path.expanduser("/var/run")
59
60        def __init__(self,icon_name):
61
62                self.isindicator_running()
63                self.createLockToken()
64               
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
75                if os.path.exists(TARGET_FILE):
76                        self.lliurexUp_running=True
77                else:
78                        self.lliurexUp_running=False
79
80                self.menuMode()         
81               
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
100                self.launch_endsession()
101
102        #def __init__   
103                       
104
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
117        def worker(self):
118                """ Timeout thread """
119               
120                if(self.is_working==False):
121                        if self.lliurexUp_running: 
122                                self.is_alive()
123
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()
129                                                        self.last_check=0
130                                                else:
131                                                        self.last_check+=5
132                                                        if(self.last_check>self.FREQUENCY):
133                                                                self.last_check=0
134                                                                self.upgrade() 
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()
145                flavours = [ x.strip() for x in result[0].split(',') ] 
146               
147                return flavours
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"]
156                group_found=False
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):
162                                                group_found=True
163                                               
164                return group_found                             
165
166        #def get_user_group                                     
167                                       
168        def populate_menu(self):
169       
170
171                label_item=_("LliureX-Up is being executed")
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
180                if self.updatedInfo:
181                        item=Gtk.ImageMenuItem()
182                        label_item=_("Update the system now")
183                        item.set_label(label_item)
184                        img=Gtk.Image()
185                        #img.set_from_stock(Gtk.STOCK_PREFERENCES,Gtk.IconSize.MENU)
186                        img.set_from_icon_name("software-properties",Gtk.IconSize.MENU)
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=[]
242                remote_users=[]
243                isrunning=[]
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
260                cmd='ps -ef | grep "lliurex-upgrade" | grep -v "grep"'
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
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)
295                               
296                else:
297                        self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
298
299                GLib.timeout_add(100,self.check_status) 
300                               
301                return
302
303        #def is_alive   
304               
305        def check_status(self):
306
307                if os.path.exists(TARGET_FILE):
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     
315                        return True
316                       
317                else:
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)
323                       
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
329                        self.remoteUpdateInfo=False
330                        self.lliurexUp_running=False
331                        self.is_working=False
332               
333                        return False           
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
415                        message=_("There are new packages ready to be updated or installed")
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
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):
474
475                syslog.syslog("iniciando")
476                DBusGMainLoop(set_as_default=True)
477                self.session_bus = dbus.SessionBus()
478               
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)
498               
499                proxy.connect_to_signal("QueryEndSession",self.on_query_end_session)
500               
501                #os.system("/usr/bin/lliurex-up-indicator-endsession &")
502
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
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")
539        #lliurexup.launch_endsession()
540        GObject.threads_init()
541        Gtk.main()
Note: See TracBrowser for help on using the repository browser.