root / pykota / trunk / bin / edpykota @ 2116

Revision 2073, 35.7 kB (checked in by jalet, 20 years ago)

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