root / pykota / trunk / bin / edpykota @ 2742

Revision 2742, 18.4 kB (checked in by jerome, 18 years ago)

Now ouputs some timing info even when debug:no is used.
Also uses psyco, which halves the time spent before deletion begins.
The storagecaching:yes directive is not at fault.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[696]1#! /usr/bin/env python
[1144]2# -*- coding: ISO-8859-15 -*-
[696]3
4# PyKota Print Quota Editor
5#
[952]6# PyKota - Print Quotas for CUPS and LPRng
[696]7#
[2622]8# (c) 2003, 2004, 2005, 2006 Jerome Alet <alet@librelogiciel.com>
[873]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.
[696]13#
[873]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
[2303]21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
[696]22#
23# $Id$
24#
[2073]25#
[696]26
[715]27import sys
[1809]28import os
29import pwd
[1956]30import grp
[2742]31import time
[2512]32from pykota.tool import PyKotaTool, PyKotaToolError, PyKotaCommandLineError, crashed, N_
[975]33from pykota.config import PyKotaConfigError
34from pykota.storage import PyKotaStorageError
[715]35
[2344]36__doc__ = N_("""edpykota v%(__version__)s (c) %(__years__)s %(__author__)s
[2267]37
[715]38A Print Quota editor for PyKota.
39
40command line usage :
41
[717]42  edpykota [options] user1 user2 ... userN
[937]43 
[717]44  edpykota [options] group1 group2 ... groupN
[715]45
46options :
47
48  -v | --version       Prints edpykota's version number then exits.
49  -h | --help          Prints this message then exits.
50 
[2712]51  -a | --add           Adds users or groups print quota entries if
52                       they don't exist in database.
[715]53                       
[2712]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.
[2728]57                       The history will be purge from all matching
58                       jobs, unless -g | --groups is used.
[921]59 
[719]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
[1156]63                       all printers.
64                       You can specify several names or wildcards,
65                       by separating them with commas.
[715]66 
[2712]67  -g | --groups        Edit groups print quota entries instead of
68                       users print quota entries.
[715]69                         
[2728]70  -L | --list          Lists users or groups print quota entries.
71 
[2712]72  -n | --noquota       Sets both soft and hard limits to None for users
73                       or groups print quota entries.
[843]74 
[1755]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.
[768]78                       
[1755]79  -R | --hardreset     Resets the actual and life time page counters
80                       for the user or group to zero on the specified
[1967]81                       printers. This is a shortcut for '--used 0'.
[1755]82                       
[2728]83  -s | --skipexisting  In combination with the --add option above, tells
84                       edpykota to not modify existing print quota entries.
85                       
[715]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.
[2454]89 
[2712]90  -I | --increase v    Increase existing Soft and Hard limits by the value
[2454]91                       of v. You can prefix v with + or -, if no sign is
92                       used, + is assumed.
[1967]93
[2712]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
[1967]99                       where they have already used some pages. Actual
100                       and Life Time page counters may be increased or decreased
[2712]101                       if u is prefixed with + or -.
[1967]102                       WARNING : BOTH page counters are modified in all cases,
103                       so be careful.
[2712]104                       NB : if u equals '0', then the action taken is
[1967]105                       the same as if --hardreset was used.
106
[815]107  user1 through userN and group1 through groupN can use wildcards
108  if the --add option is not set.
109 
[715]110examples :                             
111
[2712]112  $ edpykota --add john paul george ringo
[715]113 
[2712]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.
[715]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
[2712]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.
[715]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.
[769]129 
[815]130  $ edpykota --reset jerome "jo*"
[769]131 
[815]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.
[1755]135  You can also reset the life time page counters by using the
136  --hardreset | -R command line option.
[843]137 
[847]138  $ edpykota --printer hpcolor --noquota jerome
[843]139 
[847]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.
[848]143  Print Quotas for jerome on other printers are unchanged.
[917]144 
[2712]145  $ edpykota --delete --printer "HP*,XER*" jerome rachel
[917]146 
[2712]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.
[2344]151""") 
[715]152       
[719]153class EdPyKota(PyKotaTool) :       
154    """A class for edpykota."""
155    def main(self, names, options) :
156        """Edit user or group quotas."""
[1789]157        if not self.config.isAdmin :
[2512]158            raise PyKotaCommandLineError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
[1041]159       
160        suffix = (options["groups"] and "Group") or "User"       
[2731]161        printernames = options["printer"].split(",")
[1041]162       
[2657]163        if options["delete"] :   
[2728]164            self.display("%s...\n" % _("Deletion"))
[2742]165            #printers = self.storage.getMatchingPrinters(options["printer"])
166            #entries = getattr(self.storage, "getMatching%ss" % suffix)(",".join(names))
167            before = time.time()
168            (printers, entries, pqentries) = getattr(self.storage, "getPrinters%ssAndPQuotas" % suffix)(printernames, names)
169            after = time.time()
170            self.printInfo("Data extraction took %.4f seconds" % (after - before))
171            nbtotal = len(pqentries)
172            for i in range(nbtotal) :
173                (pqkey, pqentry) = pqentries.popitem()
174                if pqentry.Exists :
175                    pqentry.delete()
176                percent = 100.0 * float(i) / float(nbtotal)
177                self.display("\r%.02f%%" % percent)
[2657]178        else :
[2739]179            if not names :
180                names = ["*"]
181            (printers, entries, pqentries) = getattr(self.storage, "getPrinters%ssAndPQuotas" % suffix)(printernames, names)
[2731]182            skipexisting = options["skipexisting"]
[2728]183            if options["add"] :
[2731]184                self.display("%s...\n" % _("Creation"))
[2737]185                mentries = getattr(self.storage, "getMatching%ss" % suffix)(",".join(names))
[2738]186                dicnames = {}
187                for m in mentries :
188                    dicnames[m.Name] = None
189                for name in names :
190                    if not dicnames.has_key(name) :
191                        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")
[2731]192                mprinters = self.storage.getMatchingPrinters(options["printer"])
193                nbtotal = len(mprinters) * len(mentries)
194                i = 0
195                for printer in mprinters :
196                    pname = printer.Name
197                    for entry in mentries :
198                        ename = entry.Name
199                        pqkey = "%s@%s" % (ename, pname)
200                        if pqentries.has_key(pqkey) and pqentries[pqkey].Exists :
201                            if skipexisting :
202                                self.printInfo(_("%s print quota entry %s@%s already exists, skipping.") % (suffix, ename, pname))
203                                del pqentries[pqkey]
204                            else :   
205                                self.printInfo(_("%s print quota entry %s@%s already exists, will be modified.") % (suffix, ename, pname))
206                        else :       
207                            newpqentry = getattr(self.storage, "add%sPQuota" % suffix)(entry, printer)
208                            if not newpqentry.Exists :
209                                self.printInfo(_("Impossible to create a print quota entry for %s@%s") % (ename, pname))
210                            else :
211                                pqentries[pqkey] = newpqentry
[2735]212                        i += 1
[2731]213                        percent = 100.0 * float(i) / float(nbtotal)
214                        self.display("\r%.02f%%" % percent)
215                self.display("\r100.00%%\r        \r%s\n" % _("Done."))
216               
217            if not pqentries :
218                raise PyKotaCommandLineError, _("There's no %s print quota entry matching %s") % (suffix.lower(), " ".join(names))
[2657]219                   
[2728]220            if options["list"] :
221                for (name, entry) in pqentries.items() :
222                    if entry.Exists :
223                        print name
224                        print "    %s" % (_("Page counter : %s") % entry.PageCounter)
225                        print "    %s" % (_("Lifetime page counter : %s") % entry.LifePageCounter)
226                        print "    %s" % (_("Soft limit : %s") % entry.SoftLimit)
227                        print "    %s" % (_("Hard limit : %s") % entry.HardLimit)
228                        print "    %s" % (_("Date limit : %s") % entry.DateLimit)
229                        # TODO : print "    %s" % (_("Maximum job size : %s") % ((entry.MaxJobSize and (_("%s pages") % entry.MaxJobSize)) or _("Unlimited")))
230                        if hasattr(entry, "WarnCount") :
231                            print "    %s" % (_("Warning banners printed : %s") % entry.WarnCount)
232                        print
233            else :
234                self.display("%s...\n" % _("Modification"))
235               
236                used = options["used"]
237                if used :
238                    used = used.strip()
[2657]239                    try :
[2728]240                        int(used)
241                    except ValueError :
242                        raise PyKotaCommandLineError, _("Invalid used value %s.") % used
243                       
244                increase = options["increase"]
245                if increase :
[2657]246                    try :
[2728]247                        increase = int(increase.strip())
248                    except ValueError :
249                        raise PyKotaCommandLineError, _("Invalid increase value %s.") % increase
[2454]250               
[2735]251                softlimit = hardlimit = None
252                noquota = options["noquota"]
253                if not noquota :
[2728]254                    if options["softlimit"] :
255                        try :
256                            softlimit = int(options["softlimit"].strip())
257                            if softlimit < 0 :
258                                raise ValueError
259                        except ValueError :   
260                            raise PyKotaCommandLineError, _("Invalid softlimit value %s.") % options["softlimit"]
261                    if options["hardlimit"] :
262                        try :
263                            hardlimit = int(options["hardlimit"].strip())
264                            if hardlimit < 0 :
265                                raise ValueError
266                        except ValueError :   
267                            raise PyKotaCommandLineError, _("Invalid hardlimit value %s.") % options["hardlimit"]
268                    if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) :       
269                        # error, exchange them
270                        self.printInfo(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit))
271                        (softlimit, hardlimit) = (hardlimit, softlimit)
[2735]272                    if hardlimit is None :   
273                        hardlimit = softlimit
274                        if hardlimit is not None :
275                            self.printInfo(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer.Name))
276                    if softlimit is None :   
277                        softlimit = hardlimit
278                        if softlimit is not None :
279                            self.printInfo(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer.Name))
[2657]280                   
[2735]281                nbtotal = len(pqentries)   
282                i = 0
[2737]283                for (pqkey, pqentry) in pqentries.items() :
[2735]284                    ename = getattr(pqentry, suffix).Name
285                    pname = pqentry.Printer.Name
286                    if pqentry.Exists :     
287                        if noquota or ((softlimit is not None) and (hardlimit is not None)) :
288                            pqentry.setLimits(softlimit, hardlimit)
289                           
290                        if increase :
291                           if (pqentry.SoftLimit is None) \
292                               or (pqentry.HardLimit is None) :
293                               self.printInfo(_("You can't increase limits by %s when no limit is set.") % increase, "error")
294                           else :
295                               newsoft = pqentry.SoftLimit + increase         
296                               newhard = pqentry.HardLimit + increase         
297                               if (newsoft >= 0) and (newhard >= 0) :
298                                   pqentry.setLimits(newsoft, newhard)
299                               else :   
300                                   self.printInfo(_("You can't set negative limits."), "error")
[1105]301                       
[2735]302                        if options["reset"] :
303                            pqentry.reset()
[1366]304                           
[2735]305                        if options["hardreset"] :   
306                            pqentry.hardreset()
307                           
308                        if not options["groups"] :
309                            if used :
310                                pqentry.setUsage(used)
[2054]311                               
[2735]312                        pqentry.save()       
313                    i += 1           
314                    percent = 100.0 * float(i) / float(nbtotal)
315                    self.display("\r%.02f%%" % percent)
[2728]316                               
317        if not options["list"] :               
318            self.display("\r100.00%%\r        \r%s\n" % _("Done."))
[719]319                     
[715]320if __name__ == "__main__" : 
[2742]321    try : 
322       import psyco
323       psyco.profile()
324    except :   
325       pass
[1113]326    retcode = 0
[715]327    try :
328        defaults = { \
[719]329                     "printer" : "*", \
[715]330                   }
[2728]331        short_options = "vhdnagrLP:S:H:G:RU:I:s"
[2712]332        long_options = ["help", "version", \
[2728]333                        "delete", "list", \
[2712]334                        "noquota", "add", \
335                        "groups", "reset", "hardreset", \
336                        "printer=", "softlimit=", "hardlimit=", \
[2728]337                        "increase=", "used=", "skipexisting"]
[715]338       
339        # Initializes the command line tool
[2712]340        manager = EdPyKota(doc=__doc__)
341        manager.deferredInit()
[715]342       
343        # parse and checks the command line
[2712]344        (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options)
[715]345       
346        # sets long options
347        options["help"] = options["h"] or options["help"]
348        options["version"] = options["v"] or options["version"]
349        options["add"] = options["a"] or options["add"]
[895]350        options["groups"] = options["g"] or options["groups"]
[720]351        options["printer"] = options["P"] or options["printer"] or defaults["printer"]
[715]352        options["softlimit"] = options["S"] or options["softlimit"]
353        options["hardlimit"] = options["H"] or options["hardlimit"] 
[768]354        options["reset"] = options["r"] or options["reset"] 
[843]355        options["noquota"] = options["n"] or options["noquota"]
[921]356        options["delete"] = options["d"] or options["delete"] 
[1755]357        options["hardreset"] = options["R"] or options["hardreset"] 
[1967]358        options["used"] = options["U"] or options["used"]
[2454]359        options["increase"] = options["I"] or options["increase"]
[2728]360        options["list"] = options["L"] or options["list"]
361        options["skipexisting"] = options["s"] or options["skipexisting"]
[715]362       
363        if options["help"] :
[2712]364            manager.display_usage_and_quit()
[715]365        elif options["version"] :
[2712]366            manager.display_version_and_quit()
[2728]367        elif (options["add"] and options["delete"]) \
368             or (options["noquota"] and (options["hardlimit"] or options["softlimit"])) \
369             or (options["groups"] and options["used"]) \
370             or (options["skipexisting"] and not options["add"]) :
[2512]371            raise PyKotaCommandLineError, _("incompatible options, see help.")
[2658]372        elif options["delete"] and not args :
373            raise PyKotaCommandLineError, _("You have to pass user or group names on the command line")
[715]374        else :
[2712]375            retcode = manager.main(args, options)
[2216]376    except KeyboardInterrupt :       
377        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
[2609]378        retcode = -3
[2512]379    except PyKotaCommandLineError, msg :     
380        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
[2609]381        retcode = -2
[1526]382    except SystemExit :       
383        pass
[1517]384    except :
385        try :
[2712]386            manager.crashed("edpykota failed")
[1517]387        except :   
[1546]388            crashed("edpykota failed")
[1113]389        retcode = -1
[715]390
[1113]391    try :
[2712]392        manager.storage.close()
[1113]393    except (TypeError, NameError, AttributeError) :   
394        pass
395       
396    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.