root / pykota / trunk / pykota / storage.py @ 1087

Revision 1087, 11.7 kB (checked in by jalet, 21 years ago)

Really big modifications wrt new configuration file's location and content.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1# PyKota
2#
3# PyKota : Print Quotas for CUPS and LPRng
4#
5# (c) 2003 Jerome Alet <alet@librelogiciel.com>
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19#
20# $Id$
21#
22# $Log$
23# Revision 1.19  2003/07/16 21:53:07  jalet
24# Really big modifications wrt new configuration file's location and content.
25#
26# Revision 1.18  2003/07/07 08:33:18  jalet
27# Bug fix due to a typo in LDAP code
28#
29# Revision 1.17  2003/07/05 07:46:50  jalet
30# The previous bug fix was incomplete.
31#
32# Revision 1.16  2003/06/25 19:52:31  jalet
33# Should be ready for testing :-)
34#
35# Revision 1.15  2003/06/25 14:10:58  jalet
36# Exception raising for now.
37#
38# Revision 1.14  2003/06/25 14:10:01  jalet
39# Hey, it may work (edpykota --reset excepted) !
40#
41# Revision 1.13  2003/06/10 16:37:54  jalet
42# Deletion of the second user which is not needed anymore.
43# Added a debug configuration field in /etc/pykota.conf
44# All queries can now be sent to the logger in debug mode, this will
45# greatly help improve performance when time for this will come.
46#
47# Revision 1.12  2003/04/23 22:13:57  jalet
48# Preliminary support for LPRng added BUT STILL UNTESTED.
49#
50# Revision 1.11  2003/04/10 21:47:20  jalet
51# Job history added. Upgrade script neutralized for now !
52#
53# Revision 1.10  2003/03/29 13:45:27  jalet
54# GPL paragraphs were incorrectly (from memory) copied into the sources.
55# Two README files were added.
56# Upgrade script for PostgreSQL pre 1.01 schema was added.
57#
58# Revision 1.9  2003/02/17 22:55:01  jalet
59# More options can now be set per printer or globally :
60#
61#       admin
62#       adminmail
63#       gracedelay
64#       requester
65#
66# the printer option has priority when both are defined.
67#
68# Revision 1.8  2003/02/17 22:05:50  jalet
69# Storage backend now supports admin and user passwords (untested)
70#
71# Revision 1.7  2003/02/10 12:07:31  jalet
72# Now repykota should output the recorded total page number for each printer too.
73#
74# Revision 1.6  2003/02/09 13:05:43  jalet
75# Internationalization continues...
76#
77# Revision 1.5  2003/02/08 22:39:46  jalet
78# --reset command line option added
79#
80# Revision 1.4  2003/02/08 09:59:59  jalet
81# Added preliminary base class for all storages
82#
83# Revision 1.3  2003/02/05 22:10:29  jalet
84# Typos
85#
86# Revision 1.2  2003/02/05 22:02:22  jalet
87# __import__ statement didn't work as expected
88#
89# Revision 1.1  2003/02/05 21:28:17  jalet
90# Initial import into CVS
91#
92#
93#
94
95class PyKotaStorageError(Exception):
96    """An exception for Quota Storage related stuff."""
97    def __init__(self, message = ""):
98        self.message = message
99        Exception.__init__(self, message)
100    def __repr__(self):
101        return self.message
102    __str__ = __repr__
103       
104class StorageObject :
105    """Object present in the Quota Storage."""
106    def __init__(self, parent) :
107        "Initialize minimal data."""
108        self.parent = parent
109        self.ident = None
110        self.Exists = 0
111       
112class StorageUser(StorageObject) :       
113    """User class."""
114    def __init__(self, parent, name) :
115        StorageObject.__init__(self, parent)
116        self.Name = name
117        self.LimitBy = None
118        self.AccountBalance = None
119        self.LifeTimePaid = None
120        self.Email = None
121       
122    def consumeAccountBalance(self, amount) :     
123        """Consumes an amount of money from the user's account balance."""
124        newbalance = float(self.AccountBalance or 0.0) - amount
125        self.parent.writeUserAccountBalance(self, newbalance)
126        self.AccountBalance = newbalance
127       
128    def setAccountBalance(self, balance, lifetimepaid) :   
129        """Sets the user's account balance in case he pays more money."""
130        self.parent.writeUserAccountBalance(self, balance, lifetimepaid)
131        self.AccountBalance = balance
132        self.LifeTimePaid = lifetimepaid
133       
134    def setLimitBy(self, limitby) :   
135        """Sets the user's limiting factor."""
136        try :
137            limitby = limitby.lower()
138        except AttributeError :   
139            limitby = "quota"
140        if limitby in ["quota", "balance"] :
141            self.parent.writeUserLimitBy(self, limitby)
142            self.LimitBy = limitby
143       
144    def delete(self) :   
145        """Deletes an user from the Quota Storage."""
146        self.parent.beginTransaction()
147        try :
148            self.parent.deleteUser(self)
149        except PyKotaStorageError, msg :   
150            self.parent.rollbackTransaction()
151            raise PyKotaStorageError, msg
152        else :   
153            self.parent.commitTransaction()
154       
155class StorageGroup(StorageObject) :       
156    """User class."""
157    def __init__(self, parent, name) :
158        StorageObject.__init__(self, parent)
159        self.Name = name
160        self.LimitBy = None
161        self.AccountBalance = None
162        self.LifeTimePaid = None
163       
164    def setLimitBy(self, limitby) :   
165        """Sets the user's limiting factor."""
166        try :
167            limitby = limitby.lower()
168        except AttributeError :   
169            limitby = "quota"
170        if limitby in ["quota", "balance"] :
171            self.parent.writeGroupLimitBy(self, limitby)
172            self.LimitBy = limitby
173       
174    def delete(self) :   
175        """Deletes a group from the Quota Storage."""
176        self.parent.beginTransaction()
177        try :
178            self.parent.deleteGroup(self)
179        except PyKotaStorageError, msg :   
180            self.parent.rollbackTransaction()
181            raise PyKotaStorageError, msg
182        else :   
183            self.parent.commitTransaction()
184       
185class StoragePrinter(StorageObject) :
186    """Printer class."""
187    def __init__(self, parent, name) :
188        StorageObject.__init__(self, parent)
189        self.Name = name
190        self.PricePerPage = None
191        self.PricePerJob = None
192        self.LastJob = None
193       
194    def addJobToHistory(self, jobid, user, pagecounter, action, jobsize=None) :   
195        """Adds a job to the printer's history."""
196        self.parent.writeJobNew(self, user, jobid, pagecounter, action, jobsize)
197        # TODO : update LastJob object ? Probably not needed.
198       
199    def setPrices(self, priceperpage = None, priceperjob = None) :   
200        """Sets the printer's prices."""
201        if priceperpage is None :
202            priceperpage = self.PricePerPage
203        else :   
204            self.PricePerPage = float(priceperpage)
205        if priceperjob is None :   
206            priceperjob = self.PricePerJob
207        else :   
208            self.PricePerJob = float(priceperjob)
209        self.parent.writePrinterPrices(self)
210       
211class StorageUserPQuota(StorageObject) :
212    """User Print Quota class."""
213    def __init__(self, parent, user, printer) :
214        StorageObject.__init__(self, parent)
215        self.User = user
216        self.Printer = printer
217        self.PageCounter = None
218        self.LifePageCounter = None
219        self.SoftLimit = None
220        self.HardLimit = None
221        self.DateLimit = None
222       
223    def setDateLimit(self, datelimit) :   
224        """Sets the date limit for this quota."""
225        date = "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)
226        self.parent.writeUserPQuotaDateLimit(self, date)
227        self.DateLimit = date
228       
229    def setLimits(self, softlimit, hardlimit) :   
230        """Sets the soft and hard limit for this quota."""
231        self.parent.writeUserPQuotaLimits(self, softlimit, hardlimit)
232        self.SoftLimit = softlimit
233        self.HardLimit = hardlimit
234       
235    def reset(self) :   
236        """Resets page counter to 0."""
237        self.parent.writeUserPQuotaPagesCounters(self, 0, int(self.LifePageCounter or 0))
238        self.PageCounter = 0
239       
240    def increasePagesUsage(self, nbpages) :
241        """Increase the value of used pages and money."""
242        if nbpages :
243            jobprice = (float(self.Printer.PricePerPage or 0.0) * nbpages) + float(self.Printer.PricePerJob or 0.0)
244            newpagecounter = int(self.PageCounter or 0) + nbpages
245            newlifepagecounter = int(self.LifePageCounter or 0) + nbpages
246            self.parent.beginTransaction()
247            try :
248                if jobprice : # optimization : don't access the database if unneeded.
249                    self.User.consumeAccountBalance(jobprice)
250                self.parent.writeUserPQuotaPagesCounters(self, newpagecounter, newlifepagecounter)
251            except PyKotaStorageError, msg :   
252                self.parent.rollbackTransaction()
253                raise PyKotaStorageError, msg
254            else :   
255                self.parent.commitTransaction()
256                self.PageCounter = newpagecounter
257                self.LifePageCounter = newlifepagecounter
258       
259class StorageGroupPQuota(StorageObject) :
260    """Group Print Quota class."""
261    def __init__(self, parent, group, printer) :
262        StorageObject.__init__(self, parent)
263        self.Group = group
264        self.Printer = printer
265        self.PageCounter = None
266        self.LifePageCounter = None
267        self.SoftLimit = None
268        self.HardLimit = None
269        self.DateLimit = None
270       
271    def setDateLimit(self, datelimit) :   
272        """Sets the date limit for this quota."""
273        date = "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)
274        self.parent.writeGroupPQuotaDateLimit(self, date)
275        self.DateLimit = date
276       
277    def setLimits(self, softlimit, hardlimit) :   
278        """Sets the soft and hard limit for this quota."""
279        self.parent.writeGroupPQuotaLimits(self, softlimit, hardlimit)
280        self.SoftLimit = softlimit
281        self.HardLimit = hardlimit
282       
283class StorageLastJob(StorageObject) :
284    """Printer's Last Job class."""
285    def __init__(self, parent, printer) :
286        StorageObject.__init__(self, parent)
287        self.Printer = printer
288        self.JobId = None
289        self.User = None
290        self.PrinterPageCounter = None
291        self.JobSize = None
292        self.JobAction = None
293        self.JobDate = None
294       
295    def setSize(self, jobsize) :
296        """Sets the last job's size."""
297        self.parent.writeLastJobSize(self, jobsize)
298        self.JobSize = jobsize
299   
300def openConnection(pykotatool) :
301    """Returns a connection handle to the appropriate Quota Storage Database."""
302    backendinfo = pykotatool.config.getStorageBackend()
303    backend = backendinfo["storagebackend"]
304    try :
305        if not backend.isalpha() :
306            # don't trust user input
307            raise ImportError
308        #   
309        # TODO : descending compatibility
310        #
311        if backend == "postgresql" :
312            backend = "pgstorage"       # TODO : delete, this is for descending compatibility only
313        exec "from pykota.storages import %s as storagebackend" % backend.lower()   
314    except ImportError :
315        raise PyKotaStorageError, _("Unsupported quota storage backend %s") % backend
316    else :   
317        host = backendinfo["storageserver"]
318        database = backendinfo["storagename"]
319        admin = backendinfo["storageadmin"] or backendinfo["storageuser"]
320        adminpw = backendinfo["storageadminpw"] or backendinfo["storageuserpw"]
321        return getattr(storagebackend, "Storage")(pykotatool, host, database, admin, adminpw)
Note: See TracBrowser for help on using the browser.