root / pykota / trunk / pykota / accounters / hardware.py @ 1624

Revision 1624, 6.0 kB (checked in by jalet, 20 years ago)

Hardware accounting for LPRng should be OK now. UNTESTED.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1# PyKota
2# -*- coding: ISO-8859-15 -*-
3#
4# PyKota - Print Quotas for CUPS and LPRng
5#
6# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20#
21# $Id$
22#
23# $Log$
24# Revision 1.8  2004/07/22 22:41:48  jalet
25# Hardware accounting for LPRng should be OK now. UNTESTED.
26#
27# Revision 1.7  2004/07/16 12:22:47  jalet
28# LPRng support early version
29#
30# Revision 1.6  2004/07/01 19:56:42  jalet
31# Better dispatching of error messages
32#
33# Revision 1.5  2004/06/10 22:42:06  jalet
34# Better messages in logs
35#
36# Revision 1.4  2004/05/24 22:45:49  jalet
37# New 'enforcement' directive added
38# Polling loop improvements
39#
40# Revision 1.3  2004/05/24 14:36:40  jalet
41# Revert to old polling loop. Will need optimisations
42#
43# Revision 1.2  2004/05/18 14:49:22  jalet
44# Big code changes to completely remove the need for "requester" directives,
45# jsut use "hardware(... your previous requester directive's content ...)"
46#
47# Revision 1.1  2004/05/13 13:59:30  jalet
48# Code simplifications
49#
50#
51#
52
53import sys
54import os
55import popen2
56from pykota.accounter import AccounterBase, PyKotaAccounterError
57
58class Accounter(AccounterBase) :
59    def __init__(self, kotabackend, arguments) :
60        """Initializes querying accounter."""
61        AccounterBase.__init__(self, kotabackend, arguments)
62        self.isSoftware = 0
63       
64    def getPrinterInternalPageCounter(self) :   
65        """Returns the printer's internal page counter."""
66        self.filter.logdebug("Reading printer's internal page counter...")
67        try :
68            counter = self.askPrinterPageCounter(self.filter.printerhostname)
69        except PyKotaAccounterError, msg :
70            # can't get actual page counter, assume printer is off or warming up
71            # log the message anyway.
72            self.filter.printInfo("%s" % msg, "warn")
73            counter = None
74        self.filter.logdebug("Printer's internal page counter value is : %s" % str(counter))
75        return counter   
76       
77    def beginJob(self, printer) :   
78        """Saves printer internal page counter at start of job."""
79        # save page counter before job
80        self.LastPageCounter = self.getPrinterInternalPageCounter()
81        self.fakeBeginJob()
82       
83    def fakeBeginJob(self) :   
84        """Fakes a begining of a job."""
85        self.counterbefore = self.getLastPageCounter()
86       
87    def endJob(self, printer) :   
88        """Saves printer internal page counter at end of job."""
89        # save page counter after job
90        self.LastPageCounter = self.counterafter = self.getPrinterInternalPageCounter()
91       
92    def getJobSize(self) :   
93        """Returns the actual job size."""
94        try :
95            jobsize = (self.counterafter - self.counterbefore)   
96            if jobsize < 0 :
97                # Try to take care of HP printers
98                # Their internal page counter is saved to NVRAM
99                # only every 10 pages. If the printer was switched
100                # off then back on during the job, and that the
101                # counters difference is negative, we know
102                # the formula (we can't know if more than eleven
103                # pages were printed though) :
104                if jobsize > -10 :
105                    jobsize += 10
106                else :   
107                    # here we may have got a printer being replaced
108                    # DURING the job. This is HIGHLY improbable !
109                    jobsize = 0
110        except :   
111            # takes care of the case where one counter (or both) was never set.
112            jobsize = 0
113        return jobsize
114       
115    def askPrinterPageCounter(self, printer) :
116        """Returns the page counter from the printer via an external command.
117       
118           The external command must report the life time page number of the printer on stdout.
119        """
120        commandline = self.arguments.strip() % locals()
121        if printer is None :
122            raise PyKotaAccounterError, _("Unknown printer address in HARDWARE(%s) for printer %s") % (commandline, self.filter.printername)
123        self.filter.printInfo(_("Launching HARDWARE(%s)...") % commandline)
124        error = 1
125        pagecounter = None
126        child = popen2.Popen4(commandline)   
127        try :
128            line = child.fromchild.readline()
129            pagecounter = int(line.strip())
130        except ValueError :   
131            self.filter.printInfo(_("Incorrect answer : %s") % repr(line), "error")
132        except IOError :   
133            # we were interrupted by a signal, certainely a SIGTERM
134            # caused by the user cancelling the current job
135            try :
136                os.kill(child.pid, signal.SIGTERM)
137            except :   
138                pass # already killed ?
139            self.filter.printInfo(_("SIGTERM was sent to hardware accounter %s (pid: %s)") % (commandline, child.pid))
140        else :   
141            error = 0
142        child.fromchild.close()   
143        child.tochild.close()
144        try :
145            status = child.wait()
146        except OSError, msg :   
147            self.filter.logdebug("Error while waiting for hardware accounter pid %s : %s" % (child.pid, msg))
148            error = 1
149        if (not error) and os.WIFEXITED(status) and (not os.WEXITSTATUS(status)) :
150            return pagecounter
151        else :   
152            raise PyKotaAccounterError, _("Unable to query printer %s via HARDWARE(%s)") % (printer, commandline) 
153           
Note: See TracBrowser for help on using the browser.