root / pykota / trunk / bin / edpykota @ 2760

Revision 2760, 18.0 kB (checked in by jerome, 18 years ago)

Allows normal users to use edpykota --list in a restricted way.

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