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

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

Fix script

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