root / pykota / trunk / bin / edpykota @ 2743

Revision 2743, 18.1 kB (checked in by jerome, 18 years ago)

Big improvement for data extraction.

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