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

Revision 1600, 5.8 kB (checked in by jalet, 20 years ago)

LPRng support early version

  • 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.7  2004/07/16 12:22:47  jalet
25# LPRng support early version
26#
27# Revision 1.6  2004/07/01 19:56:42  jalet
28# Better dispatching of error messages
29#
30# Revision 1.5  2004/06/10 22:42:06  jalet
31# Better messages in logs
32#
33# Revision 1.4  2004/05/24 22:45:49  jalet
34# New 'enforcement' directive added
35# Polling loop improvements
36#
37# Revision 1.3  2004/05/24 14:36:40  jalet
38# Revert to old polling loop. Will need optimisations
39#
40# Revision 1.2  2004/05/18 14:49:22  jalet
41# Big code changes to completely remove the need for "requester" directives,
42# jsut use "hardware(... your previous requester directive's content ...)"
43#
44# Revision 1.1  2004/05/13 13:59:30  jalet
45# Code simplifications
46#
47#
48#
49
50import sys
51import os
52import popen2
53from pykota.accounter import AccounterBase, PyKotaAccounterError
54
55class Accounter(AccounterBase) :
56    def __init__(self, kotabackend, arguments) :
57        """Initializes querying accounter."""
58        AccounterBase.__init__(self, kotabackend, arguments)
59        self.isSoftware = 0
60       
61    def getPrinterInternalPageCounter(self) :   
62        """Returns the printer's internal page counter."""
63        self.filter.logdebug("Reading printer's internal page counter...")
64        try :
65            counter = self.askPrinterPageCounter(self.filter.printerhostname)
66        except PyKotaAccounterError, msg :
67            # can't get actual page counter, assume printer is off or warming up
68            # log the message anyway.
69            self.filter.printInfo("%s" % msg, "warn")
70            counter = None
71        self.filter.logdebug("Printer's internal page counter value is : %s" % str(counter))
72        return counter   
73       
74    def beginJob(self, userpquota) :   
75        """Saves printer internal page counter at start of job."""
76        # save page counter before job
77        self.LastPageCounter = self.counterbefore = self.getPrinterInternalPageCounter()
78       
79    def endJob(self, userpquota) :   
80        """Saves printer internal page counter at end of job."""
81        # save page counter after job
82        self.LastPageCounter = self.counterafter = self.getPrinterInternalPageCounter()
83       
84    def getJobSize(self) :   
85        """Returns the actual job size."""
86        try :
87            jobsize = (self.counterafter - self.counterbefore)   
88            if jobsize < 0 :
89                # Try to take care of HP printers
90                # Their internal page counter is saved to NVRAM
91                # only every 10 pages. If the printer was switched
92                # off then back on during the job, and that the
93                # counters difference is negative, we know
94                # the formula (we can't know if more than eleven
95                # pages were printed though) :
96                if jobsize > -10 :
97                    jobsize += 10
98                else :   
99                    # here we may have got a printer being replaced
100                    # DURING the job. This is HIGHLY improbable !
101                    jobsize = 0
102        except :   
103            # takes care of the case where one counter (or both) was never set.
104            jobsize = 0
105        return jobsize
106       
107    def askPrinterPageCounter(self, printer) :
108        """Returns the page counter from the printer via an external command.
109       
110           The external command must report the life time page number of the printer on stdout.
111        """
112        commandline = self.arguments.strip() % locals()
113        if printer is None :
114            raise PyKotaAccounterError, _("Unknown printer address in HARDWARE(%s) for printer %s") % (commandline, self.filter.printername)
115        self.filter.printInfo(_("Launching HARDWARE(%s)...") % commandline)
116        error = 1
117        pagecounter = None
118        child = popen2.Popen4(commandline)   
119        try :
120            line = child.fromchild.readline()
121            pagecounter = int(line.strip())
122        except ValueError :   
123            self.filter.printInfo(_("Incorrect answer : %s") % repr(line), "error")
124        except IOError :   
125            # we were interrupted by a signal, certainely a SIGTERM
126            # caused by the user cancelling the current job
127            try :
128                os.kill(child.pid, signal.SIGTERM)
129            except :   
130                pass # already killed ?
131            self.filter.printInfo(_("SIGTERM was sent to hardware accounter %s (pid: %s)") % (commandline, child.pid))
132        else :   
133            error = 0
134        child.fromchild.close()   
135        child.tochild.close()
136        try :
137            status = child.wait()
138        except OSError, msg :   
139            self.filter.logdebug("Error while waiting for hardware accounter pid %s : %s" % (child.pid, msg))
140            error = 1
141        if (not error) and os.WIFEXITED(status) and (not os.WEXITSTATUS(status)) :
142            return pagecounter
143        else :   
144            raise PyKotaAccounterError, _("Unable to query printer %s via HARDWARE(%s)") % (printer, commandline) 
145           
Note: See TracBrowser for help on using the browser.