root / pykota / trunk / bin / pkhint @ 1338

Revision 1338, 8.9 kB (checked in by jalet, 20 years ago)

Preliminary work on the pkhint command

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