root / pykota / trunk / bin / pkprinters @ 2927

Revision 2829, 15.4 kB (checked in by jerome, 19 years ago)

Did a pass with pylint.

  • 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 Printers Manager
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22#
23# $Id$
24#
25#
26
27import os
28import sys
29import pwd
30
31from pykota.tool import Percent, PyKotaTool, PyKotaCommandLineError, crashed, N_
32from pykota.storage import StoragePrinter
33
34__doc__ = N_("""pkprinters v%(__version__)s (c) %(__years__)s %(__author__)s
35
36A Printers Manager for PyKota.
37
38command line usage :
39
40  pkprinters [options] printer1 printer2 printer3 ... printerN
41
42options :
43
44  -v | --version       Prints pkprinters's version number then exits.
45  -h | --help          Prints this message then exits.
46 
47  -a | --add           Adds printers if they don't exist on the Quota
48                       Storage Server. If they exist, they are modified
49                       unless -s|--skipexisting is also used.
50                       
51  -d | --delete        Deletes printers from the quota storage.
52 
53  -D | --description d Adds a textual description to printers.
54                       
55  -c | --charge p[,j]  Sets the price per page and per job to charge.
56                       Job price is optional.
57                       If both are to be set, separate them with a comma.
58                       Floating point and negative values are allowed.
59 
60  -g | --groups pg1[,pg2...] Adds or Remove the printer(s) to the printer
61                       groups pg1, pg2, etc... which must already exist.
62                       A printer group is just like a normal printer,
63                       only that it is usually unknown from the printing
64                       system. Create printer groups exactly the same
65                       way that you create printers, then add other
66                       printers to them with this option.
67                       Accounting is done on a printer and on all
68                       the printer groups it belongs to, quota checking
69                       is done on a printer and on all the printer groups
70                       it belongs to.
71                       If the --remove option below is not used, the
72                       default action is to add printers to the specified
73                       printer groups.
74                       
75  -l | --list          List informations about the printer(s) and the
76                       printers groups it is a member of.
77                       
78  -r | --remove        In combination with the --groups option above,                       
79                       remove printers from the specified printers groups.
80                       
81  -s | --skipexisting  In combination with the --add option above, tells
82                       pkprinters to not modify existing printers.
83                       
84  -m | --maxjobsize s  Sets the maximum job size allowed on the printer
85                       to s pages.
86                       
87  -p | --passthrough   Activate passthrough mode for the printer. In this
88                       mode, users are allowed to print without any impact
89                       on their quota or account balance.
90                       
91  -n | --nopassthrough Deactivate passthrough mode for the printer.
92                       Without -p or -n, printers are created in
93                       normal mode, i.e. no passthrough.
94 
95  printer1 through printerN can contain wildcards if the --add option
96  is not set.
97 
98examples :                             
99
100  $ pkprinters --add -D "HP Printer" --charge 0.05,0.1 hp2100 hp2200 hp8000
101 
102  Will create three printers named hp2100, hp2200 and hp8000.
103  Their price per page will be set at 0.05 unit, and their price
104  per job will be set at 0.1 unit. Units are in your own currency,
105  or whatever you want them to mean.
106  All of their descriptions will be set to the string "HP Printer".
107  If any of these printers already exists, it will also be modified
108  unless the -s|--skipexisting command line option is also used.
109           
110  $ pkprinters --delete "*"
111 
112  This will completely delete all printers and associated quota information,
113  as well as their job history. USE WITH CARE !
114 
115  $ pkprinters --groups Laser,HP "hp*"
116 
117  This will put all printers which name matches "hp*" into printers groups
118  Laser and HP, which MUST already exist.
119 
120  $ pkprinters --groups LexMark --remove hp2200
121 
122  This will remove the hp2200 printer from the LexMark printer group.
123""")
124       
125class PKPrinters(PyKotaTool) :       
126    """A class for a printers manager."""
127    def modifyPrinter(self, printer, charges, perpage, perjob, description, passthrough, nopassthrough, maxjobsize) :
128        if charges :
129            printer.setPrices(perpage, perjob)   
130        if description is not None :        # NB : "" is allowed !
131            printer.setDescription(description)
132        if nopassthrough :   
133            printer.setPassThrough(False)
134        if passthrough :   
135            printer.setPassThrough(True)
136        if maxjobsize is not None :
137            printer.setMaxJobSize(maxjobsize)
138           
139    def managePrintersGroups(self, pgroups, printer, remove) :       
140        """Manage printer group membership."""
141        for pgroup in pgroups :
142            if remove :
143                pgroup.delPrinterFromGroup(printer)
144            else :
145                pgroup.addPrinterToGroup(printer)   
146               
147    def main(self, names, options) :
148        """Manage printers."""
149        if (not self.config.isAdmin) and (not options["list"]) :
150            raise PyKotaCommandLineError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
151           
152        if not options["list"] :   
153            percent = Percent(self)
154           
155        if not options["add"] :
156            if not options["list"] :
157                percent.display("%s..." % _("Extracting datas"))
158            if not names :      # NB : can't happen for --delete because it's catched earlier
159                names = ["*"]
160            printers = self.storage.getMatchingPrinters(",".join(names))
161            if not printers :
162                raise PyKotaCommandLineError, _("There's no printer matching %s") % " ".join(names)
163            if not options["list"] :   
164                percent.setSize(len(printers))
165               
166        if options["list"] :
167            for printer in printers :
168                parents = ", ".join([p.Name for p in self.storage.getParentPrinters(printer)])
169                print "%s [%s] (%s + #*%s)" % \
170                      (printer.Name, printer.Description, printer.PricePerJob, \
171                       printer.PricePerPage)
172                print "    %s" % (_("Passthrough mode : %s") % ((printer.PassThrough and _("ON")) or _("OFF")))
173                print "    %s" % (_("Maximum job size : %s") % ((printer.MaxJobSize and (_("%s pages") % printer.MaxJobSize)) or _("Unlimited")))
174                if parents : 
175                    print "    %s %s" % (_("in"), parents)
176                print   
177        elif options["delete"] :   
178            percent.display("\n%s..." % _("Deletion"))
179            self.storage.deleteManyPrinters(printers)
180            percent.display("\n")
181        else :
182            if options["groups"] :       
183                printersgroups = self.storage.getMatchingPrinters(options["groups"])
184                if not printersgroups :
185                    raise PyKotaCommandLineError, _("There's no printer matching %s") % " ".join(options["groups"].split(','))
186            else :         
187                printersgroups = []
188                   
189            if options["charge"] :
190                try :
191                    charges = [float(part) for part in options["charge"].split(',', 1)]
192                except ValueError :   
193                    raise PyKotaCommandLineError, _("Invalid charge amount value %s") % options["charge"]
194                else :   
195                    if len(charges) > 2 :
196                        charges = charges[:2]
197                    if len(charges) != 2 :
198                        charges = [charges[0], None]
199                    (perpage, perjob) = charges
200            else :       
201                charges = perpage = perjob = None
202                   
203            if options["maxjobsize"] :       
204                try :
205                    maxjobsize = int(options["maxjobsize"])
206                    if maxjobsize < 0 :
207                        raise ValueError
208                except ValueError :   
209                    raise PyKotaCommandLineError, _("Invalid maximum job size value %s") % options["maxjobsize"]
210            else :       
211                maxjobsize = None
212                   
213            description = options["description"]
214            if description :
215                description = description.strip()
216               
217            nopassthrough = options["nopassthrough"]   
218            passthrough = options["passthrough"]
219            remove = options["remove"]
220            skipexisting = options["skipexisting"]
221            self.storage.beginTransaction()
222            try :
223                if options["add"] :   
224                    percent.display("%s...\n" % _("Creation"))
225                    percent.setSize(len(names))
226                    for pname in names :
227                        if self.isValidName(pname) :
228                            printer = StoragePrinter(self.storage, pname)
229                            self.modifyPrinter(printer, charges, perpage, perjob, \
230                                           description, passthrough, \
231                                           nopassthrough, maxjobsize)
232                            oldprinter = self.storage.addPrinter(printer)               
233                            if oldprinter is not None :
234                                if skipexisting :
235                                    self.logdebug(_("Printer %s already exists, skipping.") % pname)
236                                else :   
237                                    self.logdebug(_("Printer %s already exists, will be modified.") % pname)
238                                    self.modifyPrinter(oldprinter, charges, \
239                                               perpage, perjob, description, \
240                                               passthrough, nopassthrough, \
241                                               maxjobsize)
242                                    oldprinter.save()           
243                                    self.managePrintersGroups(printersgroups, oldprinter, remove)
244                            elif printersgroups :       
245                                self.managePrintersGroups(printersgroups, \
246                                                          self.storage.getPrinter(pname), \
247                                                          remove)
248                        else :   
249                            raise PyKotaCommandLineError, _("Invalid printer name %s") % pname
250                        percent.oneMore()
251                else :       
252                    percent.display("\n%s...\n" % _("Modification"))
253                    for printer in printers :       
254                        self.modifyPrinter(printer, charges, perpage, perjob, \
255                                           description, passthrough, \
256                                           nopassthrough, maxjobsize)
257                        printer.save()   
258                        self.managePrintersGroups(printersgroups, printer, remove)
259                        percent.oneMore()
260            except :                   
261                self.storage.rollbackTransaction()
262                raise
263            else :   
264                self.storage.commitTransaction()
265               
266        if not options["list"] :
267            percent.done()
268                     
269if __name__ == "__main__" : 
270    retcode = 0
271    try :
272        short_options = "hvac:D:dg:lrsnpm:"
273        long_options = ["help", "version", "add", "charge=", "description=", \
274                        "delete", "groups=", "list", "remove", \
275                        "skipexisting", "passthrough", "nopassthrough", \
276                        "maxjobsize="]
277       
278        # Initializes the command line tool
279        manager = PKPrinters(doc=__doc__)
280        manager.deferredInit()
281       
282        # parse and checks the command line
283        (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options)
284       
285        # sets long options
286        options["help"] = options["h"] or options["help"]
287        options["version"] = options["v"] or options["version"]
288        options["add"] = options["a"] or options["add"]
289        options["charge"] = options["c"] or options["charge"]
290        options["description"] = options["D"] or options["description"]
291        options["delete"] = options["d"] or options["delete"] 
292        options["groups"] = options["g"] or options["groups"]
293        options["list"] = options["l"] or options["list"]
294        options["remove"] = options["r"] or options["remove"]
295        options["skipexisting"] = options["s"] or options["skipexisting"]
296        options["maxjobsize"] = options["m"] or options["maxjobsize"]
297        options["passthrough"] = options["p"] or options["passthrough"]
298        options["nopassthrough"] = options["n"] or options["nopassthrough"]
299       
300        if options["help"] :
301            manager.display_usage_and_quit()
302        elif options["version"] :
303            manager.display_version_and_quit()
304        elif (options["delete"] and (options["add"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \
305           or (options["skipexisting"] and not options["add"]) \
306           or (options["list"] and (options["add"] or options["delete"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \
307           or (options["passthrough"] and options["nopassthrough"]) \
308           or (options["remove"] and options["add"]) :
309            raise PyKotaCommandLineError, _("incompatible options, see help.")
310        elif options["remove"] and not options["groups"] :
311            raise PyKotaCommandLineError, _("You have to pass printer groups names on the command line")
312        elif (not args) and (options["add"] or options["delete"]) :
313            raise PyKotaCommandLineError, _("You have to pass printer names on the command line")
314        else :
315            retcode = manager.main(args, options)
316    except KeyboardInterrupt :       
317        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
318        retcode = -3
319    except PyKotaCommandLineError, msg :   
320        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
321        retcode = -2
322    except SystemExit :       
323        pass
324    except :
325        try :
326            manager.crashed("pkprinters failed")
327        except :   
328            crashed("pkprinters failed")
329        retcode = -1
330
331    try :
332        manager.storage.close()
333    except (TypeError, NameError, AttributeError) :   
334        pass
335       
336    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.