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

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

WIP in indicator. Fix script and po files

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