root / pykota / trunk / bin / edpykota @ 2762

Revision 2762, 17.6 kB (checked in by jerome, 18 years ago)

Make pkusers --list behave like edpykota --list : allowed to normal users,
but restricted in what can be seen.

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