#! /usr/bin/env python # PyKota Print Quota Editor # # PyKota - Print Quotas for CUPS # # (c) 2003 Jerome Alet # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. # # $Id$ # # $Log$ # Revision 1.34 2003/04/11 16:51:11 jalet # Bug fix for edpykota --add with users who already had a quota on the printer. # # Revision 1.33 2003/04/10 21:47:20 jalet # Job history added. Upgrade script neutralized for now ! # # Revision 1.32 2003/04/08 21:31:39 jalet # (anything or 0) = anything !!! Go back to school Jerome ! # # Revision 1.31 2003/04/08 21:13:44 jalet # Prepare --groups option to work. # # Revision 1.30 2003/04/08 21:10:18 jalet # Checks --groups option presence instead of --users because --users is the default. # # Revision 1.29 2003/04/05 09:28:56 jalet # Unnecessary message was logged # # Revision 1.28 2003/03/29 13:45:26 jalet # GPL paragraphs were incorrectly (from memory) copied into the sources. # Two README files were added. # Upgrade script for PostgreSQL pre 1.01 schema was added. # # Revision 1.27 2003/03/10 00:23:04 jalet # Bad english # # Revision 1.26 2003/03/10 00:11:27 jalet # Cleaner example. # # Revision 1.25 2003/03/09 23:56:21 jalet # Option noquota added to do accounting only. # # Revision 1.24 2003/02/27 23:48:41 jalet # Correctly maps PyKota's log levels to syslog log levels # # Revision 1.23 2003/02/27 22:55:20 jalet # WARN log priority doesn't exist. # # Revision 1.22 2003/02/27 09:37:02 jalet # Wildcards seem to work now # # Revision 1.21 2003/02/27 09:04:46 jalet # user and group names can be passed as wildcards if the --add option # is not set. The default is to act on all users or groups. # # Revision 1.20 2003/02/10 12:07:30 jalet # Now repykota should output the recorded total page number for each printer too. # # Revision 1.19 2003/02/09 13:40:29 jalet # typo # # Revision 1.18 2003/02/09 12:56:53 jalet # Internationalization begins... # # Revision 1.17 2003/02/08 22:47:23 jalet # Option --reset can now be used without having to use soft and hard limits # on the command line. # # Revision 1.16 2003/02/08 22:39:46 jalet # --reset command line option added # # Revision 1.15 2003/02/08 22:20:01 jalet # Clarification on why we don't check with /etc/passwd to see if the user # name is valid or not. # # Revision 1.14 2003/02/08 22:18:15 jalet # Now checks user and group names for validity before adding them # # Revision 1.13 2003/02/08 22:09:02 jalet # Only printer was added the first time. # # Revision 1.12 2003/02/08 21:44:49 jalet # Python 2.1 string module doesn't define ascii_letters # # Revision 1.11 2003/02/08 09:42:44 jalet # Better handle wrong or bad command line arguments # # Revision 1.10 2003/02/08 09:39:20 jalet # typos # # Revision 1.9 2003/02/08 09:38:06 jalet # Badly placed test # # Revision 1.8 2003/02/07 22:53:57 jalet # Checks if printer name is valid before adding it # # Revision 1.7 2003/02/07 22:17:58 jalet # Incomplete test # # Revision 1.6 2003/02/07 22:13:13 jalet # Perhaps edpykota is now able to add printers !!! Oh, stupid me ! # # Revision 1.5 2003/02/06 14:49:04 jalet # edpykota should be ok now # # Revision 1.4 2003/02/06 14:28:59 jalet # edpykota should be ok, minus some typos # # Revision 1.3 2003/02/06 10:47:21 jalet # Documentation string and command line options didn't match. # # Revision 1.2 2003/02/06 10:39:23 jalet # Preliminary edpykota work. # # Revision 1.1 2003/02/05 21:41:09 jalet # Skeletons added for all command line tools # # # import sys from pykota import version from pykota.tool import PyKotaTool, PyKotaToolError __doc__ = """edpykota v%s (C) 2003 C@LL - Conseil Internet & Logiciels Libres A Print Quota editor for PyKota. command line usage : edpykota [options] user1 user2 ... userN edpykota [options] group1 group2 ... groupN options : -v | --version Prints edpykota's version number then exits. -h | --help Prints this message then exits. -a | --add Adds users and/or printers if they don't exist on the Quota Storage Server. -u | --users Edit users print quotas, this is the default. -P | --printer p Edit quotas on printer p only. Actually p can use wildcards characters to select only some printers. The default value is *, meaning all printers. -g | --groups Edit groups print quotas instead of users. -p | --prototype u|g Uses user u or group g as a prototype to set print quotas -n | --noquota Doesn't set a quota but only does accounting. -r | --reset Resets the printed page counter for the user or group to zero. The life time page counter is kept unchanged. -S | --softlimit sl Sets the quota soft limit to sl pages. -H | --hardlimit hl Sets the quota hard limit to hl pages. user1 through userN and group1 through groupN can use wildcards if the --add option is not set. examples : $ edpykota -p jerome john paul george ringo This will set print quotas for the users john, paul, george and ringo to the same values than user jerome. User jerome must exist. $ edpykota --printer lp -S 50 -H 60 jerome This will set jerome's print quota on the lp printer to a soft limit of 50 pages, and a hard limit of 60 pages. If either user jerome or printer lp doesn't exist on the Quota Storage Server then nothing is done. $ edpykota --add --printer lp -S 50 -H 60 jerome Same as above, but if either user jerome or printer lp doesn't exist on the Quota Storage Server they are automatically added. WARNING : the CUPS PPD file for this printer must still be modified manually, as well as pykota's configuration file for a new printer to be managed successfully. $ edpykota -g -S 500 -H 550 financial support This will set print quota soft limit to 500 pages and hard limit to 550 pages for groups financial and support on all printers. $ edpykota --reset jerome "jo*" This will reset jerome's page counter to zero on all printers, as well as every user whose name begins with 'jo'. Their life time page counter on each printer will be kept unchanged. $ edpykota --printer hpcolor --noquota jerome This will tell PyKota to not limit jerome when printing on the hpcolor printer. All his jobs will be allowed on this printer, but accounting of the pages he prints will still be kept. Print Quotas for jerome on other printers are unchanged. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. Please e-mail bugs to: %s""" % (version.__version__, version.__author__) class EdPyKota(PyKotaTool) : """A class for edpykota.""" def main(self, names, options) : """Edit user or group quotas.""" printers = self.storage.getMatchingPrinters(options["printer"]) if not printers : pname = options["printer"] if options["add"] and pname : if self.isValidName(pname) : printerid = self.storage.addPrinter(pname) printers = [ (printerid, pname) ] else : raise PyKotaToolError, _("Invalid printer name %s") % pname else : raise PyKotaToolError, _("There's no printer matching %s") % pname softlimit = hardlimit = None if options["softlimit"] : try : softlimit = int(options["softlimit"].strip()) except ValueError : raise PyKotaToolError, _("Invalid softlimit value %s.") % options["softlimit"] if options["hardlimit"] : try : hardlimit = int(options["hardlimit"].strip()) except ValueError : raise PyKotaToolError, _("Invalid hardlimit value %s.") % options["hardlimit"] if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) : # error, exchange them self.logger.log_message(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit)) (softlimit, hardlimit) = (hardlimit, softlimit) if not names : if options["add"] : raise PyKotaToolError, _("You have to pass user names on the command line") else : names = [ "*" ] # all users for (printerid, printer) in printers : if options["prototype"] : if options["groups"] : prototype = self.storage.getGroupPQuota(self.storage.getGroupId(options["prototype"]), printerid) else : # default is user quota edition prototype = self.storage.getUserPQuota(self.storage.getUserId(options["prototype"]), printerid) if prototype is None : self.logger.log_message(_("Prototype %s not found in Quota Storage for printer %s.") % (options["prototype"], printer)) continue # skip this printer else : (softlimit, hardlimit) = (prototype["softlimit"], prototype["hardlimit"]) if hardlimit is None : hardlimit = softlimit if hardlimit is not None : self.logger.log_message(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer)) if softlimit is None : softlimit = hardlimit if softlimit is not None : self.logger.log_message(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer)) if (not options["reset"] and not options["noquota"] and not options["prototype"]) and ((hardlimit is None) or (softlimit is None)) : raise PyKotaToolError, _("Both hard and soft limits must be set ! Aborting.") if options["add"] : allidnames = [(self.storage.getUserId(n), n) for n in names] else : if options["groups"] : allidnames = self.storage.getPrinterGroups(printerid) else : allidnames = self.storage.getPrinterUsers(printerid) for (ident, name) in [(i, n) for (i, n) in allidnames if self.matchString(n, names)]: if options["groups"] : quota = self.storage.getGroupPQuota(ident, printerid) else : quota = self.storage.getUserPQuota(ident, printerid) if quota is None : # not found if options["add"] : # In case we want to add something, it is crucial # that we DON'T check with the system accounts files # like /etc/passwd because users may be defined # only remotely if options["groups"] : if self.isValidName(name) : (ident, printerid) = self.storage.addGroupPQuota(name, printerid) quota = self.storage.getGroupPQuota(ident, printerid) else : self.logger.log_message(_("Invalid group name %s") % name) else : if self.isValidName(name) : (ident, printerid) = self.storage.addUserPQuota(name, printerid) quota = self.storage.getUserPQuota(ident, printerid) else : self.logger.log_message(_("Invalid user name %s") % name) if quota is None : self.logger.log_message(_("Quota not found for object %s on printer %s.") % (name, printer)) else : if options["groups"] : if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) : self.storage.setGroupPQuota(ident, printerid, softlimit, hardlimit) if options["reset"] : self.storage.resetGroupPQuota(ident, printerid) self.warnGroupPQuota(name, printer) else : if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) : self.storage.setUserPQuota(ident, printerid, softlimit, hardlimit) if options["reset"] : self.storage.resetUserPQuota(ident, printerid) self.warnUserPQuota(name, printer) if __name__ == "__main__" : try : defaults = { \ "printer" : "*", \ } short_options = "vhnaugrp:P:S:H:" long_options = ["help", "version", "noquota", "add", "users", "groups", "reset", "prototype=", "printer=", "softlimit=", "hardlimit="] # Initializes the command line tool editor = EdPyKota(doc=__doc__) # parse and checks the command line (options, args) = editor.parseCommandline(sys.argv[1:], short_options, long_options) # sets long options options["help"] = options["h"] or options["help"] options["version"] = options["v"] or options["version"] options["add"] = options["a"] or options["add"] options["users"] = options["u"] or options["users"] options["groups"] = options["g"] or options["groups"] options["prototype"] = options["p"] or options["prototype"] options["printer"] = options["P"] or options["printer"] or defaults["printer"] options["softlimit"] = options["S"] or options["softlimit"] options["hardlimit"] = options["H"] or options["hardlimit"] options["reset"] = options["r"] or options["reset"] options["noquota"] = options["n"] or options["noquota"] if options["help"] : editor.display_usage_and_quit() elif options["version"] : editor.display_version_and_quit() elif options["users"] and options["groups"] : raise PyKotaToolError, _("incompatible options, see help.") elif (options["softlimit"] or options["hardlimit"]) and options["prototype"] : raise PyKotaToolError, _("incompatible options, see help.") elif options["noquota"] and (options["prototype"] or options["hardlimit"] or options["softlimit"]) : raise PyKotaToolError, _("incompatible options, see help.") elif options["groups"] : raise PyKotaToolError, _("option --groups is currently not implemented.") else : sys.exit(editor.main(args, options)) except PyKotaToolError, msg : sys.stderr.write("%s\n" % msg) sys.stderr.flush() sys.exit(-1)