root / pykota / trunk / bin / edpykota @ 2738

Revision 2738, 17.9 kB (checked in by jerome, 18 years ago)

Display missing users/groups early

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