root / pykota / trunk / bin / pkprinters @ 2768

Revision 2768, 15.2 kB (checked in by jerome, 19 years ago)

Optimized pkprinters like pkbcodes and edpykota.

  • 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 PyKotaTool, PyKotaToolError, 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["add"] :
153            if not options["list"] :
154                self.display(_("Extracting datas..."))
155            if not names :      # NB : can't happen for --delete because it's catched earlier
156                names = ["*"]
157            printers = self.storage.getMatchingPrinters(",".join(names))
158            if not printers :
159                raise PyKotaCommandLineError, _("There's no printer matching %s") % " ".join(names)
160               
161        if options["list"] :
162            for printer in printers :
163                parents = ", ".join([p.Name for p in self.storage.getParentPrinters(printer)])
164                print "%s [%s] (%s + #*%s)" % \
165                      (printer.Name, printer.Description, printer.PricePerJob, \
166                       printer.PricePerPage)
167                print "    %s" % (_("Passthrough mode : %s") % ((printer.PassThrough and _("ON")) or _("OFF")))
168                print "    %s" % (_("Maximum job size : %s") % ((printer.MaxJobSize and (_("%s pages") % printer.MaxJobSize)) or _("Unlimited")))
169                if parents : 
170                    print "    %s %s" % (_("in"), parents)
171                print   
172        elif options["delete"] :   
173            self.display("\n%s..." % _("Deletion"))
174            self.storage.deleteManyPrinters(printers)
175            self.display("\n")
176        else :
177            if options["groups"] :       
178                printersgroups = self.storage.getMatchingPrinters(options["groups"])
179                if not printersgroups :
180                    raise PyKotaCommandLineError, _("There's no printer matching %s") % " ".join(options["groups"].split(','))
181            else :         
182                printersgroups = []
183                   
184            if options["charge"] :
185                try :
186                    charges = [float(part) for part in options["charge"].split(',', 1)]
187                except ValueError :   
188                    raise PyKotaCommandLineError, _("Invalid charge amount value %s") % options["charge"]
189                else :   
190                    if len(charges) > 2 :
191                        charges = charges[:2]
192                    if len(charges) != 2 :
193                        charges = [charges[0], None]
194                    (perpage, perjob) = charges
195            else :       
196                charges = perpage = perjob = None
197                   
198            if options["maxjobsize"] :       
199                try :
200                    maxjobsize = int(options["maxjobsize"])
201                    if maxjobsize < 0 :
202                        raise ValueError
203                except ValueError :   
204                    raise PyKotaCommandLineError, _("Invalid maximum job size value %s") % options["maxjobsize"]
205            else :       
206                maxjobsize = None
207                   
208            description = options["description"]
209            if description :
210                description = description.strip()
211               
212            nopassthrough = options["nopassthrough"]   
213            passthrough = options["passthrough"]
214            remove = options["remove"]
215            skipexisting = options["skipexisting"]
216            if options["add"] :   
217                self.display("%s...\n" % _("Creation"))
218                nbtotal = len(names)
219                for i in range(nbtotal) :
220                    pname = names[i]
221                    if self.isValidName(pname) :
222                        printer = StoragePrinter(self.storage, pname)
223                        self.modifyPrinter(printer, charges, perpage, perjob,\
224                                       description, passthrough, \
225                                       nopassthrough, maxjobsize)
226                        oldprinter = self.storage.addPrinter(printer)               
227                        if oldprinter is not None :
228                            if skipexisting :
229                                self.printInfo(_("Printer %s already exists, skipping.") % pname)
230                            else :   
231                                self.printInfo(_("Printer %s already exists, will be modified.") % pname)
232                                self.modifyPrinter(oldprinter, charges, \
233                                           perpage, perjob, description, \
234                                           passthrough, nopassthrough, \
235                                           maxjobsize)
236                                oldprinter.save()           
237                                self.managePrintersGroups(printersgroups, oldprinter, remove)
238                        elif printersgroups :       
239                            self.managePrintersGroups(printersgroups, \
240                                                      self.storage.getPrinter(pname), \
241                                                      remove)
242                    else :   
243                        raise PyKotaCommandLineError, _("Invalid printer name %s") % pname
244                    percent = 100.0 * float(i) / float(nbtotal)
245                    self.display("\r%.02f%%" % percent)
246            else :       
247                self.display("\n%s...\n" % _("Modification"))
248                nbtotal = len(printers)
249                for i in range(nbtotal) :       
250                    printer = printers[i]
251                    self.modifyPrinter(printer, charges, perpage, perjob, \
252                                       description, passthrough, \
253                                       nopassthrough, maxjobsize)
254                    printer.save()   
255                    self.managePrintersGroups(printersgroups, printer, remove)
256                    percent = 100.0 * float(i) / float(nbtotal)
257                    self.display("\r%.02f%%" % percent)
258                               
259        if not options["list"] :               
260            self.done()
261                     
262if __name__ == "__main__" : 
263    retcode = 0
264    try :
265        short_options = "hvac:D:dg:lrsnpm:"
266        long_options = ["help", "version", "add", "charge=", "description=", \
267                        "delete", "groups=", "list", "remove", \
268                        "skipexisting", "passthrough", "nopassthrough", \
269                        "maxjobsize="]
270       
271        # Initializes the command line tool
272        manager = PKPrinters(doc=__doc__)
273        manager.deferredInit()
274       
275        # parse and checks the command line
276        (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options)
277       
278        # sets long options
279        options["help"] = options["h"] or options["help"]
280        options["version"] = options["v"] or options["version"]
281        options["add"] = options["a"] or options["add"]
282        options["charge"] = options["c"] or options["charge"]
283        options["description"] = options["D"] or options["description"]
284        options["delete"] = options["d"] or options["delete"] 
285        options["groups"] = options["g"] or options["groups"]
286        options["list"] = options["l"] or options["list"]
287        options["remove"] = options["r"] or options["remove"]
288        options["skipexisting"] = options["s"] or options["skipexisting"]
289        options["maxjobsize"] = options["m"] or options["maxjobsize"]
290        options["passthrough"] = options["p"] or options["passthrough"]
291        options["nopassthrough"] = options["n"] or options["nopassthrough"]
292       
293        if options["help"] :
294            manager.display_usage_and_quit()
295        elif options["version"] :
296            manager.display_version_and_quit()
297        elif (options["delete"] and (options["add"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \
298           or (options["skipexisting"] and not options["add"]) \
299           or (options["list"] and (options["add"] or options["delete"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \
300           or (options["passthrough"] and options["nopassthrough"]) \
301           or (options["remove"] and options["add"]) :
302            raise PyKotaCommandLineError, _("incompatible options, see help.")
303        elif options["remove"] and not options["groups"] :
304            raise PyKotaCommandLineError, _("You have to pass printer groups names on the command line")
305        elif (not args) and (options["add"] or options["delete"]) :
306            raise PyKotaCommandLineError, _("You have to pass printer names on the command line")
307        else :
308            retcode = manager.main(args, options)
309    except KeyboardInterrupt :       
310        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
311        retcode = -3
312    except PyKotaCommandLineError, msg :   
313        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
314        retcode = -2
315    except SystemExit :       
316        pass
317    except :
318        try :
319            manager.crashed("pkprinters failed")
320        except :   
321            crashed("pkprinters failed")
322        retcode = -1
323
324    try :
325        manager.storage.close()
326    except (TypeError, NameError, AttributeError) :   
327        pass
328       
329    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.