root / pykota / trunk / bin / pkprinters @ 2782

Revision 2782, 15.3 kB (checked in by jerome, 18 years ago)

Code cleaning.
Topped to 10000 the number of times the percent will be displayed by not displaying it if there's no change.
This is very useful when adding 25000 users on 300 printers through an ssh connection...

  • 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, 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            percent = Percent(self, "\n%s..." % _("Deletion"), len(printers))
174            self.storage.deleteManyPrinters(printers)
175            percent.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            self.storage.beginTransaction()
217            try :
218                if options["add"] :   
219                    percent = Percent(self, "%s...\n" % _("Creation"), len(names))
220                    for pname in names :
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.logdebug(_("Printer %s already exists, skipping.") % pname)
230                                else :   
231                                    self.logdebug(_("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.oneMore()
245                else :       
246                    percent = Percent(self, "\n%s...\n" % _("Modification"), len(printers))
247                    for printer in printers :       
248                        self.modifyPrinter(printer, charges, perpage, perjob, \
249                                           description, passthrough, \
250                                           nopassthrough, maxjobsize)
251                        printer.save()   
252                        self.managePrintersGroups(printersgroups, printer, remove)
253                        percent.oneMore()
254            except :                   
255                self.storage.rollbackTransaction()
256                raise
257            else :   
258                self.storage.commitTransaction()
259               
260        try :
261            percent.done()
262        except NameError :   
263            pass
264                     
265if __name__ == "__main__" : 
266    retcode = 0
267    try :
268        short_options = "hvac:D:dg:lrsnpm:"
269        long_options = ["help", "version", "add", "charge=", "description=", \
270                        "delete", "groups=", "list", "remove", \
271                        "skipexisting", "passthrough", "nopassthrough", \
272                        "maxjobsize="]
273       
274        # Initializes the command line tool
275        manager = PKPrinters(doc=__doc__)
276        manager.deferredInit()
277       
278        # parse and checks the command line
279        (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options)
280       
281        # sets long options
282        options["help"] = options["h"] or options["help"]
283        options["version"] = options["v"] or options["version"]
284        options["add"] = options["a"] or options["add"]
285        options["charge"] = options["c"] or options["charge"]
286        options["description"] = options["D"] or options["description"]
287        options["delete"] = options["d"] or options["delete"] 
288        options["groups"] = options["g"] or options["groups"]
289        options["list"] = options["l"] or options["list"]
290        options["remove"] = options["r"] or options["remove"]
291        options["skipexisting"] = options["s"] or options["skipexisting"]
292        options["maxjobsize"] = options["m"] or options["maxjobsize"]
293        options["passthrough"] = options["p"] or options["passthrough"]
294        options["nopassthrough"] = options["n"] or options["nopassthrough"]
295       
296        if options["help"] :
297            manager.display_usage_and_quit()
298        elif options["version"] :
299            manager.display_version_and_quit()
300        elif (options["delete"] and (options["add"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \
301           or (options["skipexisting"] and not options["add"]) \
302           or (options["list"] and (options["add"] or options["delete"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \
303           or (options["passthrough"] and options["nopassthrough"]) \
304           or (options["remove"] and options["add"]) :
305            raise PyKotaCommandLineError, _("incompatible options, see help.")
306        elif options["remove"] and not options["groups"] :
307            raise PyKotaCommandLineError, _("You have to pass printer groups names on the command line")
308        elif (not args) and (options["add"] or options["delete"]) :
309            raise PyKotaCommandLineError, _("You have to pass printer names on the command line")
310        else :
311            retcode = manager.main(args, options)
312    except KeyboardInterrupt :       
313        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
314        retcode = -3
315    except PyKotaCommandLineError, msg :   
316        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
317        retcode = -2
318    except SystemExit :       
319        pass
320    except :
321        try :
322            manager.crashed("pkprinters failed")
323        except :   
324            crashed("pkprinters failed")
325        retcode = -1
326
327    try :
328        manager.storage.close()
329    except (TypeError, NameError, AttributeError) :   
330        pass
331       
332    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.