root / pykota / trunk / bin / edpykota @ 2755

Revision 2755, 17.8 kB (checked in by jerome, 18 years ago)

This time is the good one (tm) (c) (etc...)

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