root / pykota / trunk / bin / edpykota @ 2054

Revision 2054, 35.3 kB (checked in by jalet, 19 years ago)

Big database structure changes. Upgrade script is now included as well as
the new LDAP schema.
Introduction of the -o | --overcharge command line option to edpykota.
The output of repykota is more complete, but doesn't fit in 80 columns anymore.
Introduction of the new 'maxdenybanners' directive.

  • 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.87  2005/02/13 22:02:28  jalet
27# Big database structure changes. Upgrade script is now included as well as
28# the new LDAP schema.
29# Introduction of the -o | --overcharge command line option to edpykota.
30# The output of repykota is more complete, but doesn't fit in 80 columns anymore.
31# Introduction of the new 'maxdenybanners' directive.
32#
33# Revision 1.86  2005/01/21 14:40:01  jalet
34# edpykota's --delete command line tool doesn't use "*" as its default argument
35# anymore when the user doesn't pass any real argument :-)
36#
37# Revision 1.85  2005/01/18 19:47:49  jalet
38# Big bug fix wrt the datelimit attribute
39#
40# Revision 1.84  2005/01/17 08:44:23  jalet
41# Modified copyright years
42#
43# Revision 1.83  2004/12/02 21:24:50  jalet
44# Integrated the patch by Wilson Roberto Afonso and Matt Hyclak to allow
45# edpykota to accept the -U | --used value command line option.
46#
47# Revision 1.82  2004/11/22 21:53:38  jalet
48# Added the reject_unknown directive to pykota.conf to reject user/group
49# creation if user or group is unknown to the system
50#
51# Revision 1.81  2004/10/12 15:37:00  jalet
52# Now outputs the name of the offending user if a mere mortal tries to use
53# one of these commands !!!
54#
55# Revision 1.80  2004/10/11 22:53:05  jalet
56# Postponed string interpolation to help message's output method
57#
58# Revision 1.79  2004/10/11 12:49:06  jalet
59# Renders help translatable
60#
61# Revision 1.78  2004/10/07 14:35:40  jalet
62# Now edpykota refuses to launch if the user is not a PyKota administrator.
63# dumpykota : now has the same error message than edpykota in this case.
64#
65# Revision 1.77  2004/09/28 17:45:31  jalet
66# Added the --hardreset command line option to edpykota
67#
68# Revision 1.76  2004/07/01 19:56:40  jalet
69# Better dispatching of error messages
70#
71# Revision 1.75  2004/06/18 13:34:47  jalet
72# Now all tracebacks include PyKota's version number
73#
74# Revision 1.74  2004/06/07 18:43:40  jalet
75# Fixed over-verbose exits when displaying help or version number
76#
77# Revision 1.73  2004/06/03 21:50:34  jalet
78# Improved error logging.
79# crashrecipient directive added.
80# Now exports the job's size in bytes too.
81#
82# Revision 1.72  2004/04/16 16:20:19  jalet
83# Note about not implemented limitby values
84#
85# Revision 1.71  2004/03/24 15:15:24  jalet
86# Began integration of Henrik Janhagen's work on quota-then-balance
87# and balance-then-quota
88#
89# Revision 1.70  2004/02/27 09:23:21  jalet
90# Minor code reorganisation
91#
92# Revision 1.69  2004/02/19 15:05:56  jalet
93# domain names changed to example.com in the doc, according to RFC2606
94#
95# Revision 1.68  2004/01/28 10:05:22  jalet
96# New user/group deletion code
97#
98# Revision 1.67  2004/01/15 11:19:07  jalet
99# Typos in messages wrt gettext.
100#
101# Revision 1.66  2004/01/12 21:54:36  jalet
102# User's email address can now be set at user's creation time.
103#
104# Revision 1.65  2004/01/08 16:24:49  jalet
105# edpykota now supports adding printers to printer groups.
106#
107# Revision 1.64  2004/01/08 14:10:32  jalet
108# Copyright year changed.
109#
110# Revision 1.63  2003/11/24 16:50:58  jalet
111# Old help message deletedd
112#
113# Revision 1.62  2003/11/12 23:28:38  jalet
114# More work on new backend. This commit may be unstable.
115#
116# Revision 1.61  2003/11/12 13:06:35  jalet
117# Bug fix wrt no user/group name command line argument to edpykota
118#
119# Revision 1.60  2003/10/09 21:25:24  jalet
120# Multiple printer names or wildcards can be passed on the command line
121# separated with commas.
122# Beta phase.
123#
124# Revision 1.59  2003/10/07 09:07:27  jalet
125# Character encoding added to please latest version of Python
126#
127# Revision 1.58  2003/10/03 12:27:01  jalet
128# Several optimizations, especially with LDAP backend
129#
130# Revision 1.57  2003/08/20 16:01:19  jalet
131# Comment added.
132#
133# Revision 1.56  2003/07/29 20:55:17  jalet
134# 1.14 is out !
135#
136# Revision 1.55  2003/07/28 09:11:12  jalet
137# PyKota now tries to add its attributes intelligently in existing LDAP
138# directories.
139#
140# Revision 1.54  2003/07/21 06:32:42  jalet
141# Prevents email messages to be sent at modification/creation time for
142# a user/group quota
143#
144# Revision 1.53  2003/07/09 06:03:41  jalet
145# Fixed typo when using edpykota --prototype
146#
147# Revision 1.52  2003/07/07 12:11:13  jalet
148# Small fix
149#
150# Revision 1.51  2003/07/07 11:55:50  jalet
151# Small fix
152#
153# Revision 1.50  2003/07/05 12:33:53  jalet
154# More on previous fix.
155#
156# Revision 1.49  2003/07/05 12:32:07  jalet
157# Ensure that the user don't pass more than two prices for a printer.
158#
159# Revision 1.48  2003/06/25 19:52:30  jalet
160# Should be ready for testing :-)
161#
162# Revision 1.47  2003/06/25 14:10:01  jalet
163# Hey, it may work (edpykota --reset excepted) !
164#
165# Revision 1.46  2003/06/16 11:59:09  jalet
166# More work on LDAP
167#
168# Revision 1.45  2003/06/11 19:32:00  jalet
169# Severe bug wrt account balance setting should be corrected.
170#
171# Revision 1.44  2003/04/29 22:03:38  jalet
172# Better error handling.
173#
174# Revision 1.43  2003/04/23 22:13:56  jalet
175# Preliminary support for LPRng added BUT STILL UNTESTED.
176#
177# Revision 1.42  2003/04/17 13:38:47  jalet
178# Docstring corrected for better manual page
179#
180# Revision 1.41  2003/04/16 12:35:49  jalet
181# Groups quota work now !
182#
183# Revision 1.40  2003/04/16 08:22:09  jalet
184# More strict error detection.
185# Minor code rewrite to avoid some repetitive tests.
186#
187# Revision 1.39  2003/04/16 08:01:53  jalet
188# edpykota --charge command line option works now.
189#
190# Revision 1.38  2003/04/15 22:02:43  jalet
191# More complete docstring
192#
193# Revision 1.37  2003/04/15 21:58:33  jalet
194# edpykota now accepts a --delete option.
195# Preparation to allow edpykota to accept much more command line options
196# (WARNING : docstring is OK, but code isn't !)
197#
198# Revision 1.36  2003/04/15 13:55:28  jalet
199# Options --limitby and --balance added to edpykota
200#
201# Revision 1.35  2003/04/15 13:06:39  jalet
202# Allow to add a printer without any user
203#
204# Revision 1.34  2003/04/11 16:51:11  jalet
205# Bug fix for edpykota --add with users who already had a quota on the printer.
206#
207# Revision 1.33  2003/04/10 21:47:20  jalet
208# Job history added. Upgrade script neutralized for now !
209#
210# Revision 1.32  2003/04/08 21:31:39  jalet
211# (anything or 0) = anything !!! Go back to school Jerome !
212#
213# Revision 1.31  2003/04/08 21:13:44  jalet
214# Prepare --groups option to work.
215#
216# Revision 1.30  2003/04/08 21:10:18  jalet
217# Checks --groups option presence instead of --users because --users is the default.
218#
219# Revision 1.29  2003/04/05 09:28:56  jalet
220# Unnecessary message was logged
221#
222# Revision 1.28  2003/03/29 13:45:26  jalet
223# GPL paragraphs were incorrectly (from memory) copied into the sources.
224# Two README files were added.
225# Upgrade script for PostgreSQL pre 1.01 schema was added.
226#
227# Revision 1.27  2003/03/10 00:23:04  jalet
228# Bad english
229#
230# Revision 1.26  2003/03/10 00:11:27  jalet
231# Cleaner example.
232#
233# Revision 1.25  2003/03/09 23:56:21  jalet
234# Option noquota added to do accounting only.
235#
236# Revision 1.24  2003/02/27 23:48:41  jalet
237# Correctly maps PyKota's log levels to syslog log levels
238#
239# Revision 1.23  2003/02/27 22:55:20  jalet
240# WARN log priority doesn't exist.
241#
242# Revision 1.22  2003/02/27 09:37:02  jalet
243# Wildcards seem to work now
244#
245# Revision 1.21  2003/02/27 09:04:46  jalet
246# user and group names can be passed as wildcards if the --add option
247# is not set. The default is to act on all users or groups.
248#
249# Revision 1.20  2003/02/10 12:07:30  jalet
250# Now repykota should output the recorded total page number for each printer too.
251#
252# Revision 1.19  2003/02/09 13:40:29  jalet
253# typo
254#
255# Revision 1.18  2003/02/09 12:56:53  jalet
256# Internationalization begins...
257#
258# Revision 1.17  2003/02/08 22:47:23  jalet
259# Option --reset can now be used without having to use soft and hard limits
260# on the command line.
261#
262# Revision 1.16  2003/02/08 22:39:46  jalet
263# --reset command line option added
264#
265# Revision 1.15  2003/02/08 22:20:01  jalet
266# Clarification on why we don't check with /etc/passwd to see if the user
267# name is valid or not.
268#
269# Revision 1.14  2003/02/08 22:18:15  jalet
270# Now checks user and group names for validity before adding them
271#
272# Revision 1.13  2003/02/08 22:09:02  jalet
273# Only printer was added the first time.
274#
275# Revision 1.12  2003/02/08 21:44:49  jalet
276# Python 2.1 string module doesn't define ascii_letters
277#
278# Revision 1.11  2003/02/08 09:42:44  jalet
279# Better handle wrong or bad command line arguments
280#
281# Revision 1.10  2003/02/08 09:39:20  jalet
282# typos
283#
284# Revision 1.9  2003/02/08 09:38:06  jalet
285# Badly placed test
286#
287# Revision 1.8  2003/02/07 22:53:57  jalet
288# Checks if printer name is valid before adding it
289#
290# Revision 1.7  2003/02/07 22:17:58  jalet
291# Incomplete test
292#
293# Revision 1.6  2003/02/07 22:13:13  jalet
294# Perhaps edpykota is now able to add printers !!! Oh, stupid me !
295#
296# Revision 1.5  2003/02/06 14:49:04  jalet
297# edpykota should be ok now
298#
299# Revision 1.4  2003/02/06 14:28:59  jalet
300# edpykota should be ok, minus some typos
301#
302# Revision 1.3  2003/02/06 10:47:21  jalet
303# Documentation string and command line options didn't match.
304#
305# Revision 1.2  2003/02/06 10:39:23  jalet
306# Preliminary edpykota work.
307#
308# Revision 1.1  2003/02/05 21:41:09  jalet
309# Skeletons added for all command line tools
310#
311#
312#
313
314import sys
315import os
316import pwd
317import grp
318from pykota.tool import PyKotaTool, PyKotaToolError, crashed, N_
319from pykota.config import PyKotaConfigError
320from pykota.storage import PyKotaStorageError
321
322__doc__ = N_("""edpykota v%s (c) 2003, 2004, 2005 C@LL - Conseil Internet & Logiciels Libres
323A Print Quota editor for PyKota.
324
325command line usage :
326
327  edpykota [options] user1 user2 ... userN
328 
329  edpykota [options] group1 group2 ... groupN
330
331options :
332
333  -v | --version       Prints edpykota's version number then exits.
334  -h | --help          Prints this message then exits.
335 
336  -a | --add           Adds users and/or printers if they don't
337                       exist on the Quota Storage Server.
338                       
339  -d | --delete        Deletes users/groups from the quota storage.
340                       Printers are never deleted.
341                       
342  -c | --charge p[,j]  Sets the price per page and per job to charge
343                       for a particular printer. Job price is optional.
344                       If both are to be set, separate them with a comma.
345                       Floating point values are allowed.
346                       
347  -o | --overcharge f  Sets the overcharging factor applied to the user
348                       when computing the cost of a print job. Positive or
349                       negative floating point values are allowed,
350                       this allows you to do some really creative
351                       things like giving money to an user whenever
352                       he prints. The number of pages in a print job
353                       is not modified by this coefficient, only the
354                       cost of the job for a particular user.
355                       Only users have a coefficient.
356 
357  -i | --ingroups g1[,g2...]  Puts the users into each of the groups
358                              listed, separated by commas. The groups
359                              must already exist in the Quota Storage.
360 
361  -u | --users         Edit users print quotas, this is the default.
362 
363  -P | --printer p     Edit quotas on printer p only. Actually p can
364                       use wildcards characters to select only
365                       some printers. The default value is *, meaning
366                       all printers.
367                       You can specify several names or wildcards,
368                       by separating them with commas.
369 
370  -G | --pgroups pg1[,pg2...] Adds the printer(s) to the printer groups
371                       pg1, pg2, etc... which must already exist.
372                       A printer group is just like a normal printer,
373                       only that it is usually unknown from the printing
374                       system. Create printer groups exactly the same
375                       way that you create printers, then add other
376                       printers to them with this option.
377                       Accounting is done on a printer and on all
378                       the printer groups it belongs to, quota checking
379                       is done on a printer and on all the printer groups
380                       it belongs to.
381 
382  -g | --groups        Edit users groups print quotas instead of users.
383                         
384  -p | --prototype u|g Uses user u or group g as a prototype to set
385                       print quotas
386                       
387  -n | --noquota       Doesn't set a quota but only does accounting.
388 
389  -r | --reset         Resets the actual page counter for the user
390                       or group to zero on the specified printers.
391                       The life time page counter is kept unchanged.
392                       
393  -R | --hardreset     Resets the actual and life time page counters
394                       for the user or group to zero on the specified
395                       printers. This is a shortcut for '--used 0'.
396                       
397  -l | --limitby l     Choose if the user/group is limited in printing                     
398                       by its account balance or by its page quota.
399                       The default value is 'quota'. Allowed values
400                       are 'quota' 'balance' 'quota-then-balance' and
401                       'balance-then-quota'.
402                       WARNING : quota-then-balance and balance-then-quota
403                       are not yet implemented.
404                       
405  -b | --balance b     Sets the user's account balance to b.                     
406                       Account balance may be increase or decreased
407                       if b is prefixed with + or -.
408                       WARNING : when decreasing account balance,
409                       the total paid so far by the user is decreased
410                       too.
411                       Groups don't have a real balance, but the
412                       sum of their users' account balance.
413                       
414  -S | --softlimit sl  Sets the quota soft limit to sl pages.                       
415 
416  -H | --hardlimit hl  Sets the quota hard limit to hl pages.
417
418  -U | --used usage    Sets the pagecounters for the user to usage pages;
419                       useful for migrating users from a different system
420                       where they have already used some pages. Actual
421                       and Life Time page counters may be increased or decreased
422                       if usage is prefixed with + or -.
423                       WARNING : BOTH page counters are modified in all cases,
424                       so be careful.
425                       NB : if 'usage' equals '0', then the action taken is
426                       the same as if --hardreset was used.
427
428  user1 through userN and group1 through groupN can use wildcards
429  if the --add option is not set.
430 
431examples :                             
432
433  $ edpykota --add -p jerome john paul george ringo/ringo@example.com
434 
435  This will add users john, paul, george and ringo to the quota
436  database, and set their print quotas to the same values than user
437  jerome. User jerome must already exist.
438  User ringo's email address will also be set to 'ringo@example.com'
439 
440  $ edpykota --printer lp -S 50 -H 60 jerome
441 
442  This will set jerome's print quota on the lp printer to a soft limit
443  of 50 pages, and a hard limit of 60 pages. If either user jerome or
444  printer lp doesn't exist on the Quota Storage Server then nothing is done.
445
446  $ edpykota --add --printer lp --ingroups coders,it -S 50 -H 60 jerome
447 
448  Same as above, but if either user jerome or printer lp doesn't exist
449  on the Quota Storage Server they are automatically added. Also
450  user jerome is put into the groups "coders" and "it" which must
451  already exist in the Quota Storage.
452           
453  $ edpykota -g -S 500 -H 550 financial support           
454 
455  This will set print quota soft limit to 500 pages and hard limit
456  to 550 pages for groups financial and support on all printers.
457 
458  $ edpykota --reset jerome "jo*"
459 
460  This will reset jerome's page counter to zero on all printers, as
461  well as every user whose name begins with 'jo'.
462  Their life time page counter on each printer will be kept unchanged.
463  You can also reset the life time page counters by using the
464  --hardreset | -R command line option.
465 
466  $ edpykota --printer hpcolor --noquota jerome
467 
468  This will tell PyKota to not limit jerome when printing on the
469  hpcolor printer. All his jobs will be allowed on this printer, but
470  accounting of the pages he prints will still be kept.
471  Print Quotas for jerome on other printers are unchanged.
472 
473  $ edpykota --limitby balance jerome
474 
475  This will tell PyKota to limit jerome by his account's balance
476  when printing.
477 
478  $ edpykota --balance +10.0 jerome
479 
480  This will increase jerome's account balance by 10.0 (in your
481  own currency). You can decrease the account balance with a
482  dash prefix, and set it to a fixed amount with no prefix.
483 
484  $ edpykota --delete jerome rachel
485 
486  This will completely delete jerome and rachel from the Quota Storage
487  database. All their quotas and jobs will be deleted too.
488 
489  $ edpykota --printer lp --charge 0.1
490 
491  This will set the page price for printer lp to 0.1. Job price
492  will not be changed.
493 
494  $ edpykota --printer hplj1,hplj2 --pgroups Laser,HP
495 
496  This will put printers hplj1 and hplj2 in printers groups Laser and HP.
497  When printing either on hplj1 or hplj2, print quota will also be
498  checked and accounted for on virtual printers Laser and HP.
499 
500  $ edpykota --overcharge 2.5 poorstudent
501 
502  This will overcharge the poorstudent user by a factor of 2.5.
503 
504  $ edpykota --overcharge -1 jerome
505 
506  User jerome will actually earn money whenever he prints.
507 
508  $ edpykota --overcharge 0 boss
509 
510  User boss can print at will, it won't cost him anything because the
511  cost of each print job will be multiplied by zero before charging
512  his account.
513
514This program is free software; you can redistribute it and/or modify
515it under the terms of the GNU General Public License as published by
516the Free Software Foundation; either version 2 of the License, or
517(at your option) any later version.
518
519This program is distributed in the hope that it will be useful,
520but WITHOUT ANY WARRANTY; without even the implied warranty of
521MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
522GNU General Public License for more details.
523
524You should have received a copy of the GNU General Public License
525along with this program; if not, write to the Free Software
526Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
527
528Please e-mail bugs to: %s""") 
529       
530class EdPyKota(PyKotaTool) :       
531    """A class for edpykota."""
532    def main(self, names, options) :
533        """Edit user or group quotas."""
534        if not self.config.isAdmin :
535            raise PyKotaToolError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
536       
537        suffix = (options["groups"] and "Group") or "User"       
538       
539        softlimit = hardlimit = None
540
541        used = options["used"]
542        if used :
543            used = used.strip()
544            try :
545                int(used)
546            except ValueError :
547                raise PyKotaToolError, _("Invalid used value %s.") % used
548
549        if not options["noquota"] :
550            if options["softlimit"] :
551                try :
552                    softlimit = int(options["softlimit"].strip())
553                except ValueError :   
554                    raise PyKotaToolError, _("Invalid softlimit value %s.") % options["softlimit"]
555            if options["hardlimit"] :
556                try :
557                    hardlimit = int(options["hardlimit"].strip())
558                except ValueError :   
559                    raise PyKotaToolError, _("Invalid hardlimit value %s.") % options["hardlimit"]
560            if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) :       
561                # error, exchange them
562                self.printInfo(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit))
563                (softlimit, hardlimit) = (hardlimit, softlimit)
564           
565        overcharge = options["overcharge"]
566        if overcharge :
567            try :
568                overcharge = float(overcharge.strip())
569            except (ValueError, AttributeError) :   
570                raise PyKotaToolError, _("Invalid overcharge value %s") % options["overcharge"]
571               
572        balance = options["balance"]
573        if balance :
574            balance = balance.strip()
575            try :
576                balancevalue = float(balance)
577            except ValueError :   
578                raise PyKotaToolError, _("Invalid balance value %s") % options["balance"]
579           
580        if options["charge"] :
581            try :
582                charges = [float(part) for part in options["charge"].split(',', 1)]
583            except ValueError :   
584                raise PyKotaToolError, _("Invalid charge amount value %s") % options["charge"]
585            else :   
586                if len(charges) > 2 :
587                    charges = charges[:2]
588                if len(charges) != 2 :
589                    charges = [charges[0], None]
590                   
591        limitby = options["limitby"]
592        if limitby :
593            limitby = limitby.strip().lower()
594        if limitby and (limitby not in ('quota', 'balance', 'quota-then-balance', 'balance-then-quota')) :   
595            raise PyKotaToolError, _("Invalid limitby value %s") % options["limitby"]
596           
597        if options["ingroups"] :   
598            groupnames = [gname.strip() for gname in options["ingroups"].split(',')]
599        else :   
600            groupnames = []
601           
602        if options["prototype"] :   
603            protoentry = getattr(self.storage, "get%s" % suffix)(options["prototype"])
604           
605        rejectunknown = self.config.getRejectUnknown()   
606        printeradded = 0
607        printers = self.storage.getMatchingPrinters(options["printer"])
608        if not printers :
609            pname = options["printer"]
610            if options["add"] and pname :
611                if self.isValidName(pname) :
612                    printers = [ self.storage.addPrinter(pname) ]
613                    if printers[0].Exists :
614                        printeradded = 1
615                    else :   
616                        raise PyKotaToolError, _("Impossible to add printer %s") % pname
617                else :   
618                    raise PyKotaToolError, _("Invalid printer name %s") % pname
619            else :
620                raise PyKotaToolError, _("There's no printer matching %s") % pname
621        if not names :   
622            if options["add"] :
623                if not printeradded :
624                    raise PyKotaToolError, _("You have to pass user or group names on the command line")
625                else :   
626                    names = getattr(self.storage, "getAll%ssNames" % suffix)()
627            elif options["delete"] :   
628                raise PyKotaToolError, _("You have to pass user or group names on the command line")
629            else :
630                names = [ "*" ] # all users or groups
631               
632        printersgroups = []       
633        if options["pgroups"] :       
634            printersgroups = self.storage.getMatchingPrinters(options["pgroups"])
635           
636        todelete = {}   
637        changed = {} # tracks changes made at the user/group level
638        for printer in printers :
639            for pgroup in printersgroups :
640                pgroup.addPrinterToGroup(printer)   
641               
642            if options["charge"] :
643                (perpage, perjob) = charges
644                printer.setPrices(perpage, perjob)   
645               
646            if options["prototype"] :
647                if protoentry.Exists :
648                    protoquota = getattr(self.storage, "get%sPQuota" % suffix)(protoentry, printer)
649                    if not protoquota.Exists :
650                        self.printInfo(_("Prototype %s not found in Quota Storage for printer %s.") % (protoentry.Name, printer.Name))
651                        continue    # skip this printer
652                    else :   
653                        (softlimit, hardlimit) = (protoquota.SoftLimit, protoquota.HardLimit)
654                else :       
655                    self.printInfo(_("Prototype object %s not found in Quota Storage.") % protoentry.Name)
656                   
657            if not options["noquota"] :   
658                if hardlimit is None :   
659                    hardlimit = softlimit
660                    if hardlimit is not None :
661                        self.printInfo(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer.Name))
662                if softlimit is None :   
663                    softlimit = hardlimit
664                    if softlimit is not None :
665                        self.printInfo(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer.Name))
666                       
667            if options["add"] :   
668                allentries = []   
669                for name in names :
670                    email = ""
671                    if not options["groups"] :
672                        splitname = name.split('/', 1)     # username/email
673                        if len(splitname) == 1 :
674                            splitname.append("")
675                        (name, email) = splitname
676                        if email and (email.count('@') != 1) :
677                            self.printInfo(_("Invalid email address %s") % email)
678                            email = ""
679                    entry = getattr(self.storage, "get%s" % suffix)(name)
680                    if email and not options["groups"] :
681                        entry.Email = email
682                    entrypquota = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
683                    allentries.append((entry, entrypquota))
684            else :   
685                allentries = getattr(self.storage, "getPrinter%ssAndQuotas" % suffix)(printer, names)
686               
687            for (entry, entrypquota) in allentries :
688                if not changed.has_key(entry.Name) :
689                    changed[entry.Name] = {}
690                    if not options["groups"] :
691                        changed[entry.Name]["ingroups"] = []
692                       
693                if not entry.Exists :       
694                    # not found
695                    if options["add"] :
696                        # In case we want to add something, it is crucial
697                        # that we DON'T check with the system accounts files
698                        # like /etc/passwd because users may be defined
699                        # only remotely
700                        if self.isValidName(entry.Name) :
701                            reject = 0
702                            if rejectunknown :
703                                if options["groups"] :
704                                    try :
705                                        grp.getgrnam(entry.Name)
706                                    except KeyError :   
707                                        self.printInfo(_("Unknown group %s") % entry.Name, "error")
708                                        reject = 1
709                                else :   
710                                    try :
711                                        pwd.getpwnam(entry.Name)
712                                    except KeyError :   
713                                        self.printInfo(_("Unknown user %s") % entry.Name, "error")
714                                        reject = 1
715                            if not reject :       
716                                entry = getattr(self.storage, "add%s" % suffix)(entry)
717                        else :   
718                            if options["groups"] :
719                                self.printInfo(_("Invalid group name %s") % entry.Name)
720                            else :   
721                                self.printInfo(_("Invalid user name %s") % entry.Name)
722                elif options["delete"] :               
723                    todelete[entry.Name] = entry
724                               
725                if entry.Exists and (not entrypquota.Exists) :
726                    # not found
727                    if options["add"] :
728                        entrypquota = getattr(self.storage, "add%sPQuota" % suffix)(entry, printer)
729                       
730                if not entrypquota.Exists :     
731                    self.printInfo(_("Quota not found for object %s on printer %s.") % (entry.Name, printer.Name))
732                else :   
733                    if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) :
734                        entrypquota.setLimits(softlimit, hardlimit)
735                    if limitby :
736                        if changed[entry.Name].get("limitby") is None :
737                            entry.setLimitBy(limitby)
738                            changed[entry.Name]["limitby"] = limitby
739                   
740                    if options["reset"] :
741                        entrypquota.reset()
742                       
743                    if options["hardreset"] :   
744                        entrypquota.hardreset()
745                       
746                    if not options["groups"] :
747                        if options["used"] :
748                            entrypquota.setUsage(used)
749                           
750                        if overcharge is not None :   
751                            if changed[entry.Name].get("overcharge") is None :
752                                entry.setOverChargeFactor(overcharge)
753                                changed[entry.Name]["overcharge"] = overcharge
754                               
755                        if balance :
756                            if changed[entry.Name].get("balance") is None :
757                                if balance.startswith("+") or balance.startswith("-") :
758                                    newbalance = float(entry.AccountBalance or 0.0) + balancevalue
759                                    newlifetimepaid = float(entry.LifeTimePaid or 0.0) + balancevalue
760                                    entry.setAccountBalance(newbalance, newlifetimepaid)
761                                else :
762                                    diff = balancevalue - float(entry.AccountBalance or 0.0)
763                                    newlifetimepaid = float(entry.LifeTimePaid or 0.0) + diff
764                                    entry.setAccountBalance(balancevalue, newlifetimepaid)
765                                changed[entry.Name]["balance"] = balance
766                               
767                        for groupname in groupnames :       
768                            # not executed if option --ingroups is not used
769                            if groupname not in changed[entry.Name]["ingroups"] :
770                                group = self.storage.getGroup(groupname)
771                                if group.Exists :
772                                    self.storage.addUserToGroup(entry, group)
773                                    changed[entry.Name]["ingroups"].append(groupname)
774                                else :
775                                    self.printInfo(_("Group %s not found in the PyKota Storage.") % groupname)
776                       
777        # Now delete what has to be deleted               
778        for (name, entry) in todelete.items() :               
779            entry.delete()
780                     
781if __name__ == "__main__" : 
782    retcode = 0
783    try :
784        defaults = { \
785                     "printer" : "*", \
786                   }
787        short_options = "vhdo:c:l:b:i:naugrp:P:S:H:G:RU:"
788        long_options = ["help", "version", "overcharge=", "charge=", "delete", "limitby=", "balance=", "ingroups=", "noquota", "add", "users", "groups", "reset", "hardreset", "prototype=", "printer=", "softlimit=", "hardlimit=", "pgroups=", "used="]
789       
790        # Initializes the command line tool
791        editor = EdPyKota(doc=__doc__)
792       
793        # parse and checks the command line
794        (options, args) = editor.parseCommandline(sys.argv[1:], short_options, long_options)
795       
796        # sets long options
797        options["help"] = options["h"] or options["help"]
798        options["version"] = options["v"] or options["version"]
799        options["add"] = options["a"] or options["add"]
800        options["users"] = options["u"] or options["users"]
801        options["groups"] = options["g"] or options["groups"]
802        options["prototype"] = options["p"] or options["prototype"]
803        options["printer"] = options["P"] or options["printer"] or defaults["printer"]
804        options["softlimit"] = options["S"] or options["softlimit"]
805        options["hardlimit"] = options["H"] or options["hardlimit"] 
806        options["reset"] = options["r"] or options["reset"] 
807        options["noquota"] = options["n"] or options["noquota"]
808        options["limitby"] = options["l"] or options["limitby"]
809        options["balance"] = options["b"] or options["balance"] 
810        options["delete"] = options["d"] or options["delete"] 
811        options["ingroups"] = options["i"] or options["ingroups"]
812        options["charge"] = options["c"] or options["charge"]
813        options["pgroups"] = options["G"] or options["pgroups"]
814        options["hardreset"] = options["R"] or options["hardreset"] 
815        options["used"] = options["U"] or options["used"]
816        options["overcharge"] = options["o"] or options["overcharge"]
817       
818        if options["help"] :
819            editor.display_usage_and_quit()
820        elif options["version"] :
821            editor.display_version_and_quit()
822        elif options["users"] and options["groups"] :   
823            raise PyKotaToolError, _("incompatible options, see help.")
824        elif (options["add"] or options["prototype"]) and options["delete"] :   
825            raise PyKotaToolError, _("incompatible options, see help.")
826        elif (options["softlimit"] or options["hardlimit"]) and options["prototype"] :   
827            raise PyKotaToolError, _("incompatible options, see help.")
828        elif options["noquota"] and (options["prototype"] or options["hardlimit"] or options["softlimit"]) :
829            raise PyKotaToolError, _("incompatible options, see help.")
830        elif options["groups"] and (options["balance"] or options["ingroups"] or options["used"] or options["overcharge"]) :
831            raise PyKotaToolError, _("incompatible options, see help.")
832        else :
833            retcode = editor.main(args, options)
834    except SystemExit :       
835        pass
836    except :
837        try :
838            editor.crashed("edpykota failed")
839        except :   
840            crashed("edpykota failed")
841        retcode = -1
842
843    try :
844        editor.storage.close()
845    except (TypeError, NameError, AttributeError) :   
846        pass
847       
848    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.