root / pykota / trunk / bin / edpykota @ 2749

Revision 2749, 18.6 kB (checked in by jerome, 18 years ago)

Now manage print quota entries the way it should be done (c) (tm) !

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