root / pykota / trunk / bin / edpykota @ 3288

Revision 3288, 17.3 kB (checked in by jerome, 16 years ago)

Moved all exceptions definitions to a dedicated module.

  • 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: UTF-8 -*-
3#
4# PyKota : Print Quotas for CUPS
5#
6# (c) 2003, 2004, 2005, 2006, 2007, 2008 Jerome Alet <alet@librelogiciel.com>
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19#
20# $Id$
21#
22#
23
24import sys
25
26from pykota.errors import PyKotaCommandLineError
27from pykota.tool import Percent, PyKotaTool, crashed, N_
28from pykota.storage import StorageUserPQuota, StorageGroupPQuota
29
30__doc__ = N_("""edpykota v%(__version__)s (c) %(__years__)s %(__author__)s
31
32A Print Quota editor for PyKota.
33
34command line usage :
35
36  edpykota [options] user1 user2 ... userN
37 
38  edpykota [options] group1 group2 ... groupN
39
40options :
41
42  -v | --version       Prints edpykota's version number then exits.
43  -h | --help          Prints this message then exits.
44 
45  -a | --add           Adds users or groups print quota entries if
46                       they don't exist in database.
47                       
48  -d | --delete        Deletes users or groups print quota entries.
49                       Users or groups are never deleted, you have
50                       to use the pkusers command to delete them.
51                       The history will be purge from all matching
52                       jobs, unless -g | --groups is used.
53 
54  -P | --printer p     Edit quotas on printer p only. Actually p can
55                       use wildcards characters to select only
56                       some printers. The default value is *, meaning
57                       all printers.
58                       You can specify several names or wildcards,
59                       by separating them with commas.
60 
61  -g | --groups        Edit groups print quota entries instead of
62                       users print quota entries.
63                         
64  -L | --list          Lists users or groups print quota entries.
65 
66  -n | --noquota       Sets both soft and hard limits to None for users
67                       or groups print quota entries.
68 
69  -r | --reset         Resets the actual page counter for the user
70                       or group to zero on the specified printers.
71                       The life time page counter is kept unchanged.
72                       
73  -R | --hardreset     Resets the actual and life time page counters
74                       for the user or group to zero on the specified
75                       printers. This is a shortcut for '--used 0'.
76                       
77  -s | --skipexisting  In combination with the --add option above, tells
78                       edpykota to not modify existing print quota entries.
79                       
80  -S | --softlimit sl  Sets the quota soft limit to sl pages.                       
81 
82  -H | --hardlimit hl  Sets the quota hard limit to hl pages.
83 
84  -I | --increase v    Increase existing Soft and Hard limits by the value
85                       of v. You can prefix v with + or -, if no sign is
86                       used, + is assumed.
87
88  -U | --used u        Sets the page counters for the user u pages on
89                       the selected printers. Doesn't work for groups, since
90                       their page counters are the sum of all their members'
91                       page counters.
92                       Useful for migrating users from a different system
93                       where they have already used some pages. Actual
94                       and Life Time page counters may be increased or decreased
95                       if u is prefixed with + or -.
96                       WARNING : BOTH page counters are modified in all cases,
97                       so be careful.
98                       NB : if u equals '0', then the action taken is
99                       the same as if --hardreset was used.
100
101  user1 through userN and group1 through groupN can use wildcards
102  if the --add option is not set.
103 
104examples :                             
105
106  $ edpykota --add john paul george ringo
107 
108  This will create print quota entries for users john, paul, george
109  and ringo on all printers. These print quota entries will have no
110  limit set.
111 
112  $ edpykota --printer lp -S 50 -H 60 jerome
113 
114  This will set jerome's print quota on the lp printer to a soft limit
115  of 50 pages, and a hard limit of 60 pages. Both user jerome and
116  printer lp have been previously created with the pkusers and pkprinters
117  commands, respectively.
118
119  $ edpykota -g -S 500 -H 550 financial support           
120 
121  This will set print quota soft limit to 500 pages and hard limit
122  to 550 pages for groups financial and support on all printers.
123 
124  $ edpykota --reset jerome "jo*"
125 
126  This will reset jerome's page counter to zero on all printers, as
127  well as every user whose name begins with 'jo'.
128  Their life time page counter on each printer will be kept unchanged.
129  You can also reset the life time page counters by using the
130  --hardreset | -R command line option.
131 
132  $ edpykota --printer hpcolor --noquota jerome
133 
134  This will tell PyKota to not limit jerome when printing on the
135  hpcolor printer. All his jobs will be allowed on this printer, but
136  accounting of the pages he prints will still be kept.
137  Print Quotas for jerome on other printers are unchanged.
138 
139  $ edpykota --delete --printer "HP*,XER*" jerome rachel
140 
141  This will delete users jerome and rachel's print quota
142  entries on all printers which name begin with 'HP' or
143  'XER'. The jobs printed by these users on these printers
144  will be deleted from the history.
145""") 
146       
147class EdPyKota(PyKotaTool) :       
148    """A class for edpykota."""
149    def modifyPQEntry(self, pqkey, pqentry, noquota, softlimit, hardlimit, increase, reset, hardreset, suffix, used) :
150        """Modifies a print quota entry."""
151        if noquota or ((softlimit is not None) and (hardlimit is not None)) :
152            pqentry.setLimits(softlimit, hardlimit)
153        if increase :
154            newsoft = (pqentry.SoftLimit or 0) + increase         
155            newhard = (pqentry.HardLimit or 0) + increase         
156            if (newsoft >= 0) and (newhard >= 0) :
157                pqentry.setLimits(newsoft, newhard)
158            else :   
159                self.printInfo(_("You can't set negative limits for %s") % pqkey, "error")
160        if reset :
161            pqentry.reset()
162        if hardreset :   
163            pqentry.hardreset()
164        if suffix == "User" :
165            if used :
166                pqentry.setUsage(used)
167   
168    def main(self, names, options) :
169        """Edit user or group quotas."""
170        names = self.sanitizeNames(options, names)
171        suffix = (options["groups"] and "Group") or "User"       
172        printernames = options["printer"].split(",")
173           
174        if not options["list"] :
175            percent = Percent(self)
176            percent.display("%s..." % _("Extracting datas"))
177        printers = self.storage.getMatchingPrinters(options["printer"])
178        entries = getattr(self.storage, "getMatching%ss" % suffix)(",".join(names))
179        if not options["list"] :
180            percent.setSize(len(printers) * len(entries))
181       
182        if options["list"] :
183            for printer in printers :
184                for entry in entries :
185                    pqentry = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
186                    if pqentry.Exists :
187                        print "%s@%s" % (entry.Name, printer.Name)
188                        print "    %s" % (_("Page counter : %s") % pqentry.PageCounter)
189                        print "    %s" % (_("Lifetime page counter : %s") % pqentry.LifePageCounter)
190                        print "    %s" % (_("Soft limit : %s") % pqentry.SoftLimit)
191                        print "    %s" % (_("Hard limit : %s") % pqentry.HardLimit)
192                        print "    %s" % (_("Date limit : %s") % pqentry.DateLimit)
193                        print "    %s (Not supported yet)" % (_("Maximum job size : %s") % ((pqentry.MaxJobSize and (_("%s pages") % pqentry.MaxJobSize)) or _("Unlimited")))
194                        if hasattr(pqentry, "WarnCount") :
195                            print "    %s" % (_("Warning banners printed : %s") % pqentry.WarnCount)
196                        print
197        elif options["delete"] :   
198            percent.display("\n%s..." % _("Deletion"))
199            getattr(self.storage, "deleteMany%sPQuotas" % suffix)(printers, entries)
200            percent.display("\n")
201        else :
202            skipexisting = options["skipexisting"]
203            used = options["used"]
204            if used :
205                used = used.strip()
206                try :
207                    int(used)
208                except ValueError :
209                    raise PyKotaCommandLineError, _("Invalid used value %s.") % used
210                   
211            increase = options["increase"]
212            if increase :
213                try :
214                    increase = int(increase.strip())
215                except ValueError :
216                    raise PyKotaCommandLineError, _("Invalid increase value %s.") % increase
217           
218            noquota = options["noquota"]
219            reset = options["reset"]       
220            hardreset = options["hardreset"]
221            softlimit = hardlimit = None
222            if not noquota :
223                if options["softlimit"] :
224                    try :
225                        softlimit = int(options["softlimit"].strip())
226                        if softlimit < 0 :
227                            raise ValueError
228                    except ValueError :   
229                        raise PyKotaCommandLineError, _("Invalid softlimit value %s.") % options["softlimit"]
230                if options["hardlimit"] :
231                    try :
232                        hardlimit = int(options["hardlimit"].strip())
233                        if hardlimit < 0 :
234                            raise ValueError
235                    except ValueError :   
236                        raise PyKotaCommandLineError, _("Invalid hardlimit value %s.") % options["hardlimit"]
237                if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) :       
238                    # error, exchange them
239                    self.printInfo(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit))
240                    (softlimit, hardlimit) = (hardlimit, softlimit)
241                if hardlimit is None :   
242                    hardlimit = softlimit
243                    if hardlimit is not None :
244                        self.printInfo(_("Undefined hard limit set to soft limit (%s).") % str(hardlimit))
245                if softlimit is None :   
246                    softlimit = hardlimit
247                    if softlimit is not None :
248                        self.printInfo(_("Undefined soft limit set to hard limit (%s).") % str(softlimit))
249                       
250            self.storage.beginTransaction()           
251            try :
252                if options["add"] :
253                    percent.display("\n%s...\n" % _("Creation"))
254                    if not entries :   
255                        self.printInfo(_("No entry matches %s. Please use pkusers to create them first.") % (" ".join(names)), "warn")
256                           
257                    factory = globals()["Storage%sPQuota" % suffix]
258                    for printer in printers :
259                        pname = printer.Name
260                        for entry in entries :
261                            ename = entry.Name
262                            pqkey = "%s@%s" % (ename, pname)
263                            pqentry = factory(self.storage, entry, printer)
264                            self.modifyPQEntry(pqkey, pqentry, noquota, \
265                                                        softlimit, hardlimit, \
266                                                        increase, reset, \
267                                                        hardreset, suffix, used)
268                            oldpqentry = getattr(self.storage, "add%sPQuota" % suffix)(pqentry)
269                            if oldpqentry is not None :   
270                                if skipexisting :
271                                    self.logdebug("%s print quota entry %s@%s already exists, skipping." % (suffix, ename, pname))
272                                else :   
273                                    self.logdebug("%s print quota entry %s@%s already exists, will be modified." % (suffix, ename, pname))
274                                    self.modifyPQEntry(pqkey, oldpqentry, noquota, \
275                                                        softlimit, hardlimit, \
276                                                        increase, reset, \
277                                                        hardreset, suffix, used)
278                                    oldpqentry.save()                   
279                            percent.oneMore()
280                else :       
281                    percent.display("\n%s...\n" % _("Modification"))
282                    for printer in printers :
283                        for entry in entries :
284                            pqkey = "%s@%s" % (entry.Name, printer.Name)
285                            pqentry = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
286                            if pqentry.Exists :     
287                                self.modifyPQEntry(pqkey, pqentry, noquota, \
288                                                    softlimit, hardlimit, \
289                                                    increase, reset, \
290                                                    hardreset, suffix, used)
291                                pqentry.save()       
292                            percent.oneMore()
293            except :                   
294                self.storage.rollbackTransaction()
295                raise
296            else :   
297                self.storage.commitTransaction()
298                           
299        if not options["list"] :
300            percent.done()
301           
302if __name__ == "__main__" : 
303    retcode = 0
304    try :
305        defaults = { \
306                     "printer" : "*", \
307                   }
308        short_options = "vhdnagrLP:S:H:G:RU:I:s"
309        long_options = ["help", "version", \
310                        "delete", "list", \
311                        "noquota", "add", \
312                        "groups", "reset", "hardreset", \
313                        "printer=", "softlimit=", "hardlimit=", \
314                        "increase=", "used=", "skipexisting"]
315       
316        # Initializes the command line tool
317        manager = EdPyKota(doc=__doc__)
318        manager.deferredInit()
319       
320        # parse and checks the command line
321        (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options)
322       
323        # sets long options
324        options["help"] = options["h"] or options["help"]
325        options["version"] = options["v"] or options["version"]
326        options["add"] = options["a"] or options["add"]
327        options["groups"] = options["g"] or options["groups"]
328        options["printer"] = options["P"] or options["printer"] or defaults["printer"]
329        options["softlimit"] = options["S"] or options["softlimit"]
330        options["hardlimit"] = options["H"] or options["hardlimit"] 
331        options["reset"] = options["r"] or options["reset"] 
332        options["noquota"] = options["n"] or options["noquota"]
333        options["delete"] = options["d"] or options["delete"] 
334        options["hardreset"] = options["R"] or options["hardreset"] 
335        options["used"] = options["U"] or options["used"]
336        options["increase"] = options["I"] or options["increase"]
337        options["list"] = options["L"] or options["list"]
338        options["skipexisting"] = options["s"] or options["skipexisting"]
339       
340        if options["help"] :
341            manager.display_usage_and_quit()
342        elif options["version"] :
343            manager.display_version_and_quit()
344        elif (options["add"] and options["delete"]) \
345             or (options["noquota"] and (options["hardlimit"] or options["softlimit"])) \
346             or (options["groups"] and options["used"]) \
347             or (options["skipexisting"] and not options["add"]) :
348            raise PyKotaCommandLineError, _("incompatible options, see help.")
349        elif options["delete"] and not args :
350            raise PyKotaCommandLineError, _("You have to pass user or group names on the command line")
351        else :
352            retcode = manager.main(args, options)
353    except KeyboardInterrupt :       
354        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
355        retcode = -3
356    except PyKotaCommandLineError, msg :     
357        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
358        retcode = -2
359    except SystemExit :       
360        pass
361    except :
362        try :
363            manager.crashed("edpykota failed")
364        except :   
365            crashed("edpykota failed")
366        retcode = -1
367
368    try :
369        manager.storage.close()
370    except (TypeError, NameError, AttributeError) :   
371        pass
372       
373    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.