root / pykota / trunk / bin / pkhint @ 1339

Revision 1339, 9.0 kB (checked in by jalet, 20 years ago)

More warnings

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