Ticket #3240: 0001-pep8-ized-logcollect.py.patch

File 0001-pep8-ized-logcollect.py.patch, 20.0 KB (added by humitos, 12 years ago)
  • logcollect.py

    From d7405a7396fc41d29219575b596ffb8fddefaf43 Mon Sep 17 00:00:00 2001
    Message-Id: <d7405a7396fc41d29219575b596ffb8fddefaf43.1336686222.git.humitos@gmail.com>
    From: Manuel Kaufmann <humitos@gmail.com>
    Date: Thu, 10 May 2012 17:47:48 -0300
    Subject: [PATCH Log 1/2] pep8-ized logcollect.py
    
    Passed pep8.py script to remove a lot of trailling whitespaces and
    things related.
    
    Signed-off-by: Manuel Kaufmann <humitos@gmail.com>
    ---
     logcollect.py |  278 ++++++++++++++++++++++++++++++---------------------------
     1 files changed, 146 insertions(+), 132 deletions(-)
    
    diff --git a/logcollect.py b/logcollect.py
    index 82c1bba..956cc24 100644
    a b  
    1 # Copyright (C) 2007, Pascal Scheffers <pascal@scheffers.net> 
     1# Copyright (C) 2007, Pascal Scheffers <pascal@scheffers.net>
    22#
    33# Permission is hereby granted, free of charge, to any person
    44# obtaining a copy of this software and associated documentation
     
    3333#  ** ...
    3434#  * Installed packages list
    3535#  * All relevant log files (all of them, at first)
    36 # 
     36#
    3737# The report is output as a tarfile
    3838#
    3939# This file has two modes:
    class MachineProperties: 
    7878            return '#/etc/issue not found'
    7979
    8080        # Needed, because we want to default to the first non blank line:
    81         first_line = '' 
     81        first_line = ''
    8282
    8383        for line in self.__read_file('/etc/issue').splitlines():
    8484            if line.lower().find('olpc build') > -1:
    85                 return line               
     85                return line
    8686            if first_line == '':
    87                 first_line=line
     87                first_line = line
    8888
    8989        return first_line
    9090
    9191    def uptime(self):
    9292        for line in self.__read_file('/proc/uptime').splitlines():
    9393            if line != '':
    94                 return line           
     94                return line
    9595        return ''
    9696
    9797    def loadavg(self):
    9898        for line in self.__read_file('/proc/loadavg').splitlines():
    9999            if line != '':
    100                 return line           
     100                return line
    101101        return ''
    102102
    103103    def kernel_version(self):
    104104        for line in self.__read_file('/proc/version').splitlines():
    105105            if line != '':
    106                 return line           
     106                return line
    107107        return ''
    108108
    109109    def memfree(self):
    class MachineProperties: 
    126126
    127127        v = self.__read_file(mfg_path)
    128128        # Remove trailing 0 character, if any:
    129         if v != '' and ord(v[len(v)-1]) == 0:
    130             v = v[:len(v)-1]
    131        
     129        if v != '' and ord(v[len(v) - 1]) == 0:
     130            v = v[:len(v) - 1]
     131
    132132        return v
    133            
     133
    134134    def laptop_serial_number(self):
    135135        return self._mfg_data('SN')
    136136
    class MachineProperties: 
    141141        s = self._mfg_data('SG')[0:1]
    142142        if s == '':
    143143            return ''
    144            
     144
    145145        return '%02X' % ord(self._mfg_data('SG')[0:1])
    146        
    147146
    148147    def laptop_uuid(self):
    149148        return self._mfg_data('U#')
    class MachineProperties: 
    165164
    166165    def laptop_localization(self):
    167166        return self._mfg_data('LO')
    168    
     167
    169168    def _battery_info(self, item):
    170169        """ from  /sys/class/power-supply/olpc-battery/ """
    171170        root = '/sys/class/power_supply/olpc-battery/'
    172         if not os.path.exists(root+item):
     171        if not os.path.exists(root + item):
    173172            return ''
    174        
    175         return self.__read_file(root+item).strip()
     173
     174        return self.__read_file(root + item).strip()
    176175
    177176    def battery_serial_number(self):
    178177        return self._battery_info('serial_number')
    179    
     178
    180179    def battery_capacity(self):
    181180        return self._battery_info('capacity') + ' ' + \
    182181                    self._battery_info('capacity_level')
    class MachineProperties: 
    184183    def battery_info(self):
    185184        #Should be just:
    186185        #return self._battery_info('uevent')
    187        
     186
    188187        #But because of a bug in the kernel, that has trash, lets filter:
    189         bi = ''       
     188        bi = ''
    190189        for line in self._battery_info('uevent').splitlines():
    191190            if line.startswith('POWER_'):
    192191                bi += line + '\n'
    193        
     192
    194193        return bi
    195        
     194
    196195    def disksize(self, path):
    197196        return os.statvfs(path).f_bsize * os.statvfs(path).f_blocks
    198    
     197
    199198    def diskfree(self, path):
    200199        return os.statvfs(path).f_bsize * os.statvfs(path).f_bavail
    201        
     200
    202201    def _read_popen(self, cmd):
    203202        p = os.popen(cmd)
    204203        s = ''
    205204        try:
    206205            for line in p:
    207                 s += line 
     206                s += line
    208207        finally:
    209             p.close()       
    210        
     208            p.close()
     209
    211210        return s
    212    
    213     def ifconfig(self):       
     211
     212    def ifconfig(self):
    214213        return self._read_popen('/sbin/ifconfig')
    215                
    216     def route_n(self):       
     214
     215    def route_n(self):
    217216        return self._read_popen('/sbin/route -n')
    218    
     217
    219218    def df_a(self):
    220219        return self._read_popen('/bin/df -a')
    221  
     220
    222221    def ps_auxfwww(self):
    223222        return self._read_popen('/bin/ps auxfwww')
    224    
     223
    225224    def usr_bin_free(self):
    226225        return self._read_popen('/usr/bin/free')
    227226
    228227    def top(self):
    229228        return self._read_popen('/usr/bin/top -bn2')
    230        
    231     def installed_activities(self):       
    232         s = ''       
     229
     230    def installed_activities(self):
     231        s = ''
    233232        for path in glob.glob('/usr/share/activities/*.activity'):
    234233            s += os.path.basename(path) + '\n'
    235234
    236235        for path in glob.glob('/home/olpc/Activities/*'):
    237236            s += '~' + os.path.basename(path) + '\n'
    238            
     237
    239238        return s
    240        
    241        
     239
    242240
    243241class LogCollect:
    244242    """Collect XO logfiles and machine metadata for reporting to OLPC
    class LogCollect: 
    248246        self._mp = MachineProperties()
    249247
    250248    def write_logs(self, archive='', logbytes=15360):
    251         """Write a zipfile containing the tails of the logfiles and machine info of the XO
    252        
     249        """Write a zipfile containing the tails of the logfiles and
     250        machine info of the XO
     251
    253252        Arguments:
    254253            archive -   Specifies the location where to store the data
    255254                        defaults to /dev/shm/logs-<xo-serial>.zip
    256                        
     255
    257256            logbytes -  Maximum number of bytes to read from each log file.
    258257                        0 means complete logfiles, not just the tail
    259258                        -1 means only save machine info, no logs
    260259        """
    261260        #This function is crammed with try...except to make sure we get as much
    262261        #data as possible, if anything fails.
    263        
    264         if archive=='':
     262
     263        if archive == '':
    265264            archive = '/dev/shm/logs.zip'
    266265            try:
    267266                #With serial number is more convenient, but might fail for some
    268267                #Unknown reason...
    269                 archive = '/dev/shm/logs-%s.zip' % self._mp.laptop_serial_number()
     268                archive = '/dev/shm/logs-%s.zip' % \
     269                    self._mp.laptop_serial_number()
    270270            except Exception:
    271271                pass
    272            
     272
    273273        z = zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED)
    274        
    275         try:           
    276             try: 
     274
     275        try:
     276            try:
    277277                z.writestr('info.txt', self.laptop_info())
    278278            except Exception, e:
    279279                z.writestr('info.txt',
    280280                           "logcollect: could not add info.txt: %s" % e)
    281            
    282             if logbytes > -1:           
     281            if logbytes > -1:
    283282                # Include some log files from /var/log.
    284                 for fn in ['dmesg', 'messages', 'cron', 'maillog','rpmpkgs',
     283                for fn in ['dmesg', 'messages', 'cron', 'maillog', 'rpmpkgs',
    285284                           'Xorg.0.log', 'spooler']:
    286285                    try:
    287                         if os.access('/var/log/'+fn, os.F_OK):
     286                        if os.access('/var/log/' + fn, os.F_OK):
    288287                            if logbytes == 0:
    289                                 z.write('/var/log/'+fn, 'var-log/'+fn)
     288                                z.write('/var/log/' + fn, 'var-log/' + fn)
    290289                            else:
    291                                 z.writestr('var-log/'+fn,
    292                                            self.file_tail('/var/log/'+fn, logbytes))
     290                                z.writestr('var-log/' + fn,
     291                                           self.file_tail('/var/log/' + fn,
     292                                                          logbytes))
    293293                    except Exception, e:
    294                         z.writestr('var-log/'+fn,
    295                                    "logcollect: could not add %s: %s" % (fn, e))
    296                        
     294                        z.writestr('var-log/' + fn,
     295                                   "logcollect: could not add %s: %s" % \
     296                                       (fn, e))
     297
    297298                # Include all current ones from sugar/logs
    298299                for path in glob.glob('/home/olpc/.sugar/default/logs/*.log'):
    299300                    try:
    300301                        if os.access(path, os.F_OK):
    301302                            if logbytes == 0:
    302                                 z.write(path, 'sugar-logs/'+os.path.basename(path))
     303                                z.write(path, 'sugar-logs/' + \
     304                                            os.path.basename(path))
    303305                            else:
    304                                 z.writestr('sugar-logs/'+os.path.basename(path),
     306                                z.writestr('sugar-logs/' + \
     307                                               os.path.basename(path),
    305308                                           self.file_tail(path, logbytes))
    306309                    except Exception, e:
    307                         z.writestr('sugar-logs/'+fn,
    308                                    "logcollect: could not add %s: %s" % (fn, e))
    309                 try:                 
     310                        z.writestr('sugar-logs/' + fn,
     311                                   "logcollect: could not add %s: %s" % \
     312                                       (fn, e))
     313                try:
    310314                    z.write('/etc/resolv.conf')
    311315                except Exception, e:
    312316                    z.writestr('/etc/resolv.conf',
    313317                               "logcollect: could not add resolv.conf: %s" % e)
    314                    
     318
    315319        except Exception, e:
    316             print 'While creating zip archive: %s' % e           
    317        
    318         z.close()       
    319        
     320            print 'While creating zip archive: %s' % e
     321
     322        z.close()
     323
    320324        return archive
    321325
    322326    def file_tail(self, filename, tailbytes):
    323327        """Read the tail (end) of the file
    324        
     328
    325329        Arguments:
    326330            filename    The name of the file to read
    327331            tailbytes   Number of bytes to include or 0 for entire file
    class LogCollect: 
    332336        f = open(filename)
    333337        try:
    334338            fsize = os.stat(filename).st_size
    335            
     339
    336340            if tailbytes > 0 and fsize > tailbytes:
    337341                f.seek(-tailbytes, 2)
    338                
     342
    339343            data = f.read()
    340344        finally:
    341345            f.close()
    342346
    343         return data       
    344              
     347        return data
    345348
    346349    def make_report(self, target='stdout'):
    347350        """Create the report
    348351
    349352        Arguments:
    350             target - where to save the logs, a path or stdout           
     353            target - where to save the logs, a path or stdout
    351354
    352355        """
    353356
    354357        li = self.laptop_info()
    355358        for k, v in li.iteritems():
    356             print k + ': ' +v
    357            
     359            print k + ': ' + v
     360
    358361        print self._mp.battery_info()
    359362
    360363    def laptop_info(self):
    361         """Return a string with laptop serial, battery type, build, memory info, etc."""
     364        """Return a string with laptop serial, battery type, build,
     365        memory info, etc."""
    362366
    363         s = ''       
     367        s = ''
    364368        try:
    365369            # Do not include UUID!
    366370            s += 'laptop-info-version: 1.0\n'
    class LogCollect: 
    368372            s += 'date: %s' % time.strftime("%a, %d %b %Y %H:%M:%S +0000",
    369373                                            time.gmtime())
    370374            s += 'memfree: %s\n' % self._mp.memfree()
    371             s += 'disksize: %s MB\n' % ( self._mp.disksize('/') / (1024*1024) )
    372             s += 'diskfree: %s MB\n' % ( self._mp.diskfree('/') / (1024*1024) )
     375            s += 'disksize: %s MB\n' % \
     376                (self._mp.disksize('/') / (1024 * 1024))
     377            s += 'diskfree: %s MB\n' % \
     378                (self._mp.diskfree('/') / (1024 * 1024))
    373379            s += 'olpc_build: %s\n' % self._mp.olpc_build()
    374380            s += 'kernel_version: %s\n' % self._mp.kernel_version()
    375381            s += 'uptime: %s\n' % self._mp.uptime()
    376             s += 'loadavg: %s\n' % self._mp.loadavg()       
     382            s += 'loadavg: %s\n' % self._mp.loadavg()
    377383            s += 'serial-number: %s\n' % self._mp.laptop_serial_number()
    378             s += 'motherboard-number: %s\n' % self._mp.laptop_motherboard_number()
    379             s += 'board-revision: %s\n' %  self._mp.laptop_board_revision()
    380             s += 'keyboard: %s\n' %  self._mp.laptop_keyboard()
    381             s += 'wireless_mac: %s\n' %  self._mp.laptop_wireless_mac()
    382             s += 'firmware: %s\n' %  self._mp.laptop_bios_version()
     384            s += 'motherboard-number: %s\n' % \
     385                self._mp.laptop_motherboard_number()
     386            s += 'board-revision: %s\n' %  \
     387                self._mp.laptop_board_revision()
     388            s += 'keyboard: %s\n' % \
     389                self._mp.laptop_keyboard()
     390            s += 'wireless_mac: %s\n' %  \
     391                self._mp.laptop_wireless_mac()
     392            s += 'firmware: %s\n' %  \
     393                self._mp.laptop_bios_version()
    383394            s += 'country: %s\n' % self._mp.laptop_country()
    384395            s += 'localization: %s\n' % self._mp.laptop_localization()
    385                
     396
    386397            s += self._mp.battery_info()
    387            
     398
    388399            s += "\n[/sbin/ifconfig]\n%s\n" % self._mp.ifconfig()
    389400            s += "\n[/sbin/route -n]\n%s\n" % self._mp.route_n()
    390            
    391             s += '\n[Installed Activities]\n%s\n' % self._mp.installed_activities()
    392    
     401
     402            s += '\n[Installed Activities]\n%s\n' % \
     403                self._mp.installed_activities()
     404
    393405            s += '\n[df -a]\n%s\n' % self._mp.df_a()
    394406            s += '\n[ps auxwww]\n%s\n' % self._mp.ps_auxfwww()
    395407            s += '\n[free]\n%s\n' % self._mp.usr_bin_free()
    396408            s += '\n[top -bn2]\n%s\n' % self._mp.top()
    397409        except Exception, e:
    398410            s += '\nException while building info:\n%s\n' % e
    399        
     411
    400412        return s
    401413
     414
    402415class LogSend:
    403    
    404416    # post_multipart and encode_multipart_formdata have been taken from
    405     #  http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
     417    # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
    406418    def post_multipart(self, host, selector, fields, files):
    407419        """
    408420        Post fields and files to an http host as multipart/form-data.
    409         fields is a sequence of (name, value) elements for regular form fields.
    410         files is a sequence of (name, filename, value) elements for data to be uploaded as files
    411         Return the server's response page.       
     421        fields is a sequence of (name, value) elements for regular
     422        form fields.
     423
     424        files is a sequence of (name, filename, value) elements for
     425        data to be uploaded as files Return the server's response
     426        page.
    412427        """
     428
    413429        content_type, body = self.encode_multipart_formdata(fields, files)
    414430        h = httplib.HTTP(host)
    415431        h.putrequest('POST', selector)
    class LogSend: 
    420436        h.send(body)
    421437        errcode, errmsg, headers = h.getreply()
    422438        return h.file.read()
    423    
     439
    424440    def encode_multipart_formdata(self, fields, files):
    425441        """
    426442        fields is a sequence of (name, value) elements for regular form fields.
    427         files is a sequence of (name, filename, value) elements for data to be uploaded as files
    428         Return (content_type, body) ready for httplib.HTTP instance
     443
     444        files is a sequence of (name, filename, value) elements for
     445        data to be uploaded as files Return (content_type, body) ready
     446        for httplib.HTTP instance
    429447        """
     448
    430449        BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
    431450        CRLF = '\r\n'
    432451        L = []
    class LogSend: 
    437456            L.append(value)
    438457        for (key, filename, value) in files:
    439458            L.append('--' + BOUNDARY)
    440             L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
     459            L.append('Content-Disposition: form-data; name="%s"; '
     460                     'filename="%s"' % (key, filename))
    441461            L.append('Content-Type: %s' % self.get_content_type(filename))
    442462            L.append('')
    443463            L.append(value)
    class LogSend: 
    446466        body = CRLF.join(L)
    447467        content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
    448468        return content_type, body
    449    
     469
    450470    def read_file(self, filename):
    451471        """Read the entire contents of a file and return it as a string"""
    452472
    class LogSend: 
    462482
    463483    def get_content_type(self, filename):
    464484        return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
    465        
     485
    466486    def http_post_logs(self, url, archive):
    467487        #host, selector, fields, files
    468488        files = ('logs', os.path.basename(archive), self.read_file(archive)),
    469        
     489
    470490        # Client= olpc will make the server return just "OK" or "FAIL"
    471491        fields = ('client', 'xo'),
    472492        urlparts = urlparse.urlsplit(url)
    class LogSend: 
    475495        print r
    476496        return (r == 'OK')
    477497
    478 
    479498# This script is dual-mode, it can be used as a command line tool and as
    480 # a library. 
     499# a library.
    481500if sys.argv[0].endswith('logcollect.py') or \
    482501        sys.argv[0].endswith('logcollect'):
    483502    print 'log-collect utility 1.0'
    484        
     503
    485504    lc = LogCollect()
    486505    ls = LogSend()
    487506
    488507    logs = ''
    489508    mode = 'http'
    490    
    491     if len(sys.argv)==1:
     509
     510    if len(sys.argv) == 1:
    492511        print """logcollect.py - send your XO logs to OLPC
    493        
     512
    494513Usage:
    495514    logcollect.py http://server.name/submit.php
    496515                         - submit logs to a server
    497                          
     516
    498517    logcollect.py file:/media/xxxx-yyyy/mylog.zip
    499518                         - save the zip file on a USB device or SD card
    500                          
     519
    501520    logcollect.py all file:/media/xxxx-yyyy/mylog.zip
    502521                        - Save to zip file and include ALL logs
    503522
    Usage: 
    510529    If you specify 'all' or 'none' you must specify http or file as well.
    511530        """
    512531        sys.exit()
    513        
    514    
    515     logbytes = 15360   
    516     if len(sys.argv)>1:
    517         mode = sys.argv[len(sys.argv)-1]
     532
     533    logbytes = 15360
     534    if len(sys.argv) > 1:
     535        mode = sys.argv[len(sys.argv) - 1]
    518536        if sys.argv[1] == 'all':
    519537            logbytes = 0
    520538        if sys.argv[1] == 'none':
    521539            logbytes = -1
    522    
    523540
    524541    if mode.startswith('file'):
    525542        # file://
    526543        logs = mode[5:]
    527  
     544
    528545    #if mode.lower().startswith('http'):
    529546    #    pass
    530547    #else if mode.lower().startswith('usb'):
    531548    #    pass
    532549    #else if mode.lower().startswith('sd'):
    533550    #    pass
    534    
     551
    535552    logs = lc.write_logs(logs, logbytes)
    536553    print 'Logs saved in %s' % logs
    537    
     554
    538555    sent_ok = False
    539     if len(sys.argv)>1:
    540        mode = sys.argv[len(sys.argv)-1]
    541    
     556    if len(sys.argv) > 1:
     557        mode = sys.argv[len(sys.argv) - 1]
     558
    542559    if mode.startswith('http'):
    543560        print "Trying to send the logs using HTTP (web)"
    544561        if len(mode) == 4:
    Usage: 
    546563            sys.exit(1)
    547564        else:
    548565            url = mode
    549            
     566
    550567        if ls.http_post_logs(url, logs):
    551568            print "Logs were sent."
    552             sent_ok = True           
     569            sent_ok = True
    553570        else:
    554571            print "FAILED to send logs."
    555  
    556572
    557573    if sent_ok:
    558574        os.remove(logs)
    559575        print "Logs were sent, tempfile deleted."
    560 
    561