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

Revision 1042, 11.0 kB (checked in by jalet, 21 years ago)

Exception raising for now.

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