Show
Ignore:
Timestamp:
04/29/03 20:37:54 (21 years ago)
Author:
jalet
Message:

Pluggable accounting methods (actually doesn't support external scripts)

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/pykota

    r966 r973  
    2323# 
    2424# $Log$ 
     25# Revision 1.29  2003/04/29 18:37:54  jalet 
     26# Pluggable accounting methods (actually doesn't support external scripts) 
     27# 
    2528# Revision 1.28  2003/04/26 08:41:24  jalet 
    2629# Small code reorganisation (UNTESTED) to allow pluggable accounting 
     
    133136 
    134137from pykota.tool import PyKotaTool, PyKotaToolError 
    135 from pykota.requester import openRequester, PyKotaRequesterError 
    136  
    137 MAXTRIES = 6     # maximum number of tries to get the printer's internal page counter 
    138 TIMETOSLEEP = 10 # number of seconds to sleep between two tries to get the printer's internal page counter 
     138from pykota.storage import PyKotaStorageError 
     139from pykota.accounter import openAccounter, PyKotaAccounterError 
    139140 
    140141class PyKotaFilter(PyKotaTool) :     
     
    143144        PyKotaTool.__init__(self) 
    144145        (self.printingsystem, self.printerhostname, self.printername, self.username, self.jobid, self.inputfile) = self.extractInfoFromCupsOrLprng() 
    145         self.requester = openRequester(self.config, self.printername) 
    146      
     146        self.accounter = openAccounter(self) 
     147     
     148    def extractInfoFromCupsOrLprng(self) :     
     149        """Returns a tuple (printingsystem, printerhostname, printername, username, jobid, filename) depending on the printing system in use (as seen by the print filter). 
     150         
     151           Returns (None, None, None, None, None, None) if no printing system is recognized. 
     152        """ 
     153        # Try to detect CUPS 
     154        if os.environ.has_key("CUPS_SERVERROOT") and os.path.isdir(os.environ.get("CUPS_SERVERROOT", "")) : 
     155            if len(sys.argv) == 7 : 
     156                inputfile = sys.argv[6] 
     157            else :     
     158                inputfile = None 
     159                 
     160            device_uri = os.environ.get("DEVICE_URI", "") 
     161            # TODO : check this for more complex urls than ipp://myprinter.dot.com:631/printers/lp 
     162            try : 
     163                (backend, destination) = device_uri.split(":", 1)  
     164            except ValueError :     
     165                raise PyKotaToolError, "Invalid DEVICE_URI : %s\n" % device_uri 
     166            while destination.startswith("/") : 
     167                destination = destination[1:] 
     168            printerhostname = destination.split("/")[0].split(":")[0] 
     169            return ("CUPS", printerhostname, os.environ.get("PRINTER"), sys.argv[2].strip(), sys.argv[1].strip(), inputfile) 
     170        else :     
     171            # Try to detect LPRng 
     172            jseen = Jseen = Pseen = nseen = rseen = None 
     173            for arg in sys.argv : 
     174                if arg.startswith("-j") : 
     175                    jseen = arg[2:].strip() 
     176                elif arg.startswith("-J") :     
     177                    Jseen = arg[2:].strip() 
     178                    if Jseen == "(STDIN)" : 
     179                        Jseen = None 
     180                elif arg.startswith("-n") :      
     181                    nseen = arg[2:].strip() 
     182                elif arg.startswith("-P") :     
     183                    Pseen = arg[2:].strip() 
     184                elif arg.startswith("-r") :     
     185                    rseen = arg[2:].strip() 
     186            if jseen and Pseen and nseen and rseen :         
     187                return ("LPRNG", rseen, Pseen, nseen, jseen, Jseen) 
     188        return (None, None, None, None, None, None)   # Unknown printing system           
     189         
    147190    def filterInput(self, inputfile) : 
    148191        """Transparent filter.""" 
     
    182225def main() :     
    183226    """Do it, and do it right !""" 
    184     global MAXTRIES, TIMETOSLEEP 
    185      
    186227    # Initializes the current tool 
    187228    kotafilter = PyKotaFilter()     
     
    216257                return kotafilter.removeJob() 
    217258        else : 
    218             # Get the page counter directly from the printer itself 
    219             # Tries MAXTRIES times, sleeping two seconds each time, in case the printer is sleeping. 
    220             # This was seen with my Apple LaserWriter 16/600 PS which doesn't answer before having warmed up. 
    221             for i in range(MAXTRIES) : 
    222                 try : 
    223                     counterbeforejob = kotafilter.requester.getPrinterPageCounter(kotafilter.printerhostname) 
    224                 except PyKotaRequesterError, msg : 
    225                     # can't get actual page counter, assume printer is off or warming up 
    226                     # log the message anyway. 
    227                     kotafilter.logger.log_message("%s" % msg, "warn") 
    228                     counterbeforejob = None 
    229                     printerIsOff = 1 
    230                 else :     
    231                     # printer answered, it is on so we can exit the loop 
    232                     printerIsOff = 0 
    233                     break 
    234                 time.sleep(TIMETOSLEEP)     
    235          
    236             # get last job information for this printer 
    237             pgc = kotafilter.storage.getPrinterPageCounter(printerid)     
    238             if pgc is None : 
    239                 # The printer hasn't been used yet, from PyKota's point of view 
    240                 lasthistoryid = None 
    241                 lastjobid = kotafilter.jobid 
    242                 lastuserid = userid 
    243                 lastusername = kotafilter.username 
    244                 lastpagecounter = counterbeforejob 
    245             else :     
    246                 # get last values from Quota Storage 
    247                 (lasthistoryid, lastjobid, lastuserid, lastusername, lastpagecounter) = (pgc["id"], pgc["jobid"], pgc["userid"], pgc["username"], pgc["pagecounter"]) 
    248                  
    249             # if printer is off then we assume the correct counter value is the last one 
    250             if printerIsOff : 
    251                 counterbeforejob = lastpagecounter 
    252                  
    253             # if the internal lifetime page counter for this printer is 0     
    254             # then this may be a printer with a volatile counter (never 
    255             # saved to NVRAM) which has just been switched off and then on 
    256             # so we use the last page counter from the Quota Storage instead 
    257             # explanation at : http://web.mit.edu/source/third/lprng/doc/LPRng-HOWTO-15.html 
    258             if counterbeforejob == 0 : 
    259                 counterbeforejob = lastpagecounter 
    260                  
    261             # Computes the last job size as the difference between internal page 
    262             # counter in the printer and last page counter taken from the Quota 
    263             # Storage database for this particular printer 
    264             try : 
    265                 jobsize = (counterbeforejob - lastpagecounter)     
    266             except TypeError :     
    267                 # never used, and internal page counter not accessible 
    268                 jobsize = 0 
    269                  
    270             if jobsize < 0 : 
    271                 # Probably an HP printer which was switched off and back on,  
    272                 # its primary counter is only saved in a 10 increment, so 
    273                 # it may be lower than the last page counter saved in the 
    274                 # Quota Storage.  
    275                 # We unconditionnally set the last job's size to  
    276                 # abs(int((10 - abs(lastcounter(snmp) - lastcounter(storage)) / 2)) 
    277                 # For more accurate accounting, don't switch off your HP printers ! 
    278                 # explanation at : http://web.mit.edu/source/third/lprng/doc/LPRng-HOWTO-15.html 
    279                 kotafilter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, lastusername, kotafilter.printername), "error") 
    280                 jobsize = abs(int((10 - abs(jobsize)) / 2))     # Workaround for HP printers' feature ! 
    281                  
    282             # update the quota for the previous user on this printer  
    283             kotafilter.storage.updateUserPQuota(lastuserid, printerid, jobsize) 
    284              
    285             # update the last job size in the history 
    286             kotafilter.storage.updateJobSizeInHistory(lasthistoryid, jobsize) 
    287              
    288             # warns the last user if he is over quota 
    289             kotafilter.warnUserPQuota(lastusername, kotafilter.printername) 
    290                  
    291             # Is the current user allowed to print at all ? 
    292             action = kotafilter.warnUserPQuota(kotafilter.username, kotafilter.printername) 
    293              
    294             # adds the current job to history     
    295             kotafilter.storage.addJobToHistory(kotafilter.jobid, kotafilter.storage.getUserId(kotafilter.username), printerid, counterbeforejob, action) 
     259            # Now does the accounting and act depending on the result 
     260            action = kotafilter.accounter.doAccounting(printerid, userid) 
    296261             
    297262            # if not allowed to print then die, else proceed. 
     
    306271 
    307272if __name__ == "__main__" :     
    308     sys.exit(main()) 
     273    try : 
     274        retcode = main() 
     275    except (PyKotaToolError, PyKotaStorageError, PyKotaAccounterError), msg : 
     276        sys.stderr.write("ERROR : PyKota filter failed (%s)\n" % msg) 
     277        sys.stderr.flush() 
     278        retcode = -1 
     279    sys.exit(retcode)     
     280