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

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

Fix endsession functions

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