Changeset 1495 for pykota/trunk/pykota
- Timestamp:
- 05/25/04 00:45:49 (20 years ago)
- Location:
- pykota/trunk/pykota
- Files:
-
- 6 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/pykota/accounter.py
r1483 r1495 22 22 # 23 23 # $Log$ 24 # Revision 1.15 2004/05/24 22:45:49 jalet 25 # New 'enforcement' directive added 26 # Polling loop improvements 27 # 24 28 # Revision 1.14 2004/05/18 14:49:19 jalet 25 29 # Big code changes to completely remove the need for "requester" directives, … … 84 88 self.filter = kotafilter 85 89 self.arguments = arguments 86 self.isDelayed = 0 # Accounting is immediate by default87 90 self.firstPassSize = None 88 91 … … 138 141 return 0 139 142 140 def doAccounting(self, userpquota) :141 """Does accounting for current job."""142 self.beginJob(userpquota)143 144 # Is the current user allowed to print at all ?145 action = self.filter.warnUserPQuota(userpquota)146 147 # update the quota for the current user on this printer, if allowed to print148 if action == "DENY" :149 jobsize = 0150 else :151 # get the job size152 jobsize = self.getJobSize()153 userpquota.increasePagesUsage(jobsize)154 155 # adds the current job to history156 jobprice = userpquota.computeJobPrice(jobsize)157 userpquota.Printer.addJobToHistory(self.filter.jobid, userpquota.User, self.getLastPageCounter(), action, jobsize, jobprice, self.filter.preserveinputfile, self.filter.title, self.filter.copies, self.filter.options)158 self.endJob(userpquota)159 return action160 161 143 def computeJobSize(self) : 162 144 """Must be overriden in children classes.""" 163 145 raise RuntimeError, "AccounterBase.computeJobSize() must be overriden !" 164 165 146 166 147 def openAccounter(kotafilter) : -
pykota/trunk/pykota/accounters/hardware.py
r1494 r1495 22 22 # 23 23 # $Log$ 24 # Revision 1.4 2004/05/24 22:45:49 jalet 25 # New 'enforcement' directive added 26 # Polling loop improvements 27 # 24 28 # Revision 1.3 2004/05/24 14:36:40 jalet 25 29 # Revert to old polling loop. Will need optimisations … … 44 48 """Initializes querying accounter.""" 45 49 AccounterBase.__init__(self, kotabackend, arguments) 46 self.isDelayed = 1 # With the pykota filter, accounting is delayed by one job47 50 48 51 def getPrinterInternalPageCounter(self) : … … 92 95 return jobsize 93 96 94 def doAccounting(self, userpquota) :95 """Does print accounting and returns if the job status is ALLOW or DENY."""96 # Get the page counter directly from the printer itself97 counterbeforejob = self.getPrinterInternalPageCounter() or 098 99 # Is the current user allowed to print at all ?100 action = self.filter.warnUserPQuota(userpquota)101 102 # adds the current job to history103 userpquota.Printer.addJobToHistory(self.filter.jobid, userpquota.User, counterbeforejob, action, filename=self.filter.preserveinputfile, title=self.filter.title, copies=self.filter.copies, options=self.filter.options)104 return action105 106 97 def askPrinterPageCounter(self, printer) : 107 98 """Returns the page counter from the printer via an external command. -
pykota/trunk/pykota/accounters/software.py
r1483 r1495 22 22 # 23 23 # $Log$ 24 # Revision 1.3 2004/05/24 22:45:49 jalet 25 # New 'enforcement' directive added 26 # Polling loop improvements 27 # 24 28 # Revision 1.2 2004/05/18 14:49:23 jalet 25 29 # Big code changes to completely remove the need for "requester" directives, … … 30 34 # 31 35 # 32 #33 36 34 37 import sys 35 38 import os 36 39 import popen2 37 import tempfile38 40 from pykota.accounter import AccounterBase, PyKotaAccounterError 39 41 … … 41 43 def computeJobSize(self) : 42 44 """Feeds an external command with our datas to let it compute the job size, and return its value.""" 43 temporary = None 44 if self.filter.inputfile is None : 45 infile = sys.stdin 46 # we will have to duplicate our standard input 47 temporary = tempfile.TemporaryFile() 48 else : 49 infile = open(self.filter.inputfile, "rb") 50 51 # launches software accounter 52 # TODO : USE tempfile.mkstemp() instead ! Needs some work ! 53 infilename = tempfile.mktemp() 54 outfilename = tempfile.mktemp() 55 errfilename = tempfile.mktemp() 45 self.filter.logdebug("Launching software accounter %s" % self.arguments) 46 MEGABYTE = 1024*1024 47 self.filter.jobdatastream.seek(0) 48 child = popen2.Popen4(self.arguments) 49 try : 50 data = self.filter.jobdatastream.read(MEGABYTE) 51 while data : 52 child.tochild.write(data) 53 data = self.filter.jobdatastream.read(MEGABYTE) 54 child.tochild.flush() 55 child.tochild.close() 56 except (IOError, OSError), msg : 57 msg = "%s : %s" % (self.arguments, msg) 58 self.filter.logger.log_message(_("Unable to compute job size with accounter %s") % msg) 59 60 pagecount = 0 61 try : 62 pagecount = int(child.fromchild.readline().strip()) 63 except (AttributeError, ValueError) : 64 self.filter.logger.log_message(_("Unable to compute job size with accounter %s") % self.arguments) 65 except (IOError, OSError), msg : 66 msg = "%s : %s" % (self.arguments, msg) 67 self.filter.logger.log_message(_("Unable to compute job size with accounter %s") % msg) 68 child.fromchild.close() 56 69 57 70 try : 58 # feed it with our data 59 fakeinput = open(infilename, "wb") 60 data = infile.read(256*1024) 61 while data : 62 fakeinput.write(data) 63 if temporary is not None : 64 temporary.write(data) 65 data = infile.read(256*1024) 66 fakeinput.close() 67 68 # launches child process 69 command = "%s <%s >%s 2>%s" % (self.arguments, infilename, outfilename, errfilename) 70 retcode = os.system(command) 71 72 # check exit status 73 if (os.WIFEXITED(retcode) and not os.WEXITSTATUS(retcode)) or os.stat(errfilename) : 74 # tries to extract the job size from the software accounter's 75 # standard output 76 childoutput = open(outfilename, "r") 77 try : 78 pagecount = int(childoutput.readline().strip()) 79 except (AttributeError, ValueError) : 80 self.filter.logger.log_message(_("Unable to compute job size with accounter %s") % self.arguments) 81 pagecount = 0 82 childoutput.close() 83 else : 84 self.filter.logger.log_message(_("Unable to compute job size with accounter %s") % self.arguments) 85 pagecount = 0 86 os.remove(infilename) 87 os.remove(outfilename) 88 os.remove(errfilename) 89 except IOError, msg : 90 # TODO : temporary files may remain on the filesystem... 91 msg = "%s : %s" % (self.arguments, msg) 92 self.filter.logger.log_message(_("Unable to compute job size with accounter %s") % msg) 93 pagecount = 0 94 95 if temporary is not None : 96 # this is a copy of our previous standard input 97 # flush, then rewind 98 temporary.flush() 99 temporary.seek(0, 0) 100 # our temporary file will be used later if the 101 # job is allowed. 102 self.filter.inputfile = temporary 103 else : 104 infile.close() 71 retcode = child.wait() 72 except OSError, msg : 73 self.filter.logger.log_message(_("Problem while waiting for software accounter pid %s to exit") % child.pid) 74 else : 75 if os.WIFEXITED(retcode) : 76 status = os.WEXITSTATUS(retcode) 77 else : 78 status = retcode 79 self.filter.logger.log_message(_("Software accounter %s exit code is %s") % (self.arguments, repr(retcode))) 80 self.filter.logdebug("Software accounter %s said job is %s pages long." % (self.arguments, pagecount)) 105 81 return pagecount 106 82 -
pykota/trunk/pykota/config.py
r1483 r1495 22 22 # 23 23 # $Log$ 24 # Revision 1.48 2004/05/24 22:45:49 jalet 25 # New 'enforcement' directive added 26 # Polling loop improvements 27 # 24 28 # Revision 1.47 2004/05/18 14:49:20 jalet 25 29 # Big code changes to completely remove the need for "requester" directives, … … 343 347 return # No command to launch in the post-hook 344 348 349 def getPrinterEnforcement(self, printername) : 350 """Returns if quota enforcement should be strict or laxist for the current printer.""" 351 validenforcements = [ "STRICT", "LAXIST" ] 352 try : 353 enforcement = self.getPrinterOption(printername, "enforcement") 354 except PyKotaConfigError : 355 return "LAXIST" 356 else : 357 enforcement = enforcement.upper() 358 if enforcement not in validenforcements : 359 raise PyKotaConfigError, _("Option enforcement in section %s only supports values in %s") % (printername, str(validenforcements)) 360 return enforcement 361 345 362 def getPrinterPolicy(self, printername) : 346 363 """Returns the default policy for the current printer.""" -
pykota/trunk/pykota/tool.py
r1492 r1495 22 22 # 23 23 # $Log$ 24 # Revision 1.90 2004/05/24 22:45:49 jalet 25 # New 'enforcement' directive added 26 # Polling loop improvements 27 # 24 28 # Revision 1.89 2004/05/21 22:02:52 jalet 25 29 # Preliminary work on pre-accounting … … 379 383 self.smtpserver = self.config.getSMTPServer() 380 384 self.maildomain = self.config.getMailDomain() 385 self.softwareJobPrice = 0.0 381 386 382 387 def logdebug(self, message) : … … 513 518 user = userpquota.User 514 519 printer = userpquota.Printer 520 enforcement = self.config.getPrinterEnforcement(printer.Name) 515 521 self.logdebug("Checking user %s's quota on printer %s" % (user.Name, printer.Name)) 516 522 (policy, dummy) = self.config.getPrinterPolicy(userpquota.Printer.Name) … … 524 530 else : 525 531 pagecounter = int(userpquota.PageCounter or 0) 532 if enforcement == "STRICT" : 533 pagecounter += self.softwareJobSize 526 534 if userpquota.SoftLimit is not None : 527 535 softlimit = int(userpquota.SoftLimit) … … 564 572 group = grouppquota.Group 565 573 printer = grouppquota.Printer 574 enforcement = self.config.getPrinterEnforcement(printer.Name) 566 575 self.logdebug("Checking group %s's quota on printer %s" % (group.Name, printer.Name)) 567 576 if group.LimitBy and (group.LimitBy.lower() == "balance") : 568 if group.AccountBalance <= 0.0 : 577 val = group.AccountBalance 578 if enforcement == "STRICT" : 579 val -= self.softwareJobPrice # use precomputed size. 580 if val <= 0.0 : 569 581 action = "DENY" 570 elif group.AccountBalance<= self.config.getPoorMan() :582 elif val <= self.config.getPoorMan() : 571 583 action = "WARN" 572 584 else : 573 585 action = "ALLOW" 574 586 else : 587 val = grouppquota.PageCounter 588 if enforcement == "STRICT" : 589 val += self.softwareJobSize 575 590 if grouppquota.SoftLimit is not None : 576 591 softlimit = int(grouppquota.SoftLimit) 577 if grouppquota.PageCounter< softlimit :592 if val < softlimit : 578 593 action = "ALLOW" 579 594 else : … … 583 598 else : 584 599 hardlimit = int(grouppquota.HardLimit) 585 if softlimit <= grouppquota.PageCounter< hardlimit :600 if softlimit <= val < hardlimit : 586 601 now = DateTime.now() 587 602 if grouppquota.DateLimit is not None : … … 600 615 # no soft limit, only a hard one. 601 616 hardlimit = int(grouppquota.HardLimit) 602 if grouppquota.PageCounter< hardlimit :617 if val < hardlimit : 603 618 action = "ALLOW" 604 619 else : … … 643 658 else : 644 659 val = float(user.AccountBalance or 0.0) 660 if self.config.getPrinterEnforcement(printer.Name) == "STRICT" : 661 val -= self.softwareJobPrice # use precomputed size. 645 662 if val <= 0.0 : 646 663 return "DENY" … … 820 837 def precomputeJobSize(self) : 821 838 """Computes the job size with a software method.""" 839 self.logdebug("Precomputing job's size with generic PDL analyzer...") 822 840 try : 823 841 parser = pdlanalyzer.PDLAnalyzer(self.jobdatastream) 824 returnparser.getJobSize()842 jobsize = parser.getJobSize() 825 843 except pdlanalyzer.PDLAnalyzerError, msg : 826 844 # Here we just log the failure, but … … 830 848 self.logger.log_message(_("Unable to precompute the job's size with the generic PDL analyzer."), "warn") 831 849 return 0 850 else : 851 if ((self.printingsystem == "CUPS") \ 852 and (self.preserveinputfile is not None)) \ 853 or (self.printingsystem != "CUPS") : 854 return jobsize * self.copies 855 else : 856 return jobsize 832 857 833 858 def sigterm_handler(self, signum, frame) : -
pykota/trunk/pykota/version.py
r1494 r1495 22 22 # 23 23 24 __version__ = "1.19alpha1 3_unofficial"24 __version__ = "1.19alpha14_unofficial" 25 25 26 26 __doc__ = """PyKota : a complete Printing Quota Solution for CUPS and LPRng."""