root / pykota / trunk / bin / edpykota @ 2782

Revision 2782, 17.7 kB (checked in by jerome, 18 years ago)

Code cleaning.
Topped to 10000 the number of times the percent will be displayed by not displaying it if there's no change.
This is very useful when adding 25000 users on 300 printers through an ssh connection...

  • 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 Percent, 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["list"] :
184            for printer in printers :
185                for entry in entries :
186                    pqentry = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
187                    if pqentry.Exists :
188                        print "%s@%s" % (entry.Name, printer.Name)
189                        print "    %s" % (_("Page counter : %s") % pqentry.PageCounter)
190                        print "    %s" % (_("Lifetime page counter : %s") % pqentry.LifePageCounter)
191                        print "    %s" % (_("Soft limit : %s") % pqentry.SoftLimit)
192                        print "    %s" % (_("Hard limit : %s") % pqentry.HardLimit)
193                        print "    %s" % (_("Date limit : %s") % pqentry.DateLimit)
194                        print "    %s (Not supported yet)" % (_("Maximum job size : %s") % ((pqentry.MaxJobSize and (_("%s pages") % pqentry.MaxJobSize)) or _("Unlimited")))
195                        if hasattr(pqentry, "WarnCount") :
196                            print "    %s" % (_("Warning banners printed : %s") % pqentry.WarnCount)
197                        print
198        elif options["delete"] :   
199            percent = Percent(self, "\n%s..." % _("Deletion"), len(printers) * len(entries))
200            getattr(self.storage, "deleteMany%sPQuotas" % suffix)(printers, entries)
201            percent.display("\n")
202        else :
203            skipexisting = options["skipexisting"]
204            used = options["used"]
205            if used :
206                used = used.strip()
207                try :
208                    int(used)
209                except ValueError :
210                    raise PyKotaCommandLineError, _("Invalid used value %s.") % used
211                   
212            increase = options["increase"]
213            if increase :
214                try :
215                    increase = int(increase.strip())
216                except ValueError :
217                    raise PyKotaCommandLineError, _("Invalid increase value %s.") % increase
218           
219            noquota = options["noquota"]
220            reset = options["reset"]       
221            hardreset = options["hardreset"]
222            softlimit = hardlimit = None
223            if not noquota :
224                if options["softlimit"] :
225                    try :
226                        softlimit = int(options["softlimit"].strip())
227                        if softlimit < 0 :
228                            raise ValueError
229                    except ValueError :   
230                        raise PyKotaCommandLineError, _("Invalid softlimit value %s.") % options["softlimit"]
231                if options["hardlimit"] :
232                    try :
233                        hardlimit = int(options["hardlimit"].strip())
234                        if hardlimit < 0 :
235                            raise ValueError
236                    except ValueError :   
237                        raise PyKotaCommandLineError, _("Invalid hardlimit value %s.") % options["hardlimit"]
238                if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) :       
239                    # error, exchange them
240                    self.printInfo(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit))
241                    (softlimit, hardlimit) = (hardlimit, softlimit)
242                if hardlimit is None :   
243                    hardlimit = softlimit
244                    if hardlimit is not None :
245                        self.printInfo(_("Undefined hard limit set to soft limit (%s).") % str(hardlimit))
246                if softlimit is None :   
247                    softlimit = hardlimit
248                    if softlimit is not None :
249                        self.printInfo(_("Undefined soft limit set to hard limit (%s).") % str(softlimit))
250                       
251            self.storage.beginTransaction()           
252            try :
253                if options["add"] :
254                    percent = Percent(self, "\n%s...\n" % _("Creation"), len(printers) * len(entries))
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                    for printer in printers :
264                        pname = printer.Name
265                        for entry in entries :
266                            ename = entry.Name
267                            pqkey = "%s@%s" % (ename, pname)
268                            pqentry = factory(self.storage, entry, printer)
269                            self.modifyPQEntry(pqkey, pqentry, noquota, \
270                                                        softlimit, hardlimit, \
271                                                        increase, reset, \
272                                                        hardreset, suffix, used)
273                            oldpqentry = getattr(self.storage, "add%sPQuota" % suffix)(pqentry)
274                            if oldpqentry is not None :   
275                                if skipexisting :
276                                    self.logdebug("%s print quota entry %s@%s already exists, skipping." % (suffix, ename, pname))
277                                else :   
278                                    self.logdebug("%s print quota entry %s@%s already exists, will be modified." % (suffix, ename, pname))
279                                    self.modifyPQEntry(pqkey, oldpqentry, noquota, \
280                                                        softlimit, hardlimit, \
281                                                        increase, reset, \
282                                                        hardreset, suffix, used)
283                                    oldpqentry.save()                   
284                            percent.oneMore()
285                else :       
286                    percent = Percent(self, "\n%s...\n" % _("Modification"), len(entries) * len(printers))
287                    for printer in printers :
288                        for entry in entries :
289                            pqkey = "%s@%s" % (entry.Name, printer.Name)
290                            pqentry = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
291                            if pqentry.Exists :     
292                                self.modifyPQEntry(pqkey, pqentry, noquota, \
293                                                    softlimit, hardlimit, \
294                                                    increase, reset, \
295                                                    hardreset, suffix, used)
296                                pqentry.save()       
297                            percent.oneMore()
298            except :                   
299                self.storage.rollbackTransaction()
300                raise
301            else :   
302                self.storage.commitTransaction()
303                           
304        try :
305            percent.done()
306        except NameError :   
307            pass
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.