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

Revision 1483, 5.7 kB (checked in by jalet, 20 years ago)

Big code changes to completely remove the need for "requester" directives,
jsut use "hardware(... your previous requester directive's content ...)"

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