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

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

Remove endsession functions

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