root / pykota / trunk / bin / pkhint @ 1340

Revision 1340, 9.1 kB (checked in by jalet, 20 years ago)

Help

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# PyKota tool to hint for printer accounters
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.3  2004/02/07 13:56:03  jalet
27# Help
28#
29# Revision 1.2  2004/02/07 13:47:55  jalet
30# More warnings
31#
32# Revision 1.1  2004/02/07 13:45:51  jalet
33# Preliminary work on the pkhint command
34#
35#
36#
37
38import sys
39import os
40
41from pykota import version
42from pykota.tool import PyKotaTool,PyKotaToolError
43from pykota.config import PyKotaConfigError
44from pykota.storage import PyKotaStorageError
45
46__doc__ = """pkhint v%s (c) 2003-2004 C@LL - Conseil Internet & Logiciels Libres
47A tool to give hints on what accounting method is best for each printer.
48
49command line usage :
50
51  pkhint [options] [printer1 printer2 printer3 ... printerN] <file.conf
52
53options :
54
55  -v | --version       Prints pkhint's version number then exits.
56  -h | --help          Prints this message then exits.
57 
58examples :                             
59
60  $ pkhint "hp*" printer103 </etc/cups/printers.conf
61 
62  Will analyze your printing system to test which accounter
63  is the best for each of the defined printer which
64  name matches one of the parameters.
65 
66  If you don't pass any argument on the command line, all
67  printers will be analyzed.
68 
69This program is free software; you can redistribute it and/or modify
70it under the terms of the GNU General Public License as published by
71the Free Software Foundation; either version 2 of the License, or
72(at your option) any later version.
73
74This program is distributed in the hope that it will be useful,
75but WITHOUT ANY WARRANTY; without even the implied warranty of
76MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
77GNU General Public License for more details.
78
79You should have received a copy of the GNU General Public License
80along with this program; if not, write to the Free Software
81Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
82
83Please e-mail bugs to: %s""" % (version.__version__, version.__author__)
84       
85SNMPTESTS = [ \
86              '/usr/bin/npadmin --pagecount %(printer)s', \
87              '/usr/bin/snmpget -v1 -c public -Ov %(printer)s mib-2.43.10.2.1.4.1.1 | cut -f 2,2 -d " "', \
88              '/usr/bin/snmpwalk -v 1 -Cc -c public %(printer)s | grep mib-2.43.10.2.1.4.1.1 | cut -d " " -f4', \
89              '/usr/bin/snmpwalk -v 1 -Cc -c public -Ov %(printer)s | grep Counter32 | tail -2 | head -1 | cut -d " " -f2', \
90            ]
91
92class PKHint(PyKotaTool) :
93    """A class to autodetect the best accounting method for printers."""
94    def extractPrintersInformation(self) :   
95        """Extracts printer information from the printing system.
96         
97           Returns a mapping { queuename : device, ... }
98        """   
99        printers = {}
100        current_printer = None
101        for line in [l.strip() for l in sys.stdin.readlines()] :
102            testline = line.lower()
103            if testline.startswith("<printer ") or testline.startswith("<defaultprinter ") :
104                # beginning of a CUPS printer definition
105                current_printer = line.split()[-1][:-1]
106            elif testline.startswith("</printer ") :
107                # end of a CUPS printer definition
108                current_printer = None
109            elif testline.startswith("deviceuri ") :
110                # CUPS printer device_uri
111                device = testline.split()[-1]
112                if current_printer is not None :
113                    printers[current_printer] = device
114            else :       
115                # LPRng printcap specific code here
116                pass
117        return printers
118       
119    def extractDevices(self) :   
120        """Extracts the list of available CUPS devices.
121       
122           Returns a mapping { device : devicetype, ... }
123           
124           WARNING : CUPS ONLY FOR NOW
125        """   
126        inp = os.popen("/usr/sbin/lpinfo -v 2>/dev/null")
127        deviceslist = [l.strip() for l in inp.readlines()]
128        inp.close()
129        devicestypes = {}
130        for device in deviceslist :
131            (dtype, dname) = device.split()
132            devicestypes[dname] = dtype
133        return devicestypes
134       
135    def searchDeviceType(self, devicestypes, device) :   
136        """Returns the device type for current device."""
137        for (k, v) in devicestypes.items() :
138            if device.startswith(k) :
139                return v
140               
141    def extractDeviceFromURI(self, device) :   
142        """Cleans the device URI to remove any trace of PyKota."""
143        if device.startswith("cupspykota:") :
144            fulldevice = device[:]
145            device = fulldevice[len("cupspykota:"):]
146            if device.startswith("//") :
147                device = device[2:]
148        try :
149            (backend, destination) = device.split(":", 1) 
150        except ValueError :   
151            raise PyKotaToolError, "Invalid DEVICE_URI : %s\n" % device
152        while destination.startswith("/") :
153            destination = destination[1:]
154        checkauth = destination.split("@", 1)   
155        if len(checkauth) == 2 :
156            destination = checkauth[1]
157        return destination.split("/")[0]
158       
159    def acceptsSNMP(self, printer) :   
160        """Tries to get the printer's internal page counter via SNMP."""
161        for command in SNMPTESTS :
162            inp = os.popen((command + " 2>/dev/null") % locals())
163            value = inp.readline().strip()
164            inp.close()
165            try :
166                pagecounter = int(value)
167            except :   
168                pass
169            else :   
170                return command
171       
172    def main(self, args, options) :
173        """Main work is done here."""
174        print "Put the following lines into your /etc/pykota/pykota.conf file :\n"
175        printers = self.extractPrintersInformation()
176        devicestypes = self.extractDevices() # TODO : IT'S CUPS ONLY FOR NOW
177        for (printer, device) in printers.items() :
178            if self.matchString(printer, args) :
179                print "[%s]" % printer
180                devicetype = self.searchDeviceType(devicestypes, device)
181                device = self.extractDeviceFromURI(device)
182                if devicetype is None :
183                    sys.stderr.write("Unknown device %s for printer %s\n" % (device, printer))
184                elif devicetype == "network" :
185                    try :
186                        hostname, port = device.split(':')
187                    except ValueError :   
188                        hostname = device
189                    snmpcommand = self.acceptsSNMP(hostname)
190                    if snmpcommand is not None :
191                        print "accounter: querying"
192                        print 'requester: external(/usr/bin/waitprinter.sh %(printer)s && ' + snmpcommand + ')'
193                elif devicetype == "direct" : 
194                    sys.stderr.write("Can't currently handle device %s for printer %s\n" % (device, printer))
195                elif devicetype == "serial" : 
196                    sys.stderr.write("Can't currently handle device %s for printer %s\n" % (device, printer))
197                else :
198                    sys.stderr.write("Can't currently handle device %s for printer %s\n" % (device, printer))
199                print   
200       
201if __name__ == "__main__" : 
202    sys.stderr.write("BEWARE : This tool doesn't support LPRng's printcap files yet.\n")
203    sys.stderr.write("This tool is currently highly experimental, so don't rely on it.\n")
204    retcode = 0
205    try :
206        short_options = "hv"
207        long_options = ["help", "version"]
208       
209        # Initializes the command line tool
210        manager = PKHint(doc=__doc__)
211       
212        (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options)
213       
214        # sets long options
215        options["help"] = options["h"] or options["help"]
216        options["version"] = options["v"] or options["version"]
217       
218        if options["help"] :
219            manager.display_usage_and_quit()
220        elif options["version"] :
221            manager.display_version_and_quit()
222        else :
223            if not args :
224                args = [ "*" ]
225            retcode = manager.main(args, options)
226    except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg :           
227        sys.stderr.write("%s\n" % msg)
228        sys.stderr.flush()
229        retcode = -1
230
231    try :
232        manager.storage.close()
233    except (TypeError, NameError, AttributeError) :   
234        pass
235       
236    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.