Changeset 1475
- Timestamp:
- 05/13/04 15:59:30 (20 years ago)
- Location:
- pykota/trunk
- Files:
-
- 2 added
- 4 removed
- 12 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/bin/pkhint
r1423 r1475 24 24 # 25 25 # $Log$ 26 # Revision 1.7 2004/05/13 13:59:27 jalet 27 # Code simplifications 28 # 26 29 # Revision 1.6 2004/03/30 12:59:47 jalet 27 30 # Fixed path problem … … 211 214 snmpcommand = self.accepts(SNMPTESTS, hostname) 212 215 if snmpcommand is not None : 213 accounter = " querying"216 accounter = "hardware" 214 217 requester = 'external(/usr/share/pykota/waitprinter.sh %(printer)s && ' + snmpcommand + ')' 215 218 configuration.append((printer, accounter, requester)) … … 217 220 netpjlcommand = self.accepts(NETPJLTESTS, hostname, port) 218 221 if netpjlcommand is not None : 219 accounter = " querying"222 accounter = "hardware" 220 223 requester = 'external(' + netpjlcommand + ')' 221 224 configuration.append((printer, accounter, requester)) -
pykota/trunk/conf/pykota.conf.sample
r1442 r1475 182 182 # supported values : 183 183 # 184 # - querying: asks the printer for its lifetime page counter184 # - hardware : asks the printer for its lifetime page counter 185 185 # via either SNMP, AppleTalk, or any external 186 186 # command. This method is the method used by 187 187 # default in PyKota since its beginning. 188 188 # 189 # - external : delegates the job's size computation to any 190 # external command of your choice. A stupid and 191 # completely unreliable example, but which 192 # shows what this command may be is : 193 # 194 # accounter: external(/bin/grep -c showpage) 195 # 196 # Another one, which should work with all DSC 197 # compliant Postscript files : 198 # 199 # accounter: external(/bin/grep -c "%%Page:") 200 # 201 # Finally the new smart external accounter which 202 # can handle both PostScript and PCL documents : 203 # 204 # accounter: external(/usr/bin/pkpgcounter) 205 # 206 # - stupid : counts the occurences of the 'showpage' postscript 207 # statement in the document to be printed. 208 # THIS IS NOT RELIABLE. This is just to serve as 209 # an example on how to implement your own accounting 210 # method. Use pkpgcounter instead. 211 # 189 # - software : delegates the job's size computation to any 190 # external command of your choice. 191 # 192 # best choice for this is probably to set it 193 # this way : 194 # 195 # accounter: software(/usr/bin/pkpgcounter) 196 # 197 # pkpgcounter is a command line tool which is 198 # part of PyKota and which can handle both 199 # DSC compliant PostScript documents and PCL5 200 # documents. More file formats will be added 201 # in the future, as time permits. 202 # 203 # while pkpgcounter is the recommended value 204 # you can use whatever command you want provided 205 # that your command accepts the job's data on its 206 # standard input and prints the job's size in pages 207 # as a single integer on its standard output. 208 # 212 209 # This value can be set either globally or on a per printer basis 213 210 # If both are defined, the printer option has priority. 214 # if not set it defaults to 'querying'. 215 # 216 # A script which seems to be accurate, copy it from the 217 # untested/postscript directory to another place. 218 # accounter: external(/usr/share/pykota/pagecount.sh) 219 # WARNING : it may not work when multiple copies are asked. 220 # this breaks ghostscript, I don't know why yet. 211 # if not set it defaults to 'hardware'. 221 212 # 222 213 # default value 223 accounter: querying 214 accounter: hardware 215 # accounter: software(/usr/bin/pkpgcounter) 224 216 225 217 # Print Quota administrator … … 326 318 327 319 # How to query the hpmarketing printer for its page counter. 328 # THIS IS ONLY USED IF YOU HAVE SET 'accounter' TO ' querying'320 # THIS IS ONLY USED IF YOU HAVE SET 'accounter' TO 'hardware' 329 321 # JUST COMMENT IT OUT IF YOU USE ANY OTHER ACCOUNTING METHOD. 330 322 # (it would be ignored anyway) … … 332 324 # In the lines below "%(printer)s" is automatically replaced 333 325 # at run time with your printer's Fully Qualified Domain Name 326 # for network printers. 334 327 # e.g. myprinter.example.com 335 328 # 336 # Only snmp(community, oid) and external(command) are supported329 # Only value supported is : external(... your command here...) 337 330 # 338 331 # Example : 332 # 339 333 # requester: external(/usr/bin/snmpget -v1 -c public -Ov %(printer)s mib-2.43.10.2.1.4.1.1 | cut -f 2,2 -d " ") 340 # and :341 # requester: snmp(public, mib-2.43.10.2.1.4.1.1)342 # are equivalent343 #344 #################################################345 # NB : the 'snmp()' requester is now deprecated #346 # because it has some accuracy problems. #347 # please use 'external()' instead. #348 #################################################349 334 # 350 335 # Another untested example, using npadmin : 336 # 351 337 # requester: external(/usr/bin/npadmin --pagecount %(printer)s) 352 338 # … … 355 341 # pagecount.ps file from untested/netatalk into /etc or any 356 342 # appropriate location) 343 # 357 344 # requester: external(/usr/share/pykota/papwaitprinter.sh "MyPrinter:LaserWriter@*" && /usr/bin/pap -p "MyPrinter:LaserWriter@*" /usr/share/pykota/pagecount.ps 2>/dev/null | /bin/grep -v status | /bin/grep -v Connect | /usr/bin/tail -1) 358 345 # … … 361 348 # requester: external(/bin/cat /usr/share/pykota/pagecount.pjl >/dev/lp0 && /usr/bin/head -2 </dev/lp0 | /usr/bin/tail -1) 362 349 # 363 #364 350 # This value can be set either globally or per printer or both. 365 351 # If both are defined, the printer option has priority. 366 #367 # NB : The SNMP oid mib-2.43.10.2.1.4.1.1 works on HP Laserjet Printers, but it may368 # be different with other brands, refer to your printer's documentation369 # for details. Also you may have to specify -v2c or -v3 depending on your370 # printer's support for different versions of the SNMP specification.371 #372 352 # 373 353 # Some examples and comments provided by Bob Martel from csuohio.edu … … 382 362 # 383 363 # requester: external(/opt/local/net-snmp/bin/snmpwalk -v 1 -Cc -c public -Ov %(printer)s | grep Counter32 | tail -2 | head -1 | cut -d " " -f2) 384 #385 364 # 386 365 # An example using netcat and a preformatted PJL job which you can find … … 390 369 # requester: external(/bin/nc -w 2 %(printer)s 9100 </usr/share/pykota/pagecount.pjl | /usr/bin/tail -2) 391 370 # 392 #393 371 # An example using the contributed pagecount.pl script which does 394 372 # the same as above, but should work on more printers : 395 373 # 396 374 # requester: external(/usr/share/pykota/pagecount.pl %(printer)s 9100) 397 #398 375 # 399 376 # WARNING : In any case, when using an external requester, please test the command line outside … … 404 381 # not yet finished (not all pages are printed, but the complete job is in 405 382 # the printer) 383 # 384 # YOU ABSOLUTELY HAVE TO BE SURE YOU HAVE A SCRIPT WHICH WAITS FOR THE 385 # PRINTER BEING READY BEFORE ASKING FOR ITS INTERNAL PAGE COUNTER. 386 # 387 # PYKOTA INCLUDES SUCH SCRIPTS FOR SNMP AND APPLETALK PRINTERS, MORE TO COME 388 # 389 # default value 406 390 requester: external(/usr/share/pykota/waitprinter.sh %(printer)s && /usr/bin/snmpget -v1 -c public -Ov %(printer)s mib-2.43.10.2.1.4.1.1 | cut -f 2,2 -d " ") 407 391 -
pykota/trunk/docs/filterpykota.sgml
r1386 r1475 72 72 73 73 <para> 74 When using the <literal> querying</literal> accounting method,74 When using the <literal>hardware</literal> accounting method, 75 75 <application>pykota</application> asks the printer for its internal page counter, reads from the Quota DataBase the internal 76 76 page counter for this printer when the previous job was launched, computes the difference, and report it as the … … 86 86 87 87 <para> 88 When using the <literal> external</literal> accounting method,88 When using the <literal>software</literal> accounting method, 89 89 and if the user is still allowed to print, 90 90 the command you specified is launched with the job's data on its … … 92 92 pages on a single line on its standard output. This number is then 93 93 read by PyKota and used to update the current user's quota information. 94 Of course checks are also done like with the <literal> querying</literal>94 Of course checks are also done like with the <literal>hardware</literal> 95 95 accounting method, to see if the current job is allowed to be printed or not. 96 96 </para> … … 108 108 109 109 $Log$ 110 Revision 1.10 2004/05/13 13:59:28 jalet 111 Code simplifications 112 110 113 Revision 1.9 2004/03/03 19:35:36 jalet 111 114 Spelling problem. Thanks to Jurandy Martins -
pykota/trunk/NEWS
r1473 r1475 22 22 PyKota NEWS : 23 23 24 - 1.19alpha8 : 25 26 - 'querying' accounting method is now called 'hardware' 27 28 - 'external' accounting method is now called 'software' 29 30 - 'stupid' accounting method doesn't exist anymore 31 32 - 'snmp' requester doesn't exist anymore 33 34 - code simplifications in external requester 35 24 36 - 1.19alpha7 : 25 37 -
pykota/trunk/pykota/accounters/Makefile.am
r1417 r1475 2 2 3 3 pykota_accounters_PYTHON = \ 4 external.py \4 software.py \ 5 5 __init__.py \ 6 querying.py \ 7 stupid.py 6 hardware.py 8 7 -
pykota/trunk/pykota/config.py
r1371 r1475 22 22 # 23 23 # $Log$ 24 # Revision 1.46 2004/05/13 13:59:28 jalet 25 # Code simplifications 26 # 24 27 # Revision 1.45 2004/03/01 10:22:30 jalet 25 28 # Can now extract per printer pre and post hooks from the configuration file … … 303 306 """Returns the accounter backend to use for a given printer. 304 307 305 if it is not set, it defaults to ' querying' which means ask printer308 if it is not set, it defaults to 'hardware' which means ask printer 306 309 for its internal lifetime page counter. 307 310 """ 308 validaccounters = [ " querying", "stupid", "external" ]311 validaccounters = [ "hardware", "software" ] 309 312 fullaccounter = self.getPrinterOption(printername, "accounter").strip() 310 if fullaccounter.lower().startswith(" external") :313 if fullaccounter.lower().startswith("software") : 311 314 try : 312 315 (accounter, args) = [x.strip() for x in fullaccounter.split('(', 1)] … … 343 346 except PyKotaConfigError : 344 347 # No requester defined, maybe it is not needed if accounting method 345 # is not set to ' querying', but if we are called, then the accounting346 # method really IS ' querying', and so there's a big problem.348 # is not set to 'hardware', but if we are called, then the accounting 349 # method really IS 'hardware', and so there's a big problem. 347 350 raise PyKotaConfigError, _("Option requester for printer %s was not set") % printername 348 351 else : … … 355 358 if not args : 356 359 raise PyKotaConfigError, _("Invalid requester %s for printer %s") % (fullrequester, printername) 357 validrequesters = [ " snmp", "external" ] # TODO : add more requesters360 validrequesters = [ "external" ] 358 361 requester = requester.lower() 359 362 if requester not in validrequesters : -
pykota/trunk/pykota/requesters/external.py
r1433 r1475 22 22 # 23 23 # $Log$ 24 # Revision 1.12 2004/05/13 13:59:30 jalet 25 # Code simplifications 26 # 24 27 # Revision 1.11 2004/04/09 22:24:47 jalet 25 28 # Began work on correct handling of child processes when jobs are cancelled by … … 63 66 # 64 67 68 import sys 65 69 import os 70 import popen2 71 import signal 66 72 from pykota.requester import PyKotaRequesterError 67 73 … … 82 88 if printer is None : 83 89 raise PyKotaRequesterError, _("Unknown printer address in EXTERNAL(%s) for printer %s") % (commandline, self.printername) 84 answer = os.popen(commandline) 90 error = 1 91 pagecounter = None 92 child = popen2.Popen4(commandline) 85 93 try : 86 pagecounter = int( answer.readline().strip())94 pagecounter = int(child.fromchild.readline().strip()) 87 95 except ValueError : 96 pass 97 except IOError : 98 # we were interrupted by a signal, certainely a SIGTERM 99 # caused by the user cancelling the current job 100 try : 101 os.kill(child.pid, signal.SIGTERM) 102 except : 103 pass # already killed ? 104 self.kotabackend.logger.log_message(_("SIGTERM was sent to external requester %s (pid: %s)") % (commandline, child.pid), "info") 105 else : 106 error = 0 107 child.fromchild.close() 108 child.tochild.close() 109 status = child.wait() 110 if (not error) and os.WIFEXITED(status) and (not os.WEXITSTATUS(status)) : 111 return pagecounter 112 else : 88 113 raise PyKotaRequesterError, _("Unable to query printer %s via EXTERNAL(%s)") % (printer, commandline) 89 answer.close()90 return pagecounter91 114 -
pykota/trunk/pykota/requesters/Makefile.am
r1417 r1475 3 3 pykota_requesters_PYTHON = \ 4 4 external.py \ 5 __init__.py \ 6 snmp.py 5 __init__.py 7 6 -
pykota/trunk/pykota/tool.py
r1469 r1475 22 22 # 23 23 # $Log$ 24 # Revision 1.86 2004/05/13 13:59:28 jalet 25 # Code simplifications 26 # 24 27 # Revision 1.85 2004/05/11 08:26:27 jalet 25 28 # Now catches connection problems to SMTP server … … 809 812 810 813 def prehook(self, userpquota) : 811 """Allows plug ing of an external hook before the job gets printed."""814 """Allows plugging of an external hook before the job gets printed.""" 812 815 prehook = self.config.getPreHook(userpquota.Printer.Name) 813 816 if prehook : … … 816 819 817 820 def posthook(self, userpquota) : 818 """Allows plug ing of an external hook after the job gets printed and/or denied."""821 """Allows plugging of an external hook after the job gets printed and/or denied.""" 819 822 posthook = self.config.getPostHook(userpquota.Printer.Name) 820 823 if posthook : -
pykota/trunk/pykota/version.py
r1473 r1475 22 22 # 23 23 24 __version__ = "1.19alpha 7_unofficial"24 __version__ = "1.19alpha8_unofficial" 25 25 26 26 __doc__ = """PyKota : a complete Printing Quota Solution for CUPS and LPRng.""" -
pykota/trunk/README
r1408 r1475 43 43 44 44 - Supports OpenLDAP as the Quota Storage backend. 45 Complete LDAP schema and sample tree are included.45 Complete LDAP schema and sample empty tree are included. 46 46 Plugging PyKota into your existing LDAP infrastructure 47 47 is really easy thanks to PyKota's great configurability. … … 49 49 Printers : 50 50 51 - Hardware or Software accounting methods are completely 52 configurable. 53 51 54 - Supports any printer which can report its internal 52 page counter. 55 page counter. Can ask printers for their internal 56 page counter via SNMP, Netatalk, or any other way. 57 This is completely configurable. 58 59 - Supports PostScript and PCL5 printers natively, 60 more formats to come. 53 61 54 62 - Supports any other printer via GhostScript. 55 63 Depending on the printer some configuration may 56 64 be needed. 57 58 - Can ask printers for their internal page counter59 via SNMP, Netatalk, or any other mean of your60 choice. This is completely configurable.61 62 - External accounting methods are configurable.63 65 64 66 Quota systems : … … 156 158 implemented : 157 159 158 - The ' querying' method consists in querying the printer (via SNMP160 - The 'hardware' method consists in querying the printer (via SNMP 159 161 or Netatalk or any other method of your choice) for its total pages 160 162 counter. … … 168 170 of one print job, but this is generally ok. 169 171 170 - The ' external' method consists in delegating the computation of the172 - The 'software' method consists in delegating the computation of the 171 173 job's size in number of pages to any external command of your choice. 172 174 The command can read the job's data from its standard input and MUST … … 174 176 account are reported immediately, both with CUPS and LPRng. 175 177 176 - The 'stupid' method consists in counting the 'showpage' PostSript177 statements in the job. THIS IS UNRELIABLE, SO DON'T USE IT, but178 can serve as an example if you plan to write your own accounting179 method for integration into PyKota. It basically works like the180 'external' method, but does the computation internally and in181 a non-reliable way.182 183 178 PyKota is known to work fine with HP Laserjet 2100 and 2200, and 184 179 Apple LaserWriter 16/600 PS, both with CUPS and LPRng, under -
pykota/trunk/setup.py
r1430 r1475 24 24 # 25 25 # $Log$ 26 # Revision 1.40 2004/05/13 13:59:27 jalet 27 # Code simplifications 28 # 26 29 # Revision 1.39 2004/04/08 17:07:41 jalet 27 30 # pkpgcounter added … … 173 176 sys.exit(-1) 174 177 178 from distutils import sysconfig 175 179 sys.path.insert(0, "pykota") 176 180 from pykota.version import __version__, __doc__ … … 179 183 ACTION_ABORT = 1 180 184 185 def checkOldModule(path) : 186 """Checks if an old PyKota module is still in the destination (in case of upgrade).""" 187 fname = os.path.join(sysconfig.get_python_lib(), "pykota", path) 188 for ext in ["py", "pyc", "pyo"] : 189 fullname = "%s.%s" % (fname, ext) 190 if os.path.isfile(fullname) : 191 sys.stderr.write("ERROR : old module %s still exists. Remove it and restart installation.\n" % fullname) 192 sys.stderr.write("INSTALLATION ABORTED !\n") 193 sys.exit(-1) 194 181 195 def checkOldScript(cmd) : 182 196 """Checks if an old shell script is still around in /usr/bin.""" … … 282 296 sys.stderr.write("\nINSTALLATION ABORTED !\nPlease correct the problem and restart installation.\n") 283 297 sys.exit(-1) 298 299 # now checks if pre-1.19alpha8 code is still there 300 for module in ["accounters/querying", "accounters/external", "requesters/snmp"] : 301 checkOldModule(module) 284 302 285 303 # Second stage, we will fail if onfiguration is incorrect for security reasons … … 348 366 349 367 # WARNING MESSAGE 350 sys.stdout.write("WARNING : IF YOU ARE UPGRADING FROM A PRE-1.1 4 TO 1.16OR ABOVE\n")368 sys.stdout.write("WARNING : IF YOU ARE UPGRADING FROM A PRE-1.19alpha7 TO 1.19alpha7 OR ABOVE\n") 351 369 sys.stdout.write("AND USE THE POSTGRESQL BACKEND, THEN YOU HAVE TO MODIFY YOUR\n") 352 sys.stdout.write("DATABASE SCHEMA USING initscripts/postgresql/upgrade-to-1.14.sql\n") 353 sys.stdout.write("AND initscripts/postgresql/upgrade-to-1.16.sql\n") 370 sys.stdout.write("DATABASE SCHEMA USING initscripts/postgresql/upgrade-to-1.19.sql\n") 354 371 sys.stdout.write("PLEASE READ DOCUMENTATION IN initscripts/postgresql/ TO LEARN HOW TO DO.\n") 355 372 sys.stdout.write("YOU CAN DO THAT AFTER THE INSTALLATION IS FINISHED, OR PRESS CTRL+C NOW.\n") 356 sys.stdout.write("\n\nYOU DON'T HAVE ANYTHING SPECIAL TO DO IF THIS IS YOUR FIRST INSTALLATION\nOR IF YOU ARE ALREADY RUNNING VERSION 1.1 6OR ABOVE.\n\n")373 sys.stdout.write("\n\nYOU DON'T HAVE ANYTHING SPECIAL TO DO IF THIS IS YOUR FIRST INSTALLATION\nOR IF YOU ARE ALREADY RUNNING VERSION 1.19alpha7 OR ABOVE.\n\n") 357 374 dummy = raw_input("Please press ENTER when you have read the message above. ") 358 375