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

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

Fix

  • Property svn:executable set to *
File size: 9.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 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"
48
49DISABLE_INDICATOR_TOKEN="/etc/lliurex-up-indicator/disableIndicator.token"
50
51
52
53class UpgradeIndicator:
54
55        ID="net.lliurex.UpIndicator"
56        GROUPS=["admins","adm"]
57        WATCH_DIR=os.path.expanduser("/var/run")
58
59        def __init__(self,icon_name):
60
61
62                self.sp_cont=0
63                self.sp_img=0
64
65                self.FREQUENCY=3600
66                self.updatedInfo=False
67                self.remoteUpdateInfo=False
68                self.is_working=False
69                self.is_cache_updated=True
70                self.last_check=0
71
72                if os.path.exists(TARGET_FILE):
73                        self.lliurexUp_running=True
74                else:
75                        self.lliurexUp_running=False
76
77                self.menuMode()         
78               
79                self.app_indicator=appindicator.Indicator.new(UpgradeIndicator.ID,icon_name,appindicator.IndicatorCategory.APPLICATION_STATUS)
80                self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
81                self.menu = Gtk.Menu()
82               
83                self.menu.add_events(Gdk.EventMask.ALL_EVENTS_MASK)
84                self.app_indicator.set_menu(self.menu)
85               
86                Notify.init(UpgradeIndicator.ID)
87
88                self.populate_menu()
89                self.start_inotify()
90
91                if self.updatedInfo:
92                        self.fcache=Gio.File.new_for_path("/var/cache/apt/pkgcache.bin")
93                        self.mcache=self.fcache.monitor_file(Gio.FileMonitorFlags.NONE,None)
94                        self.mcache.connect("changed",self.on_cache_changed)
95
96                GLib.timeout_add_seconds(5, self.worker)
97
98        #def __init__   
99                       
100
101
102        def menuMode(self):
103
104                flavours=self.get_flavour()
105                users_group=self.get_user_group()
106
107                if users_group and 'client' not in flavours:
108                        self.updatedInfo=True
109                else:
110                        self.updateInfo=False                   
111
112        #def menuMode           
113
114        def worker(self):
115                """ Timeout thread """
116               
117                if(self.is_working==False):
118                        if self.lliurexUp_running: 
119                                self.is_alive()
120
121                        if not os.path.exists(os.path.expanduser(DISABLE_INDICATOR_TOKEN)):
122                                if self.updatedInfo:
123                                        if not self.remoteUpdateInfo:
124                                                if(self.is_cache_updated==True):
125                                                        self.upgrade()
126                                                        self.last_check=0
127                                                else:
128                                                        self.last_check+=5
129                                                        if(self.last_check>self.FREQUENCY):
130                                                                self.last_check=0
131                                                                self.upgrade() 
132
133                return True     
134
135        #def worker     
136
137        def get_flavour(self):
138
139                cmd='lliurex-version -v'
140                p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
141                result=p.communicate()
142                flavours = [ x.strip() for x in result[0].split(',') ] 
143               
144                return flavours
145
146        #def get_flavour                       
147       
148
149        def get_user_group(self):
150               
151                #check if the user is in the enabled group, otherwise the indicator is closed
152                user=os.environ["USER"]
153                group_found=False
154               
155                for g in grp.getgrall():
156                        if(g.gr_name in UpgradeIndicator.GROUPS):
157                                for member in g.gr_mem:
158                                        if(member==user):
159                                                group_found=True
160                                               
161                return group_found                             
162
163        #def get_user_group                                     
164                                       
165        def populate_menu(self):
166       
167
168                label_item=_("LliureX-Up is being executed")
169                item=Gtk.ImageMenuItem()
170                item.set_label(label_item)
171                img=Gtk.Image.new_from_file(SP1)
172                item.set_image(img)
173                item.set_always_show_image(True)
174                item.remote=True
175                self.menu.insert(item,0)
176
177                if self.updatedInfo:
178                        item=Gtk.ImageMenuItem()
179                        label_item=_("Update the system now")
180                        item.set_label(label_item)
181                        img=Gtk.Image()
182                        #img.set_from_stock(Gtk.STOCK_PREFERENCES,Gtk.IconSize.MENU)
183                        img.set_from_icon_name("software-properties",Gtk.IconSize.MENU)
184                        item.set_image(img)
185                        item.set_always_show_image(True)
186                        item.connect("activate",self.open_gui)
187                        item.remote=False
188                        self.menu.insert(item,1)
189
190        #def populate_menu             
191
192        def start_inotify(self):
193
194                t=threading.Thread(target=self._inotify)
195                t.daemon=True
196                t.start()               
197
198        #def start_inotify     
199
200        def _inotify(self):
201               
202               
203                wm=WatchManager()
204                mask=pyinotify.IN_CREATE
205                       
206                class Process_handler(ProcessEvent):
207                               
208                        def __init__(self,main):
209                               
210                                self.main=main
211                               
212                        def process_IN_CREATE(self,event):
213
214                                if os.path.expanduser(event.pathname)=='/var/run/lliurexUp.lock':
215                                        self.main.lliurexUp_running=True
216                               
217       
218                notifier=Notifier(wm,Process_handler(self))
219                wdd=wm.add_watch(UpgradeIndicator.WATCH_DIR,mask,rec=True)
220                       
221                while True:
222                        try:
223                                       
224                                notifier.process_events()
225                                if notifier.check_events():
226                                        notifier.read_events()
227                               
228                        except Exception as e:
229                                notifier.stop()
230                                       
231                return False   
232
233        #def _inotify   
234
235        def remote_execute(self):
236
237                cont=0
238                remote_pts=[]
239                remote_users=[]
240                isrunning=[]
241                remote_executing=False
242
243                cmd='who | grep -v "(:0"'
244                p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
245                result=p.communicate()
246                remote_users=[ x.strip() for x in result[0].split('\n') ]
247                remote_users.pop()
248
249                for item in remote_users:
250                        tmp=re.search('(pts/\w)',item)
251                        try:
252                                remote_pts.append(tmp.group(1))
253                        except Exception as e:
254                                pass
255
256
257                cmd='ps -ef | grep "lliurex-upgrade" | grep -v "grep"'
258                p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
259                result=p.communicate()
260                isrunning= [ x.strip() for x in result[0].split('\n') ]
261                isrunning.pop()
262
263
264                for item in isrunning:
265                        if '?' in item:
266                                cont=cont+1
267                        for t in remote_pts:
268                                if t in item:
269                                        cont=cont+1
270
271                if cont>0:
272                        remote_executing=True
273
274                return remote_executing                         
275
276        #def remote_execute     
277
278        def is_alive(self):
279
280                #if os.path.exists(TARGET_FILE):
281                self.is_working=True
282
283                self.checkRemote=self.remote_execute()
284                self.remoteUpdateInfo=True
285
286                if self.checkRemote:
287                        self.menu.show_all()
288                        for item in self.menu.get_children():
289                                if not item.remote:
290                                        item.set_visible(False)
291                        self.app_indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
292                               
293                else:
294                        self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
295                       
296                GLib.timeout_add(100,self.check_status) 
297                               
298                return
299
300        #def is_alive   
301               
302        def check_status(self):
303
304                if os.path.exists(TARGET_FILE):
305                        if self.checkRemote:
306                                self.spinner_sync()
307                                for item in self.menu.get_children():
308                                        if item.remote:
309                                        #item=self.menu.get_children()[0]
310                                                item.set_image(self.sp_img)
311                                                self.sp_cont=self.sp_cont+1     
312                        return True
313                       
314                else:
315                        if self.checkRemote:
316                                img=Gtk.Image.new_from_file(SP1)
317                                for item in self.menu.get_children():
318                                        if item.remote:
319                                                item.set_image(img)
320                       
321                                message=_("The upgrade process has ended")
322                                self.show_message(message)
323                                self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
324                                time.sleep(2)
325                                self.notify.close()
326
327                        self.remoteUpdateInfo=False
328                        self.lliurexUp_running=False
329                        self.is_working=False
330                        self.is_cache_updated=False
331               
332                        return False           
333
334        #def check_status       
335       
336        def spinner_sync(self):
337       
338                if self.sp_cont>50:
339                        self.sp_cont=0
340                       
341                if self.sp_cont==0:
342                        img=Gtk.Image.new_from_file(SP1)
343                        self.sp_img=img
344                elif self.sp_cont==10:
345                        img=Gtk.Image.new_from_file(SP2)
346                        self.sp_img=img                 
347                elif self.sp_cont==20:
348                        img=Gtk.Image.new_from_file(SP3)
349                        self.sp_img=img
350                elif self.sp_cont==30:
351                        img=Gtk.Image.new_from_file(SP4)
352                        self.sp_img=img
353                elif self.sp_cont==40:
354                        img=Gtk.Image.new_from_file(SP5)
355                        self.sp_img=img
356                               
357        #def spinner_sync               
358
359
360
361        def on_cache_changed(self,monitor,file,other,type):
362                """Apt cache notification event"""
363       
364               
365                if(type==Gio.FileMonitorEvent.CHANGES_DONE_HINT and self.last_check>120): #ignore cache updates at intervals smaller than 2 minutes
366                        self.is_cache_updated=True
367               
368       
369        #def on_cache_changed
370
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               
423        #def upgrade
424
425
426        def show_message(self,message):
427
428               
429                self.notify=Notify.Notification.new(_("Lliurex-Up"),message, "lliurex-up")
430                self.notify.set_hint("transient", GLib.Variant.new_boolean(True))
431                self.notify.show()
432
433        #def _show_message     
434
435        def open_gui(self,widget):
436               
437                if not os.path.exists(TARGET_FILE):
438                        self.app_indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
439                        self.notify.close()
440                        cmd='gksu lliurex-up' + "&"
441                        os.system(cmd)
442
443        #def open_gui           
444
445        def quit(self):
446
447                Gtk.main_quit() 
448
449        #def quit       
450       
451#class UpgradeIndicator
452
453if __name__=="__main__":
454
455
456        lliurexup=UpgradeIndicator("lliurex-up")
457        GObject.threads_init()
458        Gtk.main()
Note: See TracBrowser for help on using the repository browser.