root / pykota / trunk / bin / edpykota @ 3260

Revision 3260, 17.2 kB (checked in by jerome, 16 years ago)

Changed license to GNU GPL v3 or later.
Changed Python source encoding from ISO-8859-15 to UTF-8 (only ASCII
was used anyway).

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