root / pykota / trunk / bin / edpykota @ 2761

Revision 2761, 18.2 kB (checked in by jerome, 18 years ago)

Now limits group listing to the groups the current user is a member of.

  • 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/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 modifyPQEntry(self, pqkey, pqentry, noquota, softlimit, hardlimit, increase, reset, hardreset, suffix, used) :
156        """Modifies a print quota entry."""
157        if noquota or ((softlimit is not None) and (hardlimit is not None)) :
158            pqentry.setLimits(softlimit, hardlimit)
159        if increase :
160            newsoft = (pqentry.SoftLimit or 0) + increase         
161            newhard = (pqentry.HardLimit or 0) + increase         
162            if (newsoft >= 0) and (newhard >= 0) :
163                pqentry.setLimits(newsoft, newhard)
164            else :   
165                self.printInfo(_("You can't set negative limits for %s") % pqkey, "error")
166        if reset :
167            pqentry.reset()
168        if hardreset :   
169            pqentry.hardreset()
170        if suffix == "User" :
171            if used :
172                pqentry.setUsage(used)
173   
174    def main(self, names, options) :
175        """Edit user or group quotas."""
176        if not self.config.isAdmin :
177            username = pwd.getpwuid(os.geteuid())[0]
178            if not options["list"] :
179                raise PyKotaCommandLineError, "%s : %s" % (username, _("You're not allowed to use this command."))
180            else :
181                names = [ username ]
182                if options["groups"] :
183                    user = self.storage.getUser(username)
184                    if user.Exists :
185                        names = [ g.Name for g in self.storage.getUserGroups(user) ]
186        elif not names :       
187            names = ["*"]
188           
189        suffix = (options["groups"] and "Group") or "User"       
190        printernames = options["printer"].split(",")
191           
192        if not options["list"] :
193            self.display(_("Extracting datas..."))
194        printers = self.storage.getMatchingPrinters(options["printer"])
195        entries = getattr(self.storage, "getMatching%ss" % suffix)(",".join(names))
196       
197        if options["delete"] :   
198            self.display("\n%s..." % _("Deletion"))
199            getattr(self.storage, "deleteMany%sPQuotas" % suffix)(printers, entries)
200            self.display("\n")
201            self.display("\r100.00%%\r        \r%s\n" % _("Done."))
202        elif options["list"] :
203            for printer in printers :
204                for entry in entries :
205                    pqentry = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
206                    if pqentry.Exists :
207                        print "%s@%s" % (entry.Name, printer.Name)
208                        print "    %s" % (_("Page counter : %s") % pqentry.PageCounter)
209                        print "    %s" % (_("Lifetime page counter : %s") % pqentry.LifePageCounter)
210                        print "    %s" % (_("Soft limit : %s") % pqentry.SoftLimit)
211                        print "    %s" % (_("Hard limit : %s") % pqentry.HardLimit)
212                        print "    %s" % (_("Date limit : %s") % pqentry.DateLimit)
213                        print "    %s (Not supported yet)" % (_("Maximum job size : %s") % ((pqentry.MaxJobSize and (_("%s pages") % pqentry.MaxJobSize)) or _("Unlimited")))
214                        if hasattr(pqentry, "WarnCount") :
215                            print "    %s" % (_("Warning banners printed : %s") % pqentry.WarnCount)
216                        print
217        else :
218            self.display("\n")   
219            skipexisting = options["skipexisting"]
220            used = options["used"]
221            if used :
222                used = used.strip()
223                try :
224                    int(used)
225                except ValueError :
226                    raise PyKotaCommandLineError, _("Invalid used value %s.") % used
227                   
228            increase = options["increase"]
229            if increase :
230                try :
231                    increase = int(increase.strip())
232                except ValueError :
233                    raise PyKotaCommandLineError, _("Invalid increase value %s.") % increase
234           
235            noquota = options["noquota"]
236            reset = options["reset"]       
237            hardreset = options["hardreset"]
238            softlimit = hardlimit = None
239            if not noquota :
240                if options["softlimit"] :
241                    try :
242                        softlimit = int(options["softlimit"].strip())
243                        if softlimit < 0 :
244                            raise ValueError
245                    except ValueError :   
246                        raise PyKotaCommandLineError, _("Invalid softlimit value %s.") % options["softlimit"]
247                if options["hardlimit"] :
248                    try :
249                        hardlimit = int(options["hardlimit"].strip())
250                        if hardlimit < 0 :
251                            raise ValueError
252                    except ValueError :   
253                        raise PyKotaCommandLineError, _("Invalid hardlimit value %s.") % options["hardlimit"]
254                if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) :       
255                    # error, exchange them
256                    self.printInfo(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit))
257                    (softlimit, hardlimit) = (hardlimit, softlimit)
258                if hardlimit is None :   
259                    hardlimit = softlimit
260                    if hardlimit is not None :
261                        self.printInfo(_("Undefined hard limit set to soft limit (%s).") % str(hardlimit))
262                if softlimit is None :   
263                    softlimit = hardlimit
264                    if softlimit is not None :
265                        self.printInfo(_("Undefined soft limit set to hard limit (%s).") % str(softlimit))
266                       
267            if options["add"] :
268                self.display("%s...\n" % _("Creation"))
269                dicnames = {}
270                for m in entries :
271                    dicnames[m.Name] = None
272                for name in names :
273                    if not dicnames.has_key(name) :
274                        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")
275                       
276                factory = globals()["Storage%sPQuota" % suffix]
277                nbtotal = len(printers) * len(entries)
278                i = 0
279                for printer in printers :
280                    pname = printer.Name
281                    for entry in entries :
282                        ename = entry.Name
283                        pqkey = "%s@%s" % (ename, pname)
284                        pqentry = factory(self.storage, entry, printer)
285                        self.modifyPQEntry(pqkey, pqentry, noquota, \
286                                                    softlimit, hardlimit, \
287                                                    increase, reset, \
288                                                    hardreset, suffix, used)
289                        oldpqentry = getattr(self.storage, "add%sPQuota" % suffix)(pqentry)
290                        if oldpqentry is not None :   
291                            if skipexisting :
292                                self.logdebug("%s print quota entry %s@%s already exists, skipping." % (suffix, ename, pname))
293                            else :   
294                                self.logdebug("%s print quota entry %s@%s already exists, will be modified." % (suffix, ename, pname))
295                                self.modifyPQEntry(pqkey, oldpqentry, noquota, \
296                                                    softlimit, hardlimit, \
297                                                    increase, reset, \
298                                                    hardreset, suffix, used)
299                                oldpqentry.save()                   
300                        i += 1
301                        percent = 100.0 * float(i) / float(nbtotal)
302                        self.display("\r%.02f%%" % percent)
303            else :       
304                nbtotal = len(entries) * len(printers)
305                if nbtotal :
306                    self.display("%s...\n" % _("Modification"))
307                    i = 0
308                    for printer in printers :
309                        for entry in entries :
310                            pqkey = "%s@%s" % (entry.Name, printer.Name)
311                            pqentry = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
312                            if pqentry.Exists :     
313                                self.modifyPQEntry(pqkey, pqentry, noquota, \
314                                                    softlimit, hardlimit, \
315                                                    increase, reset, \
316                                                    hardreset, suffix, used)
317                                pqentry.save()       
318                            i += 1           
319                            percent = 100.0 * float(i) / float(nbtotal)
320                            self.display("\r%.02f%%" % percent)
321            self.display("\r100.00%%\r        \r%s\n" % _("Done."))
322                     
323if __name__ == "__main__" : 
324    retcode = 0
325    try :
326        defaults = { \
327                     "printer" : "*", \
328                   }
329        short_options = "vhdnagrLP:S:H:G:RU:I:s"
330        long_options = ["help", "version", \
331                        "delete", "list", \
332                        "noquota", "add", \
333                        "groups", "reset", "hardreset", \
334                        "printer=", "softlimit=", "hardlimit=", \
335                        "increase=", "used=", "skipexisting"]
336       
337        # Initializes the command line tool
338        manager = EdPyKota(doc=__doc__)
339        manager.deferredInit()
340       
341        # parse and checks the command line
342        (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options)
343       
344        # sets long options
345        options["help"] = options["h"] or options["help"]
346        options["version"] = options["v"] or options["version"]
347        options["add"] = options["a"] or options["add"]
348        options["groups"] = options["g"] or options["groups"]
349        options["printer"] = options["P"] or options["printer"] or defaults["printer"]
350        options["softlimit"] = options["S"] or options["softlimit"]
351        options["hardlimit"] = options["H"] or options["hardlimit"] 
352        options["reset"] = options["r"] or options["reset"] 
353        options["noquota"] = options["n"] or options["noquota"]
354        options["delete"] = options["d"] or options["delete"] 
355        options["hardreset"] = options["R"] or options["hardreset"] 
356        options["used"] = options["U"] or options["used"]
357        options["increase"] = options["I"] or options["increase"]
358        options["list"] = options["L"] or options["list"]
359        options["skipexisting"] = options["s"] or options["skipexisting"]
360       
361        if options["help"] :
362            manager.display_usage_and_quit()
363        elif options["version"] :
364            manager.display_version_and_quit()
365        elif (options["add"] and options["delete"]) \
366             or (options["noquota"] and (options["hardlimit"] or options["softlimit"])) \
367             or (options["groups"] and options["used"]) \
368             or (options["skipexisting"] and not options["add"]) :
369            raise PyKotaCommandLineError, _("incompatible options, see help.")
370        elif options["delete"] and not args :
371            raise PyKotaCommandLineError, _("You have to pass user or group names on the command line")
372        else :
373            retcode = manager.main(args, options)
374    except KeyboardInterrupt :       
375        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
376        retcode = -3
377    except PyKotaCommandLineError, msg :     
378        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
379        retcode = -2
380    except SystemExit :       
381        pass
382    except :
383        try :
384            manager.crashed("edpykota failed")
385        except :   
386            crashed("edpykota failed")
387        retcode = -1
388
389    try :
390        manager.storage.close()
391    except (TypeError, NameError, AttributeError) :   
392        pass
393       
394    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.