Changeset 1517

Show
Ignore:
Timestamp:
06/03/04 23:50:34 (20 years ago)
Author:
jalet
Message:

Improved error logging.
crashrecipient directive added.
Now exports the job's size in bytes too.

Location:
pykota/trunk
Files:
11 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/cupspykota

    r1515 r1517  
    2424# 
    2525# $Log$ 
     26# Revision 1.58  2004/06/03 21:50:33  jalet 
     27# Improved error logging. 
     28# crashrecipient directive added. 
     29# Now exports the job's size in bytes too. 
     30# 
    2631# Revision 1.57  2004/06/02 22:18:07  jalet 
    2732# I think the bug when cancelling jobs should be fixed right now 
     
    330335            clienthost = self.getJobOriginatingHostname(printer.Name, user.Name, self.jobid) 
    331336            self.logdebug("Client Hostname : %s" % (clienthost or "Unknown"))     
    332             os.putenv("PYKOTAJOBORIGINATINGHOSTNAME", str(clienthost or "")) 
     337            os.environ["PYKOTAJOBORIGINATINGHOSTNAME"] = str(clienthost or "") 
    333338             
    334339            # enters first phase 
    335             os.putenv("PYKOTAPHASE", "BEFORE") 
     340            os.environ["PYKOTAPHASE"] = "BEFORE" 
    336341             
    337342            # checks the user's quota 
     
    340345                self.softwareJobPrice = userpquota.computeJobPrice(self.softwareJobSize) 
    341346                self.logdebug("Precomputed job's size is %s pages, price is %s units" % (self.softwareJobSize, self.softwareJobPrice)) 
    342             os.putenv("PYKOTAPRECOMPUTEDJOBSIZE", str(self.softwareJobSize))     
    343             os.putenv("PYKOTAPRECOMPUTEDJOBPRICE", str(self.softwareJobPrice))     
     347            os.environ["PYKOTAPRECOMPUTEDJOBSIZE"] = str(self.softwareJobSize) 
     348            os.environ["PYKOTAPRECOMPUTEDJOBPRICE"] = str(self.softwareJobPrice) 
    344349            action = self.warnUserPQuota(userpquota) 
    345350             
    346351            # exports some new environment variables 
    347             os.putenv("PYKOTAACTION", action) 
     352            os.environ["PYKOTAACTION"] = action 
    348353             
    349354            # launches the pre hook 
     
    354359        else :     
    355360            action = "ALLOW" 
    356             os.putenv("PYKOTAACTION", action) 
     361            os.environ["PYKOTAACTION"] = action 
    357362             
    358363        # pass the job's data to the real backend     
     
    367372        if policy == "OK" :         
    368373            # indicate phase change 
    369             os.putenv("PYKOTAPHASE", "AFTER") 
     374            os.environ["PYKOTAPHASE"] = "AFTER" 
    370375             
    371376            # stops accounting.  
     
    390395             
    391396            # exports some new environment variables 
    392             os.putenv("PYKOTAJOBSIZE", str(jobsize)) 
    393             os.putenv("PYKOTAJOBPRICE", str(jobprice)) 
    394              
    395             # then re-export user information with new values 
     397            os.environ["PYKOTAJOBSIZE"] = str(jobsize) 
     398            os.environ["PYKOTAJOBPRICE"] = str(jobprice) 
     399             
     400            # then re-export user information with new value 
    396401            self.exportUserInfo(userpquota) 
    397402             
     
    660665            retcode = kotabackend.mainWork() 
    661666        except : 
    662             import traceback 
    663             lines = [] 
    664             for line in traceback.format_exception(*sys.exc_info()) : 
    665                 lines.extend([l for l in line.split("\n") if l]) 
    666             sys.stderr.write("ERROR : cupspykota backend failed : \n%s" % (msg, "ERROR : ".join(["%s\n" % l for l in lines]))) 
    667             sys.stderr.flush() 
     667            try : 
     668                kotabackend.crashed("cupspykota backend failed") 
     669            except :     
     670                pass 
    668671            retcode = 1 
    669672         
  • pykota/trunk/bin/edpykota

    r1436 r1517  
    2424# 
    2525# $Log$ 
     26# Revision 1.73  2004/06/03 21:50:34  jalet 
     27# Improved error logging. 
     28# crashrecipient directive added. 
     29# Now exports the job's size in bytes too. 
     30# 
    2631# Revision 1.72  2004/04/16 16:20:19  jalet 
    2732# Note about not implemented limitby values 
     
    690695        else : 
    691696            retcode = editor.main(args, options) 
    692     except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg :             
    693         sys.stderr.write("%s\n" % msg) 
    694         sys.stderr.flush() 
     697    except : 
     698        try : 
     699            editor.crashed("edpykota failed") 
     700        except :     
     701            pass 
    695702        retcode = -1 
    696703 
  • pykota/trunk/bin/pkhint

    r1483 r1517  
    2424# 
    2525# $Log$ 
     26# Revision 1.9  2004/06/03 21:50:34  jalet 
     27# Improved error logging. 
     28# crashrecipient directive added. 
     29# Now exports the job's size in bytes too. 
     30# 
    2631# Revision 1.8  2004/05/18 14:48:47  jalet 
    2732# Big code changes to completely remove the need for "requester" directives, 
     
    266271                args = [ "*" ] 
    267272            retcode = manager.main(args, options) 
    268     except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg :             
    269         sys.stderr.write("%s\n" % msg) 
    270         sys.stderr.flush() 
     273    except : 
     274        try : 
     275            manager.crashed("pkhint failed") 
     276        except :     
     277            pass 
    271278        retcode = -1 
    272279 
  • pykota/trunk/bin/pkprinters

    r1453 r1517  
    2424# 
    2525# $Log$ 
     26# Revision 1.9  2004/06/03 21:50:34  jalet 
     27# Improved error logging. 
     28# crashrecipient directive added. 
     29# Now exports the job's size in bytes too. 
     30# 
    2631# Revision 1.8  2004/05/06 20:30:24  jalet 
    2732# Added --skipexisting command line option to pkprinters 
     
    255260        else : 
    256261            retcode = manager.main(args, options) 
    257     except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg :             
    258         sys.stderr.write("%s\n" % msg) 
    259         sys.stderr.flush() 
     262    except : 
     263        try : 
     264            manager.crashed("pkprinters failed") 
     265        except :     
     266            pass 
    260267        retcode = -1 
    261268 
  • pykota/trunk/bin/pykotme

    r1488 r1517  
    2424# 
    2525# $Log$ 
     26# Revision 1.10  2004/06/03 21:50:34  jalet 
     27# Improved error logging. 
     28# crashrecipient directive added. 
     29# Now exports the job's size in bytes too. 
     30# 
    2631# Revision 1.9  2004/05/21 20:53:34  jalet 
    2732# Now pykotme doesn't spawn a new process anymore to compute job's size, but 
     
    186191        else : 
    187192            retcode = sender.main(args, options) 
    188     except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg :             
    189         sys.stderr.write("%s\n" % msg) 
    190         sys.stderr.flush() 
     193    except : 
     194        try : 
     195            sender.crashed("pykotme failed") 
     196        except :     
     197            pass 
    191198        retcode = -1 
    192199 
  • pykota/trunk/bin/repykota

    r1257 r1517  
    2424# 
    2525# $Log$ 
     26# Revision 1.47  2004/06/03 21:50:34  jalet 
     27# Improved error logging. 
     28# crashrecipient directive added. 
     29# Now exports the job's size in bytes too. 
     30# 
    2631# Revision 1.46  2004/01/08 14:10:32  jalet 
    2732# Copyright year changed. 
     
    307312        else : 
    308313            retcode = reportTool.main(args, options) 
    309     except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError, PyKotaReporterError), msg :             
    310         sys.stderr.write("%s\n" % msg) 
    311         sys.stderr.flush() 
    312         retcode = -1  
     314    except : 
     315        try : 
     316            reportTool.crashed("repykota failed") 
     317        except :     
     318            pass 
     319        retcode = -1 
    313320 
    314321    try : 
  • pykota/trunk/bin/warnpykota

    r1257 r1517  
    2424# 
    2525# $Log$ 
     26# Revision 1.27  2004/06/03 21:50:34  jalet 
     27# Improved error logging. 
     28# crashrecipient directive added. 
     29# Now exports the job's size in bytes too. 
     30# 
    2631# Revision 1.26  2004/01/08 14:10:32  jalet 
    2732# Copyright year changed. 
     
    247252        else : 
    248253            retcode = sender.main(args, options) 
    249     except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg :             
    250         sys.stderr.write("%s\n" % msg) 
    251         sys.stderr.flush() 
     254    except : 
     255        try : 
     256            sender.crashed("warnpykota failed") 
     257        except :     
     258            pass 
    252259        retcode = -1 
    253260         
  • pykota/trunk/conf/pykota.conf.sample

    r1510 r1517  
    152152# If the value is not set then localhost is used. 
    153153smtpserver: localhost 
     154 
     155# Crash messages' recipient : in addition to the log files 
     156# each software crash can be sent to the author of PyKota 
     157# or any other person of your choice. By default this 
     158# is disabled. The recipient pykotacrashed@librelogiciel.com 
     159# reaches PyKota's author. 
     160# The 'adminmail' (defined a bit below) is CCed. 
     161# 
     162# Privacy concerns : what is sent is only : 
     163# 
     164#        - a copy of the software's traceback 
     165#        - a copy of the software's command line arguments 
     166#        - a copy of the software's environment variables 
     167#  
     168# suggested value 
     169# crashrecipient: pykotacrashed@librelogiciel.com 
    154170 
    155171# Email domain 
     
    458474# PYKOTASTATUS : contains "CANCELLED" when SIGTERM was received by PyKota 
    459475#                else is not set. 
     476# PYKOTAJOBSIZEBYTES : contains the job's size in bytes. Always available. 
    460477# PYKOTAPRECOMPUTEDJOBSIZE : contains the precomputed job's size 
    461478# PYKOTAPRECOMPUTEDJOBPRICE : contains the precomputed job's price 
  • pykota/trunk/NEWS

    r1510 r1517  
    2323 
    2424 
     25    - 1.19alpha17 : 
     26     
     27        - Mysterious bug (program exited unexpectedly without leaving 
     28          any log message) which occured once in a while when 
     29          cancelling jobs should be fixed now. 
     30           
     31        - New 'crashrecipient' directive. Disabled by   
     32          default. See sample configuration file to see how 
     33          to activate it. It is suggested that you activate it. 
     34           
     35        - New PYKOTAJOBSIZEBYTES environment variable exported,   
     36          which contains the job's size in bytes. 
     37           
    2538    - 1.19alpha16 : 
    2639     
  • pykota/trunk/pykota/tool.py

    r1516 r1517  
    2222# 
    2323# $Log$ 
     24# Revision 1.95  2004/06/03 21:50:34  jalet 
     25# Improved error logging. 
     26# crashrecipient directive added. 
     27# Now exports the job's size in bytes too. 
     28# 
    2429# Revision 1.94  2004/06/03 08:51:03  jalet 
    2530# logs job's size in bytes now 
     
    391396        self.documentation = doc 
    392397        self.config = config.PyKotaConfig("/etc/pykota") 
    393         self.logger = logger.openLogger(self.config.getLoggingBackend()) 
    394398        self.debug = self.config.getDebug() 
    395         self.storage = storage.openConnection(self) 
    396399        self.smtpserver = self.config.getSMTPServer() 
    397400        self.maildomain = self.config.getMailDomain() 
     401        self.logger = logger.openLogger(self.config.getLoggingBackend()) 
     402        self.storage = storage.openConnection(self) 
    398403        self.softwareJobSize = 0 
    399404        self.softwareJobPrice = 0.0 
     
    422427        print self.documentation 
    423428        sys.exit(0) 
     429         
     430    def crashed(self, message) :     
     431        """Outputs a crash message, and optionally sends it to software author.""" 
     432        import traceback 
     433        lines = [] 
     434        for line in traceback.format_exception(*sys.exc_info()) : 
     435            lines.extend([l for l in line.split("\n") if l]) 
     436        msg = "ERROR : ".join(["%s\n" % l for l in ([message] + lines)]) 
     437        sys.stderr.write(msg) 
     438        sys.stderr.flush() 
     439        crashrecipient = self.config.getCrashRecipient() 
     440        if crashrecipient : 
     441            try : 
     442                admin = self.config.getAdminMail("global") # Nice trick, isn't it ? 
     443                fullmessage = "========== Traceback :\n\n%s\n\n========== sys.argv :\n\n%s\n\n========== Environment :\n\n%s\n" % \ 
     444                                (msg, \ 
     445                                 "\n".join(["    %s" % repr(a) for a in sys.argv]), \ 
     446                                 "\n".join(["    %s=%s" % (k, v) for (k, v) in os.environ.items()])) 
     447                server = smtplib.SMTP(self.smtpserver) 
     448                server.sendmail(admin, [admin, crashrecipient], "From: %s\nTo: %s\nCc: %s\nSubject: PyKota crash traceback !\n\n%s" % (admin, crashrecipient, admin, fullmessage)) 
     449                server.quit() 
     450            except : 
     451                pass 
    424452         
    425453    def parseCommandline(self, argv, short, long, allownothing=0) : 
     
    816844        self.exportJobInfo() 
    817845        self.jobdatastream = self.openJobDataStream() 
    818         os.putenv("PYKOTAJOBSIZEBYTES", str(self.JobSizeBytes)) 
    819         self.logdebug("Job size is %s bytes" % self.JobSizeBytes) 
     846        os.environ["PYKOTAJOBSIZEBYTES"] = str(self.jobSizeBytes) 
     847        self.logdebug("Job size is %s bytes" % self.jobSizeBytes) 
    820848        self.logdebug("Capturing SIGTERM events.") 
    821849        signal.signal(signal.SIGTERM, self.sigterm_handler) 
     
    829857            self.logdebug("Duplicating data stream from stdin to temporary file") 
    830858            MEGABYTE = 1024*1024 
    831             self.JobSizeBytes = 0 
     859            self.jobSizeBytes = 0 
    832860            infile = tempfile.TemporaryFile() 
    833861            while 1 : 
     
    835863                if not data : 
    836864                    break 
    837                 self.JobSizeBytes += len(data)     
     865                self.jobSizeBytes += len(data)     
    838866                infile.write(data) 
    839867            infile.flush()     
     
    843871            # real file, just open it 
    844872            self.logdebug("Opening data stream %s" % self.preserveinputfile) 
    845             self.JobSizeBytes = os.stat(self.preserveinputfile)[6] 
     873            self.jobSizeBytes = os.stat(self.preserveinputfile)[6] 
    846874            return open(self.preserveinputfile, "rb") 
    847875         
     
    879907        """Sets an attribute whenever SIGTERM is received.""" 
    880908        self.gotSigTerm = 1 
    881         os.putenv("PYKOTASTATUS", "CANCELLED") 
     909        os.environ["PYKOTASTATUS"] = "CANCELLED" 
    882910        self.logger.log_message(_("SIGTERM received, job %s cancelled.") % self.jobid, "info") 
    883911         
    884912    def exportJobInfo(self) :     
    885913        """Exports job information to the environment.""" 
    886         os.putenv("PYKOTAUSERNAME", str(self.username)) 
    887         os.putenv("PYKOTAPRINTERNAME", str(self.printername)) 
    888         os.putenv("PYKOTAJOBID", str(self.jobid)) 
    889         os.putenv("PYKOTATITLE", self.title or "") 
    890         os.putenv("PYKOTAFILENAME", self.preserveinputfile or "") 
    891         os.putenv("PYKOTACOPIES", str(self.copies)) 
    892         os.putenv("PYKOTAOPTIONS", self.options or "") 
     914        os.environ["PYKOTAUSERNAME"] = str(self.username) 
     915        os.environ["PYKOTAPRINTERNAME"] = str(self.printername) 
     916        os.environ["PYKOTAJOBID"] = str(self.jobid) 
     917        os.environ["PYKOTATITLE"] = self.title or "" 
     918        os.environ["PYKOTAFILENAME"] = self.preserveinputfile or "" 
     919        os.environ["PYKOTACOPIES"] = str(self.copies) 
     920        os.environ["PYKOTAOPTIONS"] = self.options or "" 
    893921     
    894922    def exportUserInfo(self, userpquota) : 
    895923        """Exports user information to the environment.""" 
    896         os.putenv("PYKOTALIMITBY", str(userpquota.User.LimitBy)) 
    897         os.putenv("PYKOTABALANCE", str(userpquota.User.AccountBalance or 0.0)) 
    898         os.putenv("PYKOTALIFETIMEPAID", str(userpquota.User.LifeTimePaid or 0.0)) 
    899         os.putenv("PYKOTAPAGECOUNTER", str(userpquota.PageCounter or 0)) 
    900         os.putenv("PYKOTALIFEPAGECOUNTER", str(userpquota.LifePageCounter or 0)) 
    901         os.putenv("PYKOTASOFTLIMIT", str(userpquota.SoftLimit)) 
    902         os.putenv("PYKOTAHARDLIMIT", str(userpquota.HardLimit)) 
    903         os.putenv("PYKOTADATELIMIT", str(userpquota.DateLimit)) 
     924        os.environ["PYKOTALIMITBY"] = str(userpquota.User.LimitBy) 
     925        os.environ["PYKOTABALANCE"] = str(userpquota.User.AccountBalance or 0.0) 
     926        os.environ["PYKOTALIFETIMEPAID"] = str(userpquota.User.LifeTimePaid or 0.0) 
     927        os.environ["PYKOTAPAGECOUNTER"] = str(userpquota.PageCounter or 0) 
     928        os.environ["PYKOTALIFEPAGECOUNTER"] = str(userpquota.LifePageCounter or 0) 
     929        os.environ["PYKOTASOFTLIMIT"] = str(userpquota.SoftLimit) 
     930        os.environ["PYKOTAHARDLIMIT"] = str(userpquota.HardLimit) 
     931        os.environ["PYKOTADATELIMIT"] = str(userpquota.DateLimit) 
    904932         
    905933        # not really an user information, but anyway 
    906934        # exports the list of printers groups the current 
    907935        # printer is a member of 
    908         os.putenv("PYKOTAPGROUPS", ",".join([p.Name for p in self.storage.getParentPrinters(userpquota.Printer)])) 
    909              
     936        os.environ["PYKOTAPGROUPS"] = ",".join([p.Name for p in self.storage.getParentPrinters(userpquota.Printer)]) 
     937         
    910938    def prehook(self, userpquota) : 
    911939        """Allows plugging of an external hook before the job gets printed.""" 
  • pykota/trunk/pykota/version.py

    r1502 r1517  
    2222# 
    2323 
    24 __version__ = "1.19alpha16_unofficial" 
     24__version__ = "1.19alpha17_unofficial" 
    2525 
    2626__doc__ = """PyKota : a complete Printing Quota Solution for CUPS and LPRng."""