root / pykota / trunk / bin / edpykota @ 2728

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

"edpykota --delete" and "edpykota --list" now work fine.

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