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

Revision 1067, 11.6 kB (checked in by jalet, 21 years ago)

Bug fix due to a typo in LDAP code

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