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

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

Fix indicator

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