root / pykota / trunk / bin / edpykota @ 917

Revision 917, 19.3 kB (checked in by jalet, 21 years ago)

Options --limitby and --balance added to edpykota

  • 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
3# PyKota Print Quota Editor
4#
5# PyKota - Print Quotas for CUPS
6#
7# (c) 2003 Jerome Alet <alet@librelogiciel.com>
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21#
22# $Id$
23#
24# $Log$
25# Revision 1.36  2003/04/15 13:55:28  jalet
26# Options --limitby and --balance added to edpykota
27#
28# Revision 1.35  2003/04/15 13:06:39  jalet
29# Allow to add a printer without any user
30#
31# Revision 1.34  2003/04/11 16:51:11  jalet
32# Bug fix for edpykota --add with users who already had a quota on the printer.
33#
34# Revision 1.33  2003/04/10 21:47:20  jalet
35# Job history added. Upgrade script neutralized for now !
36#
37# Revision 1.32  2003/04/08 21:31:39  jalet
38# (anything or 0) = anything !!! Go back to school Jerome !
39#
40# Revision 1.31  2003/04/08 21:13:44  jalet
41# Prepare --groups option to work.
42#
43# Revision 1.30  2003/04/08 21:10:18  jalet
44# Checks --groups option presence instead of --users because --users is the default.
45#
46# Revision 1.29  2003/04/05 09:28:56  jalet
47# Unnecessary message was logged
48#
49# Revision 1.28  2003/03/29 13:45:26  jalet
50# GPL paragraphs were incorrectly (from memory) copied into the sources.
51# Two README files were added.
52# Upgrade script for PostgreSQL pre 1.01 schema was added.
53#
54# Revision 1.27  2003/03/10 00:23:04  jalet
55# Bad english
56#
57# Revision 1.26  2003/03/10 00:11:27  jalet
58# Cleaner example.
59#
60# Revision 1.25  2003/03/09 23:56:21  jalet
61# Option noquota added to do accounting only.
62#
63# Revision 1.24  2003/02/27 23:48:41  jalet
64# Correctly maps PyKota's log levels to syslog log levels
65#
66# Revision 1.23  2003/02/27 22:55:20  jalet
67# WARN log priority doesn't exist.
68#
69# Revision 1.22  2003/02/27 09:37:02  jalet
70# Wildcards seem to work now
71#
72# Revision 1.21  2003/02/27 09:04:46  jalet
73# user and group names can be passed as wildcards if the --add option
74# is not set. The default is to act on all users or groups.
75#
76# Revision 1.20  2003/02/10 12:07:30  jalet
77# Now repykota should output the recorded total page number for each printer too.
78#
79# Revision 1.19  2003/02/09 13:40:29  jalet
80# typo
81#
82# Revision 1.18  2003/02/09 12:56:53  jalet
83# Internationalization begins...
84#
85# Revision 1.17  2003/02/08 22:47:23  jalet
86# Option --reset can now be used without having to use soft and hard limits
87# on the command line.
88#
89# Revision 1.16  2003/02/08 22:39:46  jalet
90# --reset command line option added
91#
92# Revision 1.15  2003/02/08 22:20:01  jalet
93# Clarification on why we don't check with /etc/passwd to see if the user
94# name is valid or not.
95#
96# Revision 1.14  2003/02/08 22:18:15  jalet
97# Now checks user and group names for validity before adding them
98#
99# Revision 1.13  2003/02/08 22:09:02  jalet
100# Only printer was added the first time.
101#
102# Revision 1.12  2003/02/08 21:44:49  jalet
103# Python 2.1 string module doesn't define ascii_letters
104#
105# Revision 1.11  2003/02/08 09:42:44  jalet
106# Better handle wrong or bad command line arguments
107#
108# Revision 1.10  2003/02/08 09:39:20  jalet
109# typos
110#
111# Revision 1.9  2003/02/08 09:38:06  jalet
112# Badly placed test
113#
114# Revision 1.8  2003/02/07 22:53:57  jalet
115# Checks if printer name is valid before adding it
116#
117# Revision 1.7  2003/02/07 22:17:58  jalet
118# Incomplete test
119#
120# Revision 1.6  2003/02/07 22:13:13  jalet
121# Perhaps edpykota is now able to add printers !!! Oh, stupid me !
122#
123# Revision 1.5  2003/02/06 14:49:04  jalet
124# edpykota should be ok now
125#
126# Revision 1.4  2003/02/06 14:28:59  jalet
127# edpykota should be ok, minus some typos
128#
129# Revision 1.3  2003/02/06 10:47:21  jalet
130# Documentation string and command line options didn't match.
131#
132# Revision 1.2  2003/02/06 10:39:23  jalet
133# Preliminary edpykota work.
134#
135# Revision 1.1  2003/02/05 21:41:09  jalet
136# Skeletons added for all command line tools
137#
138#
139#
140
141import sys
142
143from pykota import version
144from pykota.tool import PyKotaTool, PyKotaToolError
145
146__doc__ = """edpykota v%s (C) 2003 C@LL - Conseil Internet & Logiciels Libres
147A Print Quota editor for PyKota.
148
149command line usage :
150
151  edpykota [options] user1 user2 ... userN
152  edpykota [options] group1 group2 ... groupN
153
154options :
155
156  -v | --version       Prints edpykota's version number then exits.
157  -h | --help          Prints this message then exits.
158 
159  -a | --add           Adds users and/or printers if they don't
160                       exist on the Quota Storage Server.
161                       
162  -u | --users         Edit users print quotas, this is the default.
163 
164  -P | --printer p     Edit quotas on printer p only. Actually p can
165                       use wildcards characters to select only
166                       some printers. The default value is *, meaning
167                       all printers.
168 
169  -g | --groups        Edit groups print quotas instead of users.
170                         
171  -p | --prototype u|g Uses user u or group g as a prototype to set
172                       print quotas
173                       
174  -n | --noquota       Doesn't set a quota but only does accounting.
175 
176  -r | --reset         Resets the printed page counter for the user
177                       or group to zero. The life time page counter
178                       is kept unchanged.
179                       
180  -l | --limitby l     Choose if the user/group is limited in printing                     
181                       by its account balance or by its page quota.
182                       The default value is 'quota'. Allowed values
183                       are 'quota' and 'balance'.
184                       
185  -b | --balance b     Sets the user's account balance to b.                     
186                       Account balance may be increase or decreased
187                       if b is prefixed with + or -.
188                       WARNING : when decreasing account balance,
189                       the total paid so far by the user is decreased
190                       too.
191                       Groups don't have a real balance, but the
192                       sum of their users' account balance.
193                       
194  -S | --softlimit sl  Sets the quota soft limit to sl pages.                       
195 
196  -H | --hardlimit hl  Sets the quota hard limit to hl pages.
197 
198  user1 through userN and group1 through groupN can use wildcards
199  if the --add option is not set.
200 
201examples :                             
202
203  $ edpykota -p jerome john paul george ringo
204 
205  This will set print quotas for the users john, paul, george and ringo
206  to the same values than user jerome. User jerome must exist.
207 
208  $ edpykota --printer lp -S 50 -H 60 jerome
209 
210  This will set jerome's print quota on the lp printer to a soft limit
211  of 50 pages, and a hard limit of 60 pages. If either user jerome or
212  printer lp doesn't exist on the Quota Storage Server then nothing is done.
213
214  $ edpykota --add --printer lp -S 50 -H 60 jerome
215 
216  Same as above, but if either user jerome or printer lp doesn't exist
217  on the Quota Storage Server they are automatically added.
218  WARNING : the CUPS PPD file for this printer must still be modified
219            manually, as well as pykota's configuration file for a
220            new printer to be managed successfully.
221           
222  $ edpykota -g -S 500 -H 550 financial support           
223 
224  This will set print quota soft limit to 500 pages and hard limit
225  to 550 pages for groups financial and support on all printers.
226 
227  $ edpykota --reset jerome "jo*"
228 
229  This will reset jerome's page counter to zero on all printers, as
230  well as every user whose name begins with 'jo'.
231  Their life time page counter on each printer will be kept unchanged.
232 
233  $ edpykota --printer hpcolor --noquota jerome
234 
235  This will tell PyKota to not limit jerome when printing on the
236  hpcolor printer. All his jobs will be allowed on this printer, but
237  accounting of the pages he prints will still be kept.
238  Print Quotas for jerome on other printers are unchanged.
239 
240  $ edpykota --limitby balance jerome
241 
242  This will tell PyKota to limit jerome by his account's balance
243  when printing.
244 
245  $ edpykota --balance +10.0 jerome
246 
247  This will increase jerome's account balance by 10.0 (in your
248  own currency). You can decrease the account balance with a
249  dash prefix, and set it to a fixed amount with no prefix.
250
251This program is free software; you can redistribute it and/or modify
252it under the terms of the GNU General Public License as published by
253the Free Software Foundation; either version 2 of the License, or
254(at your option) any later version.
255
256This program is distributed in the hope that it will be useful,
257but WITHOUT ANY WARRANTY; without even the implied warranty of
258MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
259GNU General Public License for more details.
260
261You should have received a copy of the GNU General Public License
262along with this program; if not, write to the Free Software
263Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
264
265Please e-mail bugs to: %s""" % (version.__version__, version.__author__)
266       
267class EdPyKota(PyKotaTool) :       
268    """A class for edpykota."""
269    def main(self, names, options) :
270        """Edit user or group quotas."""
271        printeradded = 0
272        printers = self.storage.getMatchingPrinters(options["printer"])
273        if not printers :
274            pname = options["printer"]
275            if options["add"] and pname :
276                if self.isValidName(pname) :
277                    printerid = self.storage.addPrinter(pname)
278                    printers = [ (printerid, pname) ]
279                    printeradded = 1
280                else :   
281                    raise PyKotaToolError, _("Invalid printer name %s") % pname
282            else :
283                raise PyKotaToolError, _("There's no printer matching %s") % pname
284        softlimit = hardlimit = None   
285        if options["softlimit"] :
286            try :
287                softlimit = int(options["softlimit"].strip())
288            except ValueError :   
289                raise PyKotaToolError, _("Invalid softlimit value %s.") % options["softlimit"]
290        if options["hardlimit"] :
291            try :
292                hardlimit = int(options["hardlimit"].strip())
293            except ValueError :   
294                raise PyKotaToolError, _("Invalid hardlimit value %s.") % options["hardlimit"]
295        if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) :       
296            # error, exchange them
297            self.logger.log_message(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit))
298            (softlimit, hardlimit) = (hardlimit, softlimit)
299        if not names :   
300            if options["add"] and not printeradded :
301                raise PyKotaToolError, _("You have to pass user names on the command line")
302            else :   
303                names = [ "*" ] # all users
304        for (printerid, printer) in printers :
305            if options["prototype"] :
306                if options["groups"] :
307                    prototype = self.storage.getGroupPQuota(self.storage.getGroupId(options["prototype"]), printerid)
308                else :     
309                    # default is user quota edition
310                    prototype = self.storage.getUserPQuota(self.storage.getUserId(options["prototype"]), printerid)
311                if prototype is None :
312                    self.logger.log_message(_("Prototype %s not found in Quota Storage for printer %s.") % (options["prototype"], printer))
313                    continue    # skip this printer
314                else :   
315                    (softlimit, hardlimit) = (prototype["softlimit"], prototype["hardlimit"])
316            if hardlimit is None :   
317                hardlimit = softlimit
318                if hardlimit is not None :
319                    self.logger.log_message(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer))
320            if softlimit is None :   
321                softlimit = hardlimit
322                if softlimit is not None :
323                    self.logger.log_message(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer))
324            if (not options["reset"] and not options["noquota"] and not options["prototype"] and not options["limitby"] and not options["balance"]) and ((hardlimit is None) or (softlimit is None)) :
325                raise PyKotaToolError, _("Both hard and soft limits must be set ! Aborting.")
326            if options["add"] :   
327                allidnames = [(self.storage.getUserId(n), n) for n in names]
328            else :   
329                if options["groups"] :   
330                    allidnames = self.storage.getPrinterGroups(printerid)
331                else :   
332                    allidnames = self.storage.getPrinterUsers(printerid)
333            for (ident, name) in [(i, n) for (i, n) in allidnames if self.matchString(n, names)]:
334                if options["groups"] :
335                    quota = self.storage.getGroupPQuota(ident, printerid)
336                else :
337                    quota = self.storage.getUserPQuota(ident, printerid)
338                if quota is None :
339                    # not found
340                    if options["add"] :
341                        # In case we want to add something, it is crucial
342                        # that we DON'T check with the system accounts files
343                        # like /etc/passwd because users may be defined
344                        # only remotely
345                        if options["groups"] :
346                            if self.isValidName(name) :
347                                (ident, printerid) = self.storage.addGroupPQuota(name, printerid)
348                                quota = self.storage.getGroupPQuota(ident, printerid)
349                            else :   
350                                self.logger.log_message(_("Invalid group name %s") % name)
351                        else :
352                            if self.isValidName(name) :
353                                (ident, printerid) = self.storage.addUserPQuota(name, printerid)
354                                quota = self.storage.getUserPQuota(ident, printerid)
355                            else :   
356                                self.logger.log_message(_("Invalid user name %s") % name)
357                if quota is None :     
358                    self.logger.log_message(_("Quota not found for object %s on printer %s.") % (name, printer))
359                else :   
360                    limitby = options["limitby"]
361                    if limitby :
362                        limitby = limitby.lower()
363                    if limitby and (limitby not in ('quota', 'balance')) :   
364                        limitby = 'quota'
365                    if options["groups"] :
366                        if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) :
367                            self.storage.setGroupPQuota(ident, printerid, softlimit, hardlimit)
368                        if options["reset"] :
369                            self.storage.resetGroupPQuota(ident, printerid)
370                        if limitby :
371                            self.storage.limitGroupBy(ident, limitby)
372                        self.warnGroupPQuota(name, printer)   
373                    else :
374                        if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) :
375                            self.storage.setUserPQuota(ident, printerid, softlimit, hardlimit)
376                        if options["reset"] :
377                            self.storage.resetUserPQuota(ident, printerid)
378                        if limitby :
379                            self.storage.limitUserBy(ident, limitby)
380                        balance = options["balance"]   
381                        if balance :
382                            balance = balance.strip()
383                            try :
384                                balancevalue = float(balance)
385                            except ValueError :   
386                                pass # TODO : log something when incorrect balance value
387                            else :   
388                                if balance.startswith("+") or balance.startswith("-") :
389                                    self.storage.increaseUserBalance(ident, balancevalue)
390                                else :
391                                    self.storage.setUserBalance(ident, balancevalue)
392                        self.warnUserPQuota(name, printer)   
393                     
394if __name__ == "__main__" : 
395    try :
396        defaults = { \
397                     "printer" : "*", \
398                   }
399        short_options = "vhl:b:naugrp:P:S:H:"
400        long_options = ["help", "version", "limitby=", "balance=", "noquota", "add", "users", "groups", "reset", "prototype=", "printer=", "softlimit=", "hardlimit="]
401       
402        # Initializes the command line tool
403        editor = EdPyKota(doc=__doc__)
404       
405        # parse and checks the command line
406        (options, args) = editor.parseCommandline(sys.argv[1:], short_options, long_options)
407       
408        # sets long options
409        options["help"] = options["h"] or options["help"]
410        options["version"] = options["v"] or options["version"]
411        options["add"] = options["a"] or options["add"]
412        options["users"] = options["u"] or options["users"]
413        options["groups"] = options["g"] or options["groups"]
414        options["prototype"] = options["p"] or options["prototype"]
415        options["printer"] = options["P"] or options["printer"] or defaults["printer"]
416        options["softlimit"] = options["S"] or options["softlimit"]
417        options["hardlimit"] = options["H"] or options["hardlimit"] 
418        options["reset"] = options["r"] or options["reset"] 
419        options["noquota"] = options["n"] or options["noquota"]
420        options["limitby"] = options["l"] or options["limitby"]
421        options["balance"] = options["b"] or options["balance"] 
422       
423        if options["help"] :
424            editor.display_usage_and_quit()
425        elif options["version"] :
426            editor.display_version_and_quit()
427        elif options["users"] and options["groups"] :   
428            raise PyKotaToolError, _("incompatible options, see help.")
429        elif (options["softlimit"] or options["hardlimit"]) and options["prototype"] :   
430            raise PyKotaToolError, _("incompatible options, see help.")
431        elif options["noquota"] and (options["prototype"] or options["hardlimit"] or options["softlimit"]) :
432            raise PyKotaToolError, _("incompatible options, see help.")
433        elif options["groups"] and options["balance"] :
434            raise PyKotaToolError, _("incompatible options, see help.")
435        elif options["groups"] :   
436            raise PyKotaToolError, _("option --groups is currently not implemented.")
437        else :
438            sys.exit(editor.main(args, options))
439    except PyKotaToolError, msg :           
440        sys.stderr.write("%s\n" % msg)
441        sys.stderr.flush()
442        sys.exit(-1)
Note: See TracBrowser for help on using the browser.